]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/fortran/trans-array.c
PR fortran/95090 - ICE: identifier overflow
[thirdparty/gcc.git] / gcc / fortran / trans-array.c
CommitLineData
6de9cd9a 1/* Array translation routines
8d9254fc 2 Copyright (C) 2002-2020 Free Software Foundation, Inc.
6de9cd9a
DN
3 Contributed by Paul Brook <paul@nowt.org>
4 and Steven Bosscher <s.bosscher@student.tudelft.nl>
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/* trans-array.c-- Various array related code, including scalarization,
23 allocation, initialization and other support routines. */
24
25/* How the scalarizer works.
26 In gfortran, array expressions use the same core routines as scalar
27 expressions.
28 First, a Scalarization State (SS) chain is built. This is done by walking
29 the expression tree, and building a linear list of the terms in the
30 expression. As the tree is walked, scalar subexpressions are translated.
31
32 The scalarization parameters are stored in a gfc_loopinfo structure.
33 First the start and stride of each term is calculated by
34 gfc_conv_ss_startstride. During this process the expressions for the array
35 descriptors and data pointers are also translated.
36
37 If the expression is an assignment, we must then resolve any dependencies.
eea58adb 38 In Fortran all the rhs values of an assignment must be evaluated before
6de9cd9a
DN
39 any assignments take place. This can require a temporary array to store the
40 values. We also require a temporary when we are passing array expressions
df2fba9e 41 or vector subscripts as procedure parameters.
6de9cd9a
DN
42
43 Array sections are passed without copying to a temporary. These use the
44 scalarizer to determine the shape of the section. The flag
45 loop->array_parameter tells the scalarizer that the actual values and loop
46 variables will not be required.
47
48 The function gfc_conv_loop_setup generates the scalarization setup code.
49 It determines the range of the scalarizing loop variables. If a temporary
50 is required, this is created and initialized. Code for scalar expressions
51 taken outside the loop is also generated at this time. Next the offset and
52 scaling required to translate from loop variables to array indices for each
53 term is calculated.
54
55 A call to gfc_start_scalarized_body marks the start of the scalarized
56 expression. This creates a scope and declares the loop variables. Before
57 calling this gfc_make_ss_chain_used must be used to indicate which terms
58 will be used inside this loop.
59
60 The scalar gfc_conv_* functions are then used to build the main body of the
61 scalarization loop. Scalarization loop variables and precalculated scalar
1f2959f0 62 values are automatically substituted. Note that gfc_advance_se_ss_chain
6de9cd9a
DN
63 must be used, rather than changing the se->ss directly.
64
65 For assignment expressions requiring a temporary two sub loops are
66 generated. The first stores the result of the expression in the temporary,
67 the second copies it to the result. A call to
68 gfc_trans_scalarized_loop_boundary marks the end of the main loop code and
69 the start of the copying loop. The temporary may be less than full rank.
70
71 Finally gfc_trans_scalarizing_loops is called to generate the implicit do
72 loops. The loops are added to the pre chain of the loopinfo. The post
73 chain may still contain cleanup code.
74
75 After the loop code has been added into its parent scope gfc_cleanup_loop
76 is called to free all the SS allocated by the scalarizer. */
77
78#include "config.h"
79#include "system.h"
80#include "coretypes.h"
c7131fb2 81#include "options.h"
2adfab87
AM
82#include "tree.h"
83#include "gfortran.h"
45b0be94 84#include "gimple-expr.h"
2adfab87 85#include "trans.h"
2adfab87 86#include "fold-const.h"
b7e75771 87#include "constructor.h"
6de9cd9a
DN
88#include "trans-types.h"
89#include "trans-array.h"
90#include "trans-const.h"
91#include "dependency.h"
92
b7e75771 93static bool gfc_get_array_constructor_size (mpz_t *, gfc_constructor_base);
6de9cd9a 94
13413760 95/* The contents of this structure aren't actually used, just the address. */
6de9cd9a
DN
96static gfc_ss gfc_ss_terminator_var;
97gfc_ss * const gfc_ss_terminator = &gfc_ss_terminator_var;
98
6de9cd9a
DN
99
100static tree
101gfc_array_dataptr_type (tree desc)
102{
103 return (GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc)));
104}
105
106
107/* Build expressions to access the members of an array descriptor.
108 It's surprisingly easy to mess up here, so never access
109 an array descriptor by "brute force", always use these
110 functions. This also avoids problems if we change the format
111 of an array descriptor.
112
113 To understand these magic numbers, look at the comments
114 before gfc_build_array_type() in trans-types.c.
115
116 The code within these defines should be the only code which knows the format
117 of an array descriptor.
118
119 Any code just needing to read obtain the bounds of an array should use
120 gfc_conv_array_* rather than the following functions as these will return
121 know constant values, and work with arrays which do not have descriptors.
122
123 Don't forget to #undef these! */
124
125#define DATA_FIELD 0
126#define OFFSET_FIELD 1
127#define DTYPE_FIELD 2
ff3598bc
PT
128#define SPAN_FIELD 3
129#define DIMENSION_FIELD 4
130#define CAF_TOKEN_FIELD 5
6de9cd9a
DN
131
132#define STRIDE_SUBFIELD 0
133#define LBOUND_SUBFIELD 1
134#define UBOUND_SUBFIELD 2
135
4c73896d
RH
136/* This provides READ-ONLY access to the data field. The field itself
137 doesn't have the proper type. */
138
6de9cd9a 139tree
4c73896d 140gfc_conv_descriptor_data_get (tree desc)
6de9cd9a 141{
4c73896d 142 tree field, type, t;
6de9cd9a
DN
143
144 type = TREE_TYPE (desc);
92e63bd2
TB
145 if (TREE_CODE (type) == REFERENCE_TYPE)
146 type = TREE_TYPE (type);
147
6e45f57b 148 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
6de9cd9a
DN
149
150 field = TYPE_FIELDS (type);
6e45f57b 151 gcc_assert (DATA_FIELD == 0);
6de9cd9a 152
94471a56
TB
153 t = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field), desc,
154 field, NULL_TREE);
4c73896d
RH
155 t = fold_convert (GFC_TYPE_ARRAY_DATAPTR_TYPE (type), t);
156
157 return t;
158}
159
07beea0d
AH
160/* This provides WRITE access to the data field.
161
162 TUPLES_P is true if we are generating tuples.
f04986a9 163
07beea0d
AH
164 This function gets called through the following macros:
165 gfc_conv_descriptor_data_set
726a989a 166 gfc_conv_descriptor_data_set. */
4c73896d
RH
167
168void
726a989a 169gfc_conv_descriptor_data_set (stmtblock_t *block, tree desc, tree value)
4c73896d
RH
170{
171 tree field, type, t;
172
173 type = TREE_TYPE (desc);
174 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
175
176 field = TYPE_FIELDS (type);
177 gcc_assert (DATA_FIELD == 0);
178
94471a56
TB
179 t = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field), desc,
180 field, NULL_TREE);
726a989a 181 gfc_add_modify (block, t, fold_convert (TREE_TYPE (field), value));
4c73896d
RH
182}
183
184
185/* This provides address access to the data field. This should only be
186 used by array allocation, passing this on to the runtime. */
187
188tree
189gfc_conv_descriptor_data_addr (tree desc)
190{
191 tree field, type, t;
192
193 type = TREE_TYPE (desc);
194 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
195
196 field = TYPE_FIELDS (type);
197 gcc_assert (DATA_FIELD == 0);
198
94471a56
TB
199 t = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field), desc,
200 field, NULL_TREE);
628c189e 201 return gfc_build_addr_expr (NULL_TREE, t);
6de9cd9a
DN
202}
203
568e8e1e 204static tree
6de9cd9a
DN
205gfc_conv_descriptor_offset (tree desc)
206{
207 tree type;
208 tree field;
209
210 type = TREE_TYPE (desc);
6e45f57b 211 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
6de9cd9a
DN
212
213 field = gfc_advance_chain (TYPE_FIELDS (type), OFFSET_FIELD);
6e45f57b 214 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
6de9cd9a 215
94471a56
TB
216 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
217 desc, field, NULL_TREE);
6de9cd9a
DN
218}
219
568e8e1e
PT
220tree
221gfc_conv_descriptor_offset_get (tree desc)
222{
223 return gfc_conv_descriptor_offset (desc);
224}
225
226void
227gfc_conv_descriptor_offset_set (stmtblock_t *block, tree desc,
228 tree value)
229{
230 tree t = gfc_conv_descriptor_offset (desc);
231 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
232}
233
234
6de9cd9a
DN
235tree
236gfc_conv_descriptor_dtype (tree desc)
237{
238 tree field;
239 tree type;
240
241 type = TREE_TYPE (desc);
6e45f57b 242 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
6de9cd9a
DN
243
244 field = gfc_advance_chain (TYPE_FIELDS (type), DTYPE_FIELD);
7fb43006
PT
245 gcc_assert (field != NULL_TREE
246 && TREE_TYPE (field) == get_dtype_type_node ());
6de9cd9a 247
94471a56
TB
248 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
249 desc, field, NULL_TREE);
6de9cd9a
DN
250}
251
ff3598bc
PT
252static tree
253gfc_conv_descriptor_span (tree desc)
254{
255 tree type;
256 tree field;
257
258 type = TREE_TYPE (desc);
259 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
260
261 field = gfc_advance_chain (TYPE_FIELDS (type), SPAN_FIELD);
262 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
263
264 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
265 desc, field, NULL_TREE);
266}
267
268tree
269gfc_conv_descriptor_span_get (tree desc)
270{
271 return gfc_conv_descriptor_span (desc);
272}
273
274void
275gfc_conv_descriptor_span_set (stmtblock_t *block, tree desc,
276 tree value)
277{
278 tree t = gfc_conv_descriptor_span (desc);
279 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
280}
281
c62c6622 282
17aa6ab6
MM
283tree
284gfc_conv_descriptor_rank (tree desc)
285{
286 tree tmp;
287 tree dtype;
288
289 dtype = gfc_conv_descriptor_dtype (desc);
7fb43006 290 tmp = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (dtype)), GFC_DTYPE_RANK);
db06a76e 291 gcc_assert (tmp != NULL_TREE
7fb43006
PT
292 && TREE_TYPE (tmp) == signed_char_type_node);
293 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (tmp),
294 dtype, tmp, NULL_TREE);
17aa6ab6
MM
295}
296
297
db06a76e
PT
298/* Return the element length from the descriptor dtype field. */
299
300tree
301gfc_conv_descriptor_elem_len (tree desc)
302{
303 tree tmp;
304 tree dtype;
305
306 dtype = gfc_conv_descriptor_dtype (desc);
307 tmp = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (dtype)),
308 GFC_DTYPE_ELEM_LEN);
309 gcc_assert (tmp != NULL_TREE
310 && TREE_TYPE (tmp) == size_type_node);
311 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (tmp),
312 dtype, tmp, NULL_TREE);
313}
314
315
bbf18dc5
PT
316tree
317gfc_conv_descriptor_attribute (tree desc)
318{
319 tree tmp;
320 tree dtype;
321
322 dtype = gfc_conv_descriptor_dtype (desc);
323 tmp = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (dtype)),
324 GFC_DTYPE_ATTRIBUTE);
325 gcc_assert (tmp!= NULL_TREE
326 && TREE_TYPE (tmp) == short_integer_type_node);
327 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (tmp),
328 dtype, tmp, NULL_TREE);
329}
330
331
c62c6622
TB
332tree
333gfc_get_descriptor_dimension (tree desc)
6de9cd9a 334{
c62c6622 335 tree type, field;
6de9cd9a
DN
336
337 type = TREE_TYPE (desc);
6e45f57b 338 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
6de9cd9a
DN
339
340 field = gfc_advance_chain (TYPE_FIELDS (type), DIMENSION_FIELD);
6e45f57b 341 gcc_assert (field != NULL_TREE
6de9cd9a
DN
342 && TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
343 && TREE_CODE (TREE_TYPE (TREE_TYPE (field))) == RECORD_TYPE);
344
c62c6622
TB
345 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
346 desc, field, NULL_TREE);
347}
348
349
350static tree
351gfc_conv_descriptor_dimension (tree desc, tree dim)
352{
353 tree tmp;
354
355 tmp = gfc_get_descriptor_dimension (desc);
356
357 return gfc_build_array_ref (tmp, dim, NULL);
6de9cd9a
DN
358}
359
af232d48
TB
360
361tree
362gfc_conv_descriptor_token (tree desc)
363{
364 tree type;
365 tree field;
366
367 type = TREE_TYPE (desc);
368 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
f19626cf 369 gcc_assert (flag_coarray == GFC_FCOARRAY_LIB);
af232d48 370 field = gfc_advance_chain (TYPE_FIELDS (type), CAF_TOKEN_FIELD);
16023efc
TB
371
372 /* Should be a restricted pointer - except in the finalization wrapper. */
373 gcc_assert (field != NULL_TREE
374 && (TREE_TYPE (field) == prvoid_type_node
375 || TREE_TYPE (field) == pvoid_type_node));
af232d48
TB
376
377 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
378 desc, field, NULL_TREE);
379}
380
381
568e8e1e 382static tree
6de9cd9a
DN
383gfc_conv_descriptor_stride (tree desc, tree dim)
384{
385 tree tmp;
386 tree field;
387
388 tmp = gfc_conv_descriptor_dimension (desc, dim);
389 field = TYPE_FIELDS (TREE_TYPE (tmp));
390 field = gfc_advance_chain (field, STRIDE_SUBFIELD);
6e45f57b 391 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
6de9cd9a 392
94471a56
TB
393 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
394 tmp, field, NULL_TREE);
6de9cd9a
DN
395 return tmp;
396}
397
398tree
568e8e1e
PT
399gfc_conv_descriptor_stride_get (tree desc, tree dim)
400{
a3788c44
MM
401 tree type = TREE_TYPE (desc);
402 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
403 if (integer_zerop (dim)
fe4e525c
TB
404 && (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE
405 ||GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_SHAPE_CONT
c62c6622 406 ||GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_RANK_CONT
fe4e525c 407 ||GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER_CONT))
a3788c44
MM
408 return gfc_index_one_node;
409
568e8e1e
PT
410 return gfc_conv_descriptor_stride (desc, dim);
411}
412
413void
414gfc_conv_descriptor_stride_set (stmtblock_t *block, tree desc,
415 tree dim, tree value)
416{
417 tree t = gfc_conv_descriptor_stride (desc, dim);
418 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
419}
420
421static tree
6de9cd9a
DN
422gfc_conv_descriptor_lbound (tree desc, tree dim)
423{
424 tree tmp;
425 tree field;
426
427 tmp = gfc_conv_descriptor_dimension (desc, dim);
428 field = TYPE_FIELDS (TREE_TYPE (tmp));
429 field = gfc_advance_chain (field, LBOUND_SUBFIELD);
6e45f57b 430 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
6de9cd9a 431
94471a56
TB
432 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
433 tmp, field, NULL_TREE);
6de9cd9a
DN
434 return tmp;
435}
436
437tree
568e8e1e
PT
438gfc_conv_descriptor_lbound_get (tree desc, tree dim)
439{
440 return gfc_conv_descriptor_lbound (desc, dim);
441}
442
443void
444gfc_conv_descriptor_lbound_set (stmtblock_t *block, tree desc,
445 tree dim, tree value)
446{
447 tree t = gfc_conv_descriptor_lbound (desc, dim);
448 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
449}
450
451static tree
6de9cd9a
DN
452gfc_conv_descriptor_ubound (tree desc, tree dim)
453{
454 tree tmp;
455 tree field;
456
457 tmp = gfc_conv_descriptor_dimension (desc, dim);
458 field = TYPE_FIELDS (TREE_TYPE (tmp));
459 field = gfc_advance_chain (field, UBOUND_SUBFIELD);
6e45f57b 460 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
6de9cd9a 461
94471a56
TB
462 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
463 tmp, field, NULL_TREE);
6de9cd9a
DN
464 return tmp;
465}
466
568e8e1e
PT
467tree
468gfc_conv_descriptor_ubound_get (tree desc, tree dim)
469{
470 return gfc_conv_descriptor_ubound (desc, dim);
471}
472
473void
474gfc_conv_descriptor_ubound_set (stmtblock_t *block, tree desc,
475 tree dim, tree value)
476{
477 tree t = gfc_conv_descriptor_ubound (desc, dim);
478 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
479}
6de9cd9a 480
49de9e73 481/* Build a null array descriptor constructor. */
6de9cd9a 482
331c72f3
PB
483tree
484gfc_build_null_descriptor (tree type)
6de9cd9a 485{
6de9cd9a 486 tree field;
331c72f3 487 tree tmp;
6de9cd9a 488
6e45f57b
PB
489 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
490 gcc_assert (DATA_FIELD == 0);
6de9cd9a
DN
491 field = TYPE_FIELDS (type);
492
331c72f3 493 /* Set a NULL data pointer. */
4038c495 494 tmp = build_constructor_single (type, field, null_pointer_node);
6de9cd9a 495 TREE_CONSTANT (tmp) = 1;
331c72f3
PB
496 /* All other fields are ignored. */
497
498 return tmp;
6de9cd9a
DN
499}
500
501
99d821c0
DK
502/* Modify a descriptor such that the lbound of a given dimension is the value
503 specified. This also updates ubound and offset accordingly. */
504
505void
506gfc_conv_shift_descriptor_lbound (stmtblock_t* block, tree desc,
507 int dim, tree new_lbound)
508{
509 tree offs, ubound, lbound, stride;
510 tree diff, offs_diff;
511
512 new_lbound = fold_convert (gfc_array_index_type, new_lbound);
513
514 offs = gfc_conv_descriptor_offset_get (desc);
515 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[dim]);
516 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[dim]);
517 stride = gfc_conv_descriptor_stride_get (desc, gfc_rank_cst[dim]);
518
519 /* Get difference (new - old) by which to shift stuff. */
94471a56
TB
520 diff = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
521 new_lbound, lbound);
99d821c0
DK
522
523 /* Shift ubound and offset accordingly. This has to be done before
524 updating the lbound, as they depend on the lbound expression! */
94471a56
TB
525 ubound = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
526 ubound, diff);
99d821c0 527 gfc_conv_descriptor_ubound_set (block, desc, gfc_rank_cst[dim], ubound);
94471a56
TB
528 offs_diff = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
529 diff, stride);
530 offs = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
531 offs, offs_diff);
99d821c0
DK
532 gfc_conv_descriptor_offset_set (block, desc, offs);
533
534 /* Finally set lbound to value we want. */
535 gfc_conv_descriptor_lbound_set (block, desc, gfc_rank_cst[dim], new_lbound);
536}
537
538
ff3598bc
PT
539/* Obtain offsets for trans-types.c(gfc_get_array_descr_info). */
540
541void
542gfc_get_descriptor_offsets_for_info (const_tree desc_type, tree *data_off,
2297a38e
JJ
543 tree *dtype_off, tree *span_off,
544 tree *dim_off, tree *dim_size,
545 tree *stride_suboff, tree *lower_suboff,
546 tree *upper_suboff)
ff3598bc
PT
547{
548 tree field;
549 tree type;
550
551 type = TYPE_MAIN_VARIANT (desc_type);
f2adfb89 552 field = gfc_advance_chain (TYPE_FIELDS (type), DATA_FIELD);
ff3598bc
PT
553 *data_off = byte_position (field);
554 field = gfc_advance_chain (TYPE_FIELDS (type), DTYPE_FIELD);
555 *dtype_off = byte_position (field);
2297a38e
JJ
556 field = gfc_advance_chain (TYPE_FIELDS (type), SPAN_FIELD);
557 *span_off = byte_position (field);
ff3598bc
PT
558 field = gfc_advance_chain (TYPE_FIELDS (type), DIMENSION_FIELD);
559 *dim_off = byte_position (field);
560 type = TREE_TYPE (TREE_TYPE (field));
561 *dim_size = TYPE_SIZE_UNIT (type);
562 field = gfc_advance_chain (TYPE_FIELDS (type), STRIDE_SUBFIELD);
563 *stride_suboff = byte_position (field);
564 field = gfc_advance_chain (TYPE_FIELDS (type), LBOUND_SUBFIELD);
565 *lower_suboff = byte_position (field);
566 field = gfc_advance_chain (TYPE_FIELDS (type), UBOUND_SUBFIELD);
567 *upper_suboff = byte_position (field);
568}
569
570
6de9cd9a
DN
571/* Cleanup those #defines. */
572
573#undef DATA_FIELD
574#undef OFFSET_FIELD
575#undef DTYPE_FIELD
ff3598bc 576#undef SPAN_FIELD
6de9cd9a 577#undef DIMENSION_FIELD
af232d48 578#undef CAF_TOKEN_FIELD
6de9cd9a
DN
579#undef STRIDE_SUBFIELD
580#undef LBOUND_SUBFIELD
581#undef UBOUND_SUBFIELD
582
583
584/* Mark a SS chain as used. Flags specifies in which loops the SS is used.
585 flags & 1 = Main loop body.
586 flags & 2 = temp copy loop. */
587
588void
589gfc_mark_ss_chain_used (gfc_ss * ss, unsigned flags)
590{
591 for (; ss != gfc_ss_terminator; ss = ss->next)
7a412892 592 ss->info->useflags = flags;
6de9cd9a
DN
593}
594
6de9cd9a
DN
595
596/* Free a gfc_ss chain. */
597
fcba5509 598void
6de9cd9a
DN
599gfc_free_ss_chain (gfc_ss * ss)
600{
601 gfc_ss *next;
602
603 while (ss != gfc_ss_terminator)
604 {
6e45f57b 605 gcc_assert (ss != NULL);
6de9cd9a
DN
606 next = ss->next;
607 gfc_free_ss (ss);
608 ss = next;
609 }
610}
611
612
bcc4d4e0
MM
613static void
614free_ss_info (gfc_ss_info *ss_info)
615{
2960a368
TB
616 int n;
617
c7bf4f1e
MM
618 ss_info->refcount--;
619 if (ss_info->refcount > 0)
620 return;
621
622 gcc_assert (ss_info->refcount == 0);
bcc4d4e0
MM
623
624 switch (ss_info->type)
6de9cd9a
DN
625 {
626 case GFC_SS_SECTION:
2960a368
TB
627 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
628 if (ss_info->data.array.subscript[n])
629 gfc_free_ss_chain (ss_info->data.array.subscript[n]);
6de9cd9a
DN
630 break;
631
632 default:
633 break;
634 }
635
2960a368
TB
636 free (ss_info);
637}
638
639
640/* Free a SS. */
641
642void
643gfc_free_ss (gfc_ss * ss)
644{
645 free_ss_info (ss->info);
cede9502 646 free (ss);
6de9cd9a
DN
647}
648
649
66877276
MM
650/* Creates and initializes an array type gfc_ss struct. */
651
652gfc_ss *
653gfc_get_array_ss (gfc_ss *next, gfc_expr *expr, int dimen, gfc_ss_type type)
654{
655 gfc_ss *ss;
bcc4d4e0 656 gfc_ss_info *ss_info;
66877276
MM
657 int i;
658
bcc4d4e0 659 ss_info = gfc_get_ss_info ();
c7bf4f1e 660 ss_info->refcount++;
bcc4d4e0 661 ss_info->type = type;
f98cfd3c 662 ss_info->expr = expr;
bcc4d4e0 663
66877276 664 ss = gfc_get_ss ();
bcc4d4e0 665 ss->info = ss_info;
66877276 666 ss->next = next;
cb4b9eae
MM
667 ss->dimen = dimen;
668 for (i = 0; i < ss->dimen; i++)
669 ss->dim[i] = i;
66877276
MM
670
671 return ss;
672}
673
674
a1ae4f43
MM
675/* Creates and initializes a temporary type gfc_ss struct. */
676
677gfc_ss *
678gfc_get_temp_ss (tree type, tree string_length, int dimen)
679{
680 gfc_ss *ss;
bcc4d4e0 681 gfc_ss_info *ss_info;
cb4b9eae 682 int i;
a1ae4f43 683
bcc4d4e0 684 ss_info = gfc_get_ss_info ();
c7bf4f1e 685 ss_info->refcount++;
bcc4d4e0 686 ss_info->type = GFC_SS_TEMP;
a0add3be 687 ss_info->string_length = string_length;
961e73ac 688 ss_info->data.temp.type = type;
bcc4d4e0 689
a1ae4f43 690 ss = gfc_get_ss ();
bcc4d4e0 691 ss->info = ss_info;
a1ae4f43 692 ss->next = gfc_ss_terminator;
cb4b9eae
MM
693 ss->dimen = dimen;
694 for (i = 0; i < ss->dimen; i++)
695 ss->dim[i] = i;
a1ae4f43
MM
696
697 return ss;
698}
f04986a9 699
26f77530
MM
700
701/* Creates and initializes a scalar type gfc_ss struct. */
702
703gfc_ss *
704gfc_get_scalar_ss (gfc_ss *next, gfc_expr *expr)
705{
706 gfc_ss *ss;
bcc4d4e0
MM
707 gfc_ss_info *ss_info;
708
709 ss_info = gfc_get_ss_info ();
c7bf4f1e 710 ss_info->refcount++;
bcc4d4e0 711 ss_info->type = GFC_SS_SCALAR;
f98cfd3c 712 ss_info->expr = expr;
26f77530
MM
713
714 ss = gfc_get_ss ();
bcc4d4e0 715 ss->info = ss_info;
26f77530 716 ss->next = next;
26f77530
MM
717
718 return ss;
719}
a1ae4f43
MM
720
721
6de9cd9a
DN
722/* Free all the SS associated with a loop. */
723
724void
725gfc_cleanup_loop (gfc_loopinfo * loop)
726{
4616ef9b 727 gfc_loopinfo *loop_next, **ploop;
6de9cd9a
DN
728 gfc_ss *ss;
729 gfc_ss *next;
730
731 ss = loop->ss;
732 while (ss != gfc_ss_terminator)
733 {
6e45f57b 734 gcc_assert (ss != NULL);
6de9cd9a
DN
735 next = ss->loop_chain;
736 gfc_free_ss (ss);
737 ss = next;
738 }
4616ef9b
MM
739
740 /* Remove reference to self in the parent loop. */
741 if (loop->parent)
742 for (ploop = &loop->parent->nested; *ploop; ploop = &(*ploop)->next)
743 if (*ploop == loop)
744 {
745 *ploop = loop->next;
746 break;
747 }
748
749 /* Free non-freed nested loops. */
750 for (loop = loop->nested; loop; loop = loop_next)
751 {
752 loop_next = loop->next;
753 gfc_cleanup_loop (loop);
754 free (loop);
755 }
6de9cd9a
DN
756}
757
758
4615abe8
MM
759static void
760set_ss_loop (gfc_ss *ss, gfc_loopinfo *loop)
761{
762 int n;
763
764 for (; ss != gfc_ss_terminator; ss = ss->next)
765 {
766 ss->loop = loop;
767
768 if (ss->info->type == GFC_SS_SCALAR
769 || ss->info->type == GFC_SS_REFERENCE
770 || ss->info->type == GFC_SS_TEMP)
771 continue;
772
773 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
774 if (ss->info->data.array.subscript[n] != NULL)
775 set_ss_loop (ss->info->data.array.subscript[n], loop);
776 }
777}
778
779
6de9cd9a
DN
780/* Associate a SS chain with a loop. */
781
782void
783gfc_add_ss_to_loop (gfc_loopinfo * loop, gfc_ss * head)
784{
785 gfc_ss *ss;
9d758043 786 gfc_loopinfo *nested_loop;
6de9cd9a
DN
787
788 if (head == gfc_ss_terminator)
789 return;
790
4615abe8
MM
791 set_ss_loop (head, loop);
792
6de9cd9a
DN
793 ss = head;
794 for (; ss && ss != gfc_ss_terminator; ss = ss->next)
795 {
9d758043
MM
796 if (ss->nested_ss)
797 {
798 nested_loop = ss->nested_ss->loop;
799
800 /* More than one ss can belong to the same loop. Hence, we add the
801 loop to the chain only if it is different from the previously
802 added one, to avoid duplicate nested loops. */
803 if (nested_loop != loop->nested)
804 {
4616ef9b
MM
805 gcc_assert (nested_loop->parent == NULL);
806 nested_loop->parent = loop;
807
9d758043
MM
808 gcc_assert (nested_loop->next == NULL);
809 nested_loop->next = loop->nested;
810 loop->nested = nested_loop;
811 }
4616ef9b
MM
812 else
813 gcc_assert (nested_loop->parent == loop);
9d758043
MM
814 }
815
6de9cd9a
DN
816 if (ss->next == gfc_ss_terminator)
817 ss->loop_chain = loop->ss;
818 else
819 ss->loop_chain = ss->next;
820 }
6e45f57b 821 gcc_assert (ss == gfc_ss_terminator);
6de9cd9a
DN
822 loop->ss = head;
823}
824
825
ff3598bc
PT
826/* Returns true if the expression is an array pointer. */
827
828static bool
829is_pointer_array (tree expr)
830{
ff3598bc
PT
831 if (expr == NULL_TREE
832 || !GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (expr))
833 || GFC_CLASS_TYPE_P (TREE_TYPE (expr)))
834 return false;
835
836 if (TREE_CODE (expr) == VAR_DECL
837 && GFC_DECL_PTR_ARRAY_P (expr))
838 return true;
839
840 if (TREE_CODE (expr) == PARM_DECL
841 && GFC_DECL_PTR_ARRAY_P (expr))
842 return true;
843
844 if (TREE_CODE (expr) == INDIRECT_REF
845 && GFC_DECL_PTR_ARRAY_P (TREE_OPERAND (expr, 0)))
846 return true;
847
848 /* The field declaration is marked as an pointer array. */
849 if (TREE_CODE (expr) == COMPONENT_REF
850 && GFC_DECL_PTR_ARRAY_P (TREE_OPERAND (expr, 1))
851 && !GFC_CLASS_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 1))))
852 return true;
853
854 return false;
855}
856
857
0d78e4aa
PT
858/* If the symbol or expression reference a CFI descriptor, return the
859 pointer to the converted gfc descriptor. If an array reference is
860 present as the last argument, check that it is the one applied to
861 the CFI descriptor in the expression. Note that the CFI object is
862 always the symbol in the expression! */
863
864static bool
865get_CFI_desc (gfc_symbol *sym, gfc_expr *expr,
866 tree *desc, gfc_array_ref *ar)
867{
868 tree tmp;
869
870 if (!is_CFI_desc (sym, expr))
871 return false;
872
873 if (expr && ar)
874 {
875 if (!(expr->ref && expr->ref->type == REF_ARRAY)
876 || (&expr->ref->u.ar != ar))
877 return false;
878 }
879
880 if (sym == NULL)
881 tmp = expr->symtree->n.sym->backend_decl;
882 else
883 tmp = sym->backend_decl;
884
9995ce07 885 if (tmp && DECL_LANG_SPECIFIC (tmp) && GFC_DECL_SAVED_DESCRIPTOR (tmp))
0d78e4aa
PT
886 tmp = GFC_DECL_SAVED_DESCRIPTOR (tmp);
887
888 *desc = tmp;
889 return true;
890}
891
892
ff3598bc
PT
893/* Return the span of an array. */
894
f82f425b
PT
895tree
896gfc_get_array_span (tree desc, gfc_expr *expr)
ff3598bc
PT
897{
898 tree tmp;
899
0d78e4aa
PT
900 if (is_pointer_array (desc) || get_CFI_desc (NULL, expr, &desc, NULL))
901 {
902 if (POINTER_TYPE_P (TREE_TYPE (desc)))
903 desc = build_fold_indirect_ref_loc (input_location, desc);
904
905 /* This will have the span field set. */
906 tmp = gfc_conv_descriptor_span_get (desc);
907 }
ff3598bc
PT
908 else if (TREE_CODE (desc) == COMPONENT_REF
909 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc))
910 && GFC_CLASS_TYPE_P (TREE_TYPE (TREE_OPERAND (desc, 0))))
911 {
912 /* The descriptor is a class _data field and so use the vtable
913 size for the receiving span field. */
914 tmp = gfc_get_vptr_from_expr (desc);
915 tmp = gfc_vptr_size_get (tmp);
916 }
917 else if (expr && expr->expr_type == EXPR_VARIABLE
918 && expr->symtree->n.sym->ts.type == BT_CLASS
919 && expr->ref->type == REF_COMPONENT
920 && expr->ref->next->type == REF_ARRAY
921 && expr->ref->next->next == NULL
922 && CLASS_DATA (expr->symtree->n.sym)->attr.dimension)
923 {
924 /* Dummys come in sometimes with the descriptor detached from
925 the class field or declaration. */
926 tmp = gfc_class_vptr_get (expr->symtree->n.sym->backend_decl);
927 tmp = gfc_vptr_size_get (tmp);
928 }
929 else
930 {
931 /* If none of the fancy stuff works, the span is the element
e8db6cd5
PT
932 size of the array. Attempt to deal with unbounded character
933 types if possible. Otherwise, return NULL_TREE. */
ff3598bc 934 tmp = gfc_get_element_type (TREE_TYPE (desc));
e8db6cd5 935 if (tmp && TREE_CODE (tmp) == ARRAY_TYPE
9d44426f
PT
936 && (TYPE_MAX_VALUE (TYPE_DOMAIN (tmp)) == NULL_TREE
937 || integer_zerop (TYPE_MAX_VALUE (TYPE_DOMAIN (tmp)))))
e8db6cd5
PT
938 {
939 if (expr->expr_type == EXPR_VARIABLE
940 && expr->ts.type == BT_CHARACTER)
941 tmp = fold_convert (gfc_array_index_type,
942 gfc_get_expr_charlen (expr));
943 else
944 tmp = NULL_TREE;
945 }
946 else
947 tmp = fold_convert (gfc_array_index_type,
948 size_in_bytes (tmp));
ff3598bc
PT
949 }
950 return tmp;
951}
952
953
331c72f3
PB
954/* Generate an initializer for a static pointer or allocatable array. */
955
956void
957gfc_trans_static_array_pointer (gfc_symbol * sym)
958{
959 tree type;
960
6e45f57b 961 gcc_assert (TREE_STATIC (sym->backend_decl));
331c72f3
PB
962 /* Just zero the data member. */
963 type = TREE_TYPE (sym->backend_decl);
df7df328 964 DECL_INITIAL (sym->backend_decl) = gfc_build_null_descriptor (type);
331c72f3
PB
965}
966
967
62ab4a54
RS
968/* If the bounds of SE's loop have not yet been set, see if they can be
969 determined from array spec AS, which is the array spec of a called
970 function. MAPPING maps the callee's dummy arguments to the values
971 that the caller is passing. Add any initialization and finalization
972 code to SE. */
973
974void
975gfc_set_loop_bounds_from_array_spec (gfc_interface_mapping * mapping,
976 gfc_se * se, gfc_array_spec * as)
977{
5125d6d5 978 int n, dim, total_dim;
62ab4a54 979 gfc_se tmpse;
5125d6d5 980 gfc_ss *ss;
62ab4a54
RS
981 tree lower;
982 tree upper;
983 tree tmp;
984
5125d6d5
MM
985 total_dim = 0;
986
987 if (!as || as->type != AS_EXPLICIT)
988 return;
989
990 for (ss = se->ss; ss; ss = ss->parent)
991 {
992 total_dim += ss->loop->dimen;
993 for (n = 0; n < ss->loop->dimen; n++)
994 {
995 /* The bound is known, nothing to do. */
996 if (ss->loop->to[n] != NULL_TREE)
997 continue;
998
999 dim = ss->dim[n];
1000 gcc_assert (dim < as->rank);
1001 gcc_assert (ss->loop->dimen <= as->rank);
1002
1003 /* Evaluate the lower bound. */
1004 gfc_init_se (&tmpse, NULL);
1005 gfc_apply_interface_mapping (mapping, &tmpse, as->lower[dim]);
1006 gfc_add_block_to_block (&se->pre, &tmpse.pre);
1007 gfc_add_block_to_block (&se->post, &tmpse.post);
1008 lower = fold_convert (gfc_array_index_type, tmpse.expr);
1009
1010 /* ...and the upper bound. */
1011 gfc_init_se (&tmpse, NULL);
1012 gfc_apply_interface_mapping (mapping, &tmpse, as->upper[dim]);
1013 gfc_add_block_to_block (&se->pre, &tmpse.pre);
1014 gfc_add_block_to_block (&se->post, &tmpse.post);
1015 upper = fold_convert (gfc_array_index_type, tmpse.expr);
1016
1017 /* Set the upper bound of the loop to UPPER - LOWER. */
1018 tmp = fold_build2_loc (input_location, MINUS_EXPR,
1019 gfc_array_index_type, upper, lower);
1020 tmp = gfc_evaluate_now (tmp, &se->pre);
1021 ss->loop->to[n] = tmp;
1022 }
1023 }
1024
1025 gcc_assert (total_dim == as->rank);
62ab4a54
RS
1026}
1027
1028
6de9cd9a 1029/* Generate code to allocate an array temporary, or create a variable to
5b0b7251
EE
1030 hold the data. If size is NULL, zero the descriptor so that the
1031 callee will allocate the array. If DEALLOC is true, also generate code to
1032 free the array afterwards.
ec25720b 1033
12f681a0
DK
1034 If INITIAL is not NULL, it is packed using internal_pack and the result used
1035 as data instead of allocating a fresh, unitialized area of memory.
1036
62ab4a54 1037 Initialization code is added to PRE and finalization code to POST.
ec25720b
RS
1038 DYNAMIC is true if the caller may want to extend the array later
1039 using realloc. This prevents us from putting the array on the stack. */
6de9cd9a
DN
1040
1041static void
62ab4a54 1042gfc_trans_allocate_array_storage (stmtblock_t * pre, stmtblock_t * post,
6d63e468 1043 gfc_array_info * info, tree size, tree nelem,
12f681a0 1044 tree initial, bool dynamic, bool dealloc)
6de9cd9a
DN
1045{
1046 tree tmp;
6de9cd9a 1047 tree desc;
6de9cd9a
DN
1048 bool onstack;
1049
1050 desc = info->descriptor;
4c73896d 1051 info->offset = gfc_index_zero_node;
ec25720b 1052 if (size == NULL_TREE || integer_zerop (size))
6de9cd9a 1053 {
fc90a8f2 1054 /* A callee allocated array. */
62ab4a54 1055 gfc_conv_descriptor_data_set (pre, desc, null_pointer_node);
fc90a8f2 1056 onstack = FALSE;
6de9cd9a
DN
1057 }
1058 else
1059 {
fc90a8f2 1060 /* Allocate the temporary. */
12f681a0 1061 onstack = !dynamic && initial == NULL_TREE
203c7ebf 1062 && (flag_stack_arrays
c76f8d52 1063 || gfc_can_put_var_on_stack (size));
fc90a8f2
PB
1064
1065 if (onstack)
1066 {
1067 /* Make a temporary variable to hold the data. */
94471a56
TB
1068 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (nelem),
1069 nelem, gfc_index_one_node);
c76f8d52 1070 tmp = gfc_evaluate_now (tmp, pre);
fc90a8f2
PB
1071 tmp = build_range_type (gfc_array_index_type, gfc_index_zero_node,
1072 tmp);
1073 tmp = build_array_type (gfc_get_element_type (TREE_TYPE (desc)),
1074 tmp);
1075 tmp = gfc_create_var (tmp, "A");
c76f8d52
MM
1076 /* If we're here only because of -fstack-arrays we have to
1077 emit a DECL_EXPR to make the gimplifier emit alloca calls. */
1078 if (!gfc_can_put_var_on_stack (size))
1079 gfc_add_expr_to_block (pre,
1080 fold_build1_loc (input_location,
1081 DECL_EXPR, TREE_TYPE (tmp),
1082 tmp));
628c189e 1083 tmp = gfc_build_addr_expr (NULL_TREE, tmp);
62ab4a54 1084 gfc_conv_descriptor_data_set (pre, desc, tmp);
fc90a8f2 1085 }
6de9cd9a 1086 else
fc90a8f2 1087 {
12f681a0
DK
1088 /* Allocate memory to hold the data or call internal_pack. */
1089 if (initial == NULL_TREE)
1090 {
1091 tmp = gfc_call_malloc (pre, NULL, size);
1092 tmp = gfc_evaluate_now (tmp, pre);
1093 }
1094 else
1095 {
1096 tree packed;
1097 tree source_data;
1098 tree was_packed;
1099 stmtblock_t do_copying;
1100
1101 tmp = TREE_TYPE (initial); /* Pointer to descriptor. */
1102 gcc_assert (TREE_CODE (tmp) == POINTER_TYPE);
1103 tmp = TREE_TYPE (tmp); /* The descriptor itself. */
1104 tmp = gfc_get_element_type (tmp);
1105 gcc_assert (tmp == gfc_get_element_type (TREE_TYPE (desc)));
1106 packed = gfc_create_var (build_pointer_type (tmp), "data");
1107
db3927fb
AH
1108 tmp = build_call_expr_loc (input_location,
1109 gfor_fndecl_in_pack, 1, initial);
12f681a0
DK
1110 tmp = fold_convert (TREE_TYPE (packed), tmp);
1111 gfc_add_modify (pre, packed, tmp);
1112
db3927fb
AH
1113 tmp = build_fold_indirect_ref_loc (input_location,
1114 initial);
12f681a0
DK
1115 source_data = gfc_conv_descriptor_data_get (tmp);
1116
1117 /* internal_pack may return source->data without any allocation
1118 or copying if it is already packed. If that's the case, we
1119 need to allocate and copy manually. */
1120
1121 gfc_start_block (&do_copying);
1122 tmp = gfc_call_malloc (&do_copying, NULL, size);
1123 tmp = fold_convert (TREE_TYPE (packed), tmp);
1124 gfc_add_modify (&do_copying, packed, tmp);
1125 tmp = gfc_build_memcpy_call (packed, source_data, size);
1126 gfc_add_expr_to_block (&do_copying, tmp);
1127
94471a56 1128 was_packed = fold_build2_loc (input_location, EQ_EXPR,
63ee5404 1129 logical_type_node, packed,
94471a56 1130 source_data);
12f681a0 1131 tmp = gfc_finish_block (&do_copying);
c2255bc4
AH
1132 tmp = build3_v (COND_EXPR, was_packed, tmp,
1133 build_empty_stmt (input_location));
12f681a0
DK
1134 gfc_add_expr_to_block (pre, tmp);
1135
1136 tmp = fold_convert (pvoid_type_node, packed);
1137 }
1138
62ab4a54 1139 gfc_conv_descriptor_data_set (pre, desc, tmp);
fc90a8f2 1140 }
6de9cd9a 1141 }
4c73896d 1142 info->data = gfc_conv_descriptor_data_get (desc);
6de9cd9a
DN
1143
1144 /* The offset is zero because we create temporaries with a zero
1145 lower bound. */
568e8e1e 1146 gfc_conv_descriptor_offset_set (pre, desc, gfc_index_zero_node);
6de9cd9a 1147
5b0b7251 1148 if (dealloc && !onstack)
6de9cd9a
DN
1149 {
1150 /* Free the temporary. */
4c73896d 1151 tmp = gfc_conv_descriptor_data_get (desc);
107051a5 1152 tmp = gfc_call_free (tmp);
62ab4a54 1153 gfc_add_expr_to_block (post, tmp);
6de9cd9a
DN
1154 }
1155}
1156
1157
d6b3a0d7
MM
1158/* Get the scalarizer array dimension corresponding to actual array dimension
1159 given by ARRAY_DIM.
1160
1161 For example, if SS represents the array ref a(1,:,:,1), it is a
1162 bidimensional scalarizer array, and the result would be 0 for ARRAY_DIM=1,
1163 and 1 for ARRAY_DIM=2.
1164 If SS represents transpose(a(:,1,1,:)), it is again a bidimensional
1165 scalarizer array, and the result would be 1 for ARRAY_DIM=0 and 0 for
1166 ARRAY_DIM=3.
1167 If SS represents sum(a(:,:,:,1), dim=1), it is a 2+1-dimensional scalarizer
1168 array. If called on the inner ss, the result would be respectively 0,1,2 for
1169 ARRAY_DIM=0,1,2. If called on the outer ss, the result would be 0,1
1170 for ARRAY_DIM=1,2. */
99da3840
MM
1171
1172static int
d6b3a0d7 1173get_scalarizer_dim_for_array_dim (gfc_ss *ss, int array_dim)
99da3840 1174{
d6b3a0d7
MM
1175 int array_ref_dim;
1176 int n;
99da3840
MM
1177
1178 array_ref_dim = 0;
99da3840 1179
d6b3a0d7
MM
1180 for (; ss; ss = ss->parent)
1181 for (n = 0; n < ss->dimen; n++)
1182 if (ss->dim[n] < array_dim)
1183 array_ref_dim++;
99da3840
MM
1184
1185 return array_ref_dim;
1186}
1187
1188
d6b3a0d7
MM
1189static gfc_ss *
1190innermost_ss (gfc_ss *ss)
1191{
1192 while (ss->nested_ss != NULL)
1193 ss = ss->nested_ss;
1194
1195 return ss;
1196}
1197
1198
1199
1200/* Get the array reference dimension corresponding to the given loop dimension.
1201 It is different from the true array dimension given by the dim array in
1202 the case of a partial array reference (i.e. a(:,:,1,:) for example)
1203 It is different from the loop dimension in the case of a transposed array.
1204 */
1205
1206static int
1207get_array_ref_dim_for_loop_dim (gfc_ss *ss, int loop_dim)
1208{
1209 return get_scalarizer_dim_for_array_dim (innermost_ss (ss),
1210 ss->dim[loop_dim]);
1211}
1212
1213
8e119f1b 1214/* Generate code to create and initialize the descriptor for a temporary
e7dc5b4f 1215 array. This is used for both temporaries needed by the scalarizer, and
8e119f1b
EE
1216 functions returning arrays. Adjusts the loop variables to be
1217 zero-based, and calculates the loop bounds for callee allocated arrays.
1218 Allocate the array unless it's callee allocated (we have a callee
1219 allocated array if 'callee_alloc' is true, or if loop->to[n] is
1220 NULL_TREE for any n). Also fills in the descriptor, data and offset
1221 fields of info if known. Returns the size of the array, or NULL for a
1222 callee allocated array.
ec25720b 1223
866e6d1b
PT
1224 'eltype' == NULL signals that the temporary should be a class object.
1225 The 'initial' expression is used to obtain the size of the dynamic
6bd2c800 1226 type; otherwise the allocation and initialization proceeds as for any
866e6d1b
PT
1227 other expression
1228
12f681a0 1229 PRE, POST, INITIAL, DYNAMIC and DEALLOC are as for
41645793 1230 gfc_trans_allocate_array_storage. */
6de9cd9a
DN
1231
1232tree
41645793 1233gfc_trans_create_temp_array (stmtblock_t * pre, stmtblock_t * post, gfc_ss * ss,
12f681a0
DK
1234 tree eltype, tree initial, bool dynamic,
1235 bool dealloc, bool callee_alloc, locus * where)
6de9cd9a 1236{
41645793 1237 gfc_loopinfo *loop;
06cd4e1b 1238 gfc_ss *s;
6d63e468 1239 gfc_array_info *info;
99da3840 1240 tree from[GFC_MAX_DIMENSIONS], to[GFC_MAX_DIMENSIONS];
6de9cd9a
DN
1241 tree type;
1242 tree desc;
1243 tree tmp;
1244 tree size;
1245 tree nelem;
da4340a1
TK
1246 tree cond;
1247 tree or_expr;
0a524296 1248 tree elemsize;
866e6d1b 1249 tree class_expr = NULL_TREE;
99da3840 1250 int n, dim, tmp_dim;
d35335e3 1251 int total_dim = 0;
99da3840 1252
866e6d1b
PT
1253 /* This signals a class array for which we need the size of the
1254 dynamic type. Generate an eltype and then the class expression. */
1255 if (eltype == NULL_TREE && initial)
1256 {
99c25a87
TB
1257 gcc_assert (POINTER_TYPE_P (TREE_TYPE (initial)));
1258 class_expr = build_fold_indirect_ref_loc (input_location, initial);
866e6d1b
PT
1259 eltype = TREE_TYPE (class_expr);
1260 eltype = gfc_get_element_type (eltype);
1261 /* Obtain the structure (class) expression. */
1262 class_expr = TREE_OPERAND (class_expr, 0);
1263 gcc_assert (class_expr);
1264 }
1265
99da3840
MM
1266 memset (from, 0, sizeof (from));
1267 memset (to, 0, sizeof (to));
6de9cd9a 1268
1838afec 1269 info = &ss->info->data.array;
f44d2277 1270
cb4b9eae 1271 gcc_assert (ss->dimen > 0);
41645793 1272 gcc_assert (ss->loop->dimen == ss->dimen);
bdfd2ff0 1273
73e42eef 1274 if (warn_array_temporaries && where)
48749dbc
MLI
1275 gfc_warning (OPT_Warray_temporaries,
1276 "Creating array temporary at %L", where);
bdfd2ff0 1277
6de9cd9a 1278 /* Set the lower bound to zero. */
06cd4e1b 1279 for (s = ss; s; s = s->parent)
6de9cd9a 1280 {
06cd4e1b 1281 loop = s->loop;
99da3840 1282
06cd4e1b
MM
1283 total_dim += loop->dimen;
1284 for (n = 0; n < loop->dimen; n++)
1285 {
1286 dim = s->dim[n];
1287
1288 /* Callee allocated arrays may not have a known bound yet. */
1289 if (loop->to[n])
1290 loop->to[n] = gfc_evaluate_now (
99da3840
MM
1291 fold_build2_loc (input_location, MINUS_EXPR,
1292 gfc_array_index_type,
1293 loop->to[n], loop->from[n]),
1294 pre);
06cd4e1b
MM
1295 loop->from[n] = gfc_index_zero_node;
1296
1297 /* We have just changed the loop bounds, we must clear the
1298 corresponding specloop, so that delta calculation is not skipped
121c82c9 1299 later in gfc_set_delta. */
06cd4e1b
MM
1300 loop->specloop[n] = NULL;
1301
1302 /* We are constructing the temporary's descriptor based on the loop
1303 dimensions. As the dimensions may be accessed in arbitrary order
1304 (think of transpose) the size taken from the n'th loop may not map
1305 to the n'th dimension of the array. We need to reconstruct loop
1306 infos in the right order before using it to set the descriptor
1307 bounds. */
1308 tmp_dim = get_scalarizer_dim_for_array_dim (ss, dim);
1309 from[tmp_dim] = loop->from[n];
1310 to[tmp_dim] = loop->to[n];
1311
1312 info->delta[dim] = gfc_index_zero_node;
1313 info->start[dim] = gfc_index_zero_node;
1314 info->end[dim] = gfc_index_zero_node;
1315 info->stride[dim] = gfc_index_one_node;
1316 }
6de9cd9a
DN
1317 }
1318
13413760 1319 /* Initialize the descriptor. */
6de9cd9a 1320 type =
d35335e3 1321 gfc_get_array_type_bounds (eltype, total_dim, 0, from, to, 1,
10174ddf 1322 GFC_ARRAY_UNKNOWN, true);
6de9cd9a
DN
1323 desc = gfc_create_var (type, "atmp");
1324 GFC_DECL_PACKED_ARRAY (desc) = 1;
1325
1326 info->descriptor = desc;
7ab92584 1327 size = gfc_index_one_node;
6de9cd9a 1328
c83e6ebf
RB
1329 /* Emit a DECL_EXPR for the variable sized array type in
1330 GFC_TYPE_ARRAY_DATAPTR_TYPE so the gimplification of its type
1331 sizes works correctly. */
1332 tree arraytype = TREE_TYPE (GFC_TYPE_ARRAY_DATAPTR_TYPE (type));
1333 if (! TYPE_NAME (arraytype))
1334 TYPE_NAME (arraytype) = build_decl (UNKNOWN_LOCATION, TYPE_DECL,
1335 NULL_TREE, arraytype);
1336 gfc_add_expr_to_block (pre, build1 (DECL_EXPR,
1337 arraytype, TYPE_NAME (arraytype)));
1338
6de9cd9a
DN
1339 /* Fill in the array dtype. */
1340 tmp = gfc_conv_descriptor_dtype (desc);
726a989a 1341 gfc_add_modify (pre, tmp, gfc_get_dtype (TREE_TYPE (desc)));
6de9cd9a 1342
7ab92584
SB
1343 /*
1344 Fill in the bounds and stride. This is a packed array, so:
1345
6de9cd9a
DN
1346 size = 1;
1347 for (n = 0; n < rank; n++)
7ab92584
SB
1348 {
1349 stride[n] = size
1350 delta = ubound[n] + 1 - lbound[n];
12f681a0 1351 size = size * delta;
7ab92584
SB
1352 }
1353 size = size * sizeof(element);
1354 */
1355
da4340a1
TK
1356 or_expr = NULL_TREE;
1357
ea5e803f 1358 /* If there is at least one null loop->to[n], it is a callee allocated
45bc572c 1359 array. */
d35335e3
MM
1360 for (n = 0; n < total_dim; n++)
1361 if (to[n] == NULL_TREE)
45bc572c
MM
1362 {
1363 size = NULL_TREE;
1364 break;
1365 }
1366
f28cd38e 1367 if (size == NULL_TREE)
06cd4e1b
MM
1368 for (s = ss; s; s = s->parent)
1369 for (n = 0; n < s->loop->dimen; n++)
12f681a0 1370 {
f6a40ccd 1371 dim = get_scalarizer_dim_for_array_dim (ss, s->dim[n]);
f28cd38e 1372
fc90a8f2
PB
1373 /* For a callee allocated array express the loop bounds in terms
1374 of the descriptor fields. */
94471a56 1375 tmp = fold_build2_loc (input_location,
9157ccb2 1376 MINUS_EXPR, gfc_array_index_type,
2b63684b
MM
1377 gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[dim]),
1378 gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[dim]));
06cd4e1b 1379 s->loop->to[n] = tmp;
12f681a0 1380 }
f28cd38e
MM
1381 else
1382 {
d35335e3 1383 for (n = 0; n < total_dim; n++)
f28cd38e
MM
1384 {
1385 /* Store the stride and bound components in the descriptor. */
1386 gfc_conv_descriptor_stride_set (pre, desc, gfc_rank_cst[n], size);
6de9cd9a 1387
f28cd38e
MM
1388 gfc_conv_descriptor_lbound_set (pre, desc, gfc_rank_cst[n],
1389 gfc_index_zero_node);
6de9cd9a 1390
f28cd38e 1391 gfc_conv_descriptor_ubound_set (pre, desc, gfc_rank_cst[n], to[n]);
6de9cd9a 1392
f28cd38e
MM
1393 tmp = fold_build2_loc (input_location, PLUS_EXPR,
1394 gfc_array_index_type,
1395 to[n], gfc_index_one_node);
6de9cd9a 1396
f28cd38e 1397 /* Check whether the size for this dimension is negative. */
63ee5404 1398 cond = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
f28cd38e
MM
1399 tmp, gfc_index_zero_node);
1400 cond = gfc_evaluate_now (cond, pre);
da4340a1 1401
f28cd38e
MM
1402 if (n == 0)
1403 or_expr = cond;
1404 else
1405 or_expr = fold_build2_loc (input_location, TRUTH_OR_EXPR,
63ee5404 1406 logical_type_node, or_expr, cond);
da4340a1 1407
f28cd38e
MM
1408 size = fold_build2_loc (input_location, MULT_EXPR,
1409 gfc_array_index_type, size, tmp);
1410 size = gfc_evaluate_now (size, pre);
1411 }
6de9cd9a
DN
1412 }
1413
0a524296
PT
1414 if (class_expr == NULL_TREE)
1415 elemsize = fold_convert (gfc_array_index_type,
1416 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
1417 else
1418 elemsize = gfc_class_vtab_size_get (class_expr);
1419
6de9cd9a 1420 /* Get the size of the array. */
8e119f1b 1421 if (size && !callee_alloc)
da4340a1 1422 {
999ffb1a
FXC
1423 /* If or_expr is true, then the extent in at least one
1424 dimension is zero and the size is set to zero. */
94471a56
TB
1425 size = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
1426 or_expr, gfc_index_zero_node, size);
da4340a1 1427
fcac9229 1428 nelem = size;
94471a56 1429 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
866e6d1b 1430 size, elemsize);
da4340a1 1431 }
8e119f1b 1432 else
da4340a1
TK
1433 {
1434 nelem = size;
1435 size = NULL_TREE;
1436 }
6de9cd9a 1437
0a524296
PT
1438 /* Set the span. */
1439 tmp = fold_convert (gfc_array_index_type, elemsize);
1440 gfc_conv_descriptor_span_set (pre, desc, tmp);
1441
12f681a0
DK
1442 gfc_trans_allocate_array_storage (pre, post, info, size, nelem, initial,
1443 dynamic, dealloc);
6de9cd9a 1444
06cd4e1b
MM
1445 while (ss->parent)
1446 ss = ss->parent;
1447
41645793
MM
1448 if (ss->dimen > ss->loop->temp_dim)
1449 ss->loop->temp_dim = ss->dimen;
6de9cd9a
DN
1450
1451 return size;
1452}
1453
1454
ec25720b
RS
1455/* Return the number of iterations in a loop that starts at START,
1456 ends at END, and has step STEP. */
1457
1458static tree
1459gfc_get_iteration_count (tree start, tree end, tree step)
1460{
1461 tree tmp;
1462 tree type;
1463
1464 type = TREE_TYPE (step);
94471a56
TB
1465 tmp = fold_build2_loc (input_location, MINUS_EXPR, type, end, start);
1466 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR, type, tmp, step);
1467 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp,
1468 build_int_cst (type, 1));
1469 tmp = fold_build2_loc (input_location, MAX_EXPR, type, tmp,
1470 build_int_cst (type, 0));
ec25720b
RS
1471 return fold_convert (gfc_array_index_type, tmp);
1472}
1473
1474
1475/* Extend the data in array DESC by EXTRA elements. */
1476
1477static void
1478gfc_grow_array (stmtblock_t * pblock, tree desc, tree extra)
1479{
5039610b 1480 tree arg0, arg1;
ec25720b
RS
1481 tree tmp;
1482 tree size;
1483 tree ubound;
1484
1485 if (integer_zerop (extra))
1486 return;
1487
568e8e1e 1488 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[0]);
ec25720b
RS
1489
1490 /* Add EXTRA to the upper bound. */
94471a56
TB
1491 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1492 ubound, extra);
568e8e1e 1493 gfc_conv_descriptor_ubound_set (pblock, desc, gfc_rank_cst[0], tmp);
ec25720b
RS
1494
1495 /* Get the value of the current data pointer. */
5039610b 1496 arg0 = gfc_conv_descriptor_data_get (desc);
ec25720b
RS
1497
1498 /* Calculate the new array size. */
1499 size = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
94471a56
TB
1500 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1501 ubound, gfc_index_one_node);
1502 arg1 = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
1503 fold_convert (size_type_node, tmp),
1504 fold_convert (size_type_node, size));
ec25720b 1505
4376b7cf
FXC
1506 /* Call the realloc() function. */
1507 tmp = gfc_call_realloc (pblock, arg0, arg1);
ec25720b
RS
1508 gfc_conv_descriptor_data_set (pblock, desc, tmp);
1509}
1510
1511
1512/* Return true if the bounds of iterator I can only be determined
1513 at run time. */
1514
1515static inline bool
1516gfc_iterator_has_dynamic_bounds (gfc_iterator * i)
1517{
1518 return (i->start->expr_type != EXPR_CONSTANT
1519 || i->end->expr_type != EXPR_CONSTANT
1520 || i->step->expr_type != EXPR_CONSTANT);
1521}
1522
1523
1524/* Split the size of constructor element EXPR into the sum of two terms,
1525 one of which can be determined at compile time and one of which must
1526 be calculated at run time. Set *SIZE to the former and return true
1527 if the latter might be nonzero. */
1528
1529static bool
1530gfc_get_array_constructor_element_size (mpz_t * size, gfc_expr * expr)
1531{
1532 if (expr->expr_type == EXPR_ARRAY)
1533 return gfc_get_array_constructor_size (size, expr->value.constructor);
1534 else if (expr->rank > 0)
1535 {
1536 /* Calculate everything at run time. */
1537 mpz_set_ui (*size, 0);
1538 return true;
1539 }
1540 else
1541 {
1542 /* A single element. */
1543 mpz_set_ui (*size, 1);
1544 return false;
1545 }
1546}
1547
1548
1549/* Like gfc_get_array_constructor_element_size, but applied to the whole
1550 of array constructor C. */
1551
1552static bool
b7e75771 1553gfc_get_array_constructor_size (mpz_t * size, gfc_constructor_base base)
ec25720b 1554{
b7e75771 1555 gfc_constructor *c;
ec25720b
RS
1556 gfc_iterator *i;
1557 mpz_t val;
1558 mpz_t len;
1559 bool dynamic;
1560
1561 mpz_set_ui (*size, 0);
1562 mpz_init (len);
1563 mpz_init (val);
1564
1565 dynamic = false;
b7e75771 1566 for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
ec25720b
RS
1567 {
1568 i = c->iterator;
1569 if (i && gfc_iterator_has_dynamic_bounds (i))
1570 dynamic = true;
1571 else
1572 {
1573 dynamic |= gfc_get_array_constructor_element_size (&len, c->expr);
1574 if (i)
1575 {
1576 /* Multiply the static part of the element size by the
1577 number of iterations. */
1578 mpz_sub (val, i->end->value.integer, i->start->value.integer);
1579 mpz_fdiv_q (val, val, i->step->value.integer);
1580 mpz_add_ui (val, val, 1);
1581 if (mpz_sgn (val) > 0)
1582 mpz_mul (len, len, val);
1583 else
1584 mpz_set_ui (len, 0);
1585 }
1586 mpz_add (*size, *size, len);
1587 }
1588 }
1589 mpz_clear (len);
1590 mpz_clear (val);
1591 return dynamic;
1592}
1593
1594
6de9cd9a
DN
1595/* Make sure offset is a variable. */
1596
1597static void
1598gfc_put_offset_into_var (stmtblock_t * pblock, tree * poffset,
1599 tree * offsetvar)
1600{
1601 /* We should have already created the offset variable. We cannot
13413760 1602 create it here because we may be in an inner scope. */
6e45f57b 1603 gcc_assert (*offsetvar != NULL_TREE);
726a989a 1604 gfc_add_modify (pblock, *offsetvar, *poffset);
6de9cd9a
DN
1605 *poffset = *offsetvar;
1606 TREE_USED (*offsetvar) = 1;
1607}
1608
1609
c03fc95d 1610/* Variables needed for bounds-checking. */
32be9f94 1611static bool first_len;
f04986a9 1612static tree first_len_val;
c03fc95d 1613static bool typespec_chararray_ctor;
40f20186
PB
1614
1615static void
ec25720b 1616gfc_trans_array_ctor_element (stmtblock_t * pblock, tree desc,
40f20186
PB
1617 tree offset, gfc_se * se, gfc_expr * expr)
1618{
1619 tree tmp;
40f20186
PB
1620
1621 gfc_conv_expr (se, expr);
1622
1623 /* Store the value. */
db3927fb
AH
1624 tmp = build_fold_indirect_ref_loc (input_location,
1625 gfc_conv_descriptor_data_get (desc));
1d6b7f39 1626 tmp = gfc_build_array_ref (tmp, offset, NULL);
32be9f94 1627
40f20186
PB
1628 if (expr->ts.type == BT_CHARACTER)
1629 {
691da334
FXC
1630 int i = gfc_validate_kind (BT_CHARACTER, expr->ts.kind, false);
1631 tree esize;
1632
1633 esize = size_in_bytes (gfc_get_element_type (TREE_TYPE (desc)));
1634 esize = fold_convert (gfc_charlen_type_node, esize);
94471a56 1635 esize = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
f622221a
JB
1636 TREE_TYPE (esize), esize,
1637 build_int_cst (TREE_TYPE (esize),
691da334
FXC
1638 gfc_character_kinds[i].bit_size / 8));
1639
40f20186
PB
1640 gfc_conv_string_parameter (se);
1641 if (POINTER_TYPE_P (TREE_TYPE (tmp)))
1642 {
1643 /* The temporary is an array of pointers. */
1644 se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
726a989a 1645 gfc_add_modify (&se->pre, tmp, se->expr);
40f20186
PB
1646 }
1647 else
1648 {
1649 /* The temporary is an array of string values. */
d393bbd7 1650 tmp = gfc_build_addr_expr (gfc_get_pchar_type (expr->ts.kind), tmp);
40f20186
PB
1651 /* We know the temporary and the value will be the same length,
1652 so can use memcpy. */
d393bbd7
FXC
1653 gfc_trans_string_copy (&se->pre, esize, tmp, expr->ts.kind,
1654 se->string_length, se->expr, expr->ts.kind);
32be9f94 1655 }
d3d3011f 1656 if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS) && !typespec_chararray_ctor)
32be9f94
PT
1657 {
1658 if (first_len)
1659 {
726a989a 1660 gfc_add_modify (&se->pre, first_len_val,
85c2c761 1661 fold_convert (TREE_TYPE (first_len_val),
e10e60cb 1662 se->string_length));
32be9f94
PT
1663 first_len = false;
1664 }
1665 else
1666 {
1667 /* Verify that all constructor elements are of the same
1668 length. */
e10e60cb
JB
1669 tree rhs = fold_convert (TREE_TYPE (first_len_val),
1670 se->string_length);
94471a56 1671 tree cond = fold_build2_loc (input_location, NE_EXPR,
63ee5404 1672 logical_type_node, first_len_val,
e10e60cb 1673 rhs);
32be9f94 1674 gfc_trans_runtime_check
0d52899f 1675 (true, false, cond, &se->pre, &expr->where,
32be9f94
PT
1676 "Different CHARACTER lengths (%ld/%ld) in array constructor",
1677 fold_convert (long_integer_type_node, first_len_val),
1678 fold_convert (long_integer_type_node, se->string_length));
1679 }
40f20186
PB
1680 }
1681 }
5233d455
PT
1682 else if (GFC_CLASS_TYPE_P (TREE_TYPE (se->expr))
1683 && !GFC_CLASS_TYPE_P (gfc_get_element_type (TREE_TYPE (desc))))
1684 {
1685 /* Assignment of a CLASS array constructor to a derived type array. */
1686 if (expr->expr_type == EXPR_FUNCTION)
1687 se->expr = gfc_evaluate_now (se->expr, pblock);
1688 se->expr = gfc_class_data_get (se->expr);
1689 se->expr = build_fold_indirect_ref_loc (input_location, se->expr);
1690 se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
1691 gfc_add_modify (&se->pre, tmp, se->expr);
1692 }
40f20186
PB
1693 else
1694 {
1695 /* TODO: Should the frontend already have done this conversion? */
1696 se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
726a989a 1697 gfc_add_modify (&se->pre, tmp, se->expr);
40f20186
PB
1698 }
1699
1700 gfc_add_block_to_block (pblock, &se->pre);
1701 gfc_add_block_to_block (pblock, &se->post);
1702}
1703
1704
ec25720b
RS
1705/* Add the contents of an array to the constructor. DYNAMIC is as for
1706 gfc_trans_array_constructor_value. */
6de9cd9a
DN
1707
1708static void
1709gfc_trans_array_constructor_subarray (stmtblock_t * pblock,
1710 tree type ATTRIBUTE_UNUSED,
ec25720b
RS
1711 tree desc, gfc_expr * expr,
1712 tree * poffset, tree * offsetvar,
1713 bool dynamic)
6de9cd9a
DN
1714{
1715 gfc_se se;
1716 gfc_ss *ss;
1717 gfc_loopinfo loop;
1718 stmtblock_t body;
1719 tree tmp;
ec25720b
RS
1720 tree size;
1721 int n;
6de9cd9a
DN
1722
1723 /* We need this to be a variable so we can increment it. */
1724 gfc_put_offset_into_var (pblock, poffset, offsetvar);
1725
1726 gfc_init_se (&se, NULL);
1727
1728 /* Walk the array expression. */
1729 ss = gfc_walk_expr (expr);
6e45f57b 1730 gcc_assert (ss != gfc_ss_terminator);
6de9cd9a
DN
1731
1732 /* Initialize the scalarizer. */
1733 gfc_init_loopinfo (&loop);
1734 gfc_add_ss_to_loop (&loop, ss);
1735
1736 /* Initialize the loop. */
1737 gfc_conv_ss_startstride (&loop);
bdfd2ff0 1738 gfc_conv_loop_setup (&loop, &expr->where);
6de9cd9a 1739
ec25720b
RS
1740 /* Make sure the constructed array has room for the new data. */
1741 if (dynamic)
1742 {
1743 /* Set SIZE to the total number of elements in the subarray. */
1744 size = gfc_index_one_node;
1745 for (n = 0; n < loop.dimen; n++)
1746 {
1747 tmp = gfc_get_iteration_count (loop.from[n], loop.to[n],
1748 gfc_index_one_node);
94471a56
TB
1749 size = fold_build2_loc (input_location, MULT_EXPR,
1750 gfc_array_index_type, size, tmp);
ec25720b
RS
1751 }
1752
1753 /* Grow the constructed array by SIZE elements. */
1754 gfc_grow_array (&loop.pre, desc, size);
1755 }
1756
6de9cd9a
DN
1757 /* Make the loop body. */
1758 gfc_mark_ss_chain_used (ss, 1);
1759 gfc_start_scalarized_body (&loop, &body);
1760 gfc_copy_loopinfo_to_se (&se, &loop);
1761 se.ss = ss;
1762
ec25720b 1763 gfc_trans_array_ctor_element (&body, desc, *poffset, &se, expr);
6e45f57b 1764 gcc_assert (se.ss == gfc_ss_terminator);
6de9cd9a
DN
1765
1766 /* Increment the offset. */
94471a56
TB
1767 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1768 *poffset, gfc_index_one_node);
726a989a 1769 gfc_add_modify (&body, *poffset, tmp);
6de9cd9a
DN
1770
1771 /* Finish the loop. */
6de9cd9a
DN
1772 gfc_trans_scalarizing_loops (&loop, &body);
1773 gfc_add_block_to_block (&loop.pre, &loop.post);
1774 tmp = gfc_finish_block (&loop.pre);
1775 gfc_add_expr_to_block (pblock, tmp);
1776
1777 gfc_cleanup_loop (&loop);
1778}
1779
1780
ec25720b
RS
1781/* Assign the values to the elements of an array constructor. DYNAMIC
1782 is true if descriptor DESC only contains enough data for the static
1783 size calculated by gfc_get_array_constructor_size. When true, memory
1784 for the dynamic parts must be allocated using realloc. */
6de9cd9a
DN
1785
1786static void
1787gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
b7e75771 1788 tree desc, gfc_constructor_base base,
ec25720b
RS
1789 tree * poffset, tree * offsetvar,
1790 bool dynamic)
6de9cd9a
DN
1791{
1792 tree tmp;
b63b1f86
MM
1793 tree start = NULL_TREE;
1794 tree end = NULL_TREE;
1795 tree step = NULL_TREE;
6de9cd9a 1796 stmtblock_t body;
6de9cd9a 1797 gfc_se se;
ec25720b 1798 mpz_t size;
b7e75771 1799 gfc_constructor *c;
6de9cd9a 1800
beb64b4a
DF
1801 tree shadow_loopvar = NULL_TREE;
1802 gfc_saved_var saved_loopvar;
1803
ec25720b 1804 mpz_init (size);
b7e75771 1805 for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
6de9cd9a
DN
1806 {
1807 /* If this is an iterator or an array, the offset must be a variable. */
1808 if ((c->iterator || c->expr->rank > 0) && INTEGER_CST_P (*poffset))
1809 gfc_put_offset_into_var (pblock, poffset, offsetvar);
1810
beb64b4a
DF
1811 /* Shadowing the iterator avoids changing its value and saves us from
1812 keeping track of it. Further, it makes sure that there's always a
1813 backend-decl for the symbol, even if there wasn't one before,
1814 e.g. in the case of an iterator that appears in a specification
1815 expression in an interface mapping. */
1816 if (c->iterator)
1817 {
b63b1f86
MM
1818 gfc_symbol *sym;
1819 tree type;
1820
1821 /* Evaluate loop bounds before substituting the loop variable
1822 in case they depend on it. Such a case is invalid, but it is
1823 not more expensive to do the right thing here.
1824 See PR 44354. */
1825 gfc_init_se (&se, NULL);
1826 gfc_conv_expr_val (&se, c->iterator->start);
1827 gfc_add_block_to_block (pblock, &se.pre);
1828 start = gfc_evaluate_now (se.expr, pblock);
1829
1830 gfc_init_se (&se, NULL);
1831 gfc_conv_expr_val (&se, c->iterator->end);
1832 gfc_add_block_to_block (pblock, &se.pre);
1833 end = gfc_evaluate_now (se.expr, pblock);
1834
1835 gfc_init_se (&se, NULL);
1836 gfc_conv_expr_val (&se, c->iterator->step);
1837 gfc_add_block_to_block (pblock, &se.pre);
1838 step = gfc_evaluate_now (se.expr, pblock);
1839
1840 sym = c->iterator->var->symtree->n.sym;
1841 type = gfc_typenode_for_spec (&sym->ts);
beb64b4a
DF
1842
1843 shadow_loopvar = gfc_create_var (type, "shadow_loopvar");
1844 gfc_shadow_sym (sym, shadow_loopvar, &saved_loopvar);
1845 }
1846
6de9cd9a
DN
1847 gfc_start_block (&body);
1848
1849 if (c->expr->expr_type == EXPR_ARRAY)
1850 {
1851 /* Array constructors can be nested. */
ec25720b 1852 gfc_trans_array_constructor_value (&body, type, desc,
6de9cd9a 1853 c->expr->value.constructor,
ec25720b 1854 poffset, offsetvar, dynamic);
6de9cd9a
DN
1855 }
1856 else if (c->expr->rank > 0)
1857 {
ec25720b
RS
1858 gfc_trans_array_constructor_subarray (&body, type, desc, c->expr,
1859 poffset, offsetvar, dynamic);
6de9cd9a
DN
1860 }
1861 else
1862 {
1863 /* This code really upsets the gimplifier so don't bother for now. */
1864 gfc_constructor *p;
1865 HOST_WIDE_INT n;
1866 HOST_WIDE_INT size;
1867
1868 p = c;
1869 n = 0;
1870 while (p && !(p->iterator || p->expr->expr_type != EXPR_CONSTANT))
1871 {
b7e75771 1872 p = gfc_constructor_next (p);
6de9cd9a
DN
1873 n++;
1874 }
1875 if (n < 4)
1876 {
1877 /* Scalar values. */
1878 gfc_init_se (&se, NULL);
ec25720b
RS
1879 gfc_trans_array_ctor_element (&body, desc, *poffset,
1880 &se, c->expr);
6de9cd9a 1881
94471a56
TB
1882 *poffset = fold_build2_loc (input_location, PLUS_EXPR,
1883 gfc_array_index_type,
1884 *poffset, gfc_index_one_node);
6de9cd9a
DN
1885 }
1886 else
1887 {
1888 /* Collect multiple scalar constants into a constructor. */
9771b263 1889 vec<constructor_elt, va_gc> *v = NULL;
6de9cd9a
DN
1890 tree init;
1891 tree bound;
1892 tree tmptype;
81f5094d 1893 HOST_WIDE_INT idx = 0;
6de9cd9a
DN
1894
1895 p = c;
6de9cd9a
DN
1896 /* Count the number of consecutive scalar constants. */
1897 while (p && !(p->iterator
1898 || p->expr->expr_type != EXPR_CONSTANT))
1899 {
1900 gfc_init_se (&se, NULL);
1901 gfc_conv_constant (&se, p->expr);
d393bbd7 1902
110ea21a
PT
1903 if (c->expr->ts.type != BT_CHARACTER)
1904 se.expr = fold_convert (type, se.expr);
d393bbd7
FXC
1905 /* For constant character array constructors we build
1906 an array of pointers. */
110ea21a 1907 else if (POINTER_TYPE_P (type))
d393bbd7
FXC
1908 se.expr = gfc_build_addr_expr
1909 (gfc_get_pchar_type (p->expr->ts.kind),
1910 se.expr);
1911
8748ad99
NF
1912 CONSTRUCTOR_APPEND_ELT (v,
1913 build_int_cst (gfc_array_index_type,
1914 idx++),
1915 se.expr);
6de9cd9a 1916 c = p;
b7e75771 1917 p = gfc_constructor_next (p);
6de9cd9a
DN
1918 }
1919
df09d1d5 1920 bound = size_int (n - 1);
6de9cd9a
DN
1921 /* Create an array type to hold them. */
1922 tmptype = build_range_type (gfc_array_index_type,
7ab92584 1923 gfc_index_zero_node, bound);
6de9cd9a
DN
1924 tmptype = build_array_type (type, tmptype);
1925
8748ad99 1926 init = build_constructor (tmptype, v);
6de9cd9a 1927 TREE_CONSTANT (init) = 1;
6de9cd9a
DN
1928 TREE_STATIC (init) = 1;
1929 /* Create a static variable to hold the data. */
1930 tmp = gfc_create_var (tmptype, "data");
1931 TREE_STATIC (tmp) = 1;
1932 TREE_CONSTANT (tmp) = 1;
0f0707d1 1933 TREE_READONLY (tmp) = 1;
6de9cd9a
DN
1934 DECL_INITIAL (tmp) = init;
1935 init = tmp;
1936
1937 /* Use BUILTIN_MEMCPY to assign the values. */
ec25720b 1938 tmp = gfc_conv_descriptor_data_get (desc);
db3927fb
AH
1939 tmp = build_fold_indirect_ref_loc (input_location,
1940 tmp);
1d6b7f39 1941 tmp = gfc_build_array_ref (tmp, *poffset, NULL);
628c189e
RG
1942 tmp = gfc_build_addr_expr (NULL_TREE, tmp);
1943 init = gfc_build_addr_expr (NULL_TREE, init);
6de9cd9a
DN
1944
1945 size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type));
df09d1d5 1946 bound = build_int_cst (size_type_node, n * size);
db3927fb 1947 tmp = build_call_expr_loc (input_location,
e79983f4
MM
1948 builtin_decl_explicit (BUILT_IN_MEMCPY),
1949 3, tmp, init, bound);
6de9cd9a
DN
1950 gfc_add_expr_to_block (&body, tmp);
1951
94471a56
TB
1952 *poffset = fold_build2_loc (input_location, PLUS_EXPR,
1953 gfc_array_index_type, *poffset,
ac816b02 1954 build_int_cst (gfc_array_index_type, n));
6de9cd9a
DN
1955 }
1956 if (!INTEGER_CST_P (*poffset))
1957 {
726a989a 1958 gfc_add_modify (&body, *offsetvar, *poffset);
6de9cd9a
DN
1959 *poffset = *offsetvar;
1960 }
1961 }
1962
63346ddb 1963 /* The frontend should already have done any expansions
86403f0f
TS
1964 at compile-time. */
1965 if (!c->iterator)
6de9cd9a 1966 {
86403f0f
TS
1967 /* Pass the code as is. */
1968 tmp = gfc_finish_block (&body);
1969 gfc_add_expr_to_block (pblock, tmp);
1970 }
1971 else
1972 {
1973 /* Build the implied do-loop. */
beb64b4a 1974 stmtblock_t implied_do_block;
86403f0f 1975 tree cond;
6de9cd9a 1976 tree exit_label;
86403f0f 1977 tree loopbody;
ec25720b 1978 tree tmp2;
6de9cd9a
DN
1979
1980 loopbody = gfc_finish_block (&body);
1981
beb64b4a
DF
1982 /* Create a new block that holds the implied-do loop. A temporary
1983 loop-variable is used. */
1984 gfc_start_block(&implied_do_block);
bfa7a1e9 1985
13413760 1986 /* Initialize the loop. */
b63b1f86 1987 gfc_add_modify (&implied_do_block, shadow_loopvar, start);
6de9cd9a 1988
ec25720b
RS
1989 /* If this array expands dynamically, and the number of iterations
1990 is not constant, we won't have allocated space for the static
1991 part of C->EXPR's size. Do that now. */
1992 if (dynamic && gfc_iterator_has_dynamic_bounds (c->iterator))
1993 {
1994 /* Get the number of iterations. */
beb64b4a 1995 tmp = gfc_get_iteration_count (shadow_loopvar, end, step);
ec25720b
RS
1996
1997 /* Get the static part of C->EXPR's size. */
1998 gfc_get_array_constructor_element_size (&size, c->expr);
1999 tmp2 = gfc_conv_mpz_to_tree (size, gfc_index_integer_kind);
2000
2001 /* Grow the array by TMP * TMP2 elements. */
94471a56
TB
2002 tmp = fold_build2_loc (input_location, MULT_EXPR,
2003 gfc_array_index_type, tmp, tmp2);
beb64b4a 2004 gfc_grow_array (&implied_do_block, desc, tmp);
ec25720b
RS
2005 }
2006
6de9cd9a
DN
2007 /* Generate the loop body. */
2008 exit_label = gfc_build_label_decl (NULL_TREE);
2009 gfc_start_block (&body);
2010
86403f0f
TS
2011 /* Generate the exit condition. Depending on the sign of
2012 the step variable we have to generate the correct
2013 comparison. */
63ee5404 2014 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
94471a56
TB
2015 step, build_int_cst (TREE_TYPE (step), 0));
2016 cond = fold_build3_loc (input_location, COND_EXPR,
63ee5404 2017 logical_type_node, tmp,
94471a56 2018 fold_build2_loc (input_location, GT_EXPR,
63ee5404 2019 logical_type_node, shadow_loopvar, end),
94471a56 2020 fold_build2_loc (input_location, LT_EXPR,
63ee5404 2021 logical_type_node, shadow_loopvar, end));
6de9cd9a
DN
2022 tmp = build1_v (GOTO_EXPR, exit_label);
2023 TREE_USED (exit_label) = 1;
c2255bc4
AH
2024 tmp = build3_v (COND_EXPR, cond, tmp,
2025 build_empty_stmt (input_location));
6de9cd9a
DN
2026 gfc_add_expr_to_block (&body, tmp);
2027
2028 /* The main loop body. */
2029 gfc_add_expr_to_block (&body, loopbody);
2030
86403f0f 2031 /* Increase loop variable by step. */
94471a56
TB
2032 tmp = fold_build2_loc (input_location, PLUS_EXPR,
2033 TREE_TYPE (shadow_loopvar), shadow_loopvar,
2034 step);
beb64b4a 2035 gfc_add_modify (&body, shadow_loopvar, tmp);
6de9cd9a
DN
2036
2037 /* Finish the loop. */
2038 tmp = gfc_finish_block (&body);
923ab88c 2039 tmp = build1_v (LOOP_EXPR, tmp);
beb64b4a 2040 gfc_add_expr_to_block (&implied_do_block, tmp);
6de9cd9a
DN
2041
2042 /* Add the exit label. */
2043 tmp = build1_v (LABEL_EXPR, exit_label);
beb64b4a
DF
2044 gfc_add_expr_to_block (&implied_do_block, tmp);
2045
eea58adb 2046 /* Finish the implied-do loop. */
beb64b4a
DF
2047 tmp = gfc_finish_block(&implied_do_block);
2048 gfc_add_expr_to_block(pblock, tmp);
bfa7a1e9 2049
beb64b4a 2050 gfc_restore_sym (c->iterator->var->symtree->n.sym, &saved_loopvar);
6de9cd9a 2051 }
6de9cd9a 2052 }
ec25720b 2053 mpz_clear (size);
6de9cd9a
DN
2054}
2055
2056
d751beac
LK
2057/* The array constructor code can create a string length with an operand
2058 in the form of a temporary variable. This variable will retain its
2059 context (current_function_decl). If we store this length tree in a
2060 gfc_charlen structure which is shared by a variable in another
2061 context, the resulting gfc_charlen structure with a variable in a
2062 different context, we could trip the assertion in expand_expr_real_1
2063 when it sees that a variable has been created in one context and
2064 referenced in another.
2065
2066 If this might be the case, we create a new gfc_charlen structure and
2067 link it into the current namespace. */
2068
2069static void
2070store_backend_decl (gfc_charlen **clp, tree len, bool force_new_cl)
2071{
2072 if (force_new_cl)
2073 {
2074 gfc_charlen *new_cl = gfc_new_charlen (gfc_current_ns, *clp);
2075 *clp = new_cl;
2076 }
2077 (*clp)->backend_decl = len;
2078}
2079
eea58adb 2080/* A catch-all to obtain the string length for anything that is not
6c1b5781
PT
2081 a substring of non-constant length, a constant, array or variable. */
2082
2083static void
2084get_array_ctor_all_strlen (stmtblock_t *block, gfc_expr *e, tree *len)
2085{
2086 gfc_se se;
6c1b5781
PT
2087
2088 /* Don't bother if we already know the length is a constant. */
2089 if (*len && INTEGER_CST_P (*len))
2090 return;
2091
2092 if (!e->ref && e->ts.u.cl && e->ts.u.cl->length
2093 && e->ts.u.cl->length->expr_type == EXPR_CONSTANT)
2094 {
2095 /* This is easy. */
2096 gfc_conv_const_charlen (e->ts.u.cl);
2097 *len = e->ts.u.cl->backend_decl;
2098 }
2099 else
2100 {
2101 /* Otherwise, be brutal even if inefficient. */
6c1b5781
PT
2102 gfc_init_se (&se, NULL);
2103
2104 /* No function call, in case of side effects. */
2105 se.no_function_call = 1;
2960a368 2106 if (e->rank == 0)
6c1b5781
PT
2107 gfc_conv_expr (&se, e);
2108 else
2960a368 2109 gfc_conv_expr_descriptor (&se, e);
6c1b5781
PT
2110
2111 /* Fix the value. */
2112 *len = gfc_evaluate_now (se.string_length, &se.pre);
2113
2114 gfc_add_block_to_block (block, &se.pre);
2115 gfc_add_block_to_block (block, &se.post);
2116
d751beac 2117 store_backend_decl (&e->ts.u.cl, *len, true);
6c1b5781
PT
2118 }
2119}
2120
2121
40f20186
PB
2122/* Figure out the string length of a variable reference expression.
2123 Used by get_array_ctor_strlen. */
2124
2125static void
6c1b5781 2126get_array_ctor_var_strlen (stmtblock_t *block, gfc_expr * expr, tree * len)
40f20186
PB
2127{
2128 gfc_ref *ref;
2129 gfc_typespec *ts;
1855915a 2130 mpz_t char_len;
40f20186
PB
2131
2132 /* Don't bother if we already know the length is a constant. */
2133 if (*len && INTEGER_CST_P (*len))
2134 return;
2135
2136 ts = &expr->symtree->n.sym->ts;
2137 for (ref = expr->ref; ref; ref = ref->next)
2138 {
2139 switch (ref->type)
2140 {
2141 case REF_ARRAY:
df7df328 2142 /* Array references don't change the string length. */
d5f48c7c
PT
2143 if (ts->deferred)
2144 get_array_ctor_all_strlen (block, expr, len);
40f20186
PB
2145 break;
2146
0e3e65bc 2147 case REF_COMPONENT:
f7b529fa 2148 /* Use the length of the component. */
40f20186
PB
2149 ts = &ref->u.c.component->ts;
2150 break;
2151
1855915a 2152 case REF_SUBSTRING:
d5f48c7c
PT
2153 if (ref->u.ss.end == NULL
2154 || ref->u.ss.start->expr_type != EXPR_CONSTANT
08ddab21 2155 || ref->u.ss.end->expr_type != EXPR_CONSTANT)
6c1b5781
PT
2156 {
2157 /* Note that this might evaluate expr. */
2158 get_array_ctor_all_strlen (block, expr, len);
2159 return;
2160 }
1855915a
PT
2161 mpz_init_set_ui (char_len, 1);
2162 mpz_add (char_len, char_len, ref->u.ss.end->value.integer);
2163 mpz_sub (char_len, char_len, ref->u.ss.start->value.integer);
f622221a 2164 *len = gfc_conv_mpz_to_tree_type (char_len, gfc_charlen_type_node);
1855915a
PT
2165 mpz_clear (char_len);
2166 return;
2167
a5fbc2f3
PT
2168 case REF_INQUIRY:
2169 break;
2170
40f20186 2171 default:
6c1b5781 2172 gcc_unreachable ();
40f20186
PB
2173 }
2174 }
2175
bc21d315 2176 *len = ts->u.cl->backend_decl;
40f20186
PB
2177}
2178
2179
2180/* Figure out the string length of a character array constructor.
88fec49f
DK
2181 If len is NULL, don't calculate the length; this happens for recursive calls
2182 when a sub-array-constructor is an element but not at the first position,
2183 so when we're not interested in the length.
40f20186
PB
2184 Returns TRUE if all elements are character constants. */
2185
636da744 2186bool
b7e75771 2187get_array_ctor_strlen (stmtblock_t *block, gfc_constructor_base base, tree * len)
40f20186 2188{
b7e75771 2189 gfc_constructor *c;
40f20186 2190 bool is_const;
b7e75771 2191
40f20186 2192 is_const = TRUE;
58fbb917 2193
b7e75771 2194 if (gfc_constructor_first (base) == NULL)
58fbb917 2195 {
88fec49f
DK
2196 if (len)
2197 *len = build_int_cstu (gfc_charlen_type_node, 0);
58fbb917
PT
2198 return is_const;
2199 }
2200
88fec49f
DK
2201 /* Loop over all constructor elements to find out is_const, but in len we
2202 want to store the length of the first, not the last, element. We can
2203 of course exit the loop as soon as is_const is found to be false. */
b7e75771
JD
2204 for (c = gfc_constructor_first (base);
2205 c && is_const; c = gfc_constructor_next (c))
40f20186
PB
2206 {
2207 switch (c->expr->expr_type)
2208 {
2209 case EXPR_CONSTANT:
88fec49f 2210 if (len && !(*len && INTEGER_CST_P (*len)))
d7177ab2 2211 *len = build_int_cstu (gfc_charlen_type_node,
40f20186
PB
2212 c->expr->value.character.length);
2213 break;
2214
2215 case EXPR_ARRAY:
0ee8e250 2216 if (!get_array_ctor_strlen (block, c->expr->value.constructor, len))
01201992 2217 is_const = false;
40f20186
PB
2218 break;
2219
2220 case EXPR_VARIABLE:
2221 is_const = false;
88fec49f 2222 if (len)
6c1b5781 2223 get_array_ctor_var_strlen (block, c->expr, len);
40f20186
PB
2224 break;
2225
2226 default:
01201992 2227 is_const = false;
88fec49f
DK
2228 if (len)
2229 get_array_ctor_all_strlen (block, c->expr, len);
40f20186
PB
2230 break;
2231 }
88fec49f
DK
2232
2233 /* After the first iteration, we don't want the length modified. */
2234 len = NULL;
40f20186
PB
2235 }
2236
2237 return is_const;
2238}
2239
62511fb1
RS
2240/* Check whether the array constructor C consists entirely of constant
2241 elements, and if so returns the number of those elements, otherwise
2242 return zero. Note, an empty or NULL array constructor returns zero. */
2243
b01e2f88 2244unsigned HOST_WIDE_INT
b7e75771 2245gfc_constant_array_constructor_p (gfc_constructor_base base)
62511fb1
RS
2246{
2247 unsigned HOST_WIDE_INT nelem = 0;
2248
b7e75771 2249 gfc_constructor *c = gfc_constructor_first (base);
62511fb1
RS
2250 while (c)
2251 {
2252 if (c->iterator
2253 || c->expr->rank > 0
2254 || c->expr->expr_type != EXPR_CONSTANT)
2255 return 0;
b7e75771 2256 c = gfc_constructor_next (c);
62511fb1
RS
2257 nelem++;
2258 }
2259 return nelem;
2260}
2261
2262
2263/* Given EXPR, the constant array constructor specified by an EXPR_ARRAY,
2264 and the tree type of it's elements, TYPE, return a static constant
2265 variable that is compile-time initialized. */
2266
b01e2f88 2267tree
62511fb1
RS
2268gfc_build_constant_array_constructor (gfc_expr * expr, tree type)
2269{
8748ad99 2270 tree tmptype, init, tmp;
62511fb1
RS
2271 HOST_WIDE_INT nelem;
2272 gfc_constructor *c;
2273 gfc_array_spec as;
2274 gfc_se se;
61a04b5b 2275 int i;
9771b263 2276 vec<constructor_elt, va_gc> *v = NULL;
62511fb1
RS
2277
2278 /* First traverse the constructor list, converting the constants
2279 to tree to build an initializer. */
2280 nelem = 0;
b7e75771 2281 c = gfc_constructor_first (expr->value.constructor);
62511fb1
RS
2282 while (c)
2283 {
2284 gfc_init_se (&se, NULL);
2285 gfc_conv_constant (&se, c->expr);
110ea21a
PT
2286 if (c->expr->ts.type != BT_CHARACTER)
2287 se.expr = fold_convert (type, se.expr);
2288 else if (POINTER_TYPE_P (type))
d393bbd7
FXC
2289 se.expr = gfc_build_addr_expr (gfc_get_pchar_type (c->expr->ts.kind),
2290 se.expr);
8748ad99
NF
2291 CONSTRUCTOR_APPEND_ELT (v, build_int_cst (gfc_array_index_type, nelem),
2292 se.expr);
b7e75771 2293 c = gfc_constructor_next (c);
62511fb1
RS
2294 nelem++;
2295 }
2296
65de695f 2297 /* Next determine the tree type for the array. We use the gfortran
62511fb1
RS
2298 front-end's gfc_get_nodesc_array_type in order to create a suitable
2299 GFC_ARRAY_TYPE_P that may be used by the scalarizer. */
2300
2301 memset (&as, 0, sizeof (gfc_array_spec));
2302
61a04b5b 2303 as.rank = expr->rank;
62511fb1 2304 as.type = AS_EXPLICIT;
61a04b5b
RS
2305 if (!expr->shape)
2306 {
b7e75771
JD
2307 as.lower[0] = gfc_get_int_expr (gfc_default_integer_kind, NULL, 0);
2308 as.upper[0] = gfc_get_int_expr (gfc_default_integer_kind,
2309 NULL, nelem - 1);
61a04b5b
RS
2310 }
2311 else
2312 for (i = 0; i < expr->rank; i++)
2313 {
2314 int tmp = (int) mpz_get_si (expr->shape[i]);
b7e75771
JD
2315 as.lower[i] = gfc_get_int_expr (gfc_default_integer_kind, NULL, 0);
2316 as.upper[i] = gfc_get_int_expr (gfc_default_integer_kind,
2317 NULL, tmp - 1);
61a04b5b
RS
2318 }
2319
10174ddf 2320 tmptype = gfc_get_nodesc_array_type (type, &as, PACKED_STATIC, true);
62511fb1 2321
1b4544b7
MM
2322 /* as is not needed anymore. */
2323 for (i = 0; i < as.rank + as.corank; i++)
2324 {
2325 gfc_free_expr (as.lower[i]);
2326 gfc_free_expr (as.upper[i]);
2327 }
2328
8748ad99 2329 init = build_constructor (tmptype, v);
62511fb1
RS
2330
2331 TREE_CONSTANT (init) = 1;
62511fb1
RS
2332 TREE_STATIC (init) = 1;
2333
059345ce
BS
2334 tmp = build_decl (input_location, VAR_DECL, create_tmp_var_name ("A"),
2335 tmptype);
2336 DECL_ARTIFICIAL (tmp) = 1;
2337 DECL_IGNORED_P (tmp) = 1;
62511fb1
RS
2338 TREE_STATIC (tmp) = 1;
2339 TREE_CONSTANT (tmp) = 1;
62511fb1
RS
2340 TREE_READONLY (tmp) = 1;
2341 DECL_INITIAL (tmp) = init;
059345ce 2342 pushdecl (tmp);
62511fb1
RS
2343
2344 return tmp;
2345}
2346
2347
2348/* Translate a constant EXPR_ARRAY array constructor for the scalarizer.
2349 This mostly initializes the scalarizer state info structure with the
2350 appropriate values to directly use the array created by the function
2351 gfc_build_constant_array_constructor. */
2352
2353static void
a13d9afe 2354trans_constant_array_constructor (gfc_ss * ss, tree type)
62511fb1 2355{
6d63e468 2356 gfc_array_info *info;
62511fb1 2357 tree tmp;
61a04b5b 2358 int i;
62511fb1 2359
f98cfd3c 2360 tmp = gfc_build_constant_array_constructor (ss->info->expr, type);
62511fb1 2361
1838afec 2362 info = &ss->info->data.array;
62511fb1
RS
2363
2364 info->descriptor = tmp;
628c189e 2365 info->data = gfc_build_addr_expr (NULL_TREE, tmp);
45bc572c 2366 info->offset = gfc_index_zero_node;
62511fb1 2367
cb4b9eae 2368 for (i = 0; i < ss->dimen; i++)
61a04b5b
RS
2369 {
2370 info->delta[i] = gfc_index_zero_node;
2371 info->start[i] = gfc_index_zero_node;
2372 info->end[i] = gfc_index_zero_node;
2373 info->stride[i] = gfc_index_one_node;
61a04b5b 2374 }
62511fb1
RS
2375}
2376
fa168d9f 2377
b2f82aaa
MM
2378static int
2379get_rank (gfc_loopinfo *loop)
2380{
2381 int rank;
2382
2383 rank = 0;
2384 for (; loop; loop = loop->parent)
2385 rank += loop->dimen;
2386
2387 return rank;
2388}
2389
2390
61a04b5b
RS
2391/* Helper routine of gfc_trans_array_constructor to determine if the
2392 bounds of the loop specified by LOOP are constant and simple enough
a13d9afe 2393 to use with trans_constant_array_constructor. Returns the
df2fba9e 2394 iteration count of the loop if suitable, and NULL_TREE otherwise. */
61a04b5b
RS
2395
2396static tree
f03077b0 2397constant_array_constructor_loop_size (gfc_loopinfo * l)
61a04b5b 2398{
f03077b0 2399 gfc_loopinfo *loop;
61a04b5b
RS
2400 tree size = gfc_index_one_node;
2401 tree tmp;
f03077b0 2402 int i, total_dim;
61a04b5b 2403
f03077b0
MM
2404 total_dim = get_rank (l);
2405
2406 for (loop = l; loop; loop = loop->parent)
61a04b5b 2407 {
f03077b0 2408 for (i = 0; i < loop->dimen; i++)
61a04b5b 2409 {
f03077b0
MM
2410 /* If the bounds aren't constant, return NULL_TREE. */
2411 if (!INTEGER_CST_P (loop->from[i]) || !INTEGER_CST_P (loop->to[i]))
61a04b5b 2412 return NULL_TREE;
f03077b0
MM
2413 if (!integer_zerop (loop->from[i]))
2414 {
2415 /* Only allow nonzero "from" in one-dimensional arrays. */
2416 if (total_dim != 1)
2417 return NULL_TREE;
2418 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2419 gfc_array_index_type,
2420 loop->to[i], loop->from[i]);
2421 }
2422 else
2423 tmp = loop->to[i];
2424 tmp = fold_build2_loc (input_location, PLUS_EXPR,
2425 gfc_array_index_type, tmp, gfc_index_one_node);
2426 size = fold_build2_loc (input_location, MULT_EXPR,
2427 gfc_array_index_type, size, tmp);
61a04b5b 2428 }
61a04b5b
RS
2429 }
2430
2431 return size;
2432}
2433
40f20186 2434
b2f82aaa
MM
2435static tree *
2436get_loop_upper_bound_for_array (gfc_ss *array, int array_dim)
2437{
2438 gfc_ss *ss;
2439 int n;
2440
2441 gcc_assert (array->nested_ss == NULL);
2442
2443 for (ss = array; ss; ss = ss->parent)
2444 for (n = 0; n < ss->loop->dimen; n++)
2445 if (array_dim == get_array_ref_dim_for_loop_dim (ss, n))
2446 return &(ss->loop->to[n]);
2447
2448 gcc_unreachable ();
2449}
2450
2451
d769d0df
MM
2452static gfc_loopinfo *
2453outermost_loop (gfc_loopinfo * loop)
2454{
2455 while (loop->parent != NULL)
2456 loop = loop->parent;
2457
2458 return loop;
2459}
2460
2461
6de9cd9a
DN
2462/* Array constructors are handled by constructing a temporary, then using that
2463 within the scalarization loop. This is not optimal, but seems by far the
2464 simplest method. */
2465
2466static void
6adbe654 2467trans_array_constructor (gfc_ss * ss, locus * where)
6de9cd9a 2468{
b7e75771 2469 gfc_constructor_base c;
6de9cd9a
DN
2470 tree offset;
2471 tree offsetvar;
2472 tree desc;
6de9cd9a 2473 tree type;
597553ab 2474 tree tmp;
b2f82aaa 2475 tree *loop_ubound0;
ec25720b 2476 bool dynamic;
4b7f8314
DK
2477 bool old_first_len, old_typespec_chararray_ctor;
2478 tree old_first_len_val;
d769d0df 2479 gfc_loopinfo *loop, *outer_loop;
a0add3be 2480 gfc_ss_info *ss_info;
f98cfd3c 2481 gfc_expr *expr;
fa168d9f 2482 gfc_ss *s;
90ee6453
EP
2483 tree neg_len;
2484 char *msg;
4b7f8314
DK
2485
2486 /* Save the old values for nested checking. */
2487 old_first_len = first_len;
2488 old_first_len_val = first_len_val;
2489 old_typespec_chararray_ctor = typespec_chararray_ctor;
6de9cd9a 2490
6adbe654 2491 loop = ss->loop;
d769d0df 2492 outer_loop = outermost_loop (loop);
a0add3be
MM
2493 ss_info = ss->info;
2494 expr = ss_info->expr;
f98cfd3c 2495
c03fc95d
DK
2496 /* Do bounds-checking here and in gfc_trans_array_ctor_element only if no
2497 typespec was given for the array constructor. */
3a146d46
JJ
2498 typespec_chararray_ctor = (expr->ts.type == BT_CHARACTER
2499 && expr->ts.u.cl
f98cfd3c 2500 && expr->ts.u.cl->length_from_typespec);
c03fc95d 2501
d3d3011f 2502 if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
f98cfd3c 2503 && expr->ts.type == BT_CHARACTER && !typespec_chararray_ctor)
f04986a9 2504 {
32be9f94
PT
2505 first_len_val = gfc_create_var (gfc_charlen_type_node, "len");
2506 first_len = true;
2507 }
2508
b2f82aaa 2509 gcc_assert (ss->dimen == ss->loop->dimen);
40f20186 2510
f98cfd3c
MM
2511 c = expr->value.constructor;
2512 if (expr->ts.type == BT_CHARACTER)
40f20186 2513 {
c03fc95d 2514 bool const_string;
d751beac 2515 bool force_new_cl = false;
f04986a9 2516
c03fc95d
DK
2517 /* get_array_ctor_strlen walks the elements of the constructor, if a
2518 typespec was given, we already know the string length and want the one
2519 specified there. */
f98cfd3c
MM
2520 if (typespec_chararray_ctor && expr->ts.u.cl->length
2521 && expr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
c03fc95d
DK
2522 {
2523 gfc_se length_se;
2524
2525 const_string = false;
2526 gfc_init_se (&length_se, NULL);
f98cfd3c 2527 gfc_conv_expr_type (&length_se, expr->ts.u.cl->length,
c03fc95d 2528 gfc_charlen_type_node);
a0add3be 2529 ss_info->string_length = length_se.expr;
90ee6453
EP
2530
2531 /* Check if the character length is negative. If it is, then
2532 set LEN = 0. */
2533 neg_len = fold_build2_loc (input_location, LT_EXPR,
63ee5404 2534 logical_type_node, ss_info->string_length,
f622221a
JB
2535 build_zero_cst (TREE_TYPE
2536 (ss_info->string_length)));
90ee6453
EP
2537 /* Print a warning if bounds checking is enabled. */
2538 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2539 {
2540 msg = xasprintf ("Negative character length treated as LEN = 0");
2541 gfc_trans_runtime_check (false, true, neg_len, &length_se.pre,
2542 where, msg);
2543 free (msg);
2544 }
2545
2546 ss_info->string_length
2547 = fold_build3_loc (input_location, COND_EXPR,
2548 gfc_charlen_type_node, neg_len,
f622221a
JB
2549 build_zero_cst
2550 (TREE_TYPE (ss_info->string_length)),
90ee6453
EP
2551 ss_info->string_length);
2552 ss_info->string_length = gfc_evaluate_now (ss_info->string_length,
2553 &length_se.pre);
d769d0df
MM
2554 gfc_add_block_to_block (&outer_loop->pre, &length_se.pre);
2555 gfc_add_block_to_block (&outer_loop->post, &length_se.post);
c03fc95d
DK
2556 }
2557 else
d751beac
LK
2558 {
2559 const_string = get_array_ctor_strlen (&outer_loop->pre, c,
2560 &ss_info->string_length);
2561 force_new_cl = true;
2562 }
ca39e6f2
FXC
2563
2564 /* Complex character array constructors should have been taken care of
2565 and not end up here. */
a0add3be 2566 gcc_assert (ss_info->string_length);
40f20186 2567
d751beac 2568 store_backend_decl (&expr->ts.u.cl, ss_info->string_length, force_new_cl);
0ee8e250 2569
a0add3be 2570 type = gfc_get_character_type_len (expr->ts.kind, ss_info->string_length);
40f20186
PB
2571 if (const_string)
2572 type = build_pointer_type (type);
2573 }
2574 else
574284e9
AV
2575 type = gfc_typenode_for_spec (expr->ts.type == BT_CLASS
2576 ? &CLASS_DATA (expr)->ts : &expr->ts);
40f20186 2577
ec25720b
RS
2578 /* See if the constructor determines the loop bounds. */
2579 dynamic = false;
6a56381b 2580
b2f82aaa
MM
2581 loop_ubound0 = get_loop_upper_bound_for_array (ss, 0);
2582
2583 if (expr->shape && get_rank (loop) > 1 && *loop_ubound0 == NULL_TREE)
6a56381b
PT
2584 {
2585 /* We have a multidimensional parameter. */
fa168d9f
MM
2586 for (s = ss; s; s = s->parent)
2587 {
2588 int n;
2589 for (n = 0; n < s->loop->dimen; n++)
2590 {
2591 s->loop->from[n] = gfc_index_zero_node;
2592 s->loop->to[n] = gfc_conv_mpz_to_tree (expr->shape[s->dim[n]],
2593 gfc_index_integer_kind);
2594 s->loop->to[n] = fold_build2_loc (input_location, MINUS_EXPR,
2595 gfc_array_index_type,
2596 s->loop->to[n],
2597 gfc_index_one_node);
2598 }
2599 }
6a56381b
PT
2600 }
2601
b2f82aaa 2602 if (*loop_ubound0 == NULL_TREE)
ec25720b
RS
2603 {
2604 mpz_t size;
2605
2606 /* We should have a 1-dimensional, zero-based loop. */
4616ef9b 2607 gcc_assert (loop->parent == NULL && loop->nested == NULL);
ec25720b
RS
2608 gcc_assert (loop->dimen == 1);
2609 gcc_assert (integer_zerop (loop->from[0]));
2610
2611 /* Split the constructor size into a static part and a dynamic part.
2612 Allocate the static size up-front and record whether the dynamic
2613 size might be nonzero. */
2614 mpz_init (size);
2615 dynamic = gfc_get_array_constructor_size (&size, c);
2616 mpz_sub_ui (size, size, 1);
2617 loop->to[0] = gfc_conv_mpz_to_tree (size, gfc_index_integer_kind);
2618 mpz_clear (size);
2619 }
2620
62511fb1 2621 /* Special case constant array constructors. */
61a04b5b 2622 if (!dynamic)
62511fb1 2623 {
b01e2f88 2624 unsigned HOST_WIDE_INT nelem = gfc_constant_array_constructor_p (c);
62511fb1
RS
2625 if (nelem > 0)
2626 {
61a04b5b
RS
2627 tree size = constant_array_constructor_loop_size (loop);
2628 if (size && compare_tree_int (size, nelem) == 0)
62511fb1 2629 {
a13d9afe 2630 trans_constant_array_constructor (ss, type);
4b7f8314 2631 goto finish;
62511fb1
RS
2632 }
2633 }
2634 }
2635
d769d0df
MM
2636 gfc_trans_create_temp_array (&outer_loop->pre, &outer_loop->post, ss, type,
2637 NULL_TREE, dynamic, true, false, where);
6de9cd9a 2638
1838afec 2639 desc = ss_info->data.array.descriptor;
7ab92584 2640 offset = gfc_index_zero_node;
6de9cd9a 2641 offsetvar = gfc_create_var_np (gfc_array_index_type, "offset");
01306727 2642 TREE_NO_WARNING (offsetvar) = 1;
6de9cd9a 2643 TREE_USED (offsetvar) = 0;
d769d0df 2644 gfc_trans_array_constructor_value (&outer_loop->pre, type, desc, c,
ec25720b
RS
2645 &offset, &offsetvar, dynamic);
2646
2647 /* If the array grows dynamically, the upper bound of the loop variable
2648 is determined by the array's final upper bound. */
2649 if (dynamic)
597553ab
PT
2650 {
2651 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2652 gfc_array_index_type,
2653 offsetvar, gfc_index_one_node);
d769d0df 2654 tmp = gfc_evaluate_now (tmp, &outer_loop->pre);
597553ab 2655 gfc_conv_descriptor_ubound_set (&loop->pre, desc, gfc_rank_cst[0], tmp);
d168c883 2656 if (*loop_ubound0 && VAR_P (*loop_ubound0))
d769d0df 2657 gfc_add_modify (&outer_loop->pre, *loop_ubound0, tmp);
597553ab 2658 else
b2f82aaa 2659 *loop_ubound0 = tmp;
597553ab 2660 }
6de9cd9a
DN
2661
2662 if (TREE_USED (offsetvar))
2663 pushdecl (offsetvar);
2664 else
6e45f57b 2665 gcc_assert (INTEGER_CST_P (offset));
597553ab 2666
6de9cd9a 2667#if 0
dfc46c1f 2668 /* Disable bound checking for now because it's probably broken. */
d3d3011f 2669 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
6de9cd9a 2670 {
6e45f57b 2671 gcc_unreachable ();
6de9cd9a
DN
2672 }
2673#endif
4b7f8314
DK
2674
2675finish:
2676 /* Restore old values of globals. */
2677 first_len = old_first_len;
2678 first_len_val = old_first_len_val;
2679 typespec_chararray_ctor = old_typespec_chararray_ctor;
6de9cd9a
DN
2680}
2681
2682
7a70c12d
RS
2683/* INFO describes a GFC_SS_SECTION in loop LOOP, and this function is
2684 called after evaluating all of INFO's vector dimensions. Go through
2685 each such vector dimension and see if we can now fill in any missing
2686 loop bounds. */
2687
2688static void
84952a4e 2689set_vector_loop_bounds (gfc_ss * ss)
7a70c12d 2690{
d769d0df 2691 gfc_loopinfo *loop, *outer_loop;
6d63e468 2692 gfc_array_info *info;
7a70c12d
RS
2693 gfc_se se;
2694 tree tmp;
2695 tree desc;
2696 tree zero;
2697 int n;
2698 int dim;
2699
d769d0df
MM
2700 outer_loop = outermost_loop (ss->loop);
2701
1838afec 2702 info = &ss->info->data.array;
43e7d60b 2703
f49afcb0 2704 for (; ss; ss = ss->parent)
7a70c12d 2705 {
f49afcb0
MM
2706 loop = ss->loop;
2707
2708 for (n = 0; n < loop->dimen; n++)
7a70c12d 2709 {
f49afcb0
MM
2710 dim = ss->dim[n];
2711 if (info->ref->u.ar.dimen_type[dim] != DIMEN_VECTOR
2712 || loop->to[n] != NULL)
2713 continue;
2714
7a70c12d
RS
2715 /* Loop variable N indexes vector dimension DIM, and we don't
2716 yet know the upper bound of loop variable N. Set it to the
2717 difference between the vector's upper and lower bounds. */
2718 gcc_assert (loop->from[n] == gfc_index_zero_node);
2719 gcc_assert (info->subscript[dim]
bcc4d4e0 2720 && info->subscript[dim]->info->type == GFC_SS_VECTOR);
7a70c12d
RS
2721
2722 gfc_init_se (&se, NULL);
1838afec 2723 desc = info->subscript[dim]->info->data.array.descriptor;
7a70c12d 2724 zero = gfc_rank_cst[0];
94471a56
TB
2725 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2726 gfc_array_index_type,
568e8e1e
PT
2727 gfc_conv_descriptor_ubound_get (desc, zero),
2728 gfc_conv_descriptor_lbound_get (desc, zero));
d769d0df 2729 tmp = gfc_evaluate_now (tmp, &outer_loop->pre);
7a70c12d
RS
2730 loop->to[n] = tmp;
2731 }
2732 }
2733}
2734
2735
14aeb3cd
MM
2736/* Tells whether a scalar argument to an elemental procedure is saved out
2737 of a scalarization loop as a value or as a reference. */
2738
2739bool
2740gfc_scalar_elemental_arg_saved_as_reference (gfc_ss_info * ss_info)
2741{
2742 if (ss_info->type != GFC_SS_REFERENCE)
2743 return false;
2744
4932364b
TK
2745 if (ss_info->data.scalar.needs_temporary)
2746 return false;
2747
14aeb3cd
MM
2748 /* If the actual argument can be absent (in other words, it can
2749 be a NULL reference), don't try to evaluate it; pass instead
2750 the reference directly. */
2751 if (ss_info->can_be_null_ref)
2752 return true;
2753
2754 /* If the expression is of polymorphic type, it's actual size is not known,
2755 so we avoid copying it anywhere. */
2756 if (ss_info->data.scalar.dummy_arg
2757 && ss_info->data.scalar.dummy_arg->ts.type == BT_CLASS
2758 && ss_info->expr->ts.type == BT_CLASS)
2759 return true;
2760
2761 /* If the expression is a data reference of aggregate type,
711d7c23 2762 and the data reference is not used on the left hand side,
14aeb3cd 2763 avoid a copy by saving a reference to the content. */
711d7c23 2764 if (!ss_info->data.scalar.needs_temporary
14aeb3cd 2765 && (ss_info->expr->ts.type == BT_DERIVED
711d7c23
MM
2766 || ss_info->expr->ts.type == BT_CLASS)
2767 && gfc_expr_is_variable (ss_info->expr))
14aeb3cd
MM
2768 return true;
2769
2770 /* Otherwise the expression is evaluated to a temporary variable before the
2771 scalarization loop. */
2772 return false;
2773}
2774
2775
6de9cd9a
DN
2776/* Add the pre and post chains for all the scalar expressions in a SS chain
2777 to loop. This is called after the loop parameters have been calculated,
2778 but before the actual scalarizing loops. */
6de9cd9a
DN
2779
2780static void
bdfd2ff0
TK
2781gfc_add_loop_ss_code (gfc_loopinfo * loop, gfc_ss * ss, bool subscript,
2782 locus * where)
6de9cd9a 2783{
d769d0df 2784 gfc_loopinfo *nested_loop, *outer_loop;
6de9cd9a 2785 gfc_se se;
f98cfd3c 2786 gfc_ss_info *ss_info;
1838afec 2787 gfc_array_info *info;
f98cfd3c 2788 gfc_expr *expr;
6de9cd9a
DN
2789 int n;
2790
f391a855
TB
2791 /* Don't evaluate the arguments for realloc_lhs_loop_for_fcn_call; otherwise,
2792 arguments could get evaluated multiple times. */
2793 if (ss->is_alloc_lhs)
2794 return;
2795
d769d0df
MM
2796 outer_loop = outermost_loop (loop);
2797
df2fba9e
RW
2798 /* TODO: This can generate bad code if there are ordering dependencies,
2799 e.g., a callee allocated function and an unknown size constructor. */
6e45f57b 2800 gcc_assert (ss != NULL);
6de9cd9a
DN
2801
2802 for (; ss != gfc_ss_terminator; ss = ss->loop_chain)
2803 {
6e45f57b 2804 gcc_assert (ss);
6de9cd9a 2805
30ae600f
MM
2806 /* Cross loop arrays are handled from within the most nested loop. */
2807 if (ss->nested_ss != NULL)
2808 continue;
2809
f98cfd3c
MM
2810 ss_info = ss->info;
2811 expr = ss_info->expr;
1838afec 2812 info = &ss_info->data.array;
f98cfd3c
MM
2813
2814 switch (ss_info->type)
6de9cd9a
DN
2815 {
2816 case GFC_SS_SCALAR:
2817 /* Scalar expression. Evaluate this now. This includes elemental
2818 dimension indices, but not array section bounds. */
2819 gfc_init_se (&se, NULL);
f98cfd3c 2820 gfc_conv_expr (&se, expr);
d769d0df 2821 gfc_add_block_to_block (&outer_loop->pre, &se.pre);
6de9cd9a 2822
43a68a9d
PT
2823 if (expr->ts.type != BT_CHARACTER
2824 && !gfc_is_alloc_class_scalar_function (expr))
ae772c2d
PT
2825 {
2826 /* Move the evaluation of scalar expressions outside the
2827 scalarization loop, except for WHERE assignments. */
2828 if (subscript)
2829 se.expr = convert(gfc_array_index_type, se.expr);
42d0058e 2830 if (!ss_info->where)
d769d0df
MM
2831 se.expr = gfc_evaluate_now (se.expr, &outer_loop->pre);
2832 gfc_add_block_to_block (&outer_loop->pre, &se.post);
ae772c2d
PT
2833 }
2834 else
d769d0df 2835 gfc_add_block_to_block (&outer_loop->post, &se.post);
6de9cd9a 2836
99dd5a29 2837 ss_info->data.scalar.value = se.expr;
a0add3be 2838 ss_info->string_length = se.string_length;
6de9cd9a
DN
2839 break;
2840
2841 case GFC_SS_REFERENCE:
0192ef20 2842 /* Scalar argument to elemental procedure. */
6de9cd9a 2843 gfc_init_se (&se, NULL);
14aeb3cd
MM
2844 if (gfc_scalar_elemental_arg_saved_as_reference (ss_info))
2845 gfc_conv_expr_reference (&se, expr);
0192ef20
MM
2846 else
2847 {
14aeb3cd 2848 /* Evaluate the argument outside the loop and pass
0192ef20
MM
2849 a reference to the value. */
2850 gfc_conv_expr (&se, expr);
2851 }
da78a067
PT
2852
2853 /* Ensure that a pointer to the string is stored. */
2854 if (expr->ts.type == BT_CHARACTER)
2855 gfc_conv_string_parameter (&se);
2856
d769d0df
MM
2857 gfc_add_block_to_block (&outer_loop->pre, &se.pre);
2858 gfc_add_block_to_block (&outer_loop->post, &se.post);
c49ea23d
PT
2859 if (gfc_is_class_scalar_expr (expr))
2860 /* This is necessary because the dynamic type will always be
2861 large than the declared type. In consequence, assigning
2862 the value to a temporary could segfault.
2863 OOP-TODO: see if this is generally correct or is the value
2864 has to be written to an allocated temporary, whose address
2865 is passed via ss_info. */
2866 ss_info->data.scalar.value = se.expr;
2867 else
2868 ss_info->data.scalar.value = gfc_evaluate_now (se.expr,
2869 &outer_loop->pre);
6de9cd9a 2870
a0add3be 2871 ss_info->string_length = se.string_length;
6de9cd9a
DN
2872 break;
2873
2874 case GFC_SS_SECTION:
7a70c12d 2875 /* Add the expressions for scalar and vector subscripts. */
6de9cd9a 2876 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
1838afec 2877 if (info->subscript[n])
573234ac 2878 gfc_add_loop_ss_code (loop, info->subscript[n], true, where);
7a70c12d 2879
84952a4e 2880 set_vector_loop_bounds (ss);
7a70c12d
RS
2881 break;
2882
2883 case GFC_SS_VECTOR:
2884 /* Get the vector's descriptor and store it in SS. */
2885 gfc_init_se (&se, NULL);
2960a368 2886 gfc_conv_expr_descriptor (&se, expr);
d769d0df
MM
2887 gfc_add_block_to_block (&outer_loop->pre, &se.pre);
2888 gfc_add_block_to_block (&outer_loop->post, &se.post);
1838afec 2889 info->descriptor = se.expr;
6de9cd9a
DN
2890 break;
2891
2892 case GFC_SS_INTRINSIC:
2893 gfc_add_intrinsic_ss_code (loop, ss);
2894 break;
2895
2896 case GFC_SS_FUNCTION:
2897 /* Array function return value. We call the function and save its
2898 result in a temporary for use inside the loop. */
2899 gfc_init_se (&se, NULL);
2900 se.loop = loop;
2901 se.ss = ss;
a6b22eea
PT
2902 if (gfc_is_class_array_function (expr))
2903 expr->must_finalize = 1;
f98cfd3c 2904 gfc_conv_expr (&se, expr);
d769d0df
MM
2905 gfc_add_block_to_block (&outer_loop->pre, &se.pre);
2906 gfc_add_block_to_block (&outer_loop->post, &se.post);
a0add3be 2907 ss_info->string_length = se.string_length;
6de9cd9a
DN
2908 break;
2909
2910 case GFC_SS_CONSTRUCTOR:
f98cfd3c 2911 if (expr->ts.type == BT_CHARACTER
a0add3be 2912 && ss_info->string_length == NULL
f98cfd3c 2913 && expr->ts.u.cl
d751beac
LK
2914 && expr->ts.u.cl->length
2915 && expr->ts.u.cl->length->expr_type == EXPR_CONSTANT)
f2d3cb25
PT
2916 {
2917 gfc_init_se (&se, NULL);
f98cfd3c 2918 gfc_conv_expr_type (&se, expr->ts.u.cl->length,
f2d3cb25 2919 gfc_charlen_type_node);
a0add3be 2920 ss_info->string_length = se.expr;
d769d0df
MM
2921 gfc_add_block_to_block (&outer_loop->pre, &se.pre);
2922 gfc_add_block_to_block (&outer_loop->post, &se.post);
f2d3cb25 2923 }
6adbe654 2924 trans_array_constructor (ss, where);
6de9cd9a
DN
2925 break;
2926
fc90a8f2 2927 case GFC_SS_TEMP:
e9cfef64
PB
2928 case GFC_SS_COMPONENT:
2929 /* Do nothing. These are handled elsewhere. */
fc90a8f2
PB
2930 break;
2931
6de9cd9a 2932 default:
6e45f57b 2933 gcc_unreachable ();
6de9cd9a
DN
2934 }
2935 }
30ae600f 2936
573234ac 2937 if (!subscript)
30ae600f
MM
2938 for (nested_loop = loop->nested; nested_loop;
2939 nested_loop = nested_loop->next)
2940 gfc_add_loop_ss_code (nested_loop, nested_loop->ss, subscript, where);
6de9cd9a
DN
2941}
2942
2943
2944/* Translate expressions for the descriptor and data pointer of a SS. */
2945/*GCC ARRAYS*/
2946
2947static void
2948gfc_conv_ss_descriptor (stmtblock_t * block, gfc_ss * ss, int base)
2949{
2950 gfc_se se;
f98cfd3c 2951 gfc_ss_info *ss_info;
1838afec 2952 gfc_array_info *info;
6de9cd9a
DN
2953 tree tmp;
2954
f98cfd3c 2955 ss_info = ss->info;
1838afec 2956 info = &ss_info->data.array;
f98cfd3c 2957
6de9cd9a 2958 /* Get the descriptor for the array to be scalarized. */
f98cfd3c 2959 gcc_assert (ss_info->expr->expr_type == EXPR_VARIABLE);
6de9cd9a
DN
2960 gfc_init_se (&se, NULL);
2961 se.descriptor_only = 1;
f98cfd3c 2962 gfc_conv_expr_lhs (&se, ss_info->expr);
6de9cd9a 2963 gfc_add_block_to_block (block, &se.pre);
1838afec 2964 info->descriptor = se.expr;
a0add3be 2965 ss_info->string_length = se.string_length;
6de9cd9a
DN
2966
2967 if (base)
2968 {
cef026ec
AV
2969 if (ss_info->expr->ts.type == BT_CHARACTER && !ss_info->expr->ts.deferred
2970 && ss_info->expr->ts.u.cl->length == NULL)
2971 {
2972 /* Emit a DECL_EXPR for the variable sized array type in
2973 GFC_TYPE_ARRAY_DATAPTR_TYPE so the gimplification of its type
2974 sizes works correctly. */
2975 tree arraytype = TREE_TYPE (
2976 GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (info->descriptor)));
2977 if (! TYPE_NAME (arraytype))
2978 TYPE_NAME (arraytype) = build_decl (UNKNOWN_LOCATION, TYPE_DECL,
2979 NULL_TREE, arraytype);
2980 gfc_add_expr_to_block (block, build1 (DECL_EXPR, arraytype,
2981 TYPE_NAME (arraytype)));
2982 }
6de9cd9a
DN
2983 /* Also the data pointer. */
2984 tmp = gfc_conv_array_data (se.expr);
2985 /* If this is a variable or address of a variable we use it directly.
2054fc29 2986 Otherwise we must evaluate it now to avoid breaking dependency
6de9cd9a
DN
2987 analysis by pulling the expressions for elemental array indices
2988 inside the loop. */
2989 if (!(DECL_P (tmp)
2990 || (TREE_CODE (tmp) == ADDR_EXPR
2991 && DECL_P (TREE_OPERAND (tmp, 0)))))
2992 tmp = gfc_evaluate_now (tmp, block);
1838afec 2993 info->data = tmp;
6de9cd9a
DN
2994
2995 tmp = gfc_conv_array_offset (se.expr);
1838afec 2996 info->offset = gfc_evaluate_now (tmp, block);
597553ab
PT
2997
2998 /* Make absolutely sure that the saved_offset is indeed saved
2999 so that the variable is still accessible after the loops
3000 are translated. */
1838afec 3001 info->saved_offset = info->offset;
6de9cd9a
DN
3002 }
3003}
3004
3005
1f2959f0 3006/* Initialize a gfc_loopinfo structure. */
6de9cd9a
DN
3007
3008void
3009gfc_init_loopinfo (gfc_loopinfo * loop)
3010{
3011 int n;
3012
3013 memset (loop, 0, sizeof (gfc_loopinfo));
3014 gfc_init_block (&loop->pre);
3015 gfc_init_block (&loop->post);
3016
3d03ead0 3017 /* Initially scalarize in order and default to no loop reversal. */
6de9cd9a 3018 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
3d03ead0
PT
3019 {
3020 loop->order[n] = n;
aed5574e 3021 loop->reverse[n] = GFC_INHIBIT_REVERSE;
3d03ead0 3022 }
6de9cd9a
DN
3023
3024 loop->ss = gfc_ss_terminator;
3025}
3026
3027
e7dc5b4f 3028/* Copies the loop variable info to a gfc_se structure. Does not copy the SS
6de9cd9a
DN
3029 chain. */
3030
3031void
3032gfc_copy_loopinfo_to_se (gfc_se * se, gfc_loopinfo * loop)
3033{
3034 se->loop = loop;
3035}
3036
3037
3038/* Return an expression for the data pointer of an array. */
3039
3040tree
3041gfc_conv_array_data (tree descriptor)
3042{
3043 tree type;
3044
3045 type = TREE_TYPE (descriptor);
3046 if (GFC_ARRAY_TYPE_P (type))
3047 {
3048 if (TREE_CODE (type) == POINTER_TYPE)
3049 return descriptor;
3050 else
3051 {
13413760 3052 /* Descriptorless arrays. */
628c189e 3053 return gfc_build_addr_expr (NULL_TREE, descriptor);
6de9cd9a
DN
3054 }
3055 }
3056 else
4c73896d 3057 return gfc_conv_descriptor_data_get (descriptor);
6de9cd9a
DN
3058}
3059
3060
3061/* Return an expression for the base offset of an array. */
3062
3063tree
3064gfc_conv_array_offset (tree descriptor)
3065{
3066 tree type;
3067
3068 type = TREE_TYPE (descriptor);
3069 if (GFC_ARRAY_TYPE_P (type))
3070 return GFC_TYPE_ARRAY_OFFSET (type);
3071 else
568e8e1e 3072 return gfc_conv_descriptor_offset_get (descriptor);
6de9cd9a
DN
3073}
3074
3075
3076/* Get an expression for the array stride. */
3077
3078tree
3079gfc_conv_array_stride (tree descriptor, int dim)
3080{
3081 tree tmp;
3082 tree type;
3083
3084 type = TREE_TYPE (descriptor);
3085
3086 /* For descriptorless arrays use the array size. */
3087 tmp = GFC_TYPE_ARRAY_STRIDE (type, dim);
3088 if (tmp != NULL_TREE)
3089 return tmp;
3090
568e8e1e 3091 tmp = gfc_conv_descriptor_stride_get (descriptor, gfc_rank_cst[dim]);
6de9cd9a
DN
3092 return tmp;
3093}
3094
3095
3096/* Like gfc_conv_array_stride, but for the lower bound. */
3097
3098tree
3099gfc_conv_array_lbound (tree descriptor, int dim)
3100{
3101 tree tmp;
3102 tree type;
3103
3104 type = TREE_TYPE (descriptor);
3105
3106 tmp = GFC_TYPE_ARRAY_LBOUND (type, dim);
3107 if (tmp != NULL_TREE)
3108 return tmp;
3109
568e8e1e 3110 tmp = gfc_conv_descriptor_lbound_get (descriptor, gfc_rank_cst[dim]);
6de9cd9a
DN
3111 return tmp;
3112}
3113
3114
3115/* Like gfc_conv_array_stride, but for the upper bound. */
3116
3117tree
3118gfc_conv_array_ubound (tree descriptor, int dim)
3119{
3120 tree tmp;
3121 tree type;
3122
3123 type = TREE_TYPE (descriptor);
3124
3125 tmp = GFC_TYPE_ARRAY_UBOUND (type, dim);
3126 if (tmp != NULL_TREE)
3127 return tmp;
3128
3129 /* This should only ever happen when passing an assumed shape array
3130 as an actual parameter. The value will never be used. */
3131 if (GFC_ARRAY_TYPE_P (TREE_TYPE (descriptor)))
7ab92584 3132 return gfc_index_zero_node;
6de9cd9a 3133
568e8e1e 3134 tmp = gfc_conv_descriptor_ubound_get (descriptor, gfc_rank_cst[dim]);
6de9cd9a
DN
3135 return tmp;
3136}
3137
3138
6de9cd9a
DN
3139/* Generate code to perform an array index bound check. */
3140
3141static tree
36e783e3
MM
3142trans_array_bound_check (gfc_se * se, gfc_ss *ss, tree index, int n,
3143 locus * where, bool check_upper)
6de9cd9a 3144{
6de9cd9a 3145 tree fault;
c6ec7cc6 3146 tree tmp_lo, tmp_up;
36e783e3 3147 tree descriptor;
dd18a33b 3148 char *msg;
d19c0f4f 3149 const char * name = NULL;
6de9cd9a 3150
d3d3011f 3151 if (!(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS))
6de9cd9a
DN
3152 return index;
3153
1838afec 3154 descriptor = ss->info->data.array.descriptor;
36e783e3 3155
6de9cd9a 3156 index = gfc_evaluate_now (index, &se->pre);
dd18a33b 3157
d19c0f4f 3158 /* We find a name for the error message. */
f98cfd3c 3159 name = ss->info->expr->symtree->n.sym->name;
14bf3267 3160 gcc_assert (name != NULL);
d19c0f4f 3161
d168c883 3162 if (VAR_P (descriptor))
e3e529d1
SK
3163 name = IDENTIFIER_POINTER (DECL_NAME (descriptor));
3164
c6ec7cc6 3165 /* If upper bound is present, include both bounds in the error message. */
c099916d
FXC
3166 if (check_upper)
3167 {
c6ec7cc6
DW
3168 tmp_lo = gfc_conv_array_lbound (descriptor, n);
3169 tmp_up = gfc_conv_array_ubound (descriptor, n);
3170
3171 if (name)
1a33dc9e
UB
3172 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
3173 "outside of expected range (%%ld:%%ld)", n+1, name);
c6ec7cc6 3174 else
1a33dc9e
UB
3175 msg = xasprintf ("Index '%%ld' of dimension %d "
3176 "outside of expected range (%%ld:%%ld)", n+1);
c6ec7cc6 3177
63ee5404 3178 fault = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
94471a56 3179 index, tmp_lo);
c6ec7cc6
DW
3180 gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
3181 fold_convert (long_integer_type_node, index),
3182 fold_convert (long_integer_type_node, tmp_lo),
3183 fold_convert (long_integer_type_node, tmp_up));
63ee5404 3184 fault = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
94471a56 3185 index, tmp_up);
c6ec7cc6
DW
3186 gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
3187 fold_convert (long_integer_type_node, index),
3188 fold_convert (long_integer_type_node, tmp_lo),
3189 fold_convert (long_integer_type_node, tmp_up));
cede9502 3190 free (msg);
c6ec7cc6
DW
3191 }
3192 else
3193 {
3194 tmp_lo = gfc_conv_array_lbound (descriptor, n);
3195
c099916d 3196 if (name)
1a33dc9e
UB
3197 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
3198 "below lower bound of %%ld", n+1, name);
c099916d 3199 else
1a33dc9e
UB
3200 msg = xasprintf ("Index '%%ld' of dimension %d "
3201 "below lower bound of %%ld", n+1);
c6ec7cc6 3202
63ee5404 3203 fault = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
94471a56 3204 index, tmp_lo);
0d52899f 3205 gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
c8fe94c7 3206 fold_convert (long_integer_type_node, index),
c6ec7cc6 3207 fold_convert (long_integer_type_node, tmp_lo));
cede9502 3208 free (msg);
c099916d 3209 }
6de9cd9a
DN
3210
3211 return index;
3212}
3213
3214
6de9cd9a 3215/* Return the offset for an index. Performs bound checking for elemental
9157ccb2
MM
3216 dimensions. Single element references are processed separately.
3217 DIM is the array dimension, I is the loop dimension. */
6de9cd9a
DN
3218
3219static tree
36e783e3
MM
3220conv_array_index_offset (gfc_se * se, gfc_ss * ss, int dim, int i,
3221 gfc_array_ref * ar, tree stride)
6de9cd9a 3222{
6d63e468 3223 gfc_array_info *info;
6de9cd9a 3224 tree index;
7a70c12d
RS
3225 tree desc;
3226 tree data;
6de9cd9a 3227
1838afec 3228 info = &ss->info->data.array;
36e783e3 3229
6de9cd9a
DN
3230 /* Get the index into the array for this dimension. */
3231 if (ar)
3232 {
6e45f57b 3233 gcc_assert (ar->type != AR_ELEMENT);
7a70c12d 3234 switch (ar->dimen_type[dim])
6de9cd9a 3235 {
a3935ffc
TB
3236 case DIMEN_THIS_IMAGE:
3237 gcc_unreachable ();
3238 break;
7a70c12d 3239 case DIMEN_ELEMENT:
6de9cd9a 3240 /* Elemental dimension. */
6e45f57b 3241 gcc_assert (info->subscript[dim]
bcc4d4e0 3242 && info->subscript[dim]->info->type == GFC_SS_SCALAR);
6de9cd9a 3243 /* We've already translated this value outside the loop. */
99dd5a29 3244 index = info->subscript[dim]->info->data.scalar.value;
6de9cd9a 3245
36e783e3
MM
3246 index = trans_array_bound_check (se, ss, index, dim, &ar->where,
3247 ar->as->type != AS_ASSUMED_SIZE
3248 || dim < ar->dimen - 1);
7a70c12d
RS
3249 break;
3250
3251 case DIMEN_VECTOR:
3252 gcc_assert (info && se->loop);
3253 gcc_assert (info->subscript[dim]
bcc4d4e0 3254 && info->subscript[dim]->info->type == GFC_SS_VECTOR);
1838afec 3255 desc = info->subscript[dim]->info->data.array.descriptor;
7a70c12d
RS
3256
3257 /* Get a zero-based index into the vector. */
94471a56
TB
3258 index = fold_build2_loc (input_location, MINUS_EXPR,
3259 gfc_array_index_type,
3260 se->loop->loopvar[i], se->loop->from[i]);
7a70c12d
RS
3261
3262 /* Multiply the index by the stride. */
94471a56
TB
3263 index = fold_build2_loc (input_location, MULT_EXPR,
3264 gfc_array_index_type,
3265 index, gfc_conv_array_stride (desc, 0));
7a70c12d
RS
3266
3267 /* Read the vector to get an index into info->descriptor. */
db3927fb
AH
3268 data = build_fold_indirect_ref_loc (input_location,
3269 gfc_conv_array_data (desc));
1d6b7f39 3270 index = gfc_build_array_ref (data, index, NULL);
7a70c12d 3271 index = gfc_evaluate_now (index, &se->pre);
92375a20 3272 index = fold_convert (gfc_array_index_type, index);
7a70c12d
RS
3273
3274 /* Do any bounds checking on the final info->descriptor index. */
36e783e3
MM
3275 index = trans_array_bound_check (se, ss, index, dim, &ar->where,
3276 ar->as->type != AS_ASSUMED_SIZE
3277 || dim < ar->dimen - 1);
7a70c12d
RS
3278 break;
3279
3280 case DIMEN_RANGE:
6de9cd9a 3281 /* Scalarized dimension. */
6e45f57b 3282 gcc_assert (info && se->loop);
6de9cd9a 3283
9157ccb2 3284 /* Multiply the loop variable by the stride and delta. */
6de9cd9a 3285 index = se->loop->loopvar[i];
9157ccb2 3286 if (!integer_onep (info->stride[dim]))
94471a56
TB
3287 index = fold_build2_loc (input_location, MULT_EXPR,
3288 gfc_array_index_type, index,
3289 info->stride[dim]);
9157ccb2 3290 if (!integer_zerop (info->delta[dim]))
94471a56
TB
3291 index = fold_build2_loc (input_location, PLUS_EXPR,
3292 gfc_array_index_type, index,
3293 info->delta[dim]);
7a70c12d 3294 break;
6de9cd9a 3295
7a70c12d
RS
3296 default:
3297 gcc_unreachable ();
6de9cd9a
DN
3298 }
3299 }
3300 else
3301 {
e9cfef64 3302 /* Temporary array or derived type component. */
6e45f57b 3303 gcc_assert (se->loop);
6de9cd9a 3304 index = se->loop->loopvar[se->loop->order[i]];
30a390c8 3305
f04986a9 3306 /* Pointer functions can have stride[0] different from unity.
30a390c8 3307 Use the stride returned by the function call and stored in
f04986a9 3308 the descriptor for the temporary. */
bcc4d4e0 3309 if (se->ss && se->ss->info->type == GFC_SS_FUNCTION
f98cfd3c
MM
3310 && se->ss->info->expr
3311 && se->ss->info->expr->symtree
3312 && se->ss->info->expr->symtree->n.sym->result
3313 && se->ss->info->expr->symtree->n.sym->result->attr.pointer)
30a390c8
PT
3314 stride = gfc_conv_descriptor_stride_get (info->descriptor,
3315 gfc_rank_cst[dim]);
3316
43a68a9d 3317 if (info->delta[dim] && !integer_zerop (info->delta[dim]))
94471a56
TB
3318 index = fold_build2_loc (input_location, PLUS_EXPR,
3319 gfc_array_index_type, index, info->delta[dim]);
6de9cd9a
DN
3320 }
3321
3322 /* Multiply by the stride. */
2368eaf9 3323 if (stride != NULL && !integer_onep (stride))
94471a56
TB
3324 index = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
3325 index, stride);
6de9cd9a
DN
3326
3327 return index;
3328}
3329
3330
c49ea23d
PT
3331/* Build a scalarized array reference using the vptr 'size'. */
3332
3333static bool
3334build_class_array_ref (gfc_se *se, tree base, tree index)
3335{
3336 tree type;
3337 tree size;
3338 tree offset;
574284e9 3339 tree decl = NULL_TREE;
c49ea23d
PT
3340 tree tmp;
3341 gfc_expr *expr = se->ss->info->expr;
3342 gfc_ref *ref;
574284e9 3343 gfc_ref *class_ref = NULL;
c49ea23d
PT
3344 gfc_typespec *ts;
3345
574284e9
AV
3346 if (se->expr && DECL_P (se->expr) && DECL_LANG_SPECIFIC (se->expr)
3347 && GFC_DECL_SAVED_DESCRIPTOR (se->expr)
3348 && GFC_CLASS_TYPE_P (TREE_TYPE (GFC_DECL_SAVED_DESCRIPTOR (se->expr))))
3349 decl = se->expr;
c49ea23d 3350 else
c49ea23d 3351 {
574284e9
AV
3352 if (expr == NULL
3353 || (expr->ts.type != BT_CLASS
a6b22eea 3354 && !gfc_is_class_array_function (expr)
574284e9
AV
3355 && !gfc_is_class_array_ref (expr, NULL)))
3356 return false;
3357
3358 if (expr->symtree && expr->symtree->n.sym->ts.type == BT_CLASS)
3359 ts = &expr->symtree->n.sym->ts;
3360 else
3361 ts = NULL;
3362
3363 for (ref = expr->ref; ref; ref = ref->next)
c49ea23d 3364 {
574284e9
AV
3365 if (ref->type == REF_COMPONENT
3366 && ref->u.c.component->ts.type == BT_CLASS
3367 && ref->next && ref->next->type == REF_COMPONENT
3368 && strcmp (ref->next->u.c.component->name, "_data") == 0
3369 && ref->next->next
3370 && ref->next->next->type == REF_ARRAY
3371 && ref->next->next->u.ar.type != AR_ELEMENT)
3372 {
3373 ts = &ref->u.c.component->ts;
3374 class_ref = ref;
3375 break;
3376 }
f04986a9 3377 }
c49ea23d 3378
574284e9
AV
3379 if (ts == NULL)
3380 return false;
3381 }
c49ea23d 3382
574284e9 3383 if (class_ref == NULL && expr && expr->symtree->n.sym->attr.function
a6b22eea
PT
3384 && expr->symtree->n.sym == expr->symtree->n.sym->result
3385 && expr->symtree->n.sym->backend_decl == current_function_decl)
bcb9f394 3386 {
bcb9f394
TB
3387 decl = gfc_get_fake_result_decl (expr->symtree->n.sym, 0);
3388 }
a6b22eea 3389 else if (expr && gfc_is_class_array_function (expr))
43a68a9d
PT
3390 {
3391 size = NULL_TREE;
3392 decl = NULL_TREE;
3393 for (tmp = base; tmp; tmp = TREE_OPERAND (tmp, 0))
3394 {
3395 tree type;
3396 type = TREE_TYPE (tmp);
3397 while (type)
3398 {
3399 if (GFC_CLASS_TYPE_P (type))
3400 decl = tmp;
3401 if (type != TYPE_CANONICAL (type))
3402 type = TYPE_CANONICAL (type);
3403 else
3404 type = NULL_TREE;
3405 }
d168c883 3406 if (VAR_P (tmp))
43a68a9d
PT
3407 break;
3408 }
3409
3410 if (decl == NULL_TREE)
3411 return false;
a6b22eea
PT
3412
3413 se->class_vptr = gfc_evaluate_now (gfc_class_vptr_get (decl), &se->pre);
43a68a9d 3414 }
bcb9f394 3415 else if (class_ref == NULL)
f3b0bb7a 3416 {
574284e9
AV
3417 if (decl == NULL_TREE)
3418 decl = expr->symtree->n.sym->backend_decl;
f3b0bb7a
AV
3419 /* For class arrays the tree containing the class is stored in
3420 GFC_DECL_SAVED_DESCRIPTOR of the sym's backend_decl.
3421 For all others it's sym's backend_decl directly. */
3422 if (DECL_LANG_SPECIFIC (decl) && GFC_DECL_SAVED_DESCRIPTOR (decl))
3423 decl = GFC_DECL_SAVED_DESCRIPTOR (decl);
3424 }
c49ea23d
PT
3425 else
3426 {
3427 /* Remove everything after the last class reference, convert the
3428 expression and then recover its tailend once more. */
3429 gfc_se tmpse;
3430 ref = class_ref->next;
3431 class_ref->next = NULL;
3432 gfc_init_se (&tmpse, NULL);
3433 gfc_conv_expr (&tmpse, expr);
574284e9 3434 gfc_add_block_to_block (&se->pre, &tmpse.pre);
c49ea23d
PT
3435 decl = tmpse.expr;
3436 class_ref->next = ref;
3437 }
3438
43a68a9d
PT
3439 if (POINTER_TYPE_P (TREE_TYPE (decl)))
3440 decl = build_fold_indirect_ref_loc (input_location, decl);
3441
3442 if (!GFC_CLASS_TYPE_P (TREE_TYPE (decl)))
3443 return false;
3444
34d9d749 3445 size = gfc_class_vtab_size_get (decl);
c49ea23d 3446
cef026ec
AV
3447 /* For unlimited polymorphic entities then _len component needs to be
3448 multiplied with the size. If no _len component is present, then
3449 gfc_class_len_or_zero_get () return a zero_node. */
3450 tmp = gfc_class_len_or_zero_get (decl);
3451 if (!integer_zerop (tmp))
3452 size = fold_build2 (MULT_EXPR, TREE_TYPE (index),
3453 fold_convert (TREE_TYPE (index), size),
3454 fold_build2 (MAX_EXPR, TREE_TYPE (index),
3455 fold_convert (TREE_TYPE (index), tmp),
3456 fold_convert (TREE_TYPE (index),
3457 integer_one_node)));
3458 else
3459 size = fold_convert (TREE_TYPE (index), size);
3460
c49ea23d
PT
3461 /* Build the address of the element. */
3462 type = TREE_TYPE (TREE_TYPE (base));
c49ea23d
PT
3463 offset = fold_build2_loc (input_location, MULT_EXPR,
3464 gfc_array_index_type,
3465 index, size);
3466 tmp = gfc_build_addr_expr (pvoid_type_node, base);
3467 tmp = fold_build_pointer_plus_loc (input_location, tmp, offset);
3468 tmp = fold_convert (build_pointer_type (type), tmp);
3469
3470 /* Return the element in the se expression. */
3471 se->expr = build_fold_indirect_ref_loc (input_location, tmp);
3472 return true;
3473}
3474
3475
6de9cd9a
DN
3476/* Build a scalarized reference to an array. */
3477
3478static void
3479gfc_conv_scalarized_array_ref (gfc_se * se, gfc_array_ref * ar)
3480{
6d63e468 3481 gfc_array_info *info;
1d6b7f39 3482 tree decl = NULL_TREE;
6de9cd9a 3483 tree index;
b120c8b2 3484 tree base;
cb4b9eae 3485 gfc_ss *ss;
f98cfd3c 3486 gfc_expr *expr;
6de9cd9a
DN
3487 int n;
3488
cb4b9eae 3489 ss = se->ss;
f98cfd3c 3490 expr = ss->info->expr;
1838afec 3491 info = &ss->info->data.array;
6de9cd9a
DN
3492 if (ar)
3493 n = se->loop->order[0];
3494 else
3495 n = 0;
3496
cb4b9eae 3497 index = conv_array_index_offset (se, ss, ss->dim[n], n, ar, info->stride0);
6de9cd9a
DN
3498 /* Add the offset for this dimension to the stored offset for all other
3499 dimensions. */
43a68a9d 3500 if (info->offset && !integer_zerop (info->offset))
94471a56
TB
3501 index = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3502 index, info->offset);
6de9cd9a 3503
b120c8b2
PT
3504 base = build_fold_indirect_ref_loc (input_location, info->data);
3505
3506 /* Use the vptr 'size' field to access the element of a class array. */
3507 if (build_class_array_ref (se, base, index))
3508 return;
3509
0d78e4aa 3510 if (get_CFI_desc (NULL, expr, &decl, ar))
94f3d11c 3511 decl = build_fold_indirect_ref_loc (input_location, decl);
d5f48c7c 3512
ff3598bc
PT
3513 /* A pointer array component can be detected from its field decl. Fix
3514 the descriptor, mark the resulting variable decl and pass it to
3515 gfc_build_array_ref. */
ba08c70a
PT
3516 if (is_pointer_array (info->descriptor)
3517 || (expr && expr->ts.deferred && info->descriptor
3518 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (info->descriptor))))
ff3598bc
PT
3519 {
3520 if (TREE_CODE (info->descriptor) == COMPONENT_REF)
4e227341 3521 decl = info->descriptor;
ff3598bc
PT
3522 else if (TREE_CODE (info->descriptor) == INDIRECT_REF)
3523 decl = TREE_OPERAND (info->descriptor, 0);
3524
3525 if (decl == NULL_TREE)
3526 decl = info->descriptor;
3527 }
3528
b120c8b2 3529 se->expr = gfc_build_array_ref (base, index, decl);
6de9cd9a
DN
3530}
3531
3532
3533/* Translate access of temporary array. */
3534
3535void
3536gfc_conv_tmp_array_ref (gfc_se * se)
3537{
a0add3be 3538 se->string_length = se->ss->info->string_length;
6de9cd9a 3539 gfc_conv_scalarized_array_ref (se, NULL);
3db5d687 3540 gfc_advance_se_ss_chain (se);
6de9cd9a
DN
3541}
3542
428f80e6
RG
3543/* Add T to the offset pair *OFFSET, *CST_OFFSET. */
3544
3545static void
3546add_to_offset (tree *cst_offset, tree *offset, tree t)
3547{
3548 if (TREE_CODE (t) == INTEGER_CST)
3549 *cst_offset = int_const_binop (PLUS_EXPR, *cst_offset, t);
3550 else
3551 {
3552 if (!integer_zerop (*offset))
3553 *offset = fold_build2_loc (input_location, PLUS_EXPR,
3554 gfc_array_index_type, *offset, t);
3555 else
3556 *offset = t;
3557 }
3558}
6de9cd9a 3559
8f75db9f
PT
3560
3561static tree
f3b0bb7a 3562build_array_ref (tree desc, tree offset, tree decl, tree vptr)
8f75db9f
PT
3563{
3564 tree tmp;
f04986a9 3565 tree type;
ff3598bc 3566 tree cdesc;
f3b0bb7a
AV
3567
3568 /* For class arrays the class declaration is stored in the saved
3569 descriptor. */
3570 if (INDIRECT_REF_P (desc)
3571 && DECL_LANG_SPECIFIC (TREE_OPERAND (desc, 0))
3572 && GFC_DECL_SAVED_DESCRIPTOR (TREE_OPERAND (desc, 0)))
ff3598bc 3573 cdesc = gfc_class_data_get (GFC_DECL_SAVED_DESCRIPTOR (
f3b0bb7a
AV
3574 TREE_OPERAND (desc, 0)));
3575 else
ff3598bc 3576 cdesc = desc;
8f75db9f 3577
f04986a9
PT
3578 /* Class container types do not always have the GFC_CLASS_TYPE_P
3579 but the canonical type does. */
ff3598bc
PT
3580 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (cdesc))
3581 && TREE_CODE (cdesc) == COMPONENT_REF)
8f75db9f 3582 {
ff3598bc 3583 type = TREE_TYPE (TREE_OPERAND (cdesc, 0));
f04986a9
PT
3584 if (TYPE_CANONICAL (type)
3585 && GFC_CLASS_TYPE_P (TYPE_CANONICAL (type)))
ff3598bc 3586 vptr = gfc_class_vptr_get (TREE_OPERAND (cdesc, 0));
8f75db9f
PT
3587 }
3588
f04986a9
PT
3589 tmp = gfc_conv_array_data (desc);
3590 tmp = build_fold_indirect_ref_loc (input_location, tmp);
f3b0bb7a 3591 tmp = gfc_build_array_ref (tmp, offset, decl, vptr);
8f75db9f
PT
3592 return tmp;
3593}
3594
3595
6de9cd9a
DN
3596/* Build an array reference. se->expr already holds the array descriptor.
3597 This should be either a variable, indirect variable reference or component
3598 reference. For arrays which do not have a descriptor, se->expr will be
3599 the data pointer.
3600 a(i, j, k) = base[offset + i * stride[0] + j * stride[1] + k * stride[2]]*/
3601
3602void
31f02c77 3603gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_expr *expr,
dd18a33b 3604 locus * where)
6de9cd9a
DN
3605{
3606 int n;
428f80e6 3607 tree offset, cst_offset;
6de9cd9a
DN
3608 tree tmp;
3609 tree stride;
ff3598bc 3610 tree decl = NULL_TREE;
6de9cd9a 3611 gfc_se indexse;
59e36b72 3612 gfc_se tmpse;
31f02c77
TB
3613 gfc_symbol * sym = expr->symtree->n.sym;
3614 char *var_name = NULL;
6de9cd9a 3615
d3a9eea2 3616 if (ar->dimen == 0)
4409de24 3617 {
56b070e3
PT
3618 gcc_assert (ar->codimen || sym->attr.select_rank_temporary
3619 || (ar->as && ar->as->corank));
b8ff4e88 3620
badd9e69
TB
3621 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se->expr)))
3622 se->expr = build_fold_indirect_ref (gfc_conv_array_data (se->expr));
3623 else
3624 {
3625 if (GFC_ARRAY_TYPE_P (TREE_TYPE (se->expr))
3626 && TREE_CODE (TREE_TYPE (se->expr)) == POINTER_TYPE)
3627 se->expr = build_fold_indirect_ref_loc (input_location, se->expr);
0c53708e 3628
1cc0e193 3629 /* Use the actual tree type and not the wrapped coarray. */
0c53708e
TB
3630 if (!se->want_pointer)
3631 se->expr = fold_convert (TYPE_MAIN_VARIANT (TREE_TYPE (se->expr)),
3632 se->expr);
badd9e69
TB
3633 }
3634
4409de24
TB
3635 return;
3636 }
d3a9eea2 3637
e7dc5b4f 3638 /* Handle scalarized references separately. */
6de9cd9a
DN
3639 if (ar->type != AR_ELEMENT)
3640 {
3641 gfc_conv_scalarized_array_ref (se, ar);
068e7338 3642 gfc_advance_se_ss_chain (se);
6de9cd9a
DN
3643 return;
3644 }
3645
31f02c77
TB
3646 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
3647 {
3648 size_t len;
3649 gfc_ref *ref;
3650
3651 len = strlen (sym->name) + 1;
3652 for (ref = expr->ref; ref; ref = ref->next)
3653 {
3654 if (ref->type == REF_ARRAY && &ref->u.ar == ar)
3655 break;
3656 if (ref->type == REF_COMPONENT)
7b11fbb8 3657 len += 2 + strlen (ref->u.c.component->name);
31f02c77
TB
3658 }
3659
3660 var_name = XALLOCAVEC (char, len);
3661 strcpy (var_name, sym->name);
3662
3663 for (ref = expr->ref; ref; ref = ref->next)
3664 {
3665 if (ref->type == REF_ARRAY && &ref->u.ar == ar)
3666 break;
3667 if (ref->type == REF_COMPONENT)
3668 {
3669 strcat (var_name, "%%");
3670 strcat (var_name, ref->u.c.component->name);
3671 }
3672 }
3673 }
3674
428f80e6
RG
3675 cst_offset = offset = gfc_index_zero_node;
3676 add_to_offset (&cst_offset, &offset, gfc_conv_array_offset (se->expr));
6de9cd9a 3677
428f80e6
RG
3678 /* Calculate the offsets from all the dimensions. Make sure to associate
3679 the final offset so that we form a chain of loop invariant summands. */
3680 for (n = ar->dimen - 1; n >= 0; n--)
6de9cd9a 3681 {
1f2959f0 3682 /* Calculate the index for this dimension. */
068e7338 3683 gfc_init_se (&indexse, se);
6de9cd9a
DN
3684 gfc_conv_expr_type (&indexse, ar->start[n], gfc_array_index_type);
3685 gfc_add_block_to_block (&se->pre, &indexse.pre);
3686
980fa45e 3687 if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS) && ! expr->no_bounds_check)
6de9cd9a
DN
3688 {
3689 /* Check array bounds. */
3690 tree cond;
dd18a33b 3691 char *msg;
6de9cd9a 3692
a90552d5
FXC
3693 /* Evaluate the indexse.expr only once. */
3694 indexse.expr = save_expr (indexse.expr);
3695
c099916d 3696 /* Lower bound. */
6de9cd9a 3697 tmp = gfc_conv_array_lbound (se->expr, n);
59e36b72
PT
3698 if (sym->attr.temporary)
3699 {
3700 gfc_init_se (&tmpse, se);
3701 gfc_conv_expr_type (&tmpse, ar->as->lower[n],
3702 gfc_array_index_type);
3703 gfc_add_block_to_block (&se->pre, &tmpse.pre);
3704 tmp = tmpse.expr;
3705 }
3706
63ee5404 3707 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
94471a56 3708 indexse.expr, tmp);
1a33dc9e
UB
3709 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
3710 "below lower bound of %%ld", n+1, var_name);
0d52899f 3711 gfc_trans_runtime_check (true, false, cond, &se->pre, where, msg,
c8fe94c7
FXC
3712 fold_convert (long_integer_type_node,
3713 indexse.expr),
3714 fold_convert (long_integer_type_node, tmp));
cede9502 3715 free (msg);
6de9cd9a 3716
c099916d
FXC
3717 /* Upper bound, but not for the last dimension of assumed-size
3718 arrays. */
b3aefde2 3719 if (n < ar->dimen - 1 || ar->as->type != AS_ASSUMED_SIZE)
c099916d
FXC
3720 {
3721 tmp = gfc_conv_array_ubound (se->expr, n);
59e36b72
PT
3722 if (sym->attr.temporary)
3723 {
3724 gfc_init_se (&tmpse, se);
3725 gfc_conv_expr_type (&tmpse, ar->as->upper[n],
3726 gfc_array_index_type);
3727 gfc_add_block_to_block (&se->pre, &tmpse.pre);
3728 tmp = tmpse.expr;
3729 }
3730
94471a56 3731 cond = fold_build2_loc (input_location, GT_EXPR,
63ee5404 3732 logical_type_node, indexse.expr, tmp);
1a33dc9e
UB
3733 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
3734 "above upper bound of %%ld", n+1, var_name);
0d52899f 3735 gfc_trans_runtime_check (true, false, cond, &se->pre, where, msg,
c8fe94c7
FXC
3736 fold_convert (long_integer_type_node,
3737 indexse.expr),
3738 fold_convert (long_integer_type_node, tmp));
cede9502 3739 free (msg);
c099916d 3740 }
6de9cd9a
DN
3741 }
3742
3743 /* Multiply the index by the stride. */
3744 stride = gfc_conv_array_stride (se->expr, n);
94471a56
TB
3745 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
3746 indexse.expr, stride);
6de9cd9a
DN
3747
3748 /* And add it to the total. */
428f80e6 3749 add_to_offset (&cst_offset, &offset, tmp);
6de9cd9a
DN
3750 }
3751
428f80e6
RG
3752 if (!integer_zerop (cst_offset))
3753 offset = fold_build2_loc (input_location, PLUS_EXPR,
3754 gfc_array_index_type, offset, cst_offset);
1d6b7f39 3755
ff3598bc
PT
3756 /* A pointer array component can be detected from its field decl. Fix
3757 the descriptor, mark the resulting variable decl and pass it to
3758 build_array_ref. */
0d78e4aa
PT
3759 if (get_CFI_desc (sym, expr, &decl, ar))
3760 decl = build_fold_indirect_ref_loc (input_location, decl);
ff3598bc
PT
3761 if (!expr->ts.deferred && !sym->attr.codimension
3762 && is_pointer_array (se->expr))
3763 {
3764 if (TREE_CODE (se->expr) == COMPONENT_REF)
4e227341 3765 decl = se->expr;
ff3598bc
PT
3766 else if (TREE_CODE (se->expr) == INDIRECT_REF)
3767 decl = TREE_OPERAND (se->expr, 0);
3768 else
3769 decl = se->expr;
3770 }
3771 else if (expr->ts.deferred
3772 || (sym->ts.type == BT_CHARACTER
3773 && sym->attr.select_type_temporary))
ba08c70a
PT
3774 {
3775 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se->expr)))
3776 {
3777 decl = se->expr;
3778 if (TREE_CODE (decl) == INDIRECT_REF)
3779 decl = TREE_OPERAND (decl, 0);
3780 }
3781 else
3782 decl = sym->backend_decl;
3783 }
ff3598bc
PT
3784 else if (sym->ts.type == BT_CLASS)
3785 decl = NULL_TREE;
3786
3787 se->expr = build_array_ref (se->expr, offset, decl, se->class_vptr);
6de9cd9a
DN
3788}
3789
3790
1190b611
MM
3791/* Add the offset corresponding to array's ARRAY_DIM dimension and loop's
3792 LOOP_DIM dimension (if any) to array's offset. */
3793
3794static void
3795add_array_offset (stmtblock_t *pblock, gfc_loopinfo *loop, gfc_ss *ss,
3796 gfc_array_ref *ar, int array_dim, int loop_dim)
3797{
3798 gfc_se se;
6d63e468 3799 gfc_array_info *info;
1190b611
MM
3800 tree stride, index;
3801
1838afec 3802 info = &ss->info->data.array;
1190b611
MM
3803
3804 gfc_init_se (&se, NULL);
3805 se.loop = loop;
3806 se.expr = info->descriptor;
3807 stride = gfc_conv_array_stride (info->descriptor, array_dim);
36e783e3 3808 index = conv_array_index_offset (&se, ss, array_dim, loop_dim, ar, stride);
1190b611
MM
3809 gfc_add_block_to_block (pblock, &se.pre);
3810
3811 info->offset = fold_build2_loc (input_location, PLUS_EXPR,
3812 gfc_array_index_type,
3813 info->offset, index);
3814 info->offset = gfc_evaluate_now (info->offset, pblock);
3815}
3816
3817
6de9cd9a
DN
3818/* Generate the code to be executed immediately before entering a
3819 scalarization loop. */
3820
3821static void
3822gfc_trans_preloop_setup (gfc_loopinfo * loop, int dim, int flag,
3823 stmtblock_t * pblock)
3824{
6de9cd9a 3825 tree stride;
1838afec 3826 gfc_ss_info *ss_info;
6d63e468 3827 gfc_array_info *info;
bcc4d4e0 3828 gfc_ss_type ss_type;
8e24054b
MM
3829 gfc_ss *ss, *pss;
3830 gfc_loopinfo *ploop;
1fb35a90 3831 gfc_array_ref *ar;
6de9cd9a
DN
3832 int i;
3833
3834 /* This code will be executed before entering the scalarization loop
3835 for this dimension. */
3836 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3837 {
1838afec
MM
3838 ss_info = ss->info;
3839
7a412892 3840 if ((ss_info->useflags & flag) == 0)
6de9cd9a
DN
3841 continue;
3842
1838afec 3843 ss_type = ss_info->type;
bcc4d4e0
MM
3844 if (ss_type != GFC_SS_SECTION
3845 && ss_type != GFC_SS_FUNCTION
3846 && ss_type != GFC_SS_CONSTRUCTOR
3847 && ss_type != GFC_SS_COMPONENT)
6de9cd9a
DN
3848 continue;
3849
1838afec 3850 info = &ss_info->data.array;
6de9cd9a 3851
cb4b9eae
MM
3852 gcc_assert (dim < ss->dimen);
3853 gcc_assert (ss->dimen == loop->dimen);
6de9cd9a 3854
1fb35a90 3855 if (info->ref)
7f6d568e 3856 ar = &info->ref->u.ar;
1fb35a90 3857 else
7f6d568e
MM
3858 ar = NULL;
3859
8e24054b
MM
3860 if (dim == loop->dimen - 1 && loop->parent != NULL)
3861 {
3862 /* If we are in the outermost dimension of this loop, the previous
3863 dimension shall be in the parent loop. */
3864 gcc_assert (ss->parent != NULL);
3865
3866 pss = ss->parent;
3867 ploop = loop->parent;
3868
3869 /* ss and ss->parent are about the same array. */
3870 gcc_assert (ss_info == pss->info);
3871 }
3872 else
3873 {
3874 ploop = loop;
3875 pss = ss;
3876 }
3877
e2b3e6bd 3878 if (dim == loop->dimen - 1)
4f9a70fa
MM
3879 i = 0;
3880 else
3881 i = dim + 1;
1fb35a90 3882
7f6d568e 3883 /* For the time being, there is no loop reordering. */
8e24054b
MM
3884 gcc_assert (i == ploop->order[i]);
3885 i = ploop->order[i];
1fb35a90 3886
8e24054b 3887 if (dim == loop->dimen - 1 && loop->parent == NULL)
6de9cd9a 3888 {
8e24054b
MM
3889 stride = gfc_conv_array_stride (info->descriptor,
3890 innermost_ss (ss)->dim[i]);
bee1695c
MM
3891
3892 /* Calculate the stride of the innermost loop. Hopefully this will
3893 allow the backend optimizers to do their stuff more effectively.
3894 */
3895 info->stride0 = gfc_evaluate_now (stride, pblock);
3896
6de9cd9a
DN
3897 /* For the outermost loop calculate the offset due to any
3898 elemental dimensions. It will have been initialized with the
3899 base offset of the array. */
3900 if (info->ref)
3901 {
1fb35a90 3902 for (i = 0; i < ar->dimen; i++)
6de9cd9a 3903 {
1fb35a90 3904 if (ar->dimen_type[i] != DIMEN_ELEMENT)
6de9cd9a
DN
3905 continue;
3906
1190b611 3907 add_array_offset (pblock, loop, ss, ar, i, /* unused */ -1);
6de9cd9a 3908 }
6de9cd9a 3909 }
6de9cd9a
DN
3910 }
3911 else
1190b611 3912 /* Add the offset for the previous loop dimension. */
8e24054b 3913 add_array_offset (pblock, ploop, ss, ar, pss->dim[i], i);
6de9cd9a 3914
e7dc5b4f 3915 /* Remember this offset for the second loop. */
8e24054b 3916 if (dim == loop->temp_dim - 1 && loop->parent == NULL)
6de9cd9a
DN
3917 info->saved_offset = info->offset;
3918 }
3919}
3920
3921
3922/* Start a scalarized expression. Creates a scope and declares loop
3923 variables. */
3924
3925void
3926gfc_start_scalarized_body (gfc_loopinfo * loop, stmtblock_t * pbody)
3927{
3928 int dim;
3929 int n;
3930 int flags;
3931
6e45f57b 3932 gcc_assert (!loop->array_parameter);
6de9cd9a 3933
c6d741b8 3934 for (dim = loop->dimen - 1; dim >= 0; dim--)
6de9cd9a
DN
3935 {
3936 n = loop->order[dim];
3937
3938 gfc_start_block (&loop->code[n]);
3939
3940 /* Create the loop variable. */
3941 loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "S");
3942
3943 if (dim < loop->temp_dim)
3944 flags = 3;
3945 else
3946 flags = 1;
3947 /* Calculate values that will be constant within this loop. */
3948 gfc_trans_preloop_setup (loop, dim, flags, &loop->code[n]);
3949 }
3950 gfc_start_block (pbody);
3951}
3952
3953
3954/* Generates the actual loop code for a scalarization loop. */
3955
80927a56 3956void
6de9cd9a
DN
3957gfc_trans_scalarized_loop_end (gfc_loopinfo * loop, int n,
3958 stmtblock_t * pbody)
3959{
3960 stmtblock_t block;
3961 tree cond;
3962 tree tmp;
3963 tree loopbody;
3964 tree exit_label;
34d01e1d
VL
3965 tree stmt;
3966 tree init;
3967 tree incr;
6de9cd9a 3968
57bf3072
JJ
3969 if ((ompws_flags & (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_WS
3970 | OMPWS_SCALARIZER_BODY))
34d01e1d
VL
3971 == (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_WS)
3972 && n == loop->dimen - 1)
3973 {
3974 /* We create an OMP_FOR construct for the outermost scalarized loop. */
3975 init = make_tree_vec (1);
3976 cond = make_tree_vec (1);
3977 incr = make_tree_vec (1);
3978
3979 /* Cycle statement is implemented with a goto. Exit statement must not
3980 be present for this loop. */
3981 exit_label = gfc_build_label_decl (NULL_TREE);
3982 TREE_USED (exit_label) = 1;
3983
3984 /* Label for cycle statements (if needed). */
3985 tmp = build1_v (LABEL_EXPR, exit_label);
3986 gfc_add_expr_to_block (pbody, tmp);
3987
3988 stmt = make_node (OMP_FOR);
3989
3990 TREE_TYPE (stmt) = void_type_node;
3991 OMP_FOR_BODY (stmt) = loopbody = gfc_finish_block (pbody);
3992
c2255bc4
AH
3993 OMP_FOR_CLAUSES (stmt) = build_omp_clause (input_location,
3994 OMP_CLAUSE_SCHEDULE);
34d01e1d
VL
3995 OMP_CLAUSE_SCHEDULE_KIND (OMP_FOR_CLAUSES (stmt))
3996 = OMP_CLAUSE_SCHEDULE_STATIC;
3997 if (ompws_flags & OMPWS_NOWAIT)
3998 OMP_CLAUSE_CHAIN (OMP_FOR_CLAUSES (stmt))
c2255bc4 3999 = build_omp_clause (input_location, OMP_CLAUSE_NOWAIT);
34d01e1d
VL
4000
4001 /* Initialize the loopvar. */
4002 TREE_VEC_ELT (init, 0) = build2_v (MODIFY_EXPR, loop->loopvar[n],
4003 loop->from[n]);
4004 OMP_FOR_INIT (stmt) = init;
4005 /* The exit condition. */
5d44e5c8 4006 TREE_VEC_ELT (cond, 0) = build2_loc (input_location, LE_EXPR,
63ee5404 4007 logical_type_node,
5d44e5c8
TB
4008 loop->loopvar[n], loop->to[n]);
4009 SET_EXPR_LOCATION (TREE_VEC_ELT (cond, 0), input_location);
34d01e1d
VL
4010 OMP_FOR_COND (stmt) = cond;
4011 /* Increment the loopvar. */
5d44e5c8
TB
4012 tmp = build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4013 loop->loopvar[n], gfc_index_one_node);
94471a56 4014 TREE_VEC_ELT (incr, 0) = fold_build2_loc (input_location, MODIFY_EXPR,
34d01e1d
VL
4015 void_type_node, loop->loopvar[n], tmp);
4016 OMP_FOR_INCR (stmt) = incr;
4017
4018 ompws_flags &= ~OMPWS_CURR_SINGLEUNIT;
4019 gfc_add_expr_to_block (&loop->code[n], stmt);
4020 }
4021 else
4022 {
3d03ead0
PT
4023 bool reverse_loop = (loop->reverse[n] == GFC_REVERSE_SET)
4024 && (loop->temp_ss == NULL);
4025
34d01e1d 4026 loopbody = gfc_finish_block (pbody);
6de9cd9a 4027
3d03ead0 4028 if (reverse_loop)
fab27f52 4029 std::swap (loop->from[n], loop->to[n]);
3d03ead0 4030
34d01e1d 4031 /* Initialize the loopvar. */
80927a56
JJ
4032 if (loop->loopvar[n] != loop->from[n])
4033 gfc_add_modify (&loop->code[n], loop->loopvar[n], loop->from[n]);
6de9cd9a 4034
34d01e1d 4035 exit_label = gfc_build_label_decl (NULL_TREE);
6de9cd9a 4036
34d01e1d
VL
4037 /* Generate the loop body. */
4038 gfc_init_block (&block);
6de9cd9a 4039
34d01e1d 4040 /* The exit condition. */
94471a56 4041 cond = fold_build2_loc (input_location, reverse_loop ? LT_EXPR : GT_EXPR,
63ee5404 4042 logical_type_node, loop->loopvar[n], loop->to[n]);
34d01e1d
VL
4043 tmp = build1_v (GOTO_EXPR, exit_label);
4044 TREE_USED (exit_label) = 1;
c2255bc4 4045 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
34d01e1d 4046 gfc_add_expr_to_block (&block, tmp);
6de9cd9a 4047
34d01e1d
VL
4048 /* The main body. */
4049 gfc_add_expr_to_block (&block, loopbody);
6de9cd9a 4050
34d01e1d 4051 /* Increment the loopvar. */
94471a56
TB
4052 tmp = fold_build2_loc (input_location,
4053 reverse_loop ? MINUS_EXPR : PLUS_EXPR,
4054 gfc_array_index_type, loop->loopvar[n],
4055 gfc_index_one_node);
3d03ead0 4056
34d01e1d 4057 gfc_add_modify (&block, loop->loopvar[n], tmp);
6de9cd9a 4058
34d01e1d
VL
4059 /* Build the loop. */
4060 tmp = gfc_finish_block (&block);
4061 tmp = build1_v (LOOP_EXPR, tmp);
4062 gfc_add_expr_to_block (&loop->code[n], tmp);
4063
4064 /* Add the exit label. */
4065 tmp = build1_v (LABEL_EXPR, exit_label);
4066 gfc_add_expr_to_block (&loop->code[n], tmp);
4067 }
6de9cd9a 4068
6de9cd9a
DN
4069}
4070
4071
4072/* Finishes and generates the loops for a scalarized expression. */
4073
4074void
4075gfc_trans_scalarizing_loops (gfc_loopinfo * loop, stmtblock_t * body)
4076{
4077 int dim;
4078 int n;
4079 gfc_ss *ss;
4080 stmtblock_t *pblock;
4081 tree tmp;
4082
4083 pblock = body;
4084 /* Generate the loops. */
c6d741b8 4085 for (dim = 0; dim < loop->dimen; dim++)
6de9cd9a
DN
4086 {
4087 n = loop->order[dim];
4088 gfc_trans_scalarized_loop_end (loop, n, pblock);
4089 loop->loopvar[n] = NULL_TREE;
4090 pblock = &loop->code[n];
4091 }
4092
4093 tmp = gfc_finish_block (pblock);
4094 gfc_add_expr_to_block (&loop->pre, tmp);
4095
4096 /* Clear all the used flags. */
39abb03c 4097 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
2eace29a
MM
4098 if (ss->parent == NULL)
4099 ss->info->useflags = 0;
6de9cd9a
DN
4100}
4101
4102
4103/* Finish the main body of a scalarized expression, and start the secondary
4104 copying body. */
4105
4106void
4107gfc_trans_scalarized_loop_boundary (gfc_loopinfo * loop, stmtblock_t * body)
4108{
4109 int dim;
4110 int n;
4111 stmtblock_t *pblock;
4112 gfc_ss *ss;
4113
4114 pblock = body;
4115 /* We finish as many loops as are used by the temporary. */
4116 for (dim = 0; dim < loop->temp_dim - 1; dim++)
4117 {
4118 n = loop->order[dim];
4119 gfc_trans_scalarized_loop_end (loop, n, pblock);
4120 loop->loopvar[n] = NULL_TREE;
4121 pblock = &loop->code[n];
4122 }
4123
4124 /* We don't want to finish the outermost loop entirely. */
4125 n = loop->order[loop->temp_dim - 1];
4126 gfc_trans_scalarized_loop_end (loop, n, pblock);
4127
4128 /* Restore the initial offsets. */
4129 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
4130 {
bcc4d4e0 4131 gfc_ss_type ss_type;
1838afec
MM
4132 gfc_ss_info *ss_info;
4133
4134 ss_info = ss->info;
bcc4d4e0 4135
7a412892 4136 if ((ss_info->useflags & 2) == 0)
6de9cd9a
DN
4137 continue;
4138
1838afec 4139 ss_type = ss_info->type;
bcc4d4e0
MM
4140 if (ss_type != GFC_SS_SECTION
4141 && ss_type != GFC_SS_FUNCTION
4142 && ss_type != GFC_SS_CONSTRUCTOR
4143 && ss_type != GFC_SS_COMPONENT)
6de9cd9a
DN
4144 continue;
4145
1838afec 4146 ss_info->data.array.offset = ss_info->data.array.saved_offset;
6de9cd9a
DN
4147 }
4148
4149 /* Restart all the inner loops we just finished. */
4150 for (dim = loop->temp_dim - 2; dim >= 0; dim--)
4151 {
4152 n = loop->order[dim];
4153
4154 gfc_start_block (&loop->code[n]);
4155
4156 loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "Q");
4157
4158 gfc_trans_preloop_setup (loop, dim, 2, &loop->code[n]);
4159 }
4160
4161 /* Start a block for the secondary copying code. */
4162 gfc_start_block (body);
4163}
4164
4165
287b3dd2
MM
4166/* Precalculate (either lower or upper) bound of an array section.
4167 BLOCK: Block in which the (pre)calculation code will go.
4168 BOUNDS[DIM]: Where the bound value will be stored once evaluated.
4169 VALUES[DIM]: Specified bound (NULL <=> unspecified).
4170 DESC: Array descriptor from which the bound will be picked if unspecified
4171 (either lower or upper bound according to LBOUND). */
4172
4173static void
4174evaluate_bound (stmtblock_t *block, tree *bounds, gfc_expr ** values,
97561cdc 4175 tree desc, int dim, bool lbound, bool deferred)
287b3dd2
MM
4176{
4177 gfc_se se;
4178 gfc_expr * input_val = values[dim];
4179 tree *output = &bounds[dim];
4180
4181
4182 if (input_val)
4183 {
4184 /* Specified section bound. */
4185 gfc_init_se (&se, NULL);
4186 gfc_conv_expr_type (&se, input_val, gfc_array_index_type);
4187 gfc_add_block_to_block (block, &se.pre);
4188 *output = se.expr;
4189 }
591bb5e4 4190 else if (deferred && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
97561cdc
AV
4191 {
4192 /* The gfc_conv_array_lbound () routine returns a constant zero for
591bb5e4 4193 deferred length arrays, which in the scalarizer wreaks havoc, when
97561cdc
AV
4194 copying to a (newly allocated) one-based array.
4195 Keep returning the actual result in sync for both bounds. */
4196 *output = lbound ? gfc_conv_descriptor_lbound_get (desc,
4197 gfc_rank_cst[dim]):
4198 gfc_conv_descriptor_ubound_get (desc,
4199 gfc_rank_cst[dim]);
4200 }
287b3dd2
MM
4201 else
4202 {
4203 /* No specific bound specified so use the bound of the array. */
4204 *output = lbound ? gfc_conv_array_lbound (desc, dim) :
4205 gfc_conv_array_ubound (desc, dim);
4206 }
4207 *output = gfc_evaluate_now (*output, block);
4208}
4209
4210
6de9cd9a
DN
4211/* Calculate the lower bound of an array section. */
4212
4213static void
cf664522 4214gfc_conv_section_startstride (stmtblock_t * block, gfc_ss * ss, int dim)
6de9cd9a 4215{
a3935ffc 4216 gfc_expr *stride = NULL;
6de9cd9a
DN
4217 tree desc;
4218 gfc_se se;
6d63e468 4219 gfc_array_info *info;
3ca39858 4220 gfc_array_ref *ar;
6de9cd9a 4221
bcc4d4e0 4222 gcc_assert (ss->info->type == GFC_SS_SECTION);
6de9cd9a 4223
1838afec 4224 info = &ss->info->data.array;
3ca39858 4225 ar = &info->ref->u.ar;
6de9cd9a 4226
3ca39858 4227 if (ar->dimen_type[dim] == DIMEN_VECTOR)
6de9cd9a 4228 {
7a70c12d 4229 /* We use a zero-based index to access the vector. */
9157ccb2 4230 info->start[dim] = gfc_index_zero_node;
9157ccb2 4231 info->end[dim] = NULL;
065c6f9d 4232 info->stride[dim] = gfc_index_one_node;
7a70c12d 4233 return;
6de9cd9a
DN
4234 }
4235
b0ac6998
MM
4236 gcc_assert (ar->dimen_type[dim] == DIMEN_RANGE
4237 || ar->dimen_type[dim] == DIMEN_THIS_IMAGE);
7a70c12d 4238 desc = info->descriptor;
065c6f9d 4239 stride = ar->stride[dim];
6de9cd9a 4240
97561cdc 4241
6de9cd9a
DN
4242 /* Calculate the start of the range. For vector subscripts this will
4243 be the range of the vector. */
97561cdc
AV
4244 evaluate_bound (block, info->start, ar->start, desc, dim, true,
4245 ar->as->type == AS_DEFERRED);
6de9cd9a 4246
8424e0d8
PT
4247 /* Similarly calculate the end. Although this is not used in the
4248 scalarizer, it is needed when checking bounds and where the end
4249 is an expression with side-effects. */
97561cdc
AV
4250 evaluate_bound (block, info->end, ar->end, desc, dim, false,
4251 ar->as->type == AS_DEFERRED);
4252
8424e0d8 4253
6de9cd9a 4254 /* Calculate the stride. */
065c6f9d 4255 if (stride == NULL)
9157ccb2 4256 info->stride[dim] = gfc_index_one_node;
065c6f9d 4257 else
6de9cd9a
DN
4258 {
4259 gfc_init_se (&se, NULL);
4260 gfc_conv_expr_type (&se, stride, gfc_array_index_type);
cf664522
MM
4261 gfc_add_block_to_block (block, &se.pre);
4262 info->stride[dim] = gfc_evaluate_now (se.expr, block);
6de9cd9a
DN
4263 }
4264}
4265
4266
4267/* Calculates the range start and stride for a SS chain. Also gets the
4268 descriptor and data pointer. The range of vector subscripts is the size
4269 of the vector. Array bounds are also checked. */
4270
4271void
4272gfc_conv_ss_startstride (gfc_loopinfo * loop)
4273{
4274 int n;
4275 tree tmp;
4276 gfc_ss *ss;
6de9cd9a
DN
4277 tree desc;
4278
1f65468a
MM
4279 gfc_loopinfo * const outer_loop = outermost_loop (loop);
4280
6de9cd9a
DN
4281 loop->dimen = 0;
4282 /* Determine the rank of the loop. */
199c387d 4283 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
6de9cd9a 4284 {
bcc4d4e0 4285 switch (ss->info->type)
6de9cd9a
DN
4286 {
4287 case GFC_SS_SECTION:
4288 case GFC_SS_CONSTRUCTOR:
4289 case GFC_SS_FUNCTION:
e9cfef64 4290 case GFC_SS_COMPONENT:
cb4b9eae 4291 loop->dimen = ss->dimen;
199c387d 4292 goto done;
6de9cd9a 4293
f5f701ad
PT
4294 /* As usual, lbound and ubound are exceptions!. */
4295 case GFC_SS_INTRINSIC:
f98cfd3c 4296 switch (ss->info->expr->value.function.isym->id)
f5f701ad
PT
4297 {
4298 case GFC_ISYM_LBOUND:
4299 case GFC_ISYM_UBOUND:
a3935ffc
TB
4300 case GFC_ISYM_LCOBOUND:
4301 case GFC_ISYM_UCOBOUND:
4302 case GFC_ISYM_THIS_IMAGE:
cb4b9eae 4303 loop->dimen = ss->dimen;
199c387d 4304 goto done;
f5f701ad
PT
4305
4306 default:
4307 break;
4308 }
4309
6de9cd9a
DN
4310 default:
4311 break;
4312 }
4313 }
4314
ca39e6f2
FXC
4315 /* We should have determined the rank of the expression by now. If
4316 not, that's bad news. */
199c387d 4317 gcc_unreachable ();
6de9cd9a 4318
199c387d 4319done:
13413760 4320 /* Loop over all the SS in the chain. */
6de9cd9a
DN
4321 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
4322 {
f98cfd3c 4323 gfc_ss_info *ss_info;
08dcec61 4324 gfc_array_info *info;
f98cfd3c 4325 gfc_expr *expr;
08dcec61 4326
f98cfd3c
MM
4327 ss_info = ss->info;
4328 expr = ss_info->expr;
1838afec 4329 info = &ss_info->data.array;
08dcec61 4330
f98cfd3c
MM
4331 if (expr && expr->shape && !info->shape)
4332 info->shape = expr->shape;
e9cfef64 4333
f98cfd3c 4334 switch (ss_info->type)
6de9cd9a
DN
4335 {
4336 case GFC_SS_SECTION:
30ae600f
MM
4337 /* Get the descriptor for the array. If it is a cross loops array,
4338 we got the descriptor already in the outermost loop. */
4339 if (ss->parent == NULL)
1f65468a
MM
4340 gfc_conv_ss_descriptor (&outer_loop->pre, ss,
4341 !loop->array_parameter);
6de9cd9a 4342
cb4b9eae 4343 for (n = 0; n < ss->dimen; n++)
1f65468a 4344 gfc_conv_section_startstride (&outer_loop->pre, ss, ss->dim[n]);
6de9cd9a
DN
4345 break;
4346
f5f701ad 4347 case GFC_SS_INTRINSIC:
f98cfd3c 4348 switch (expr->value.function.isym->id)
f5f701ad
PT
4349 {
4350 /* Fall through to supply start and stride. */
4351 case GFC_ISYM_LBOUND:
4352 case GFC_ISYM_UBOUND:
e5a24119
MM
4353 {
4354 gfc_expr *arg;
4355
4356 /* This is the variant without DIM=... */
4357 gcc_assert (expr->value.function.actual->next->expr == NULL);
4358
4359 arg = expr->value.function.actual->expr;
4360 if (arg->rank == -1)
4361 {
4362 gfc_se se;
4363 tree rank, tmp;
4364
4365 /* The rank (hence the return value's shape) is unknown,
4366 we have to retrieve it. */
4367 gfc_init_se (&se, NULL);
4368 se.descriptor_only = 1;
4369 gfc_conv_expr (&se, arg);
4370 /* This is a bare variable, so there is no preliminary
4371 or cleanup code. */
4372 gcc_assert (se.pre.head == NULL_TREE
4373 && se.post.head == NULL_TREE);
4374 rank = gfc_conv_descriptor_rank (se.expr);
4375 tmp = fold_build2_loc (input_location, MINUS_EXPR,
4376 gfc_array_index_type,
4377 fold_convert (gfc_array_index_type,
4378 rank),
4379 gfc_index_one_node);
1f65468a 4380 info->end[0] = gfc_evaluate_now (tmp, &outer_loop->pre);
e5a24119
MM
4381 info->start[0] = gfc_index_zero_node;
4382 info->stride[0] = gfc_index_one_node;
4383 continue;
4384 }
4385 /* Otherwise fall through GFC_SS_FUNCTION. */
81fea426 4386 gcc_fallthrough ();
e5a24119 4387 }
a3935ffc
TB
4388 case GFC_ISYM_LCOBOUND:
4389 case GFC_ISYM_UCOBOUND:
4390 case GFC_ISYM_THIS_IMAGE:
f5f701ad 4391 break;
a3935ffc 4392
f5f701ad
PT
4393 default:
4394 continue;
4395 }
4396
191816a3 4397 /* FALLTHRU */
6de9cd9a
DN
4398 case GFC_SS_CONSTRUCTOR:
4399 case GFC_SS_FUNCTION:
cb4b9eae 4400 for (n = 0; n < ss->dimen; n++)
6de9cd9a 4401 {
cb4b9eae 4402 int dim = ss->dim[n];
ae9054ba 4403
1838afec
MM
4404 info->start[dim] = gfc_index_zero_node;
4405 info->end[dim] = gfc_index_zero_node;
4406 info->stride[dim] = gfc_index_one_node;
6de9cd9a
DN
4407 }
4408 break;
4409
4410 default:
4411 break;
4412 }
4413 }
4414
d1ecece9 4415 /* The rest is just runtime bounds checking. */
d3d3011f 4416 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
6de9cd9a
DN
4417 {
4418 stmtblock_t block;
ef31fe62 4419 tree lbound, ubound;
6de9cd9a
DN
4420 tree end;
4421 tree size[GFC_MAX_DIMENSIONS];
c6ec7cc6 4422 tree stride_pos, stride_neg, non_zerosized, tmp2, tmp3;
6d63e468 4423 gfc_array_info *info;
dd18a33b 4424 char *msg;
6de9cd9a
DN
4425 int dim;
4426
4427 gfc_start_block (&block);
4428
6de9cd9a
DN
4429 for (n = 0; n < loop->dimen; n++)
4430 size[n] = NULL_TREE;
4431
4432 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
4433 {
ba4698e1 4434 stmtblock_t inner;
f98cfd3c
MM
4435 gfc_ss_info *ss_info;
4436 gfc_expr *expr;
4437 locus *expr_loc;
4438 const char *expr_name;
ba4698e1 4439
f98cfd3c
MM
4440 ss_info = ss->info;
4441 if (ss_info->type != GFC_SS_SECTION)
6de9cd9a
DN
4442 continue;
4443
597553ab 4444 /* Catch allocatable lhs in f2003. */
d1ecece9 4445 if (flag_realloc_lhs && ss->no_bounds_check)
597553ab
PT
4446 continue;
4447
f98cfd3c
MM
4448 expr = ss_info->expr;
4449 expr_loc = &expr->where;
4450 expr_name = expr->symtree->name;
4451
ba4698e1
FXC
4452 gfc_start_block (&inner);
4453
6de9cd9a 4454 /* TODO: range checking for mapped dimensions. */
1838afec 4455 info = &ss_info->data.array;
6de9cd9a 4456
7a70c12d
RS
4457 /* This code only checks ranges. Elemental and vector
4458 dimensions are checked later. */
6de9cd9a
DN
4459 for (n = 0; n < loop->dimen; n++)
4460 {
c099916d
FXC
4461 bool check_upper;
4462
cb4b9eae 4463 dim = ss->dim[n];
7a70c12d
RS
4464 if (info->ref->u.ar.dimen_type[dim] != DIMEN_RANGE)
4465 continue;
c099916d 4466
1954a27b 4467 if (dim == info->ref->u.ar.dimen - 1
b3aefde2 4468 && info->ref->u.ar.as->type == AS_ASSUMED_SIZE)
c099916d
FXC
4469 check_upper = false;
4470 else
4471 check_upper = true;
ef31fe62
FXC
4472
4473 /* Zero stride is not allowed. */
63ee5404 4474 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
94471a56 4475 info->stride[dim], gfc_index_zero_node);
1a33dc9e
UB
4476 msg = xasprintf ("Zero stride is not allowed, for dimension %d "
4477 "of array '%s'", dim + 1, expr_name);
0d52899f 4478 gfc_trans_runtime_check (true, false, tmp, &inner,
f98cfd3c 4479 expr_loc, msg);
cede9502 4480 free (msg);
ef31fe62 4481
1838afec 4482 desc = info->descriptor;
c099916d
FXC
4483
4484 /* This is the run-time equivalent of resolve.c's
9157ccb2
MM
4485 check_dimension(). The logical is more readable there
4486 than it is here, with all the trees. */
c099916d 4487 lbound = gfc_conv_array_lbound (desc, dim);
9157ccb2 4488 end = info->end[dim];
c099916d
FXC
4489 if (check_upper)
4490 ubound = gfc_conv_array_ubound (desc, dim);
4491 else
4492 ubound = NULL;
4493
ef31fe62 4494 /* non_zerosized is true when the selected range is not
9157ccb2 4495 empty. */
94471a56 4496 stride_pos = fold_build2_loc (input_location, GT_EXPR,
63ee5404 4497 logical_type_node, info->stride[dim],
94471a56 4498 gfc_index_zero_node);
63ee5404 4499 tmp = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
94471a56
TB
4500 info->start[dim], end);
4501 stride_pos = fold_build2_loc (input_location, TRUTH_AND_EXPR,
63ee5404 4502 logical_type_node, stride_pos, tmp);
94471a56
TB
4503
4504 stride_neg = fold_build2_loc (input_location, LT_EXPR,
63ee5404 4505 logical_type_node,
94471a56 4506 info->stride[dim], gfc_index_zero_node);
63ee5404 4507 tmp = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
94471a56
TB
4508 info->start[dim], end);
4509 stride_neg = fold_build2_loc (input_location, TRUTH_AND_EXPR,
63ee5404 4510 logical_type_node,
94471a56
TB
4511 stride_neg, tmp);
4512 non_zerosized = fold_build2_loc (input_location, TRUTH_OR_EXPR,
63ee5404 4513 logical_type_node,
94471a56 4514 stride_pos, stride_neg);
ef31fe62
FXC
4515
4516 /* Check the start of the range against the lower and upper
f04986a9
PT
4517 bounds of the array, if the range is not empty.
4518 If upper bound is present, include both bounds in the
c6ec7cc6 4519 error message. */
c099916d
FXC
4520 if (check_upper)
4521 {
94471a56 4522 tmp = fold_build2_loc (input_location, LT_EXPR,
63ee5404 4523 logical_type_node,
94471a56
TB
4524 info->start[dim], lbound);
4525 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
63ee5404 4526 logical_type_node,
94471a56
TB
4527 non_zerosized, tmp);
4528 tmp2 = fold_build2_loc (input_location, GT_EXPR,
63ee5404 4529 logical_type_node,
94471a56
TB
4530 info->start[dim], ubound);
4531 tmp2 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
63ee5404 4532 logical_type_node,
94471a56 4533 non_zerosized, tmp2);
1a33dc9e
UB
4534 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
4535 "outside of expected range (%%ld:%%ld)",
4536 dim + 1, expr_name);
9157ccb2 4537 gfc_trans_runtime_check (true, false, tmp, &inner,
f98cfd3c 4538 expr_loc, msg,
9157ccb2
MM
4539 fold_convert (long_integer_type_node, info->start[dim]),
4540 fold_convert (long_integer_type_node, lbound),
c6ec7cc6 4541 fold_convert (long_integer_type_node, ubound));
9157ccb2 4542 gfc_trans_runtime_check (true, false, tmp2, &inner,
f98cfd3c 4543 expr_loc, msg,
9157ccb2
MM
4544 fold_convert (long_integer_type_node, info->start[dim]),
4545 fold_convert (long_integer_type_node, lbound),
c6ec7cc6 4546 fold_convert (long_integer_type_node, ubound));
cede9502 4547 free (msg);
c099916d 4548 }
c6ec7cc6
DW
4549 else
4550 {
94471a56 4551 tmp = fold_build2_loc (input_location, LT_EXPR,
63ee5404 4552 logical_type_node,
94471a56
TB
4553 info->start[dim], lbound);
4554 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
63ee5404 4555 logical_type_node, non_zerosized, tmp);
1a33dc9e
UB
4556 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
4557 "below lower bound of %%ld",
4558 dim + 1, expr_name);
9157ccb2 4559 gfc_trans_runtime_check (true, false, tmp, &inner,
f98cfd3c 4560 expr_loc, msg,
9157ccb2 4561 fold_convert (long_integer_type_node, info->start[dim]),
c6ec7cc6 4562 fold_convert (long_integer_type_node, lbound));
cede9502 4563 free (msg);
c6ec7cc6 4564 }
f04986a9 4565
ef31fe62
FXC
4566 /* Compute the last element of the range, which is not
4567 necessarily "end" (think 0:5:3, which doesn't contain 5)
4568 and check it against both lower and upper bounds. */
c6ec7cc6 4569
94471a56
TB
4570 tmp = fold_build2_loc (input_location, MINUS_EXPR,
4571 gfc_array_index_type, end,
4572 info->start[dim]);
4573 tmp = fold_build2_loc (input_location, TRUNC_MOD_EXPR,
4574 gfc_array_index_type, tmp,
4575 info->stride[dim]);
4576 tmp = fold_build2_loc (input_location, MINUS_EXPR,
4577 gfc_array_index_type, end, tmp);
4578 tmp2 = fold_build2_loc (input_location, LT_EXPR,
63ee5404 4579 logical_type_node, tmp, lbound);
94471a56 4580 tmp2 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
63ee5404 4581 logical_type_node, non_zerosized, tmp2);
c099916d
FXC
4582 if (check_upper)
4583 {
94471a56 4584 tmp3 = fold_build2_loc (input_location, GT_EXPR,
63ee5404 4585 logical_type_node, tmp, ubound);
94471a56 4586 tmp3 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
63ee5404 4587 logical_type_node, non_zerosized, tmp3);
1a33dc9e
UB
4588 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
4589 "outside of expected range (%%ld:%%ld)",
4590 dim + 1, expr_name);
c6ec7cc6 4591 gfc_trans_runtime_check (true, false, tmp2, &inner,
f98cfd3c 4592 expr_loc, msg,
c6ec7cc6 4593 fold_convert (long_integer_type_node, tmp),
f04986a9 4594 fold_convert (long_integer_type_node, ubound),
c6ec7cc6
DW
4595 fold_convert (long_integer_type_node, lbound));
4596 gfc_trans_runtime_check (true, false, tmp3, &inner,
f98cfd3c 4597 expr_loc, msg,
c6ec7cc6 4598 fold_convert (long_integer_type_node, tmp),
f04986a9 4599 fold_convert (long_integer_type_node, ubound),
c6ec7cc6 4600 fold_convert (long_integer_type_node, lbound));
cede9502 4601 free (msg);
c099916d 4602 }
c6ec7cc6
DW
4603 else
4604 {
1a33dc9e
UB
4605 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
4606 "below lower bound of %%ld",
4607 dim + 1, expr_name);
c6ec7cc6 4608 gfc_trans_runtime_check (true, false, tmp2, &inner,
f98cfd3c 4609 expr_loc, msg,
c6ec7cc6
DW
4610 fold_convert (long_integer_type_node, tmp),
4611 fold_convert (long_integer_type_node, lbound));
cede9502 4612 free (msg);
c6ec7cc6 4613 }
9157ccb2 4614
6de9cd9a 4615 /* Check the section sizes match. */
94471a56
TB
4616 tmp = fold_build2_loc (input_location, MINUS_EXPR,
4617 gfc_array_index_type, end,
4618 info->start[dim]);
4619 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR,
4620 gfc_array_index_type, tmp,
4621 info->stride[dim]);
4622 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4623 gfc_array_index_type,
4624 gfc_index_one_node, tmp);
4625 tmp = fold_build2_loc (input_location, MAX_EXPR,
4626 gfc_array_index_type, tmp,
4627 build_int_cst (gfc_array_index_type, 0));
6de9cd9a 4628 /* We remember the size of the first section, and check all the
9157ccb2 4629 others against this. */
6de9cd9a
DN
4630 if (size[n])
4631 {
94471a56 4632 tmp3 = fold_build2_loc (input_location, NE_EXPR,
63ee5404 4633 logical_type_node, tmp, size[n]);
1a33dc9e
UB
4634 msg = xasprintf ("Array bound mismatch for dimension %d "
4635 "of array '%s' (%%ld/%%ld)",
4636 dim + 1, expr_name);
6c559604 4637
0d52899f 4638 gfc_trans_runtime_check (true, false, tmp3, &inner,
f98cfd3c 4639 expr_loc, msg,
c8fe94c7
FXC
4640 fold_convert (long_integer_type_node, tmp),
4641 fold_convert (long_integer_type_node, size[n]));
6c559604 4642
cede9502 4643 free (msg);
6de9cd9a
DN
4644 }
4645 else
ba4698e1 4646 size[n] = gfc_evaluate_now (tmp, &inner);
6de9cd9a 4647 }
ba4698e1
FXC
4648
4649 tmp = gfc_finish_block (&inner);
4650
4651 /* For optional arguments, only check bounds if the argument is
4652 present. */
f98cfd3c
MM
4653 if (expr->symtree->n.sym->attr.optional
4654 || expr->symtree->n.sym->attr.not_always_present)
ba4698e1 4655 tmp = build3_v (COND_EXPR,
f98cfd3c 4656 gfc_conv_expr_present (expr->symtree->n.sym),
c2255bc4 4657 tmp, build_empty_stmt (input_location));
ba4698e1
FXC
4658
4659 gfc_add_expr_to_block (&block, tmp);
4660
6de9cd9a 4661 }
6de9cd9a
DN
4662
4663 tmp = gfc_finish_block (&block);
1f65468a 4664 gfc_add_expr_to_block (&outer_loop->pre, tmp);
6de9cd9a 4665 }
30ae600f
MM
4666
4667 for (loop = loop->nested; loop; loop = loop->next)
4668 gfc_conv_ss_startstride (loop);
6de9cd9a
DN
4669}
4670
ecb3baaa
TK
4671/* Return true if both symbols could refer to the same data object. Does
4672 not take account of aliasing due to equivalence statements. */
4673
4674static int
4675symbols_could_alias (gfc_symbol *lsym, gfc_symbol *rsym, bool lsym_pointer,
4676 bool lsym_target, bool rsym_pointer, bool rsym_target)
4677{
4678 /* Aliasing isn't possible if the symbols have different base types. */
4679 if (gfc_compare_types (&lsym->ts, &rsym->ts) == 0)
4680 return 0;
4681
4682 /* Pointers can point to other pointers and target objects. */
4683
4684 if ((lsym_pointer && (rsym_pointer || rsym_target))
4685 || (rsym_pointer && (lsym_pointer || lsym_target)))
4686 return 1;
4687
4688 /* Special case: Argument association, cf. F90 12.4.1.6, F2003 12.4.1.7
4689 and F2008 12.5.2.13 items 3b and 4b. The pointer case (a) is already
4690 checked above. */
4691 if (lsym_target && rsym_target
4692 && ((lsym->attr.dummy && !lsym->attr.contiguous
4693 && (!lsym->attr.dimension || lsym->as->type == AS_ASSUMED_SHAPE))
4694 || (rsym->attr.dummy && !rsym->attr.contiguous
4695 && (!rsym->attr.dimension
4696 || rsym->as->type == AS_ASSUMED_SHAPE))))
4697 return 1;
4698
4699 return 0;
4700}
4701
6de9cd9a 4702
13795658 4703/* Return true if the two SS could be aliased, i.e. both point to the same data
6de9cd9a
DN
4704 object. */
4705/* TODO: resolve aliases based on frontend expressions. */
4706
4707static int
4708gfc_could_be_alias (gfc_ss * lss, gfc_ss * rss)
4709{
4710 gfc_ref *lref;
4711 gfc_ref *rref;
f98cfd3c 4712 gfc_expr *lexpr, *rexpr;
6de9cd9a
DN
4713 gfc_symbol *lsym;
4714 gfc_symbol *rsym;
ecb3baaa 4715 bool lsym_pointer, lsym_target, rsym_pointer, rsym_target;
6de9cd9a 4716
f98cfd3c
MM
4717 lexpr = lss->info->expr;
4718 rexpr = rss->info->expr;
4719
4720 lsym = lexpr->symtree->n.sym;
4721 rsym = rexpr->symtree->n.sym;
ecb3baaa
TK
4722
4723 lsym_pointer = lsym->attr.pointer;
4724 lsym_target = lsym->attr.target;
4725 rsym_pointer = rsym->attr.pointer;
4726 rsym_target = rsym->attr.target;
4727
4728 if (symbols_could_alias (lsym, rsym, lsym_pointer, lsym_target,
4729 rsym_pointer, rsym_target))
6de9cd9a
DN
4730 return 1;
4731
272cec5d
TK
4732 if (rsym->ts.type != BT_DERIVED && rsym->ts.type != BT_CLASS
4733 && lsym->ts.type != BT_DERIVED && lsym->ts.type != BT_CLASS)
6de9cd9a
DN
4734 return 0;
4735
13413760 4736 /* For derived types we must check all the component types. We can ignore
6de9cd9a
DN
4737 array references as these will have the same base type as the previous
4738 component ref. */
1838afec 4739 for (lref = lexpr->ref; lref != lss->info->data.array.ref; lref = lref->next)
6de9cd9a
DN
4740 {
4741 if (lref->type != REF_COMPONENT)
4742 continue;
4743
ecb3baaa
TK
4744 lsym_pointer = lsym_pointer || lref->u.c.sym->attr.pointer;
4745 lsym_target = lsym_target || lref->u.c.sym->attr.target;
4746
4747 if (symbols_could_alias (lref->u.c.sym, rsym, lsym_pointer, lsym_target,
4748 rsym_pointer, rsym_target))
6de9cd9a
DN
4749 return 1;
4750
ecb3baaa
TK
4751 if ((lsym_pointer && (rsym_pointer || rsym_target))
4752 || (rsym_pointer && (lsym_pointer || lsym_target)))
4753 {
4754 if (gfc_compare_types (&lref->u.c.component->ts,
4755 &rsym->ts))
4756 return 1;
4757 }
4758
1838afec 4759 for (rref = rexpr->ref; rref != rss->info->data.array.ref;
6de9cd9a
DN
4760 rref = rref->next)
4761 {
4762 if (rref->type != REF_COMPONENT)
4763 continue;
4764
ecb3baaa
TK
4765 rsym_pointer = rsym_pointer || rref->u.c.sym->attr.pointer;
4766 rsym_target = lsym_target || rref->u.c.sym->attr.target;
4767
4768 if (symbols_could_alias (lref->u.c.sym, rref->u.c.sym,
4769 lsym_pointer, lsym_target,
4770 rsym_pointer, rsym_target))
6de9cd9a 4771 return 1;
ecb3baaa
TK
4772
4773 if ((lsym_pointer && (rsym_pointer || rsym_target))
4774 || (rsym_pointer && (lsym_pointer || lsym_target)))
4775 {
4776 if (gfc_compare_types (&lref->u.c.component->ts,
4777 &rref->u.c.sym->ts))
4778 return 1;
4779 if (gfc_compare_types (&lref->u.c.sym->ts,
4780 &rref->u.c.component->ts))
4781 return 1;
4782 if (gfc_compare_types (&lref->u.c.component->ts,
4783 &rref->u.c.component->ts))
4784 return 1;
4785 }
6de9cd9a
DN
4786 }
4787 }
4788
ecb3baaa
TK
4789 lsym_pointer = lsym->attr.pointer;
4790 lsym_target = lsym->attr.target;
ecb3baaa 4791
1838afec 4792 for (rref = rexpr->ref; rref != rss->info->data.array.ref; rref = rref->next)
6de9cd9a
DN
4793 {
4794 if (rref->type != REF_COMPONENT)
4795 break;
4796
ecb3baaa
TK
4797 rsym_pointer = rsym_pointer || rref->u.c.sym->attr.pointer;
4798 rsym_target = lsym_target || rref->u.c.sym->attr.target;
4799
4800 if (symbols_could_alias (rref->u.c.sym, lsym,
4801 lsym_pointer, lsym_target,
4802 rsym_pointer, rsym_target))
6de9cd9a 4803 return 1;
ecb3baaa
TK
4804
4805 if ((lsym_pointer && (rsym_pointer || rsym_target))
4806 || (rsym_pointer && (lsym_pointer || lsym_target)))
4807 {
4808 if (gfc_compare_types (&lsym->ts, &rref->u.c.component->ts))
4809 return 1;
4810 }
6de9cd9a
DN
4811 }
4812
4813 return 0;
4814}
4815
4816
4817/* Resolve array data dependencies. Creates a temporary if required. */
4818/* TODO: Calc dependencies with gfc_expr rather than gfc_ss, and move to
4819 dependency.c. */
4820
4821void
4822gfc_conv_resolve_dependencies (gfc_loopinfo * loop, gfc_ss * dest,
4823 gfc_ss * rss)
4824{
4825 gfc_ss *ss;
4826 gfc_ref *lref;
4827 gfc_ref *rref;
711d7c23 4828 gfc_ss_info *ss_info;
f98cfd3c
MM
4829 gfc_expr *dest_expr;
4830 gfc_expr *ss_expr;
6de9cd9a 4831 int nDepend = 0;
af804603 4832 int i, j;
6de9cd9a
DN
4833
4834 loop->temp_ss = NULL;
f98cfd3c 4835 dest_expr = dest->info->expr;
6de9cd9a
DN
4836
4837 for (ss = rss; ss != gfc_ss_terminator; ss = ss->next)
4838 {
711d7c23
MM
4839 ss_info = ss->info;
4840 ss_expr = ss_info->expr;
343ab492 4841
711d7c23 4842 if (ss_info->array_outer_dependency)
30c931de
PT
4843 {
4844 nDepend = 1;
4845 break;
4846 }
4847
711d7c23 4848 if (ss_info->type != GFC_SS_SECTION)
343ab492 4849 {
203c7ebf 4850 if (flag_realloc_lhs
343ab492
PT
4851 && dest_expr != ss_expr
4852 && gfc_is_reallocatable_lhs (dest_expr)
4853 && ss_expr->rank)
4854 nDepend = gfc_check_dependency (dest_expr, ss_expr, true);
6de9cd9a 4855
502b97e4
TK
4856 /* Check for cases like c(:)(1:2) = c(2)(2:3) */
4857 if (!nDepend && dest_expr->rank > 0
4858 && dest_expr->ts.type == BT_CHARACTER
4859 && ss_expr->expr_type == EXPR_VARIABLE)
1b961de9 4860
502b97e4
TK
4861 nDepend = gfc_check_dependency (dest_expr, ss_expr, false);
4862
711d7c23
MM
4863 if (ss_info->type == GFC_SS_REFERENCE
4864 && gfc_check_dependency (dest_expr, ss_expr, false))
4865 ss_info->data.scalar.needs_temporary = 1;
4866
213c3b7b
TK
4867 if (nDepend)
4868 break;
4869 else
4870 continue;
343ab492 4871 }
f98cfd3c
MM
4872
4873 if (dest_expr->symtree->n.sym != ss_expr->symtree->n.sym)
6de9cd9a 4874 {
7d1f1e61 4875 if (gfc_could_be_alias (dest, ss)
f98cfd3c 4876 || gfc_are_equivalenced_arrays (dest_expr, ss_expr))
7d1f1e61
PT
4877 {
4878 nDepend = 1;
4879 break;
4880 }
6de9cd9a 4881 }
7d1f1e61 4882 else
6de9cd9a 4883 {
f98cfd3c
MM
4884 lref = dest_expr->ref;
4885 rref = ss_expr->ref;
6de9cd9a 4886
3d03ead0
PT
4887 nDepend = gfc_dep_resolver (lref, rref, &loop->reverse[0]);
4888
4f06d65b
PT
4889 if (nDepend == 1)
4890 break;
af804603 4891
cb4b9eae
MM
4892 for (i = 0; i < dest->dimen; i++)
4893 for (j = 0; j < ss->dimen; j++)
af804603 4894 if (i != j
cb4b9eae 4895 && dest->dim[i] == ss->dim[j])
af804603
MM
4896 {
4897 /* If we don't access array elements in the same order,
4898 there is a dependency. */
4899 nDepend = 1;
4900 goto temporary;
4901 }
6de9cd9a
DN
4902#if 0
4903 /* TODO : loop shifting. */
4904 if (nDepend == 1)
4905 {
4906 /* Mark the dimensions for LOOP SHIFTING */
4907 for (n = 0; n < loop->dimen; n++)
4908 {
4909 int dim = dest->data.info.dim[n];
4910
4911 if (lref->u.ar.dimen_type[dim] == DIMEN_VECTOR)
4912 depends[n] = 2;
4913 else if (! gfc_is_same_range (&lref->u.ar,
4914 &rref->u.ar, dim, 0))
4915 depends[n] = 1;
4916 }
4917
13413760 4918 /* Put all the dimensions with dependencies in the
6de9cd9a
DN
4919 innermost loops. */
4920 dim = 0;
4921 for (n = 0; n < loop->dimen; n++)
4922 {
6e45f57b 4923 gcc_assert (loop->order[n] == n);
6de9cd9a
DN
4924 if (depends[n])
4925 loop->order[dim++] = n;
4926 }
6de9cd9a
DN
4927 for (n = 0; n < loop->dimen; n++)
4928 {
4929 if (! depends[n])
4930 loop->order[dim++] = n;
4931 }
4932
6e45f57b 4933 gcc_assert (dim == loop->dimen);
6de9cd9a
DN
4934 break;
4935 }
4936#endif
4937 }
4938 }
4939
af804603
MM
4940temporary:
4941
6de9cd9a
DN
4942 if (nDepend == 1)
4943 {
f98cfd3c 4944 tree base_type = gfc_typenode_for_spec (&dest_expr->ts);
eca18fb4
AP
4945 if (GFC_ARRAY_TYPE_P (base_type)
4946 || GFC_DESCRIPTOR_TYPE_P (base_type))
4947 base_type = gfc_get_element_type (base_type);
a0add3be 4948 loop->temp_ss = gfc_get_temp_ss (base_type, dest->info->string_length,
a1ae4f43 4949 loop->dimen);
6de9cd9a
DN
4950 gfc_add_ss_to_loop (loop, loop->temp_ss);
4951 }
4952 else
4953 loop->temp_ss = NULL;
4954}
4955
4956
1d9370e9
MM
4957/* Browse through each array's information from the scalarizer and set the loop
4958 bounds according to the "best" one (per dimension), i.e. the one which
eea58adb 4959 provides the most information (constant bounds, shape, etc.). */
6de9cd9a 4960
1d9370e9
MM
4961static void
4962set_loop_bounds (gfc_loopinfo *loop)
6de9cd9a 4963{
9157ccb2 4964 int n, dim, spec_dim;
6d63e468
MM
4965 gfc_array_info *info;
4966 gfc_array_info *specinfo;
1d9370e9 4967 gfc_ss *ss;
6de9cd9a 4968 tree tmp;
1d9370e9 4969 gfc_ss **loopspec;
ec25720b 4970 bool dynamic[GFC_MAX_DIMENSIONS];
6de9cd9a
DN
4971 mpz_t *cshape;
4972 mpz_t i;
478ad83d 4973 bool nonoptional_arr;
6de9cd9a 4974
1f65468a
MM
4975 gfc_loopinfo * const outer_loop = outermost_loop (loop);
4976
1d9370e9
MM
4977 loopspec = loop->specloop;
4978
6de9cd9a 4979 mpz_init (i);
c6d741b8 4980 for (n = 0; n < loop->dimen; n++)
6de9cd9a
DN
4981 {
4982 loopspec[n] = NULL;
ec25720b 4983 dynamic[n] = false;
478ad83d
TB
4984
4985 /* If there are both optional and nonoptional array arguments, scalarize
4986 over the nonoptional; otherwise, it does not matter as then all
4987 (optional) arrays have to be present per F2008, 125.2.12p3(6). */
4988
4989 nonoptional_arr = false;
4990
4991 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
4992 if (ss->info->type != GFC_SS_SCALAR && ss->info->type != GFC_SS_TEMP
4993 && ss->info->type != GFC_SS_REFERENCE && !ss->info->can_be_null_ref)
502af491
PCC
4994 {
4995 nonoptional_arr = true;
4996 break;
4997 }
478ad83d 4998
6de9cd9a 4999 /* We use one SS term, and use that to determine the bounds of the
9157ccb2 5000 loop for this dimension. We try to pick the simplest term. */
6de9cd9a
DN
5001 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
5002 {
596a9579
MM
5003 gfc_ss_type ss_type;
5004
bcc4d4e0 5005 ss_type = ss->info->type;
596a9579
MM
5006 if (ss_type == GFC_SS_SCALAR
5007 || ss_type == GFC_SS_TEMP
478ad83d
TB
5008 || ss_type == GFC_SS_REFERENCE
5009 || (ss->info->can_be_null_ref && nonoptional_arr))
9157ccb2
MM
5010 continue;
5011
1838afec 5012 info = &ss->info->data.array;
cb4b9eae 5013 dim = ss->dim[n];
9157ccb2
MM
5014
5015 if (loopspec[n] != NULL)
5016 {
1838afec 5017 specinfo = &loopspec[n]->info->data.array;
cb4b9eae 5018 spec_dim = loopspec[n]->dim[n];
9157ccb2
MM
5019 }
5020 else
5021 {
eea58adb 5022 /* Silence uninitialized warnings. */
9157ccb2
MM
5023 specinfo = NULL;
5024 spec_dim = 0;
5025 }
5026
08dcec61 5027 if (info->shape)
6de9cd9a 5028 {
08dcec61 5029 gcc_assert (info->shape[dim]);
6de9cd9a 5030 /* The frontend has worked out the size for us. */
9157ccb2 5031 if (!loopspec[n]
08dcec61 5032 || !specinfo->shape
9157ccb2 5033 || !integer_zerop (specinfo->start[spec_dim]))
45bc572c
MM
5034 /* Prefer zero-based descriptors if possible. */
5035 loopspec[n] = ss;
6de9cd9a
DN
5036 continue;
5037 }
5038
bcc4d4e0 5039 if (ss_type == GFC_SS_CONSTRUCTOR)
6de9cd9a 5040 {
b7e75771 5041 gfc_constructor_base base;
e9cfef64 5042 /* An unknown size constructor will always be rank one.
40f20186 5043 Higher rank constructors will either have known shape,
e9cfef64 5044 or still be wrapped in a call to reshape. */
6e45f57b 5045 gcc_assert (loop->dimen == 1);
ec25720b
RS
5046
5047 /* Always prefer to use the constructor bounds if the size
5048 can be determined at compile time. Prefer not to otherwise,
5049 since the general case involves realloc, and it's better to
5050 avoid that overhead if possible. */
f98cfd3c 5051 base = ss->info->expr->value.constructor;
b7e75771 5052 dynamic[n] = gfc_get_array_constructor_size (&i, base);
ec25720b
RS
5053 if (!dynamic[n] || !loopspec[n])
5054 loopspec[n] = ss;
6de9cd9a
DN
5055 continue;
5056 }
5057
597553ab
PT
5058 /* Avoid using an allocatable lhs in an assignment, since
5059 there might be a reallocation coming. */
5060 if (loopspec[n] && ss->is_alloc_lhs)
5061 continue;
5062
9157ccb2 5063 if (!loopspec[n])
ec25720b 5064 loopspec[n] = ss;
6de9cd9a 5065 /* Criteria for choosing a loop specifier (most important first):
ec25720b 5066 doesn't need realloc
6de9cd9a
DN
5067 stride of one
5068 known stride
5069 known lower bound
5070 known upper bound
5071 */
96b2ffe1 5072 else if (loopspec[n]->info->type == GFC_SS_CONSTRUCTOR && dynamic[n])
6de9cd9a 5073 loopspec[n] = ss;
9157ccb2
MM
5074 else if (integer_onep (info->stride[dim])
5075 && !integer_onep (specinfo->stride[spec_dim]))
ec25720b 5076 loopspec[n] = ss;
9157ccb2
MM
5077 else if (INTEGER_CST_P (info->stride[dim])
5078 && !INTEGER_CST_P (specinfo->stride[spec_dim]))
ec25720b 5079 loopspec[n] = ss;
9157ccb2 5080 else if (INTEGER_CST_P (info->start[dim])
96b2ffe1
MM
5081 && !INTEGER_CST_P (specinfo->start[spec_dim])
5082 && integer_onep (info->stride[dim])
8f96b844 5083 == integer_onep (specinfo->stride[spec_dim])
96b2ffe1 5084 && INTEGER_CST_P (info->stride[dim])
8f96b844 5085 == INTEGER_CST_P (specinfo->stride[spec_dim]))
ec25720b
RS
5086 loopspec[n] = ss;
5087 /* We don't work out the upper bound.
5088 else if (INTEGER_CST_P (info->finish[n])
5089 && ! INTEGER_CST_P (specinfo->finish[n]))
5090 loopspec[n] = ss; */
6de9cd9a
DN
5091 }
5092
ca39e6f2
FXC
5093 /* We should have found the scalarization loop specifier. If not,
5094 that's bad news. */
5095 gcc_assert (loopspec[n]);
6de9cd9a 5096
1838afec 5097 info = &loopspec[n]->info->data.array;
cb4b9eae 5098 dim = loopspec[n]->dim[n];
6de9cd9a
DN
5099
5100 /* Set the extents of this range. */
08dcec61 5101 cshape = info->shape;
c6d741b8 5102 if (cshape && INTEGER_CST_P (info->start[dim])
9157ccb2 5103 && INTEGER_CST_P (info->stride[dim]))
6de9cd9a 5104 {
9157ccb2 5105 loop->from[n] = info->start[dim];
d6b3a0d7 5106 mpz_set (i, cshape[get_array_ref_dim_for_loop_dim (loopspec[n], n)]);
6de9cd9a
DN
5107 mpz_sub_ui (i, i, 1);
5108 /* To = from + (size - 1) * stride. */
5109 tmp = gfc_conv_mpz_to_tree (i, gfc_index_integer_kind);
9157ccb2 5110 if (!integer_onep (info->stride[dim]))
94471a56
TB
5111 tmp = fold_build2_loc (input_location, MULT_EXPR,
5112 gfc_array_index_type, tmp,
5113 info->stride[dim]);
5114 loop->to[n] = fold_build2_loc (input_location, PLUS_EXPR,
5115 gfc_array_index_type,
5116 loop->from[n], tmp);
6de9cd9a
DN
5117 }
5118 else
5119 {
9157ccb2 5120 loop->from[n] = info->start[dim];
bcc4d4e0 5121 switch (loopspec[n]->info->type)
6de9cd9a
DN
5122 {
5123 case GFC_SS_CONSTRUCTOR:
ec25720b
RS
5124 /* The upper bound is calculated when we expand the
5125 constructor. */
5126 gcc_assert (loop->to[n] == NULL_TREE);
6de9cd9a
DN
5127 break;
5128
5129 case GFC_SS_SECTION:
993ac38b
PT
5130 /* Use the end expression if it exists and is not constant,
5131 so that it is only evaluated once. */
9157ccb2 5132 loop->to[n] = info->end[dim];
6de9cd9a
DN
5133 break;
5134
859b6600 5135 case GFC_SS_FUNCTION:
fc90a8f2 5136 /* The loop bound will be set when we generate the call. */
859b6600
MM
5137 gcc_assert (loop->to[n] == NULL_TREE);
5138 break;
fc90a8f2 5139
e5a24119
MM
5140 case GFC_SS_INTRINSIC:
5141 {
5142 gfc_expr *expr = loopspec[n]->info->expr;
5143
5144 /* The {l,u}bound of an assumed rank. */
5145 gcc_assert ((expr->value.function.isym->id == GFC_ISYM_LBOUND
5146 || expr->value.function.isym->id == GFC_ISYM_UBOUND)
5147 && expr->value.function.actual->next->expr == NULL
5148 && expr->value.function.actual->expr->rank == -1);
5149
5150 loop->to[n] = info->end[dim];
5151 break;
5152 }
5153
276515e6
PT
5154 case GFC_SS_COMPONENT:
5155 {
5156 if (info->end[dim] != NULL_TREE)
5157 {
5158 loop->to[n] = info->end[dim];
5159 break;
5160 }
5161 else
5162 gcc_unreachable ();
5163 }
5164
6de9cd9a 5165 default:
6e45f57b 5166 gcc_unreachable ();
6de9cd9a
DN
5167 }
5168 }
5169
5170 /* Transform everything so we have a simple incrementing variable. */
3120f511 5171 if (integer_onep (info->stride[dim]))
9157ccb2 5172 info->delta[dim] = gfc_index_zero_node;
3120f511 5173 else
6de9cd9a
DN
5174 {
5175 /* Set the delta for this section. */
1f65468a 5176 info->delta[dim] = gfc_evaluate_now (loop->from[n], &outer_loop->pre);
6de9cd9a
DN
5177 /* Number of iterations is (end - start + step) / step.
5178 with start = 0, this simplifies to
5179 last = end / step;
5180 for (i = 0; i<=last; i++){...}; */
94471a56
TB
5181 tmp = fold_build2_loc (input_location, MINUS_EXPR,
5182 gfc_array_index_type, loop->to[n],
5183 loop->from[n]);
5184 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR,
5185 gfc_array_index_type, tmp, info->stride[dim]);
5186 tmp = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
5187 tmp, build_int_cst (gfc_array_index_type, -1));
1f65468a 5188 loop->to[n] = gfc_evaluate_now (tmp, &outer_loop->pre);
6de9cd9a 5189 /* Make the loop variable start at 0. */
7ab92584 5190 loop->from[n] = gfc_index_zero_node;
6de9cd9a
DN
5191 }
5192 }
1d9370e9 5193 mpz_clear (i);
30ae600f
MM
5194
5195 for (loop = loop->nested; loop; loop = loop->next)
5196 set_loop_bounds (loop);
1d9370e9
MM
5197}
5198
5199
1d9370e9
MM
5200/* Initialize the scalarization loop. Creates the loop variables. Determines
5201 the range of the loop variables. Creates a temporary if required.
5202 Also generates code for scalar expressions which have been
5203 moved outside the loop. */
5204
5205void
5206gfc_conv_loop_setup (gfc_loopinfo * loop, locus * where)
5207{
5208 gfc_ss *tmp_ss;
5209 tree tmp;
1d9370e9
MM
5210
5211 set_loop_bounds (loop);
6de9cd9a 5212
fc90a8f2
PB
5213 /* Add all the scalar code that can be taken out of the loops.
5214 This may include calculating the loop bounds, so do it before
5215 allocating the temporary. */
bdfd2ff0 5216 gfc_add_loop_ss_code (loop, loop->ss, false, where);
fc90a8f2 5217
cb4b9eae 5218 tmp_ss = loop->temp_ss;
6de9cd9a 5219 /* If we want a temporary then create it. */
cb4b9eae 5220 if (tmp_ss != NULL)
6de9cd9a 5221 {
bcc4d4e0
MM
5222 gfc_ss_info *tmp_ss_info;
5223
5224 tmp_ss_info = tmp_ss->info;
5225 gcc_assert (tmp_ss_info->type == GFC_SS_TEMP);
4616ef9b 5226 gcc_assert (loop->parent == NULL);
640670c7
PT
5227
5228 /* Make absolutely sure that this is a complete type. */
a0add3be 5229 if (tmp_ss_info->string_length)
961e73ac 5230 tmp_ss_info->data.temp.type
d393bbd7 5231 = gfc_get_character_type_len_for_eltype
961e73ac 5232 (TREE_TYPE (tmp_ss_info->data.temp.type),
a0add3be 5233 tmp_ss_info->string_length);
640670c7 5234
961e73ac 5235 tmp = tmp_ss_info->data.temp.type;
1838afec 5236 memset (&tmp_ss_info->data.array, 0, sizeof (gfc_array_info));
bcc4d4e0 5237 tmp_ss_info->type = GFC_SS_SECTION;
ffc3bba4 5238
cb4b9eae 5239 gcc_assert (tmp_ss->dimen != 0);
ffc3bba4 5240
41645793
MM
5241 gfc_trans_create_temp_array (&loop->pre, &loop->post, tmp_ss, tmp,
5242 NULL_TREE, false, true, false, where);
6de9cd9a
DN
5243 }
5244
6de9cd9a
DN
5245 /* For array parameters we don't have loop variables, so don't calculate the
5246 translations. */
121c82c9
MM
5247 if (!loop->array_parameter)
5248 gfc_set_delta (loop);
1d9370e9
MM
5249}
5250
5251
5252/* Calculates how to transform from loop variables to array indices for each
5253 array: once loop bounds are chosen, sets the difference (DELTA field) between
5254 loop bounds and array reference bounds, for each array info. */
5255
121c82c9
MM
5256void
5257gfc_set_delta (gfc_loopinfo *loop)
1d9370e9
MM
5258{
5259 gfc_ss *ss, **loopspec;
5260 gfc_array_info *info;
5261 tree tmp;
5262 int n, dim;
5263
1f65468a
MM
5264 gfc_loopinfo * const outer_loop = outermost_loop (loop);
5265
1d9370e9
MM
5266 loopspec = loop->specloop;
5267
6de9cd9a
DN
5268 /* Calculate the translation from loop variables to array indices. */
5269 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
5270 {
bcc4d4e0 5271 gfc_ss_type ss_type;
45bc572c 5272
bcc4d4e0
MM
5273 ss_type = ss->info->type;
5274 if (ss_type != GFC_SS_SECTION
5275 && ss_type != GFC_SS_COMPONENT
5276 && ss_type != GFC_SS_CONSTRUCTOR)
6de9cd9a
DN
5277 continue;
5278
1838afec 5279 info = &ss->info->data.array;
6de9cd9a 5280
cb4b9eae 5281 for (n = 0; n < ss->dimen; n++)
6de9cd9a 5282 {
e9cfef64 5283 /* If we are specifying the range the delta is already set. */
6de9cd9a
DN
5284 if (loopspec[n] != ss)
5285 {
cb4b9eae 5286 dim = ss->dim[n];
9157ccb2 5287
6de9cd9a 5288 /* Calculate the offset relative to the loop variable.
9157ccb2 5289 First multiply by the stride. */
c96111c0 5290 tmp = loop->from[n];
9157ccb2 5291 if (!integer_onep (info->stride[dim]))
94471a56
TB
5292 tmp = fold_build2_loc (input_location, MULT_EXPR,
5293 gfc_array_index_type,
5294 tmp, info->stride[dim]);
6de9cd9a
DN
5295
5296 /* Then subtract this from our starting value. */
94471a56
TB
5297 tmp = fold_build2_loc (input_location, MINUS_EXPR,
5298 gfc_array_index_type,
5299 info->start[dim], tmp);
6de9cd9a 5300
1f65468a 5301 info->delta[dim] = gfc_evaluate_now (tmp, &outer_loop->pre);
6de9cd9a
DN
5302 }
5303 }
5304 }
30ae600f
MM
5305
5306 for (loop = loop->nested; loop; loop = loop->next)
121c82c9 5307 gfc_set_delta (loop);
6de9cd9a
DN
5308}
5309
5310
99d821c0
DK
5311/* Calculate the size of a given array dimension from the bounds. This
5312 is simply (ubound - lbound + 1) if this expression is positive
5313 or 0 if it is negative (pick either one if it is zero). Optionally
5314 (if or_expr is present) OR the (expression != 0) condition to it. */
5315
5316tree
5317gfc_conv_array_extent_dim (tree lbound, tree ubound, tree* or_expr)
5318{
5319 tree res;
5320 tree cond;
5321
5322 /* Calculate (ubound - lbound + 1). */
94471a56
TB
5323 res = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
5324 ubound, lbound);
5325 res = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type, res,
5326 gfc_index_one_node);
99d821c0
DK
5327
5328 /* Check whether the size for this dimension is negative. */
63ee5404 5329 cond = fold_build2_loc (input_location, LE_EXPR, logical_type_node, res,
94471a56
TB
5330 gfc_index_zero_node);
5331 res = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type, cond,
5332 gfc_index_zero_node, res);
99d821c0
DK
5333
5334 /* Build OR expression. */
5335 if (or_expr)
94471a56 5336 *or_expr = fold_build2_loc (input_location, TRUTH_OR_EXPR,
63ee5404 5337 logical_type_node, *or_expr, cond);
99d821c0
DK
5338
5339 return res;
5340}
5341
5342
5343/* For an array descriptor, get the total number of elements. This is just
155e5d5f 5344 the product of the extents along from_dim to to_dim. */
99d821c0 5345
155e5d5f
TB
5346static tree
5347gfc_conv_descriptor_size_1 (tree desc, int from_dim, int to_dim)
99d821c0
DK
5348{
5349 tree res;
5350 int dim;
5351
5352 res = gfc_index_one_node;
5353
155e5d5f 5354 for (dim = from_dim; dim < to_dim; ++dim)
99d821c0
DK
5355 {
5356 tree lbound;
5357 tree ubound;
5358 tree extent;
5359
5360 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[dim]);
5361 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[dim]);
5362
5363 extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
94471a56
TB
5364 res = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
5365 res, extent);
99d821c0
DK
5366 }
5367
5368 return res;
5369}
5370
5371
155e5d5f
TB
5372/* Full size of an array. */
5373
5374tree
5375gfc_conv_descriptor_size (tree desc, int rank)
5376{
5377 return gfc_conv_descriptor_size_1 (desc, 0, rank);
5378}
5379
5380
5381/* Size of a coarray for all dimensions but the last. */
5382
5383tree
5384gfc_conv_descriptor_cosize (tree desc, int rank, int corank)
5385{
5386 return gfc_conv_descriptor_size_1 (desc, rank, rank + corank - 1);
5387}
5388
5389
1ab3acf4
JB
5390/* Fills in an array descriptor, and returns the size of the array.
5391 The size will be a simple_val, ie a variable or a constant. Also
5392 calculates the offset of the base. The pointer argument overflow,
5393 which should be of integer type, will increase in value if overflow
5394 occurs during the size calculation. Returns the size of the array.
6de9cd9a
DN
5395 {
5396 stride = 1;
5397 offset = 0;
5398 for (n = 0; n < rank; n++)
5399 {
99d821c0
DK
5400 a.lbound[n] = specified_lower_bound;
5401 offset = offset + a.lbond[n] * stride;
5402 size = 1 - lbound;
5403 a.ubound[n] = specified_upper_bound;
5404 a.stride[n] = stride;
4f13e17f 5405 size = size >= 0 ? ubound + size : 0; //size = ubound + 1 - lbound
1ab3acf4 5406 overflow += size == 0 ? 0: (MAX/size < stride ? 1: 0);
99d821c0 5407 stride = stride * size;
6de9cd9a 5408 }
badd9e69
TB
5409 for (n = rank; n < rank+corank; n++)
5410 (Set lcobound/ucobound as above.)
1ab3acf4 5411 element_size = sizeof (array element);
badd9e69
TB
5412 if (!rank)
5413 return element_size
1ab3acf4
JB
5414 stride = (size_t) stride;
5415 overflow += element_size == 0 ? 0: (MAX/element_size < stride ? 1: 0);
5416 stride = stride * element_size;
6de9cd9a
DN
5417 return (stride);
5418 } */
5419/*GCC ARRAYS*/
5420
5421static tree
f33beee9 5422gfc_array_init_size (tree descriptor, int rank, int corank, tree * poffset,
4f13e17f 5423 gfc_expr ** lower, gfc_expr ** upper, stmtblock_t * pblock,
c49ea23d 5424 stmtblock_t * descriptor_block, tree * overflow,
1792349b 5425 tree expr3_elem_size, tree *nelems, gfc_expr *expr3,
da46c08e
PT
5426 tree expr3_desc, bool e3_has_nodescriptor, gfc_expr *expr,
5427 tree *element_size)
6de9cd9a
DN
5428{
5429 tree type;
5430 tree tmp;
5431 tree size;
5432 tree offset;
5433 tree stride;
3c86fb4e
TK
5434 tree or_expr;
5435 tree thencase;
5436 tree elsecase;
79cae72e 5437 tree cond;
3c86fb4e
TK
5438 tree var;
5439 stmtblock_t thenblock;
5440 stmtblock_t elseblock;
6de9cd9a
DN
5441 gfc_expr *ubound;
5442 gfc_se se;
5443 int n;
5444
5445 type = TREE_TYPE (descriptor);
5446
7ab92584
SB
5447 stride = gfc_index_one_node;
5448 offset = gfc_index_zero_node;
6de9cd9a 5449
3c9f5092
AV
5450 /* Set the dtype before the alloc, because registration of coarrays needs
5451 it initialized. */
d168c883
JJ
5452 if (expr->ts.type == BT_CHARACTER
5453 && expr->ts.deferred
5454 && VAR_P (expr->ts.u.cl->backend_decl))
afbc5ae8
PT
5455 {
5456 type = gfc_typenode_for_spec (&expr->ts);
5457 tmp = gfc_conv_descriptor_dtype (descriptor);
3c9f5092 5458 gfc_add_modify (pblock, tmp, gfc_get_dtype_rank_type (rank, type));
afbc5ae8 5459 }
9d44426f
PT
5460 else if (expr->ts.type == BT_CHARACTER
5461 && expr->ts.deferred
5462 && TREE_CODE (descriptor) == COMPONENT_REF)
5463 {
5464 /* Deferred character components have their string length tucked away
5465 in a hidden field of the derived type. Obtain that and use it to
5466 set the dtype. The charlen backend decl is zero because the field
5467 type is zero length. */
5468 gfc_ref *ref;
5469 tmp = NULL_TREE;
5470 for (ref = expr->ref; ref; ref = ref->next)
5471 if (ref->type == REF_COMPONENT
5472 && gfc_deferred_strlen (ref->u.c.component, &tmp))
5473 break;
5474 gcc_assert (tmp != NULL_TREE);
5475 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (tmp),
5476 TREE_OPERAND (descriptor, 0), tmp, NULL_TREE);
5477 tmp = fold_convert (gfc_charlen_type_node, tmp);
5478 type = gfc_get_character_type_len (expr->ts.kind, tmp);
5479 tmp = gfc_conv_descriptor_dtype (descriptor);
5480 gfc_add_modify (pblock, tmp, gfc_get_dtype_rank_type (rank, type));
5481 }
afbc5ae8
PT
5482 else
5483 {
950ab3f1
PT
5484 tmp = gfc_conv_descriptor_dtype (descriptor);
5485 gfc_add_modify (pblock, tmp, gfc_get_dtype (type));
afbc5ae8 5486 }
6de9cd9a 5487
63ee5404 5488 or_expr = logical_false_node;
3c86fb4e 5489
6de9cd9a
DN
5490 for (n = 0; n < rank; n++)
5491 {
99d821c0
DK
5492 tree conv_lbound;
5493 tree conv_ubound;
5494
6de9cd9a 5495 /* We have 3 possibilities for determining the size of the array:
99d821c0
DK
5496 lower == NULL => lbound = 1, ubound = upper[n]
5497 upper[n] = NULL => lbound = 1, ubound = lower[n]
5498 upper[n] != NULL => lbound = lower[n], ubound = upper[n] */
6de9cd9a
DN
5499 ubound = upper[n];
5500
5501 /* Set lower bound. */
5502 gfc_init_se (&se, NULL);
1792349b
AV
5503 if (expr3_desc != NULL_TREE)
5504 {
c1525930
TB
5505 if (e3_has_nodescriptor)
5506 /* The lbound of nondescriptor arrays like array constructors,
5507 nonallocatable/nonpointer function results/variables,
5508 start at zero, but when allocating it, the standard expects
5509 the array to start at one. */
1792349b
AV
5510 se.expr = gfc_index_one_node;
5511 else
5512 se.expr = gfc_conv_descriptor_lbound_get (expr3_desc,
5513 gfc_rank_cst[n]);
5514 }
5515 else if (lower == NULL)
7ab92584 5516 se.expr = gfc_index_one_node;
6de9cd9a
DN
5517 else
5518 {
6e45f57b 5519 gcc_assert (lower[n]);
99d821c0
DK
5520 if (ubound)
5521 {
6de9cd9a
DN
5522 gfc_conv_expr_type (&se, lower[n], gfc_array_index_type);
5523 gfc_add_block_to_block (pblock, &se.pre);
99d821c0
DK
5524 }
5525 else
5526 {
5527 se.expr = gfc_index_one_node;
5528 ubound = lower[n];
5529 }
6de9cd9a 5530 }
f04986a9 5531 gfc_conv_descriptor_lbound_set (descriptor_block, descriptor,
4f13e17f 5532 gfc_rank_cst[n], se.expr);
99d821c0 5533 conv_lbound = se.expr;
6de9cd9a
DN
5534
5535 /* Work out the offset for this component. */
94471a56
TB
5536 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
5537 se.expr, stride);
5538 offset = fold_build2_loc (input_location, MINUS_EXPR,
5539 gfc_array_index_type, offset, tmp);
6de9cd9a 5540
6de9cd9a
DN
5541 /* Set upper bound. */
5542 gfc_init_se (&se, NULL);
1792349b
AV
5543 if (expr3_desc != NULL_TREE)
5544 {
c1525930 5545 if (e3_has_nodescriptor)
1792349b 5546 {
c1525930
TB
5547 /* The lbound of nondescriptor arrays like array constructors,
5548 nonallocatable/nonpointer function results/variables,
5549 start at zero, but when allocating it, the standard expects
5550 the array to start at one. Therefore fix the upper bound to be
5551 (desc.ubound - desc.lbound) + 1. */
1792349b
AV
5552 tmp = fold_build2_loc (input_location, MINUS_EXPR,
5553 gfc_array_index_type,
5554 gfc_conv_descriptor_ubound_get (
5555 expr3_desc, gfc_rank_cst[n]),
5556 gfc_conv_descriptor_lbound_get (
5557 expr3_desc, gfc_rank_cst[n]));
5558 tmp = fold_build2_loc (input_location, PLUS_EXPR,
5559 gfc_array_index_type, tmp,
5560 gfc_index_one_node);
5561 se.expr = gfc_evaluate_now (tmp, pblock);
5562 }
5563 else
5564 se.expr = gfc_conv_descriptor_ubound_get (expr3_desc,
5565 gfc_rank_cst[n]);
5566 }
5567 else
5568 {
5569 gcc_assert (ubound);
5570 gfc_conv_expr_type (&se, ubound, gfc_array_index_type);
5571 gfc_add_block_to_block (pblock, &se.pre);
3e4d188a
AV
5572 if (ubound->expr_type == EXPR_FUNCTION)
5573 se.expr = gfc_evaluate_now (se.expr, pblock);
1792349b 5574 }
4f13e17f 5575 gfc_conv_descriptor_ubound_set (descriptor_block, descriptor,
99d821c0
DK
5576 gfc_rank_cst[n], se.expr);
5577 conv_ubound = se.expr;
6de9cd9a
DN
5578
5579 /* Store the stride. */
4f13e17f 5580 gfc_conv_descriptor_stride_set (descriptor_block, descriptor,
99d821c0 5581 gfc_rank_cst[n], stride);
3c86fb4e 5582
99d821c0
DK
5583 /* Calculate size and check whether extent is negative. */
5584 size = gfc_conv_array_extent_dim (conv_lbound, conv_ubound, &or_expr);
1ab3acf4
JB
5585 size = gfc_evaluate_now (size, pblock);
5586
5587 /* Check whether multiplying the stride by the number of
5588 elements in this dimension would overflow. We must also check
5589 whether the current dimension has zero size in order to avoid
f04986a9 5590 division by zero.
1ab3acf4 5591 */
f04986a9
PT
5592 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
5593 gfc_array_index_type,
5594 fold_convert (gfc_array_index_type,
1ab3acf4
JB
5595 TYPE_MAX_VALUE (gfc_array_index_type)),
5596 size);
79cae72e 5597 cond = gfc_unlikely (fold_build2_loc (input_location, LT_EXPR,
63ee5404 5598 logical_type_node, tmp, stride),
ed9c79e1 5599 PRED_FORTRAN_OVERFLOW);
79cae72e
JJ
5600 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node, cond,
5601 integer_one_node, integer_zero_node);
5602 cond = gfc_unlikely (fold_build2_loc (input_location, EQ_EXPR,
63ee5404 5603 logical_type_node, size,
ed9c79e1
JJ
5604 gfc_index_zero_node),
5605 PRED_FORTRAN_SIZE_ZERO);
79cae72e
JJ
5606 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node, cond,
5607 integer_zero_node, tmp);
1ab3acf4
JB
5608 tmp = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
5609 *overflow, tmp);
5610 *overflow = gfc_evaluate_now (tmp, pblock);
f04986a9 5611
6de9cd9a 5612 /* Multiply the stride by the number of elements in this dimension. */
94471a56
TB
5613 stride = fold_build2_loc (input_location, MULT_EXPR,
5614 gfc_array_index_type, stride, size);
6de9cd9a
DN
5615 stride = gfc_evaluate_now (stride, pblock);
5616 }
5617
f33beee9
TB
5618 for (n = rank; n < rank + corank; n++)
5619 {
5620 ubound = upper[n];
5621
5622 /* Set lower bound. */
5623 gfc_init_se (&se, NULL);
5624 if (lower == NULL || lower[n] == NULL)
5625 {
5626 gcc_assert (n == rank + corank - 1);
5627 se.expr = gfc_index_one_node;
5628 }
5629 else
5630 {
99d821c0
DK
5631 if (ubound || n == rank + corank - 1)
5632 {
f33beee9
TB
5633 gfc_conv_expr_type (&se, lower[n], gfc_array_index_type);
5634 gfc_add_block_to_block (pblock, &se.pre);
99d821c0
DK
5635 }
5636 else
5637 {
5638 se.expr = gfc_index_one_node;
5639 ubound = lower[n];
5640 }
f33beee9 5641 }
f04986a9 5642 gfc_conv_descriptor_lbound_set (descriptor_block, descriptor,
4f13e17f 5643 gfc_rank_cst[n], se.expr);
f33beee9
TB
5644
5645 if (n < rank + corank - 1)
5646 {
5647 gfc_init_se (&se, NULL);
5648 gcc_assert (ubound);
5649 gfc_conv_expr_type (&se, ubound, gfc_array_index_type);
5650 gfc_add_block_to_block (pblock, &se.pre);
4f13e17f 5651 gfc_conv_descriptor_ubound_set (descriptor_block, descriptor,
99d821c0 5652 gfc_rank_cst[n], se.expr);
f33beee9
TB
5653 }
5654 }
5655
6de9cd9a 5656 /* The stride is the number of elements in the array, so multiply by the
eea58adb 5657 size of an element to get the total size. Obviously, if there is a
c49ea23d 5658 SOURCE expression (expr3) we must use its element size. */
4daa71b0
PT
5659 if (expr3_elem_size != NULL_TREE)
5660 tmp = expr3_elem_size;
5661 else if (expr3 != NULL)
c49ea23d
PT
5662 {
5663 if (expr3->ts.type == BT_CLASS)
5664 {
5665 gfc_se se_sz;
5666 gfc_expr *sz = gfc_copy_expr (expr3);
5667 gfc_add_vptr_component (sz);
5668 gfc_add_size_component (sz);
5669 gfc_init_se (&se_sz, NULL);
5670 gfc_conv_expr (&se_sz, sz);
5671 gfc_free_expr (sz);
5672 tmp = se_sz.expr;
5673 }
5674 else
5675 {
5676 tmp = gfc_typenode_for_spec (&expr3->ts);
5677 tmp = TYPE_SIZE_UNIT (tmp);
5678 }
5679 }
5680 else
5681 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
5682
1ab3acf4 5683 /* Convert to size_t. */
da46c08e 5684 *element_size = fold_convert (size_type_node, tmp);
badd9e69
TB
5685
5686 if (rank == 0)
da46c08e 5687 return *element_size;
badd9e69 5688
4daa71b0 5689 *nelems = gfc_evaluate_now (stride, pblock);
79cae72e 5690 stride = fold_convert (size_type_node, stride);
1ab3acf4
JB
5691
5692 /* First check for overflow. Since an array of type character can
5693 have zero element_size, we must check for that before
5694 dividing. */
f04986a9 5695 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
79cae72e 5696 size_type_node,
da46c08e 5697 TYPE_MAX_VALUE (size_type_node), *element_size);
79cae72e 5698 cond = gfc_unlikely (fold_build2_loc (input_location, LT_EXPR,
63ee5404 5699 logical_type_node, tmp, stride),
ed9c79e1 5700 PRED_FORTRAN_OVERFLOW);
79cae72e 5701 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node, cond,
1ab3acf4 5702 integer_one_node, integer_zero_node);
79cae72e 5703 cond = gfc_unlikely (fold_build2_loc (input_location, EQ_EXPR,
da46c08e 5704 logical_type_node, *element_size,
ed9c79e1
JJ
5705 build_int_cst (size_type_node, 0)),
5706 PRED_FORTRAN_SIZE_ZERO);
79cae72e 5707 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node, cond,
1ab3acf4
JB
5708 integer_zero_node, tmp);
5709 tmp = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
5710 *overflow, tmp);
5711 *overflow = gfc_evaluate_now (tmp, pblock);
5712
79cae72e 5713 size = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
da46c08e 5714 stride, *element_size);
6de9cd9a
DN
5715
5716 if (poffset != NULL)
5717 {
5718 offset = gfc_evaluate_now (offset, pblock);
5719 *poffset = offset;
5720 }
5721
fcac9229
RS
5722 if (integer_zerop (or_expr))
5723 return size;
5724 if (integer_onep (or_expr))
79cae72e 5725 return build_int_cst (size_type_node, 0);
fcac9229 5726
3c86fb4e
TK
5727 var = gfc_create_var (TREE_TYPE (size), "size");
5728 gfc_start_block (&thenblock);
79cae72e 5729 gfc_add_modify (&thenblock, var, build_int_cst (size_type_node, 0));
3c86fb4e
TK
5730 thencase = gfc_finish_block (&thenblock);
5731
5732 gfc_start_block (&elseblock);
726a989a 5733 gfc_add_modify (&elseblock, var, size);
3c86fb4e
TK
5734 elsecase = gfc_finish_block (&elseblock);
5735
5736 tmp = gfc_evaluate_now (or_expr, pblock);
5737 tmp = build3_v (COND_EXPR, tmp, thencase, elsecase);
5738 gfc_add_expr_to_block (pblock, tmp);
5739
5740 return var;
6de9cd9a
DN
5741}
5742
5743
1792349b
AV
5744/* Retrieve the last ref from the chain. This routine is specific to
5745 gfc_array_allocate ()'s needs. */
5746
5747bool
5748retrieve_last_ref (gfc_ref **ref_in, gfc_ref **prev_ref_in)
5749{
5750 gfc_ref *ref, *prev_ref;
5751
5752 ref = *ref_in;
5753 /* Prevent warnings for uninitialized variables. */
5754 prev_ref = *prev_ref_in;
5755 while (ref && ref->next != NULL)
5756 {
5757 gcc_assert (ref->type != REF_ARRAY || ref->u.ar.type == AR_ELEMENT
5758 || (ref->u.ar.dimen == 0 && ref->u.ar.codimen > 0));
5759 prev_ref = ref;
5760 ref = ref->next;
5761 }
5762
5763 if (ref == NULL || ref->type != REF_ARRAY)
5764 return false;
5765
5766 *ref_in = ref;
5767 *prev_ref_in = prev_ref;
5768 return true;
5769}
5770
1f2959f0 5771/* Initializes the descriptor and generates a call to _gfor_allocate. Does
6de9cd9a
DN
5772 the work for an ALLOCATE statement. */
5773/*GCC ARRAYS*/
5774
5b725b8d 5775bool
8f992d64 5776gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree status, tree errmsg,
4daa71b0 5777 tree errlen, tree label_finish, tree expr3_elem_size,
1792349b 5778 tree *nelems, gfc_expr *expr3, tree e3_arr_desc,
c1525930 5779 bool e3_has_nodescriptor)
6de9cd9a
DN
5780{
5781 tree tmp;
5782 tree pointer;
badd9e69 5783 tree offset = NULL_TREE;
979d4598 5784 tree token = NULL_TREE;
6de9cd9a 5785 tree size;
1ab3acf4 5786 tree msg;
badd9e69 5787 tree error = NULL_TREE;
1ab3acf4 5788 tree overflow; /* Boolean storing whether size calculation overflows. */
badd9e69 5789 tree var_overflow = NULL_TREE;
1ab3acf4 5790 tree cond;
4f13e17f 5791 tree set_descriptor;
6090f915 5792 tree not_prev_allocated = NULL_TREE;
da46c08e 5793 tree element_size = NULL_TREE;
4f13e17f 5794 stmtblock_t set_descriptor_block;
1ab3acf4 5795 stmtblock_t elseblock;
6de9cd9a
DN
5796 gfc_expr **lower;
5797 gfc_expr **upper;
3c9f5092 5798 gfc_ref *ref, *prev_ref = NULL, *coref;
de91486c
AV
5799 bool allocatable, coarray, dimension, alloc_w_e3_arr_spec = false,
5800 non_ulimate_coarray_ptr_comp;
5b725b8d
TK
5801
5802 ref = expr->ref;
5803
5804 /* Find the last reference in the chain. */
1792349b
AV
5805 if (!retrieve_last_ref (&ref, &prev_ref))
5806 return false;
5807
e457a6fc
AV
5808 /* Take the allocatable and coarray properties solely from the expr-ref's
5809 attributes and not from source=-expression. */
f33beee9 5810 if (!prev_ref)
d3a9eea2 5811 {
ea6363a3 5812 allocatable = expr->symtree->n.sym->attr.allocatable;
badd9e69 5813 dimension = expr->symtree->n.sym->attr.dimension;
de91486c 5814 non_ulimate_coarray_ptr_comp = false;
d3a9eea2 5815 }
f33beee9 5816 else
d3a9eea2 5817 {
ea6363a3 5818 allocatable = prev_ref->u.c.component->attr.allocatable;
de91486c
AV
5819 /* Pointer components in coarrayed derived types must be treated
5820 specially in that they are registered without a check if the are
5821 already associated. This does not hold for ultimate coarray
5822 pointers. */
5823 non_ulimate_coarray_ptr_comp = (prev_ref->u.c.component->attr.pointer
5824 && !prev_ref->u.c.component->attr.codimension);
badd9e69 5825 dimension = prev_ref->u.c.component->attr.dimension;
d3a9eea2
TB
5826 }
5827
3c9f5092
AV
5828 /* For allocatable/pointer arrays in derived types, one of the refs has to be
5829 a coarray. In this case it does not matter whether we are on this_image
5830 or not. */
5831 coarray = false;
5832 for (coref = expr->ref; coref; coref = coref->next)
5833 if (coref->type == REF_ARRAY && coref->u.ar.codimen > 0)
5834 {
5835 coarray = true;
5836 break;
5837 }
5838
badd9e69
TB
5839 if (!dimension)
5840 gcc_assert (coarray);
5046aff5 5841
e457a6fc
AV
5842 if (ref->u.ar.type == AR_FULL && expr3 != NULL)
5843 {
7090cac9 5844 gfc_ref *old_ref = ref;
e457a6fc
AV
5845 /* F08:C633: Array shape from expr3. */
5846 ref = expr3->ref;
5847
5848 /* Find the last reference in the chain. */
5849 if (!retrieve_last_ref (&ref, &prev_ref))
7090cac9
AV
5850 {
5851 if (expr3->expr_type == EXPR_FUNCTION
5852 && gfc_expr_attr (expr3).dimension)
5853 ref = old_ref;
5854 else
5855 return false;
5856 }
e457a6fc
AV
5857 alloc_w_e3_arr_spec = true;
5858 }
5859
6de9cd9a
DN
5860 /* Figure out the size of the array. */
5861 switch (ref->u.ar.type)
5862 {
5863 case AR_ELEMENT:
f33beee9
TB
5864 if (!coarray)
5865 {
5866 lower = NULL;
5867 upper = ref->u.ar.start;
5868 break;
5869 }
5870 /* Fall through. */
5871
5872 case AR_SECTION:
5873 lower = ref->u.ar.start;
5874 upper = ref->u.ar.end;
6de9cd9a
DN
5875 break;
5876
5877 case AR_FULL:
1792349b
AV
5878 gcc_assert (ref->u.ar.as->type == AS_EXPLICIT
5879 || alloc_w_e3_arr_spec);
6de9cd9a
DN
5880
5881 lower = ref->u.ar.as->lower;
5882 upper = ref->u.ar.as->upper;
5883 break;
5884
6de9cd9a 5885 default:
6e45f57b 5886 gcc_unreachable ();
6de9cd9a
DN
5887 break;
5888 }
5889
1ab3acf4 5890 overflow = integer_zero_node;
4f13e17f 5891
ba08c70a
PT
5892 if (expr->ts.type == BT_CHARACTER
5893 && TREE_CODE (se->string_length) == COMPONENT_REF
9d44426f
PT
5894 && expr->ts.u.cl->backend_decl != se->string_length
5895 && VAR_P (expr->ts.u.cl->backend_decl))
5896 gfc_add_modify (&se->pre, expr->ts.u.cl->backend_decl,
5897 fold_convert (TREE_TYPE (expr->ts.u.cl->backend_decl),
5898 se->string_length));
ba08c70a 5899
4f13e17f 5900 gfc_init_block (&set_descriptor_block);
3c9f5092
AV
5901 /* Take the corank only from the actual ref and not from the coref. The
5902 later will mislead the generation of the array dimensions for allocatable/
5903 pointer components in derived types. */
1792349b
AV
5904 size = gfc_array_init_size (se->expr, alloc_w_e3_arr_spec ? expr->rank
5905 : ref->u.ar.as->rank,
e457a6fc
AV
5906 coarray ? ref->u.ar.as->corank : 0,
5907 &offset, lower, upper,
c49ea23d 5908 &se->pre, &set_descriptor_block, &overflow,
1792349b 5909 expr3_elem_size, nelems, expr3, e3_arr_desc,
da46c08e 5910 e3_has_nodescriptor, expr, &element_size);
4f13e17f 5911
81fa8ab2 5912 if (dimension)
badd9e69 5913 {
badd9e69
TB
5914 var_overflow = gfc_create_var (integer_type_node, "overflow");
5915 gfc_add_modify (&se->pre, var_overflow, overflow);
1ab3acf4 5916
81fa8ab2
TB
5917 if (status == NULL_TREE)
5918 {
5919 /* Generate the block of code handling overflow. */
5920 msg = gfc_build_addr_expr (pchar_type_node,
5921 gfc_build_localized_cstring_const
1ab3acf4
JB
5922 ("Integer overflow when calculating the amount of "
5923 "memory to allocate"));
81fa8ab2
TB
5924 error = build_call_expr_loc (input_location,
5925 gfor_fndecl_runtime_error, 1, msg);
5926 }
5927 else
5928 {
5929 tree status_type = TREE_TYPE (status);
5930 stmtblock_t set_status_block;
1ab3acf4 5931
81fa8ab2
TB
5932 gfc_start_block (&set_status_block);
5933 gfc_add_modify (&set_status_block, status,
5934 build_int_cst (status_type, LIBERROR_ALLOCATION));
5935 error = gfc_finish_block (&set_status_block);
5936 }
1ab3acf4 5937 }
6de9cd9a
DN
5938
5939 /* Allocate memory to store the data. */
4daa71b0
PT
5940 if (POINTER_TYPE_P (TREE_TYPE (se->expr)))
5941 se->expr = build_fold_indirect_ref_loc (input_location, se->expr);
5942
f19626cf 5943 if (coarray && flag_coarray == GFC_FCOARRAY_LIB)
3c9f5092 5944 {
de91486c
AV
5945 pointer = non_ulimate_coarray_ptr_comp ? se->expr
5946 : gfc_conv_descriptor_data_get (se->expr);
26f391e8 5947 token = gfc_conv_descriptor_token (se->expr);
3c9f5092
AV
5948 token = gfc_build_addr_expr (NULL_TREE, token);
5949 }
de91486c
AV
5950 else
5951 pointer = gfc_conv_descriptor_data_get (se->expr);
5952 STRIP_NOPS (pointer);
979d4598 5953
6090f915
TK
5954 if (allocatable)
5955 {
5956 not_prev_allocated = gfc_create_var (logical_type_node,
5957 "not_prev_allocated");
5958 tmp = fold_build2_loc (input_location, EQ_EXPR,
5959 logical_type_node, pointer,
5960 build_int_cst (TREE_TYPE (pointer), 0));
5961
5962 gfc_add_modify (&se->pre, not_prev_allocated, tmp);
5963 }
5964
5965 gfc_start_block (&elseblock);
5966
8f992d64 5967 /* The allocatable variant takes the old pointer as first argument. */
ea6363a3 5968 if (allocatable)
979d4598 5969 gfc_allocate_allocatable (&elseblock, pointer, size, token,
3c9f5092
AV
5970 status, errmsg, errlen, label_finish, expr,
5971 coref != NULL ? coref->u.ar.as->corank : 0);
de91486c
AV
5972 else if (non_ulimate_coarray_ptr_comp && token)
5973 /* The token is set only for GFC_FCOARRAY_LIB mode. */
5974 gfc_allocate_using_caf_lib (&elseblock, pointer, size, token, status,
5975 errmsg, errlen,
5976 GFC_CAF_COARRAY_ALLOC_ALLOCATE_ONLY);
5039610b 5977 else
4f13e17f 5978 gfc_allocate_using_malloc (&elseblock, pointer, size, status);
1ab3acf4 5979
badd9e69
TB
5980 if (dimension)
5981 {
5982 cond = gfc_unlikely (fold_build2_loc (input_location, NE_EXPR,
63ee5404 5983 logical_type_node, var_overflow, integer_zero_node),
ed9c79e1 5984 PRED_FORTRAN_OVERFLOW);
f04986a9 5985 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
badd9e69
TB
5986 error, gfc_finish_block (&elseblock));
5987 }
5988 else
5989 tmp = gfc_finish_block (&elseblock);
1ab3acf4 5990
6de9cd9a
DN
5991 gfc_add_expr_to_block (&se->pre, tmp);
5992
da46c08e 5993 /* Update the array descriptor with the offset and the span. */
badd9e69 5994 if (dimension)
ff3598bc 5995 {
da46c08e
PT
5996 gfc_conv_descriptor_offset_set (&set_descriptor_block, se->expr, offset);
5997 tmp = fold_convert (gfc_array_index_type, element_size);
ff3598bc
PT
5998 gfc_conv_descriptor_span_set (&set_descriptor_block, se->expr, tmp);
5999 }
6000
4f13e17f
DC
6001 set_descriptor = gfc_finish_block (&set_descriptor_block);
6002 if (status != NULL_TREE)
6003 {
6004 cond = fold_build2_loc (input_location, EQ_EXPR,
63ee5404 6005 logical_type_node, status,
4f13e17f 6006 build_int_cst (TREE_TYPE (status), 0));
6090f915
TK
6007
6008 if (not_prev_allocated != NULL_TREE)
6009 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
6010 logical_type_node, cond, not_prev_allocated);
6011
4f13e17f
DC
6012 gfc_add_expr_to_block (&se->pre,
6013 fold_build3_loc (input_location, COND_EXPR, void_type_node,
7f7fa20f 6014 cond,
ed9c79e1 6015 set_descriptor,
f04986a9 6016 build_empty_stmt (input_location)));
4f13e17f
DC
6017 }
6018 else
6019 gfc_add_expr_to_block (&se->pre, set_descriptor);
5b725b8d
TK
6020
6021 return true;
6de9cd9a
DN
6022}
6023
6024
6de9cd9a
DN
6025/* Create an array constructor from an initialization expression.
6026 We assume the frontend already did any expansions and conversions. */
6027
6028tree
6029gfc_conv_array_initializer (tree type, gfc_expr * expr)
6030{
6031 gfc_constructor *c;
6de9cd9a 6032 tree tmp;
6de9cd9a 6033 gfc_se se;
21ea4922 6034 tree index, range;
9771b263 6035 vec<constructor_elt, va_gc> *v = NULL;
6de9cd9a 6036
c3f34952
TB
6037 if (expr->expr_type == EXPR_VARIABLE
6038 && expr->symtree->n.sym->attr.flavor == FL_PARAMETER
6039 && expr->symtree->n.sym->value)
6040 expr = expr->symtree->n.sym->value;
6041
6de9cd9a
DN
6042 switch (expr->expr_type)
6043 {
6044 case EXPR_CONSTANT:
6045 case EXPR_STRUCTURE:
6046 /* A single scalar or derived type value. Create an array with all
6047 elements equal to that value. */
6048 gfc_init_se (&se, NULL);
f04986a9 6049
e9cfef64
PB
6050 if (expr->expr_type == EXPR_CONSTANT)
6051 gfc_conv_constant (&se, expr);
6052 else
6053 gfc_conv_structure (&se, expr, 1);
6de9cd9a 6054
0eaf1412
JJ
6055 CONSTRUCTOR_APPEND_ELT (v, build2 (RANGE_EXPR, gfc_array_index_type,
6056 TYPE_MIN_VALUE (TYPE_DOMAIN (type)),
6057 TYPE_MAX_VALUE (TYPE_DOMAIN (type))),
6058 se.expr);
6de9cd9a
DN
6059 break;
6060
6061 case EXPR_ARRAY:
4038c495 6062 /* Create a vector of all the elements. */
b7e75771
JD
6063 for (c = gfc_constructor_first (expr->value.constructor);
6064 c; c = gfc_constructor_next (c))
6de9cd9a
DN
6065 {
6066 if (c->iterator)
6067 {
6068 /* Problems occur when we get something like
63346ddb 6069 integer :: a(lots) = (/(i, i=1, lots)/) */
29e0597e
TB
6070 gfc_fatal_error ("The number of elements in the array "
6071 "constructor at %L requires an increase of "
6072 "the allowed %d upper limit. See "
6073 "%<-fmax-array-constructor%> option",
c61819ff 6074 &expr->where, flag_max_array_constructor);
63346ddb 6075 return NULL_TREE;
6de9cd9a 6076 }
b7e75771
JD
6077 if (mpz_cmp_si (c->offset, 0) != 0)
6078 index = gfc_conv_mpz_to_tree (c->offset, gfc_index_integer_kind);
6de9cd9a
DN
6079 else
6080 index = NULL_TREE;
6de9cd9a 6081
21ea4922
JJ
6082 if (mpz_cmp_si (c->repeat, 1) > 0)
6083 {
6084 tree tmp1, tmp2;
6085 mpz_t maxval;
6086
6087 mpz_init (maxval);
6088 mpz_add (maxval, c->offset, c->repeat);
6089 mpz_sub_ui (maxval, maxval, 1);
6090 tmp2 = gfc_conv_mpz_to_tree (maxval, gfc_index_integer_kind);
6091 if (mpz_cmp_si (c->offset, 0) != 0)
6092 {
6093 mpz_add_ui (maxval, c->offset, 1);
6094 tmp1 = gfc_conv_mpz_to_tree (maxval, gfc_index_integer_kind);
6095 }
6096 else
6097 tmp1 = gfc_conv_mpz_to_tree (c->offset, gfc_index_integer_kind);
6098
6099 range = fold_build2 (RANGE_EXPR, gfc_array_index_type, tmp1, tmp2);
6100 mpz_clear (maxval);
6101 }
6102 else
6103 range = NULL;
6104
6de9cd9a
DN
6105 gfc_init_se (&se, NULL);
6106 switch (c->expr->expr_type)
6107 {
6108 case EXPR_CONSTANT:
6109 gfc_conv_constant (&se, c->expr);
8b393e9f
BE
6110
6111 /* See gfortran.dg/charlen_15.f90 for instance. */
6112 if (TREE_CODE (se.expr) == STRING_CST
6113 && TREE_CODE (type) == ARRAY_TYPE)
6114 {
6115 tree atype = type;
6116 while (TREE_CODE (TREE_TYPE (atype)) == ARRAY_TYPE)
6117 atype = TREE_TYPE (atype);
22cd0312
BE
6118 gcc_checking_assert (TREE_CODE (TREE_TYPE (atype))
6119 == INTEGER_TYPE);
6120 gcc_checking_assert (TREE_TYPE (TREE_TYPE (se.expr))
6121 == TREE_TYPE (atype));
6122 if (tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (se.expr)))
6123 > tree_to_uhwi (TYPE_SIZE_UNIT (atype)))
8b393e9f
BE
6124 {
6125 unsigned HOST_WIDE_INT size
6126 = tree_to_uhwi (TYPE_SIZE_UNIT (atype));
6127 const char *p = TREE_STRING_POINTER (se.expr);
6128
6129 se.expr = build_string (size, p);
8b393e9f 6130 }
22cd0312 6131 TREE_TYPE (se.expr) = atype;
8b393e9f 6132 }
6de9cd9a
DN
6133 break;
6134
6135 case EXPR_STRUCTURE:
6136 gfc_conv_structure (&se, c->expr, 1);
6de9cd9a
DN
6137 break;
6138
6139 default:
c1cfed03
PT
6140 /* Catch those occasional beasts that do not simplify
6141 for one reason or another, assuming that if they are
6142 standard defying the frontend will catch them. */
6143 gfc_conv_expr (&se, c->expr);
c1cfed03 6144 break;
6de9cd9a 6145 }
21ea4922
JJ
6146
6147 if (range == NULL_TREE)
6148 CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
6149 else
6150 {
6151 if (index != NULL_TREE)
6152 CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
6153 CONSTRUCTOR_APPEND_ELT (v, range, se.expr);
6154 }
6de9cd9a 6155 }
6de9cd9a
DN
6156 break;
6157
5046aff5
PT
6158 case EXPR_NULL:
6159 return gfc_build_null_descriptor (type);
6160
6de9cd9a 6161 default:
6e45f57b 6162 gcc_unreachable ();
6de9cd9a
DN
6163 }
6164
6165 /* Create a constructor from the list of elements. */
4038c495 6166 tmp = build_constructor (type, v);
6de9cd9a 6167 TREE_CONSTANT (tmp) = 1;
6de9cd9a
DN
6168 return tmp;
6169}
6170
6171
9f3761c5
TB
6172/* Generate code to evaluate non-constant coarray cobounds. */
6173
6174void
6175gfc_trans_array_cobounds (tree type, stmtblock_t * pblock,
6176 const gfc_symbol *sym)
6177{
6178 int dim;
6179 tree ubound;
6180 tree lbound;
6181 gfc_se se;
6182 gfc_array_spec *as;
6183
f3b0bb7a 6184 as = IS_CLASS_ARRAY (sym) ? CLASS_DATA (sym)->as : sym->as;
9f3761c5
TB
6185
6186 for (dim = as->rank; dim < as->rank + as->corank; dim++)
6187 {
6188 /* Evaluate non-constant array bound expressions. */
6189 lbound = GFC_TYPE_ARRAY_LBOUND (type, dim);
6190 if (as->lower[dim] && !INTEGER_CST_P (lbound))
6191 {
6192 gfc_init_se (&se, NULL);
6193 gfc_conv_expr_type (&se, as->lower[dim], gfc_array_index_type);
6194 gfc_add_block_to_block (pblock, &se.pre);
6195 gfc_add_modify (pblock, lbound, se.expr);
6196 }
6197 ubound = GFC_TYPE_ARRAY_UBOUND (type, dim);
6198 if (as->upper[dim] && !INTEGER_CST_P (ubound))
6199 {
6200 gfc_init_se (&se, NULL);
6201 gfc_conv_expr_type (&se, as->upper[dim], gfc_array_index_type);
6202 gfc_add_block_to_block (pblock, &se.pre);
6203 gfc_add_modify (pblock, ubound, se.expr);
6204 }
6205 }
6206}
6207
6208
6de9cd9a
DN
6209/* Generate code to evaluate non-constant array bounds. Sets *poffset and
6210 returns the size (in elements) of the array. */
6211
6212static tree
6213gfc_trans_array_bounds (tree type, gfc_symbol * sym, tree * poffset,
6214 stmtblock_t * pblock)
6215{
6216 gfc_array_spec *as;
6217 tree size;
6218 tree stride;
6219 tree offset;
6220 tree ubound;
6221 tree lbound;
6222 tree tmp;
6223 gfc_se se;
6224
6225 int dim;
6226
f3b0bb7a 6227 as = IS_CLASS_ARRAY (sym) ? CLASS_DATA (sym)->as : sym->as;
6de9cd9a 6228
7ab92584
SB
6229 size = gfc_index_one_node;
6230 offset = gfc_index_zero_node;
6de9cd9a
DN
6231 for (dim = 0; dim < as->rank; dim++)
6232 {
6233 /* Evaluate non-constant array bound expressions. */
6234 lbound = GFC_TYPE_ARRAY_LBOUND (type, dim);
6235 if (as->lower[dim] && !INTEGER_CST_P (lbound))
6236 {
6237 gfc_init_se (&se, NULL);
6238 gfc_conv_expr_type (&se, as->lower[dim], gfc_array_index_type);
6239 gfc_add_block_to_block (pblock, &se.pre);
726a989a 6240 gfc_add_modify (pblock, lbound, se.expr);
6de9cd9a
DN
6241 }
6242 ubound = GFC_TYPE_ARRAY_UBOUND (type, dim);
6243 if (as->upper[dim] && !INTEGER_CST_P (ubound))
6244 {
6245 gfc_init_se (&se, NULL);
6246 gfc_conv_expr_type (&se, as->upper[dim], gfc_array_index_type);
6247 gfc_add_block_to_block (pblock, &se.pre);
726a989a 6248 gfc_add_modify (pblock, ubound, se.expr);
6de9cd9a 6249 }
f7b529fa 6250 /* The offset of this dimension. offset = offset - lbound * stride. */
94471a56
TB
6251 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
6252 lbound, size);
6253 offset = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
6254 offset, tmp);
6de9cd9a
DN
6255
6256 /* The size of this dimension, and the stride of the next. */
6257 if (dim + 1 < as->rank)
6258 stride = GFC_TYPE_ARRAY_STRIDE (type, dim + 1);
6259 else
417ab240 6260 stride = GFC_TYPE_ARRAY_SIZE (type);
6de9cd9a
DN
6261
6262 if (ubound != NULL_TREE && !(stride && INTEGER_CST_P (stride)))
6263 {
6264 /* Calculate stride = size * (ubound + 1 - lbound). */
94471a56
TB
6265 tmp = fold_build2_loc (input_location, MINUS_EXPR,
6266 gfc_array_index_type,
6267 gfc_index_one_node, lbound);
6268 tmp = fold_build2_loc (input_location, PLUS_EXPR,
6269 gfc_array_index_type, ubound, tmp);
6270 tmp = fold_build2_loc (input_location, MULT_EXPR,
6271 gfc_array_index_type, size, tmp);
6de9cd9a 6272 if (stride)
726a989a 6273 gfc_add_modify (pblock, stride, tmp);
6de9cd9a
DN
6274 else
6275 stride = gfc_evaluate_now (tmp, pblock);
5b440a1c
PT
6276
6277 /* Make sure that negative size arrays are translated
6278 to being zero size. */
63ee5404 6279 tmp = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
94471a56
TB
6280 stride, gfc_index_zero_node);
6281 tmp = fold_build3_loc (input_location, COND_EXPR,
6282 gfc_array_index_type, tmp,
6283 stride, gfc_index_zero_node);
726a989a 6284 gfc_add_modify (pblock, stride, tmp);
6de9cd9a
DN
6285 }
6286
6287 size = stride;
6288 }
9f3761c5
TB
6289
6290 gfc_trans_array_cobounds (type, pblock, sym);
417ab240
JJ
6291 gfc_trans_vla_type_sizes (sym, pblock);
6292
6de9cd9a
DN
6293 *poffset = offset;
6294 return size;
6295}
6296
6297
6298/* Generate code to initialize/allocate an array variable. */
6299
0019d498
DK
6300void
6301gfc_trans_auto_array_allocation (tree decl, gfc_symbol * sym,
6302 gfc_wrapped_block * block)
6de9cd9a 6303{
0019d498 6304 stmtblock_t init;
6de9cd9a 6305 tree type;
c76f8d52 6306 tree tmp = NULL_TREE;
6de9cd9a
DN
6307 tree size;
6308 tree offset;
c76f8d52
MM
6309 tree space;
6310 tree inittree;
6de9cd9a
DN
6311 bool onstack;
6312
6e45f57b 6313 gcc_assert (!(sym->attr.pointer || sym->attr.allocatable));
6de9cd9a
DN
6314
6315 /* Do nothing for USEd variables. */
6316 if (sym->attr.use_assoc)
0019d498 6317 return;
6de9cd9a
DN
6318
6319 type = TREE_TYPE (decl);
6e45f57b 6320 gcc_assert (GFC_ARRAY_TYPE_P (type));
6de9cd9a
DN
6321 onstack = TREE_CODE (type) != POINTER_TYPE;
6322
f315a6b4 6323 gfc_init_block (&init);
6de9cd9a
DN
6324
6325 /* Evaluate character string length. */
6326 if (sym->ts.type == BT_CHARACTER
bc21d315 6327 && onstack && !INTEGER_CST_P (sym->ts.u.cl->backend_decl))
6de9cd9a 6328 {
0019d498 6329 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
6de9cd9a 6330
0019d498 6331 gfc_trans_vla_type_sizes (sym, &init);
417ab240 6332
1a186ec5 6333 /* Emit a DECL_EXPR for this variable, which will cause the
13795658 6334 gimplifier to allocate storage, and all that good stuff. */
94471a56 6335 tmp = fold_build1_loc (input_location, DECL_EXPR, TREE_TYPE (decl), decl);
0019d498 6336 gfc_add_expr_to_block (&init, tmp);
6de9cd9a
DN
6337 }
6338
6339 if (onstack)
6340 {
0019d498
DK
6341 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
6342 return;
6de9cd9a
DN
6343 }
6344
6345 type = TREE_TYPE (type);
6346
6e45f57b
PB
6347 gcc_assert (!sym->attr.use_assoc);
6348 gcc_assert (!TREE_STATIC (decl));
cb9e4f55 6349 gcc_assert (!sym->module);
6de9cd9a
DN
6350
6351 if (sym->ts.type == BT_CHARACTER
bc21d315 6352 && !INTEGER_CST_P (sym->ts.u.cl->backend_decl))
0019d498 6353 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
6de9cd9a 6354
0019d498 6355 size = gfc_trans_array_bounds (type, sym, &offset, &init);
6de9cd9a 6356
83d890b9
AL
6357 /* Don't actually allocate space for Cray Pointees. */
6358 if (sym->attr.cray_pointee)
6359 {
d168c883 6360 if (VAR_P (GFC_TYPE_ARRAY_OFFSET (type)))
0019d498
DK
6361 gfc_add_modify (&init, GFC_TYPE_ARRAY_OFFSET (type), offset);
6362
6363 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
6364 return;
83d890b9
AL
6365 }
6366
203c7ebf 6367 if (flag_stack_arrays)
c76f8d52
MM
6368 {
6369 gcc_assert (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE);
9c81750c 6370 space = build_decl (gfc_get_location (&sym->declared_at),
c76f8d52
MM
6371 VAR_DECL, create_tmp_var_name ("A"),
6372 TREE_TYPE (TREE_TYPE (decl)));
6373 gfc_trans_vla_type_sizes (sym, &init);
6374 }
6375 else
6376 {
6377 /* The size is the number of elements in the array, so multiply by the
6378 size of an element to get the total size. */
6379 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
6380 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
6381 size, fold_convert (gfc_array_index_type, tmp));
6382
6383 /* Allocate memory to hold the data. */
6384 tmp = gfc_call_malloc (&init, TREE_TYPE (decl), size);
6385 gfc_add_modify (&init, decl, tmp);
6de9cd9a 6386
c76f8d52 6387 /* Free the temporary. */
107051a5 6388 tmp = gfc_call_free (decl);
c76f8d52
MM
6389 space = NULL_TREE;
6390 }
6de9cd9a
DN
6391
6392 /* Set offset of the array. */
d168c883 6393 if (VAR_P (GFC_TYPE_ARRAY_OFFSET (type)))
0019d498 6394 gfc_add_modify (&init, GFC_TYPE_ARRAY_OFFSET (type), offset);
6de9cd9a
DN
6395
6396 /* Automatic arrays should not have initializers. */
6e45f57b 6397 gcc_assert (!sym->value);
6de9cd9a 6398
c76f8d52 6399 inittree = gfc_finish_block (&init);
6de9cd9a 6400
c76f8d52
MM
6401 if (space)
6402 {
6403 tree addr;
6404 pushdecl (space);
6405
6406 /* Don't create new scope, emit the DECL_EXPR in exactly the scope
6407 where also space is located. */
6408 gfc_init_block (&init);
6409 tmp = fold_build1_loc (input_location, DECL_EXPR,
6410 TREE_TYPE (space), space);
6411 gfc_add_expr_to_block (&init, tmp);
9c81750c 6412 addr = fold_build1_loc (gfc_get_location (&sym->declared_at),
c76f8d52
MM
6413 ADDR_EXPR, TREE_TYPE (decl), space);
6414 gfc_add_modify (&init, decl, addr);
6415 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
6416 tmp = NULL_TREE;
6417 }
6418 gfc_add_init_cleanup (block, inittree, tmp);
6de9cd9a
DN
6419}
6420
6421
6422/* Generate entry and exit code for g77 calling convention arrays. */
6423
0019d498
DK
6424void
6425gfc_trans_g77_array (gfc_symbol * sym, gfc_wrapped_block * block)
6de9cd9a
DN
6426{
6427 tree parm;
6428 tree type;
6429 locus loc;
6430 tree offset;
6431 tree tmp;
363aab21 6432 tree stmt;
0019d498 6433 stmtblock_t init;
6de9cd9a 6434
363aab21 6435 gfc_save_backend_locus (&loc);
6de9cd9a
DN
6436 gfc_set_backend_locus (&sym->declared_at);
6437
6438 /* Descriptor type. */
6439 parm = sym->backend_decl;
6440 type = TREE_TYPE (parm);
6e45f57b 6441 gcc_assert (GFC_ARRAY_TYPE_P (type));
6de9cd9a 6442
0019d498 6443 gfc_start_block (&init);
6de9cd9a
DN
6444
6445 if (sym->ts.type == BT_CHARACTER
d168c883 6446 && VAR_P (sym->ts.u.cl->backend_decl))
0019d498 6447 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
6de9cd9a
DN
6448
6449 /* Evaluate the bounds of the array. */
0019d498 6450 gfc_trans_array_bounds (type, sym, &offset, &init);
6de9cd9a
DN
6451
6452 /* Set the offset. */
d168c883 6453 if (VAR_P (GFC_TYPE_ARRAY_OFFSET (type)))
0019d498 6454 gfc_add_modify (&init, GFC_TYPE_ARRAY_OFFSET (type), offset);
6de9cd9a 6455
1f2959f0 6456 /* Set the pointer itself if we aren't using the parameter directly. */
6de9cd9a
DN
6457 if (TREE_CODE (parm) != PARM_DECL)
6458 {
6459 tmp = convert (TREE_TYPE (parm), GFC_DECL_SAVED_DESCRIPTOR (parm));
0019d498 6460 gfc_add_modify (&init, parm, tmp);
6de9cd9a 6461 }
0019d498 6462 stmt = gfc_finish_block (&init);
6de9cd9a 6463
363aab21 6464 gfc_restore_backend_locus (&loc);
6de9cd9a 6465
6de9cd9a 6466 /* Add the initialization code to the start of the function. */
54129a64
PT
6467
6468 if (sym->attr.optional || sym->attr.not_always_present)
6469 {
6470 tmp = gfc_conv_expr_present (sym);
c2255bc4 6471 stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt (input_location));
54129a64 6472 }
f04986a9 6473
0019d498 6474 gfc_add_init_cleanup (block, stmt, NULL_TREE);
6de9cd9a
DN
6475}
6476
6477
6478/* Modify the descriptor of an array parameter so that it has the
6479 correct lower bound. Also move the upper bound accordingly.
6480 If the array is not packed, it will be copied into a temporary.
6481 For each dimension we set the new lower and upper bounds. Then we copy the
6482 stride and calculate the offset for this dimension. We also work out
6483 what the stride of a packed array would be, and see it the two match.
6484 If the array need repacking, we set the stride to the values we just
6485 calculated, recalculate the offset and copy the array data.
6486 Code is also added to copy the data back at the end of the function.
6487 */
6488
0019d498
DK
6489void
6490gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc,
6491 gfc_wrapped_block * block)
6de9cd9a
DN
6492{
6493 tree size;
6494 tree type;
6495 tree offset;
6496 locus loc;
0019d498
DK
6497 stmtblock_t init;
6498 tree stmtInit, stmtCleanup;
6de9cd9a
DN
6499 tree lbound;
6500 tree ubound;
6501 tree dubound;
6502 tree dlbound;
6503 tree dumdesc;
6504 tree tmp;
e8300d6e 6505 tree stride, stride2;
6de9cd9a
DN
6506 tree stmt_packed;
6507 tree stmt_unpacked;
6508 tree partial;
6509 gfc_se se;
6510 int n;
6511 int checkparm;
6512 int no_repack;
3d79abbd 6513 bool optional_arg;
f3b0bb7a
AV
6514 gfc_array_spec *as;
6515 bool is_classarray = IS_CLASS_ARRAY (sym);
6de9cd9a 6516
fc90a8f2 6517 /* Do nothing for pointer and allocatable arrays. */
f3b0bb7a
AV
6518 if ((sym->ts.type != BT_CLASS && sym->attr.pointer)
6519 || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)->attr.class_pointer)
6520 || sym->attr.allocatable
6521 || (is_classarray && CLASS_DATA (sym)->attr.allocatable))
0019d498 6522 return;
fc90a8f2 6523
f3b0bb7a 6524 if (!is_classarray && sym->attr.dummy && gfc_is_nodesc_array (sym))
0019d498
DK
6525 {
6526 gfc_trans_g77_array (sym, block);
6527 return;
6528 }
6de9cd9a 6529
8e9218f2 6530 loc.nextc = NULL;
363aab21 6531 gfc_save_backend_locus (&loc);
8e9218f2
AV
6532 /* loc.nextc is not set by save_backend_locus but the location routines
6533 depend on it. */
6534 if (loc.nextc == NULL)
6535 loc.nextc = loc.lb->line;
6de9cd9a
DN
6536 gfc_set_backend_locus (&sym->declared_at);
6537
6538 /* Descriptor type. */
6539 type = TREE_TYPE (tmpdesc);
6e45f57b 6540 gcc_assert (GFC_ARRAY_TYPE_P (type));
6de9cd9a 6541 dumdesc = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
f3b0bb7a
AV
6542 if (is_classarray)
6543 /* For a class array the dummy array descriptor is in the _class
6544 component. */
6545 dumdesc = gfc_class_data_get (dumdesc);
6546 else
6547 dumdesc = build_fold_indirect_ref_loc (input_location, dumdesc);
6548 as = IS_CLASS_ARRAY (sym) ? CLASS_DATA (sym)->as : sym->as;
0019d498 6549 gfc_start_block (&init);
6de9cd9a
DN
6550
6551 if (sym->ts.type == BT_CHARACTER
d168c883 6552 && VAR_P (sym->ts.u.cl->backend_decl))
0019d498 6553 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
6de9cd9a 6554
f3b0bb7a 6555 checkparm = (as->type == AS_EXPLICIT
d3d3011f 6556 && (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS));
6de9cd9a
DN
6557
6558 no_repack = !(GFC_DECL_PACKED_ARRAY (tmpdesc)
0019d498 6559 || GFC_DECL_PARTIAL_PACKED_ARRAY (tmpdesc));
6de9cd9a
DN
6560
6561 if (GFC_DECL_PARTIAL_PACKED_ARRAY (tmpdesc))
6562 {
6563 /* For non-constant shape arrays we only check if the first dimension
0019d498
DK
6564 is contiguous. Repacking higher dimensions wouldn't gain us
6565 anything as we still don't know the array stride. */
63ee5404 6566 partial = gfc_create_var (logical_type_node, "partial");
6de9cd9a 6567 TREE_USED (partial) = 1;
568e8e1e 6568 tmp = gfc_conv_descriptor_stride_get (dumdesc, gfc_rank_cst[0]);
63ee5404 6569 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, tmp,
94471a56 6570 gfc_index_one_node);
0019d498 6571 gfc_add_modify (&init, partial, tmp);
6de9cd9a
DN
6572 }
6573 else
0019d498 6574 partial = NULL_TREE;
6de9cd9a
DN
6575
6576 /* The naming of stmt_unpacked and stmt_packed may be counter-intuitive
6577 here, however I think it does the right thing. */
6578 if (no_repack)
6579 {
6580 /* Set the first stride. */
568e8e1e 6581 stride = gfc_conv_descriptor_stride_get (dumdesc, gfc_rank_cst[0]);
0019d498 6582 stride = gfc_evaluate_now (stride, &init);
6de9cd9a 6583
63ee5404 6584 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
94471a56
TB
6585 stride, gfc_index_zero_node);
6586 tmp = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
6587 tmp, gfc_index_one_node, stride);
6de9cd9a 6588 stride = GFC_TYPE_ARRAY_STRIDE (type, 0);
0019d498 6589 gfc_add_modify (&init, stride, tmp);
6de9cd9a
DN
6590
6591 /* Allow the user to disable array repacking. */
6592 stmt_unpacked = NULL_TREE;
6593 }
6594 else
6595 {
6e45f57b 6596 gcc_assert (integer_onep (GFC_TYPE_ARRAY_STRIDE (type, 0)));
1f2959f0 6597 /* A library call to repack the array if necessary. */
6de9cd9a 6598 tmp = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
db3927fb
AH
6599 stmt_unpacked = build_call_expr_loc (input_location,
6600 gfor_fndecl_in_pack, 1, tmp);
6de9cd9a 6601
7ab92584 6602 stride = gfc_index_one_node;
bdfd2ff0 6603
73e42eef 6604 if (warn_array_temporaries)
48749dbc
MLI
6605 gfc_warning (OPT_Warray_temporaries,
6606 "Creating array temporary at %L", &loc);
6de9cd9a
DN
6607 }
6608
6609 /* This is for the case where the array data is used directly without
6610 calling the repack function. */
6611 if (no_repack || partial != NULL_TREE)
4c73896d 6612 stmt_packed = gfc_conv_descriptor_data_get (dumdesc);
6de9cd9a
DN
6613 else
6614 stmt_packed = NULL_TREE;
6615
6616 /* Assign the data pointer. */
6617 if (stmt_packed != NULL_TREE && stmt_unpacked != NULL_TREE)
6618 {
6619 /* Don't repack unknown shape arrays when the first stride is 1. */
94471a56
TB
6620 tmp = fold_build3_loc (input_location, COND_EXPR, TREE_TYPE (stmt_packed),
6621 partial, stmt_packed, stmt_unpacked);
6de9cd9a
DN
6622 }
6623 else
6624 tmp = stmt_packed != NULL_TREE ? stmt_packed : stmt_unpacked;
0019d498 6625 gfc_add_modify (&init, tmpdesc, fold_convert (type, tmp));
6de9cd9a 6626
7ab92584
SB
6627 offset = gfc_index_zero_node;
6628 size = gfc_index_one_node;
6de9cd9a
DN
6629
6630 /* Evaluate the bounds of the array. */
f3b0bb7a 6631 for (n = 0; n < as->rank; n++)
6de9cd9a 6632 {
f3b0bb7a 6633 if (checkparm || !as->upper[n])
6de9cd9a
DN
6634 {
6635 /* Get the bounds of the actual parameter. */
568e8e1e
PT
6636 dubound = gfc_conv_descriptor_ubound_get (dumdesc, gfc_rank_cst[n]);
6637 dlbound = gfc_conv_descriptor_lbound_get (dumdesc, gfc_rank_cst[n]);
6de9cd9a
DN
6638 }
6639 else
0019d498 6640 {
6de9cd9a
DN
6641 dubound = NULL_TREE;
6642 dlbound = NULL_TREE;
0019d498 6643 }
6de9cd9a
DN
6644
6645 lbound = GFC_TYPE_ARRAY_LBOUND (type, n);
6646 if (!INTEGER_CST_P (lbound))
0019d498
DK
6647 {
6648 gfc_init_se (&se, NULL);
f3b0bb7a 6649 gfc_conv_expr_type (&se, as->lower[n],
0019d498
DK
6650 gfc_array_index_type);
6651 gfc_add_block_to_block (&init, &se.pre);
6652 gfc_add_modify (&init, lbound, se.expr);
6653 }
6de9cd9a
DN
6654
6655 ubound = GFC_TYPE_ARRAY_UBOUND (type, n);
6656 /* Set the desired upper bound. */
f3b0bb7a 6657 if (as->upper[n])
6de9cd9a
DN
6658 {
6659 /* We know what we want the upper bound to be. */
0019d498
DK
6660 if (!INTEGER_CST_P (ubound))
6661 {
6de9cd9a 6662 gfc_init_se (&se, NULL);
f3b0bb7a 6663 gfc_conv_expr_type (&se, as->upper[n],
0019d498
DK
6664 gfc_array_index_type);
6665 gfc_add_block_to_block (&init, &se.pre);
6666 gfc_add_modify (&init, ubound, se.expr);
6667 }
6de9cd9a
DN
6668
6669 /* Check the sizes match. */
6670 if (checkparm)
6671 {
6672 /* Check (ubound(a) - lbound(a) == ubound(b) - lbound(b)). */
dd18a33b 6673 char * msg;
6c559604 6674 tree temp;
6de9cd9a 6675
94471a56
TB
6676 temp = fold_build2_loc (input_location, MINUS_EXPR,
6677 gfc_array_index_type, ubound, lbound);
6678 temp = fold_build2_loc (input_location, PLUS_EXPR,
6679 gfc_array_index_type,
6680 gfc_index_one_node, temp);
6681 stride2 = fold_build2_loc (input_location, MINUS_EXPR,
6682 gfc_array_index_type, dubound,
6683 dlbound);
6684 stride2 = fold_build2_loc (input_location, PLUS_EXPR,
6685 gfc_array_index_type,
6686 gfc_index_one_node, stride2);
6687 tmp = fold_build2_loc (input_location, NE_EXPR,
6688 gfc_array_index_type, temp, stride2);
1a33dc9e
UB
6689 msg = xasprintf ("Dimension %d of array '%s' has extent "
6690 "%%ld instead of %%ld", n+1, sym->name);
6c559604 6691
f04986a9 6692 gfc_trans_runtime_check (true, false, tmp, &init, &loc, msg,
6c559604
SK
6693 fold_convert (long_integer_type_node, temp),
6694 fold_convert (long_integer_type_node, stride2));
6695
cede9502 6696 free (msg);
6de9cd9a
DN
6697 }
6698 }
6699 else
6700 {
6701 /* For assumed shape arrays move the upper bound by the same amount
6702 as the lower bound. */
94471a56
TB
6703 tmp = fold_build2_loc (input_location, MINUS_EXPR,
6704 gfc_array_index_type, dubound, dlbound);
6705 tmp = fold_build2_loc (input_location, PLUS_EXPR,
6706 gfc_array_index_type, tmp, lbound);
0019d498 6707 gfc_add_modify (&init, ubound, tmp);
6de9cd9a 6708 }
f7b529fa 6709 /* The offset of this dimension. offset = offset - lbound * stride. */
94471a56
TB
6710 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
6711 lbound, stride);
6712 offset = fold_build2_loc (input_location, MINUS_EXPR,
6713 gfc_array_index_type, offset, tmp);
6de9cd9a
DN
6714
6715 /* The size of this dimension, and the stride of the next. */
f3b0bb7a 6716 if (n + 1 < as->rank)
0019d498
DK
6717 {
6718 stride = GFC_TYPE_ARRAY_STRIDE (type, n + 1);
6de9cd9a 6719
0019d498
DK
6720 if (no_repack || partial != NULL_TREE)
6721 stmt_unpacked =
6722 gfc_conv_descriptor_stride_get (dumdesc, gfc_rank_cst[n+1]);
6de9cd9a 6723
0019d498
DK
6724 /* Figure out the stride if not a known constant. */
6725 if (!INTEGER_CST_P (stride))
6726 {
6727 if (no_repack)
6728 stmt_packed = NULL_TREE;
6729 else
6730 {
6731 /* Calculate stride = size * (ubound + 1 - lbound). */
94471a56
TB
6732 tmp = fold_build2_loc (input_location, MINUS_EXPR,
6733 gfc_array_index_type,
6734 gfc_index_one_node, lbound);
6735 tmp = fold_build2_loc (input_location, PLUS_EXPR,
6736 gfc_array_index_type, ubound, tmp);
6737 size = fold_build2_loc (input_location, MULT_EXPR,
6738 gfc_array_index_type, size, tmp);
0019d498
DK
6739 stmt_packed = size;
6740 }
6de9cd9a 6741
0019d498
DK
6742 /* Assign the stride. */
6743 if (stmt_packed != NULL_TREE && stmt_unpacked != NULL_TREE)
94471a56
TB
6744 tmp = fold_build3_loc (input_location, COND_EXPR,
6745 gfc_array_index_type, partial,
6746 stmt_unpacked, stmt_packed);
0019d498
DK
6747 else
6748 tmp = (stmt_packed != NULL_TREE) ? stmt_packed : stmt_unpacked;
6749 gfc_add_modify (&init, stride, tmp);
6750 }
6751 }
417ab240
JJ
6752 else
6753 {
6754 stride = GFC_TYPE_ARRAY_SIZE (type);
6755
6756 if (stride && !INTEGER_CST_P (stride))
6757 {
6758 /* Calculate size = stride * (ubound + 1 - lbound). */
94471a56
TB
6759 tmp = fold_build2_loc (input_location, MINUS_EXPR,
6760 gfc_array_index_type,
6761 gfc_index_one_node, lbound);
6762 tmp = fold_build2_loc (input_location, PLUS_EXPR,
6763 gfc_array_index_type,
6764 ubound, tmp);
6765 tmp = fold_build2_loc (input_location, MULT_EXPR,
6766 gfc_array_index_type,
6767 GFC_TYPE_ARRAY_STRIDE (type, n), tmp);
0019d498 6768 gfc_add_modify (&init, stride, tmp);
417ab240
JJ
6769 }
6770 }
6de9cd9a
DN
6771 }
6772
d73b65b6
TB
6773 gfc_trans_array_cobounds (type, &init, sym);
6774
6de9cd9a 6775 /* Set the offset. */
d168c883 6776 if (VAR_P (GFC_TYPE_ARRAY_OFFSET (type)))
0019d498 6777 gfc_add_modify (&init, GFC_TYPE_ARRAY_OFFSET (type), offset);
6de9cd9a 6778
0019d498 6779 gfc_trans_vla_type_sizes (sym, &init);
417ab240 6780
0019d498 6781 stmtInit = gfc_finish_block (&init);
6de9cd9a
DN
6782
6783 /* Only do the entry/initialization code if the arg is present. */
6784 dumdesc = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
d198b59a
JJ
6785 optional_arg = (sym->attr.optional
6786 || (sym->ns->proc_name->attr.entry_master
6787 && sym->attr.dummy));
3d79abbd 6788 if (optional_arg)
6de9cd9a 6789 {
892c7427
TB
6790 tree zero_init = fold_convert (TREE_TYPE (tmpdesc), null_pointer_node);
6791 zero_init = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
6792 tmpdesc, zero_init);
6793 tmp = gfc_conv_expr_present (sym, true);
6794 stmtInit = build3_v (COND_EXPR, tmp, stmtInit, zero_init);
6de9cd9a 6795 }
6de9cd9a
DN
6796
6797 /* Cleanup code. */
0019d498
DK
6798 if (no_repack)
6799 stmtCleanup = NULL_TREE;
6800 else
6de9cd9a 6801 {
0019d498 6802 stmtblock_t cleanup;
6de9cd9a 6803 gfc_start_block (&cleanup);
0019d498 6804
6de9cd9a
DN
6805 if (sym->attr.intent != INTENT_IN)
6806 {
6807 /* Copy the data back. */
db3927fb
AH
6808 tmp = build_call_expr_loc (input_location,
6809 gfor_fndecl_in_unpack, 2, dumdesc, tmpdesc);
6de9cd9a
DN
6810 gfc_add_expr_to_block (&cleanup, tmp);
6811 }
6812
6813 /* Free the temporary. */
1529b8d9 6814 tmp = gfc_call_free (tmpdesc);
6de9cd9a
DN
6815 gfc_add_expr_to_block (&cleanup, tmp);
6816
0019d498 6817 stmtCleanup = gfc_finish_block (&cleanup);
f04986a9 6818
6de9cd9a 6819 /* Only do the cleanup if the array was repacked. */
b2d83bd2
AV
6820 if (is_classarray)
6821 /* For a class array the dummy array descriptor is in the _class
6822 component. */
6823 tmp = gfc_class_data_get (dumdesc);
6824 else
6825 tmp = build_fold_indirect_ref_loc (input_location, dumdesc);
4c73896d 6826 tmp = gfc_conv_descriptor_data_get (tmp);
63ee5404 6827 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
94471a56 6828 tmp, tmpdesc);
0019d498
DK
6829 stmtCleanup = build3_v (COND_EXPR, tmp, stmtCleanup,
6830 build_empty_stmt (input_location));
6de9cd9a 6831
3d79abbd 6832 if (optional_arg)
0019d498
DK
6833 {
6834 tmp = gfc_conv_expr_present (sym);
6835 stmtCleanup = build3_v (COND_EXPR, tmp, stmtCleanup,
6836 build_empty_stmt (input_location));
6837 }
6de9cd9a 6838 }
0019d498 6839
6de9cd9a
DN
6840 /* We don't need to free any memory allocated by internal_pack as it will
6841 be freed at the end of the function by pop_context. */
0019d498 6842 gfc_add_init_cleanup (block, stmtInit, stmtCleanup);
363aab21
MM
6843
6844 gfc_restore_backend_locus (&loc);
6de9cd9a
DN
6845}
6846
6847
1d6b7f39 6848/* Calculate the overall offset, including subreferences. */
bbf18dc5 6849void
1d6b7f39
PT
6850gfc_get_dataptr_offset (stmtblock_t *block, tree parm, tree desc, tree offset,
6851 bool subref, gfc_expr *expr)
6852{
6853 tree tmp;
6854 tree field;
6855 tree stride;
6856 tree index;
6857 gfc_ref *ref;
6858 gfc_se start;
6859 int n;
6860
6861 /* If offset is NULL and this is not a subreferenced array, there is
6862 nothing to do. */
6863 if (offset == NULL_TREE)
6864 {
6865 if (subref)
6866 offset = gfc_index_zero_node;
6867 else
6868 return;
6869 }
6870
f3b0bb7a 6871 tmp = build_array_ref (desc, offset, NULL, NULL);
1d6b7f39
PT
6872
6873 /* Offset the data pointer for pointer assignments from arrays with
df2fba9e 6874 subreferences; e.g. my_integer => my_type(:)%integer_component. */
1d6b7f39
PT
6875 if (subref)
6876 {
6877 /* Go past the array reference. */
6878 for (ref = expr->ref; ref; ref = ref->next)
6879 if (ref->type == REF_ARRAY &&
6880 ref->u.ar.type != AR_ELEMENT)
6881 {
6882 ref = ref->next;
6883 break;
6884 }
6885
6886 /* Calculate the offset for each subsequent subreference. */
6887 for (; ref; ref = ref->next)
6888 {
6889 switch (ref->type)
6890 {
6891 case REF_COMPONENT:
6892 field = ref->u.c.component->backend_decl;
6893 gcc_assert (field && TREE_CODE (field) == FIELD_DECL);
94471a56
TB
6894 tmp = fold_build3_loc (input_location, COMPONENT_REF,
6895 TREE_TYPE (field),
6896 tmp, field, NULL_TREE);
1d6b7f39
PT
6897 break;
6898
6899 case REF_SUBSTRING:
6900 gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE);
6901 gfc_init_se (&start, NULL);
6902 gfc_conv_expr_type (&start, ref->u.ss.start, gfc_charlen_type_node);
6903 gfc_add_block_to_block (block, &start.pre);
6904 tmp = gfc_build_array_ref (tmp, start.expr, NULL);
6905 break;
6906
6907 case REF_ARRAY:
6908 gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE
6909 && ref->u.ar.type == AR_ELEMENT);
6910
6911 /* TODO - Add bounds checking. */
6912 stride = gfc_index_one_node;
6913 index = gfc_index_zero_node;
6914 for (n = 0; n < ref->u.ar.dimen; n++)
6915 {
6916 tree itmp;
6917 tree jtmp;
6918
6919 /* Update the index. */
6920 gfc_init_se (&start, NULL);
6921 gfc_conv_expr_type (&start, ref->u.ar.start[n], gfc_array_index_type);
6922 itmp = gfc_evaluate_now (start.expr, block);
6923 gfc_init_se (&start, NULL);
6924 gfc_conv_expr_type (&start, ref->u.ar.as->lower[n], gfc_array_index_type);
6925 jtmp = gfc_evaluate_now (start.expr, block);
94471a56
TB
6926 itmp = fold_build2_loc (input_location, MINUS_EXPR,
6927 gfc_array_index_type, itmp, jtmp);
6928 itmp = fold_build2_loc (input_location, MULT_EXPR,
6929 gfc_array_index_type, itmp, stride);
6930 index = fold_build2_loc (input_location, PLUS_EXPR,
6931 gfc_array_index_type, itmp, index);
1d6b7f39
PT
6932 index = gfc_evaluate_now (index, block);
6933
6934 /* Update the stride. */
6935 gfc_init_se (&start, NULL);
6936 gfc_conv_expr_type (&start, ref->u.ar.as->upper[n], gfc_array_index_type);
94471a56
TB
6937 itmp = fold_build2_loc (input_location, MINUS_EXPR,
6938 gfc_array_index_type, start.expr,
6939 jtmp);
6940 itmp = fold_build2_loc (input_location, PLUS_EXPR,
6941 gfc_array_index_type,
6942 gfc_index_one_node, itmp);
6943 stride = fold_build2_loc (input_location, MULT_EXPR,
6944 gfc_array_index_type, stride, itmp);
1d6b7f39
PT
6945 stride = gfc_evaluate_now (stride, block);
6946 }
6947
6948 /* Apply the index to obtain the array element. */
6949 tmp = gfc_build_array_ref (tmp, index, NULL);
6950 break;
6951
9de42a8e
PT
6952 case REF_INQUIRY:
6953 switch (ref->u.i)
6954 {
6955 case INQUIRY_RE:
6956 tmp = fold_build1_loc (input_location, REALPART_EXPR,
6957 TREE_TYPE (TREE_TYPE (tmp)), tmp);
6958 break;
6959
6960 case INQUIRY_IM:
6961 tmp = fold_build1_loc (input_location, IMAGPART_EXPR,
6962 TREE_TYPE (TREE_TYPE (tmp)), tmp);
6963 break;
6964
6965 default:
6966 break;
6967 }
6968 break;
6969
1d6b7f39
PT
6970 default:
6971 gcc_unreachable ();
6972 break;
6973 }
6974 }
6975 }
6976
6977 /* Set the target data pointer. */
6978 offset = gfc_build_addr_expr (gfc_array_dataptr_type (desc), tmp);
6979 gfc_conv_descriptor_data_set (block, parm, offset);
6980}
6981
6982
5d63a35f
PT
6983/* gfc_conv_expr_descriptor needs the string length an expression
6984 so that the size of the temporary can be obtained. This is done
6985 by adding up the string lengths of all the elements in the
6986 expression. Function with non-constant expressions have their
6987 string lengths mapped onto the actual arguments using the
6988 interface mapping machinery in trans-expr.c. */
0a164a3c 6989static void
5d63a35f 6990get_array_charlen (gfc_expr *expr, gfc_se *se)
0a164a3c
PT
6991{
6992 gfc_interface_mapping mapping;
6993 gfc_formal_arglist *formal;
6994 gfc_actual_arglist *arg;
6995 gfc_se tse;
d5f48c7c 6996 gfc_expr *e;
0a164a3c 6997
bc21d315
JW
6998 if (expr->ts.u.cl->length
6999 && gfc_is_constant_expr (expr->ts.u.cl->length))
0a164a3c 7000 {
bc21d315
JW
7001 if (!expr->ts.u.cl->backend_decl)
7002 gfc_conv_string_length (expr->ts.u.cl, expr, &se->pre);
5d63a35f 7003 return;
0a164a3c
PT
7004 }
7005
5d63a35f
PT
7006 switch (expr->expr_type)
7007 {
d5f48c7c
PT
7008 case EXPR_ARRAY:
7009
7010 /* This is somewhat brutal. The expression for the first
7011 element of the array is evaluated and assigned to a
7012 new string length for the original expression. */
7013 e = gfc_constructor_first (expr->value.constructor)->expr;
7014
7015 gfc_init_se (&tse, NULL);
7016 if (e->rank)
7017 gfc_conv_expr_descriptor (&tse, e);
7018 else
7019 gfc_conv_expr (&tse, e);
7020
7021 gfc_add_block_to_block (&se->pre, &tse.pre);
7022 gfc_add_block_to_block (&se->post, &tse.post);
7023
7024 if (!expr->ts.u.cl->backend_decl || !VAR_P (expr->ts.u.cl->backend_decl))
7025 {
7026 expr->ts.u.cl = gfc_new_charlen (gfc_current_ns, NULL);
7027 expr->ts.u.cl->backend_decl =
7028 gfc_create_var (gfc_charlen_type_node, "sln");
7029 }
7030
7031 gfc_add_modify (&se->pre, expr->ts.u.cl->backend_decl,
7032 tse.string_length);
7033
7034 return;
7035
5d63a35f
PT
7036 case EXPR_OP:
7037 get_array_charlen (expr->value.op.op1, se);
7038
bc21d315 7039 /* For parentheses the expression ts.u.cl is identical. */
5d63a35f
PT
7040 if (expr->value.op.op == INTRINSIC_PARENTHESES)
7041 return;
7042
d5f48c7c 7043 expr->ts.u.cl->backend_decl =
5d63a35f
PT
7044 gfc_create_var (gfc_charlen_type_node, "sln");
7045
7046 if (expr->value.op.op2)
7047 {
7048 get_array_charlen (expr->value.op.op2, se);
7049
71a7778c
PT
7050 gcc_assert (expr->value.op.op == INTRINSIC_CONCAT);
7051
5d63a35f
PT
7052 /* Add the string lengths and assign them to the expression
7053 string length backend declaration. */
bc21d315 7054 gfc_add_modify (&se->pre, expr->ts.u.cl->backend_decl,
94471a56
TB
7055 fold_build2_loc (input_location, PLUS_EXPR,
7056 gfc_charlen_type_node,
bc21d315
JW
7057 expr->value.op.op1->ts.u.cl->backend_decl,
7058 expr->value.op.op2->ts.u.cl->backend_decl));
5d63a35f
PT
7059 }
7060 else
bc21d315
JW
7061 gfc_add_modify (&se->pre, expr->ts.u.cl->backend_decl,
7062 expr->value.op.op1->ts.u.cl->backend_decl);
5d63a35f
PT
7063 break;
7064
7065 case EXPR_FUNCTION:
7066 if (expr->value.function.esym == NULL
bc21d315 7067 || expr->ts.u.cl->length->expr_type == EXPR_CONSTANT)
5d63a35f 7068 {
bc21d315 7069 gfc_conv_string_length (expr->ts.u.cl, expr, &se->pre);
5d63a35f
PT
7070 break;
7071 }
7072
7073 /* Map expressions involving the dummy arguments onto the actual
7074 argument expressions. */
7075 gfc_init_interface_mapping (&mapping);
4cbc9039 7076 formal = gfc_sym_get_dummy_args (expr->symtree->n.sym);
5d63a35f
PT
7077 arg = expr->value.function.actual;
7078
7079 /* Set se = NULL in the calls to the interface mapping, to suppress any
7080 backend stuff. */
7081 for (; arg != NULL; arg = arg->next, formal = formal ? formal->next : NULL)
7082 {
7083 if (!arg->expr)
7084 continue;
7085 if (formal->sym)
7086 gfc_add_interface_mapping (&mapping, formal->sym, NULL, arg->expr);
7087 }
7088
7089 gfc_init_se (&tse, NULL);
7090
7091 /* Build the expression for the character length and convert it. */
bc21d315 7092 gfc_apply_interface_mapping (&mapping, &tse, expr->ts.u.cl->length);
0a164a3c 7093
5d63a35f
PT
7094 gfc_add_block_to_block (&se->pre, &tse.pre);
7095 gfc_add_block_to_block (&se->post, &tse.post);
7096 tse.expr = fold_convert (gfc_charlen_type_node, tse.expr);
94471a56 7097 tse.expr = fold_build2_loc (input_location, MAX_EXPR,
f622221a
JB
7098 TREE_TYPE (tse.expr), tse.expr,
7099 build_zero_cst (TREE_TYPE (tse.expr)));
bc21d315 7100 expr->ts.u.cl->backend_decl = tse.expr;
5d63a35f
PT
7101 gfc_free_interface_mapping (&mapping);
7102 break;
0a164a3c 7103
5d63a35f 7104 default:
bc21d315 7105 gfc_conv_string_length (expr->ts.u.cl, expr, &se->pre);
5d63a35f
PT
7106 break;
7107 }
0a164a3c
PT
7108}
7109
cb4b9eae 7110
b4e9d41d
MM
7111/* Helper function to check dimensions. */
7112static bool
a7fb208d 7113transposed_dims (gfc_ss *ss)
b4e9d41d
MM
7114{
7115 int n;
a7fb208d 7116
cb4b9eae
MM
7117 for (n = 0; n < ss->dimen; n++)
7118 if (ss->dim[n] != n)
a7fb208d
MM
7119 return true;
7120 return false;
b4e9d41d 7121}
0a164a3c 7122
2960a368
TB
7123
7124/* Convert the last ref of a scalar coarray from an AR_ELEMENT to an
7125 AR_FULL, suitable for the scalarizer. */
7126
7127static gfc_ss *
7128walk_coarray (gfc_expr *e)
7129{
7130 gfc_ss *ss;
7131
7132 gcc_assert (gfc_get_corank (e) > 0);
7133
7134 ss = gfc_walk_expr (e);
7135
7136 /* Fix scalar coarray. */
7137 if (ss == gfc_ss_terminator)
7138 {
7139 gfc_ref *ref;
7140
7141 ref = e->ref;
7142 while (ref)
7143 {
7144 if (ref->type == REF_ARRAY
7145 && ref->u.ar.codimen > 0)
7146 break;
7147
7148 ref = ref->next;
7149 }
7150
7151 gcc_assert (ref != NULL);
7152 if (ref->u.ar.type == AR_ELEMENT)
7153 ref->u.ar.type = AR_SECTION;
7154 ss = gfc_reverse_ss (gfc_walk_array_ref (ss, e, ref));
7155 }
7156
7157 return ss;
7158}
7159
7160
7a70c12d 7161/* Convert an array for passing as an actual argument. Expressions and
7ab92584 7162 vector subscripts are evaluated and stored in a temporary, which is then
6de9cd9a
DN
7163 passed. For whole arrays the descriptor is passed. For array sections
7164 a modified copy of the descriptor is passed, but using the original data.
7a70c12d
RS
7165
7166 This function is also used for array pointer assignments, and there
7167 are three cases:
7168
3e90ac4e 7169 - se->want_pointer && !se->direct_byref
7a70c12d
RS
7170 EXPR is an actual argument. On exit, se->expr contains a
7171 pointer to the array descriptor.
7172
3e90ac4e 7173 - !se->want_pointer && !se->direct_byref
7a70c12d
RS
7174 EXPR is an actual argument to an intrinsic function or the
7175 left-hand side of a pointer assignment. On exit, se->expr
7176 contains the descriptor for EXPR.
7177
3e90ac4e 7178 - !se->want_pointer && se->direct_byref
7a70c12d
RS
7179 EXPR is the right-hand side of a pointer assignment and
7180 se->expr is the descriptor for the previously-evaluated
7181 left-hand side. The function creates an assignment from
f04986a9 7182 EXPR to se->expr.
0b4f2770
MM
7183
7184
7185 The se->force_tmp flag disables the non-copying descriptor optimization
7186 that is used for transpose. It may be used in cases where there is an
7187 alias between the transpose argument and another argument in the same
7188 function call. */
6de9cd9a
DN
7189
7190void
2960a368 7191gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
6de9cd9a 7192{
2960a368 7193 gfc_ss *ss;
bcc4d4e0 7194 gfc_ss_type ss_type;
f98cfd3c 7195 gfc_ss_info *ss_info;
6de9cd9a 7196 gfc_loopinfo loop;
6d63e468 7197 gfc_array_info *info;
6de9cd9a
DN
7198 int need_tmp;
7199 int n;
7200 tree tmp;
7201 tree desc;
7202 stmtblock_t block;
7203 tree start;
7204 tree offset;
7205 int full;
1d6b7f39 7206 bool subref_array_target = false;
9d44426f 7207 bool deferred_array_component = false;
f98cfd3c 7208 gfc_expr *arg, *ss_expr;
6de9cd9a 7209
2960a368
TB
7210 if (se->want_coarray)
7211 ss = walk_coarray (expr);
7212 else
7213 ss = gfc_walk_expr (expr);
7214
0b4f2770 7215 gcc_assert (ss != NULL);
6e45f57b 7216 gcc_assert (ss != gfc_ss_terminator);
6de9cd9a 7217
f98cfd3c
MM
7218 ss_info = ss->info;
7219 ss_type = ss_info->type;
7220 ss_expr = ss_info->expr;
bcc4d4e0 7221
2960a368
TB
7222 /* Special case: TRANSPOSE which needs no temporary. */
7223 while (expr->expr_type == EXPR_FUNCTION && expr->value.function.isym
01512446 7224 && (arg = gfc_get_noncopying_intrinsic_argument (expr)) != NULL)
2960a368
TB
7225 {
7226 /* This is a call to transpose which has already been handled by the
7227 scalarizer, so that we just need to get its argument's descriptor. */
7228 gcc_assert (expr->value.function.isym->id == GFC_ISYM_TRANSPOSE);
7229 expr = expr->value.function.actual->expr;
7230 }
7231
fc90a8f2
PB
7232 /* Special case things we know we can pass easily. */
7233 switch (expr->expr_type)
6de9cd9a 7234 {
fc90a8f2
PB
7235 case EXPR_VARIABLE:
7236 /* If we have a linear array section, we can pass it directly.
7237 Otherwise we need to copy it into a temporary. */
6de9cd9a 7238
bcc4d4e0 7239 gcc_assert (ss_type == GFC_SS_SECTION);
f98cfd3c 7240 gcc_assert (ss_expr == expr);
1838afec 7241 info = &ss_info->data.array;
6de9cd9a
DN
7242
7243 /* Get the descriptor for the array. */
0b4f2770 7244 gfc_conv_ss_descriptor (&se->pre, ss, 0);
6de9cd9a 7245 desc = info->descriptor;
7a70c12d 7246
9d44426f
PT
7247 /* The charlen backend decl for deferred character components cannot
7248 be used because it is fixed at zero. Instead, the hidden string
7249 length component is used. */
7250 if (expr->ts.type == BT_CHARACTER
7251 && expr->ts.deferred
7252 && TREE_CODE (desc) == COMPONENT_REF)
7253 deferred_array_component = true;
7254
1d6b7f39
PT
7255 subref_array_target = se->direct_byref && is_subref_array (expr);
7256 need_tmp = gfc_ref_needs_temporary_p (expr->ref)
7257 && !subref_array_target;
7258
0b4f2770
MM
7259 if (se->force_tmp)
7260 need_tmp = 1;
0a524296
PT
7261 else if (se->force_no_tmp)
7262 need_tmp = 0;
0b4f2770 7263
7a70c12d
RS
7264 if (need_tmp)
7265 full = 0;
7266 else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
6de9cd9a
DN
7267 {
7268 /* Create a new descriptor if the array doesn't have one. */
7269 full = 0;
7270 }
2960a368 7271 else if (info->ref->u.ar.type == AR_FULL || se->descriptor_only)
6de9cd9a
DN
7272 full = 1;
7273 else if (se->direct_byref)
7274 full = 0;
7275 else
a61a36ab 7276 full = gfc_full_array_ref_p (info->ref, NULL);
ca2940c3 7277
a7fb208d 7278 if (full && !transposed_dims (ss))
6de9cd9a 7279 {
99d821c0 7280 if (se->direct_byref && !se->byref_noassign)
6de9cd9a
DN
7281 {
7282 /* Copy the descriptor for pointer assignments. */
726a989a 7283 gfc_add_modify (&se->pre, se->expr, desc);
1d6b7f39
PT
7284
7285 /* Add any offsets from subreferences. */
7286 gfc_get_dataptr_offset (&se->pre, se->expr, desc, NULL_TREE,
7287 subref_array_target, expr);
ff3598bc
PT
7288
7289 /* ....and set the span field. */
f82f425b 7290 tmp = gfc_get_array_span (desc, expr);
ba08c70a 7291 if (tmp != NULL_TREE && !integer_zerop (tmp))
e8db6cd5 7292 gfc_conv_descriptor_span_set (&se->pre, se->expr, tmp);
6de9cd9a
DN
7293 }
7294 else if (se->want_pointer)
7295 {
7296 /* We pass full arrays directly. This means that pointers and
fc90a8f2 7297 allocatable arrays should also work. */
628c189e 7298 se->expr = gfc_build_addr_expr (NULL_TREE, desc);
6de9cd9a
DN
7299 }
7300 else
7301 {
7302 se->expr = desc;
7303 }
ca2940c3 7304
9d44426f 7305 if (expr->ts.type == BT_CHARACTER && !deferred_array_component)
ca2940c3 7306 se->string_length = gfc_get_expr_charlen (expr);
9d44426f
PT
7307 /* The ss_info string length is returned set to the value of the
7308 hidden string length component. */
7309 else if (deferred_array_component)
7310 se->string_length = ss_info->string_length;
ca2940c3 7311
2960a368 7312 gfc_free_ss_chain (ss);
6de9cd9a
DN
7313 return;
7314 }
fc90a8f2 7315 break;
f04986a9 7316
fc90a8f2
PB
7317 case EXPR_FUNCTION:
7318 /* A transformational function return value will be a temporary
7319 array descriptor. We still need to go through the scalarizer
eea58adb 7320 to create the descriptor. Elemental functions are handled as
e7dc5b4f 7321 arbitrary expressions, i.e. copy to a temporary. */
fc90a8f2
PB
7322
7323 if (se->direct_byref)
7324 {
f98cfd3c 7325 gcc_assert (ss_type == GFC_SS_FUNCTION && ss_expr == expr);
fc90a8f2
PB
7326
7327 /* For pointer assignments pass the descriptor directly. */
0b4f2770
MM
7328 if (se->ss == NULL)
7329 se->ss = ss;
7330 else
7331 gcc_assert (se->ss == ss);
ff3598bc
PT
7332
7333 if (!is_pointer_array (se->expr))
7334 {
7335 tmp = gfc_get_element_type (TREE_TYPE (se->expr));
7336 tmp = fold_convert (gfc_array_index_type,
7337 size_in_bytes (tmp));
7338 gfc_conv_descriptor_span_set (&se->pre, se->expr, tmp);
7339 }
7340
628c189e 7341 se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
fc90a8f2 7342 gfc_conv_expr (se, expr);
ff3598bc 7343
2960a368 7344 gfc_free_ss_chain (ss);
fc90a8f2
PB
7345 return;
7346 }
7347
f98cfd3c 7348 if (ss_expr != expr || ss_type != GFC_SS_FUNCTION)
fc90a8f2 7349 {
f98cfd3c 7350 if (ss_expr != expr)
bef6486a
MM
7351 /* Elemental function. */
7352 gcc_assert ((expr->value.function.esym != NULL
7353 && expr->value.function.esym->attr.elemental)
7354 || (expr->value.function.isym != NULL
0c08de8f
MM
7355 && expr->value.function.isym->elemental)
7356 || gfc_inline_intrinsic_function_p (expr));
bef6486a 7357 else
bcc4d4e0 7358 gcc_assert (ss_type == GFC_SS_INTRINSIC);
bef6486a 7359
fc90a8f2 7360 need_tmp = 1;
0a164a3c 7361 if (expr->ts.type == BT_CHARACTER
bc21d315 7362 && expr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
5d63a35f 7363 get_array_charlen (expr, se);
0a164a3c 7364
fc90a8f2
PB
7365 info = NULL;
7366 }
7367 else
7368 {
7369 /* Transformational function. */
1838afec 7370 info = &ss_info->data.array;
fc90a8f2
PB
7371 need_tmp = 0;
7372 }
7373 break;
7374
114e4d10
RS
7375 case EXPR_ARRAY:
7376 /* Constant array constructors don't need a temporary. */
bcc4d4e0 7377 if (ss_type == GFC_SS_CONSTRUCTOR
114e4d10
RS
7378 && expr->ts.type != BT_CHARACTER
7379 && gfc_constant_array_constructor_p (expr->value.constructor))
7380 {
7381 need_tmp = 0;
1838afec 7382 info = &ss_info->data.array;
114e4d10
RS
7383 }
7384 else
7385 {
7386 need_tmp = 1;
114e4d10
RS
7387 info = NULL;
7388 }
7389 break;
7390
fc90a8f2
PB
7391 default:
7392 /* Something complicated. Copy it into a temporary. */
6de9cd9a 7393 need_tmp = 1;
6de9cd9a 7394 info = NULL;
fc90a8f2 7395 break;
6de9cd9a
DN
7396 }
7397
0b4f2770
MM
7398 /* If we are creating a temporary, we don't need to bother about aliases
7399 anymore. */
7400 if (need_tmp)
7401 se->force_tmp = 0;
7402
6de9cd9a
DN
7403 gfc_init_loopinfo (&loop);
7404
7405 /* Associate the SS with the loop. */
7406 gfc_add_ss_to_loop (&loop, ss);
7407
13413760 7408 /* Tell the scalarizer not to bother creating loop variables, etc. */
6de9cd9a
DN
7409 if (!need_tmp)
7410 loop.array_parameter = 1;
7411 else
7a70c12d
RS
7412 /* The right-hand side of a pointer assignment mustn't use a temporary. */
7413 gcc_assert (!se->direct_byref);
6de9cd9a 7414
980fa45e
TK
7415 /* Do we need bounds checking or not? */
7416 ss->no_bounds_check = expr->no_bounds_check;
7417
6de9cd9a
DN
7418 /* Setup the scalarizing loops and bounds. */
7419 gfc_conv_ss_startstride (&loop);
7420
7421 if (need_tmp)
7422 {
d5f48c7c
PT
7423 if (expr->ts.type == BT_CHARACTER
7424 && (!expr->ts.u.cl->backend_decl || expr->expr_type == EXPR_ARRAY))
5d63a35f 7425 get_array_charlen (expr, se);
07368af0 7426
a1ae4f43
MM
7427 /* Tell the scalarizer to make a temporary. */
7428 loop.temp_ss = gfc_get_temp_ss (gfc_typenode_for_spec (&expr->ts),
7429 ((expr->ts.type == BT_CHARACTER)
7430 ? expr->ts.u.cl->backend_decl
7431 : NULL),
7432 loop.dimen);
07368af0 7433
a0add3be 7434 se->string_length = loop.temp_ss->info->string_length;
cb4b9eae 7435 gcc_assert (loop.temp_ss->dimen == loop.dimen);
6de9cd9a
DN
7436 gfc_add_ss_to_loop (&loop, loop.temp_ss);
7437 }
7438
bdfd2ff0 7439 gfc_conv_loop_setup (&loop, & expr->where);
6de9cd9a
DN
7440
7441 if (need_tmp)
7442 {
7443 /* Copy into a temporary and pass that. We don't need to copy the data
7444 back because expressions and vector subscripts must be INTENT_IN. */
7445 /* TODO: Optimize passing function return values. */
7446 gfc_se lse;
7447 gfc_se rse;
4ee822df 7448 bool deep_copy;
6de9cd9a
DN
7449
7450 /* Start the copying loops. */
7451 gfc_mark_ss_chain_used (loop.temp_ss, 1);
7452 gfc_mark_ss_chain_used (ss, 1);
7453 gfc_start_scalarized_body (&loop, &block);
7454
7455 /* Copy each data element. */
7456 gfc_init_se (&lse, NULL);
7457 gfc_copy_loopinfo_to_se (&lse, &loop);
7458 gfc_init_se (&rse, NULL);
7459 gfc_copy_loopinfo_to_se (&rse, &loop);
7460
7461 lse.ss = loop.temp_ss;
7462 rse.ss = ss;
7463
7464 gfc_conv_scalarized_array_ref (&lse, NULL);
2b052ce2
PT
7465 if (expr->ts.type == BT_CHARACTER)
7466 {
7467 gfc_conv_expr (&rse, expr);
20b1cbc3 7468 if (POINTER_TYPE_P (TREE_TYPE (rse.expr)))
db3927fb
AH
7469 rse.expr = build_fold_indirect_ref_loc (input_location,
7470 rse.expr);
2b052ce2
PT
7471 }
7472 else
7473 gfc_conv_expr_val (&rse, expr);
6de9cd9a
DN
7474
7475 gfc_add_block_to_block (&block, &rse.pre);
7476 gfc_add_block_to_block (&block, &lse.pre);
7477
129c14bd 7478 lse.string_length = rse.string_length;
4ee822df
LK
7479
7480 deep_copy = !se->data_not_needed
7481 && (expr->expr_type == EXPR_VARIABLE
7482 || expr->expr_type == EXPR_ARRAY);
ed673c00 7483 tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts,
4ee822df 7484 deep_copy, false);
129c14bd 7485 gfc_add_expr_to_block (&block, tmp);
6de9cd9a
DN
7486
7487 /* Finish the copying loops. */
7488 gfc_trans_scalarizing_loops (&loop, &block);
7489
1838afec 7490 desc = loop.temp_ss->info->data.array.descriptor;
6de9cd9a 7491 }
a7fb208d 7492 else if (expr->expr_type == EXPR_FUNCTION && !transposed_dims (ss))
fc90a8f2
PB
7493 {
7494 desc = info->descriptor;
a0add3be 7495 se->string_length = ss_info->string_length;
fc90a8f2 7496 }
6de9cd9a
DN
7497 else
7498 {
fc90a8f2
PB
7499 /* We pass sections without copying to a temporary. Make a new
7500 descriptor and point it at the section we want. The loop variable
7501 limits will be the limits of the section.
7502 A function may decide to repack the array to speed up access, but
7503 we're not bothered about that here. */
a3935ffc 7504 int dim, ndim, codim;
6de9cd9a
DN
7505 tree parm;
7506 tree parmtype;
7507 tree stride;
7508 tree from;
7509 tree to;
7510 tree base;
3244f4cd 7511 bool onebased = false, rank_remap;
6de9cd9a 7512
cb4b9eae 7513 ndim = info->ref ? info->ref->u.ar.dimen : ss->dimen;
3244f4cd 7514 rank_remap = ss->dimen < ndim;
c2558afc 7515
23c3d0f9 7516 if (se->want_coarray)
6bd0ce7b 7517 {
7c5950bd
MM
7518 gfc_array_ref *ar = &info->ref->u.ar;
7519
6bd0ce7b 7520 codim = gfc_get_corank (expr);
a04b23d8 7521 for (n = 0; n < codim - 1; n++)
6bd0ce7b 7522 {
065c6f9d 7523 /* Make sure we are not lost somehow. */
a04b23d8 7524 gcc_assert (ar->dimen_type[n + ndim] == DIMEN_THIS_IMAGE);
065c6f9d 7525
621babd8 7526 /* Make sure the call to gfc_conv_section_startstride won't
cf664522 7527 generate unnecessary code to calculate stride. */
a04b23d8 7528 gcc_assert (ar->stride[n + ndim] == NULL);
065c6f9d 7529
cf664522 7530 gfc_conv_section_startstride (&loop.pre, ss, n + ndim);
a04b23d8
MM
7531 loop.from[n + loop.dimen] = info->start[n + ndim];
7532 loop.to[n + loop.dimen] = info->end[n + ndim];
6bd0ce7b
MM
7533 }
7534
a04b23d8 7535 gcc_assert (n == codim - 1);
7c5950bd 7536 evaluate_bound (&loop.pre, info->start, ar->start,
97561cdc
AV
7537 info->descriptor, n + ndim, true,
7538 ar->as->type == AS_DEFERRED);
a04b23d8 7539 loop.from[n + loop.dimen] = info->start[n + ndim];
6bd0ce7b 7540 }
23c3d0f9
MM
7541 else
7542 codim = 0;
7543
fc90a8f2 7544 /* Set the string_length for a character array. */
20c9dc8a 7545 if (expr->ts.type == BT_CHARACTER)
d5f48c7c
PT
7546 {
7547 se->string_length = gfc_get_expr_charlen (expr);
7548 if (VAR_P (se->string_length)
7549 && expr->ts.u.cl->backend_decl == se->string_length)
7550 tmp = ss_info->string_length;
7551 else
7552 tmp = se->string_length;
7553
7554 if (expr->ts.deferred)
7555 gfc_add_modify (&se->pre, expr->ts.u.cl->backend_decl, tmp);
7556 }
20c9dc8a 7557
3244f4cd
AV
7558 /* If we have an array section or are assigning make sure that
7559 the lower bound is 1. References to the full
7560 array should otherwise keep the original bounds. */
7561 if ((!info->ref || info->ref->u.ar.type != AR_FULL) && !se->want_pointer)
7562 for (dim = 0; dim < loop.dimen; dim++)
7563 if (!integer_onep (loop.from[dim]))
7564 {
7565 tmp = fold_build2_loc (input_location, MINUS_EXPR,
7566 gfc_array_index_type, gfc_index_one_node,
7567 loop.from[dim]);
7568 loop.to[dim] = fold_build2_loc (input_location, PLUS_EXPR,
7569 gfc_array_index_type,
7570 loop.to[dim], tmp);
7571 loop.from[dim] = gfc_index_one_node;
7572 }
7573
6de9cd9a 7574 desc = info->descriptor;
99d821c0 7575 if (se->direct_byref && !se->byref_noassign)
6de9cd9a 7576 {
e8db6cd5 7577 /* For pointer assignments we fill in the destination. */
6de9cd9a
DN
7578 parm = se->expr;
7579 parmtype = TREE_TYPE (parm);
7580 }
7581 else
7582 {
7583 /* Otherwise make a new one. */
d5ace305
PT
7584 if (expr->ts.type == BT_CHARACTER && expr->ts.deferred)
7585 parmtype = gfc_typenode_for_spec (&expr->ts);
7586 else
7587 parmtype = gfc_get_element_type (TREE_TYPE (desc));
7588
a7525708
MM
7589 parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen, codim,
7590 loop.from, loop.to, 0,
10174ddf 7591 GFC_ARRAY_UNKNOWN, false);
6de9cd9a 7592 parm = gfc_create_var (parmtype, "parm");
574284e9
AV
7593
7594 /* When expression is a class object, then add the class' handle to
7595 the parm_decl. */
7596 if (expr->ts.type == BT_CLASS && expr->expr_type == EXPR_VARIABLE)
7597 {
7598 gfc_expr *class_expr = gfc_find_and_cut_at_last_class_ref (expr);
7599 gfc_se classse;
7600
7601 /* class_expr can be NULL, when no _class ref is in expr.
7602 We must not fix this here with a gfc_fix_class_ref (). */
7603 if (class_expr)
7604 {
7605 gfc_init_se (&classse, NULL);
7606 gfc_conv_expr (&classse, class_expr);
7607 gfc_free_expr (class_expr);
7608
7609 gcc_assert (classse.pre.head == NULL_TREE
7610 && classse.post.head == NULL_TREE);
7611 gfc_allocate_lang_decl (parm);
7612 GFC_DECL_SAVED_DESCRIPTOR (parm) = classse.expr;
7613 }
7614 }
6de9cd9a
DN
7615 }
7616
e8db6cd5 7617 /* Set the span field. */
d5f48c7c
PT
7618 if (expr->ts.type == BT_CHARACTER && ss_info->string_length)
7619 tmp = ss_info->string_length;
7620 else
7621 tmp = gfc_get_array_span (desc, expr);
e8db6cd5
PT
7622 if (tmp != NULL_TREE)
7623 gfc_conv_descriptor_span_set (&loop.pre, parm, tmp);
7624
7ab92584 7625 offset = gfc_index_zero_node;
6de9cd9a
DN
7626
7627 /* The following can be somewhat confusing. We have two
7628 descriptors, a new one and the original array.
7629 {parm, parmtype, dim} refer to the new one.
0b4f2770 7630 {desc, type, n, loop} refer to the original, which maybe
6de9cd9a 7631 a descriptorless array.
e7dc5b4f 7632 The bounds of the scalarization are the bounds of the section.
6de9cd9a
DN
7633 We don't have to worry about numeric overflows when calculating
7634 the offsets because all elements are within the array data. */
7635
7636 /* Set the dtype. */
7637 tmp = gfc_conv_descriptor_dtype (parm);
726a989a 7638 gfc_add_modify (&loop.pre, tmp, gfc_get_dtype (parmtype));
6de9cd9a 7639
a7d318ea
TB
7640 /* Set offset for assignments to pointer only to zero if it is not
7641 the full array. */
1cf43a1d
PT
7642 if ((se->direct_byref || se->use_offset)
7643 && ((info->ref && info->ref->u.ar.type != AR_FULL)
7644 || (expr->expr_type == EXPR_ARRAY && se->use_offset)))
7ab92584 7645 base = gfc_index_zero_node;
c4ba8848
PT
7646 else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
7647 base = gfc_evaluate_now (gfc_conv_array_offset (desc), &loop.pre);
6de9cd9a
DN
7648 else
7649 base = NULL_TREE;
7650
114e4d10 7651 for (n = 0; n < ndim; n++)
6de9cd9a
DN
7652 {
7653 stride = gfc_conv_array_stride (desc, n);
7654
7655 /* Work out the offset. */
114e4d10
RS
7656 if (info->ref
7657 && info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
6de9cd9a 7658 {
6e45f57b 7659 gcc_assert (info->subscript[n]
bcc4d4e0 7660 && info->subscript[n]->info->type == GFC_SS_SCALAR);
99dd5a29 7661 start = info->subscript[n]->info->data.scalar.value;
6de9cd9a
DN
7662 }
7663 else
7664 {
6de9cd9a 7665 /* Evaluate and remember the start of the section. */
9157ccb2 7666 start = info->start[n];
6de9cd9a
DN
7667 stride = gfc_evaluate_now (stride, &loop.pre);
7668 }
7669
7670 tmp = gfc_conv_array_lbound (desc, n);
94471a56
TB
7671 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp),
7672 start, tmp);
7673 tmp = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (tmp),
7674 tmp, stride);
7675 offset = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (tmp),
7676 offset, tmp);
6de9cd9a 7677
114e4d10
RS
7678 if (info->ref
7679 && info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
6de9cd9a
DN
7680 {
7681 /* For elemental dimensions, we only need the offset. */
7682 continue;
7683 }
7684
7685 /* Vector subscripts need copying and are handled elsewhere. */
114e4d10
RS
7686 if (info->ref)
7687 gcc_assert (info->ref->u.ar.dimen_type[n] == DIMEN_RANGE);
f04986a9 7688
0b4f2770
MM
7689 /* look for the corresponding scalarizer dimension: dim. */
7690 for (dim = 0; dim < ndim; dim++)
cb4b9eae 7691 if (ss->dim[dim] == n)
0b4f2770
MM
7692 break;
7693
7694 /* loop exited early: the DIM being looked for has been found. */
7695 gcc_assert (dim < ndim);
6de9cd9a
DN
7696
7697 /* Set the new lower bound. */
7698 from = loop.from[dim];
7699 to = loop.to[dim];
4fd9a813 7700
f3b0bb7a 7701 onebased = integer_onep (from);
568e8e1e
PT
7702 gfc_conv_descriptor_lbound_set (&loop.pre, parm,
7703 gfc_rank_cst[dim], from);
6de9cd9a
DN
7704
7705 /* Set the new upper bound. */
568e8e1e
PT
7706 gfc_conv_descriptor_ubound_set (&loop.pre, parm,
7707 gfc_rank_cst[dim], to);
6de9cd9a
DN
7708
7709 /* Multiply the stride by the section stride to get the
7710 total stride. */
94471a56
TB
7711 stride = fold_build2_loc (input_location, MULT_EXPR,
7712 gfc_array_index_type,
7713 stride, info->stride[n]);
6de9cd9a 7714
4f90ee6c 7715 if ((se->direct_byref || se->use_offset)
1cf43a1d
PT
7716 && ((info->ref && info->ref->u.ar.type != AR_FULL)
7717 || (expr->expr_type == EXPR_ARRAY && se->use_offset)))
c4ba8848 7718 {
94471a56
TB
7719 base = fold_build2_loc (input_location, MINUS_EXPR,
7720 TREE_TYPE (base), base, stride);
c4ba8848 7721 }
1cf43a1d 7722 else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)) || se->use_offset)
c4ba8848 7723 {
b8ac4f3b 7724 bool toonebased;
c4ba8848 7725 tmp = gfc_conv_array_lbound (desc, n);
b8ac4f3b
AV
7726 toonebased = integer_onep (tmp);
7727 // lb(arr) - from (- start + 1)
94471a56 7728 tmp = fold_build2_loc (input_location, MINUS_EXPR,
3244f4cd 7729 TREE_TYPE (base), tmp, from);
b8ac4f3b
AV
7730 if (onebased && toonebased)
7731 {
7732 tmp = fold_build2_loc (input_location, MINUS_EXPR,
7733 TREE_TYPE (base), tmp, start);
7734 tmp = fold_build2_loc (input_location, PLUS_EXPR,
7735 TREE_TYPE (base), tmp,
7736 gfc_index_one_node);
7737 }
94471a56
TB
7738 tmp = fold_build2_loc (input_location, MULT_EXPR,
7739 TREE_TYPE (base), tmp,
7740 gfc_conv_array_stride (desc, n));
7741 base = fold_build2_loc (input_location, PLUS_EXPR,
7742 TREE_TYPE (base), tmp, base);
c4ba8848 7743 }
6de9cd9a
DN
7744
7745 /* Store the new stride. */
568e8e1e
PT
7746 gfc_conv_descriptor_stride_set (&loop.pre, parm,
7747 gfc_rank_cst[dim], stride);
6de9cd9a
DN
7748 }
7749
700535b7 7750 for (n = loop.dimen; n < loop.dimen + codim; n++)
a3935ffc 7751 {
bb033c9a
MM
7752 from = loop.from[n];
7753 to = loop.to[n];
a3935ffc 7754 gfc_conv_descriptor_lbound_set (&loop.pre, parm,
bb033c9a 7755 gfc_rank_cst[n], from);
700535b7 7756 if (n < loop.dimen + codim - 1)
a3935ffc 7757 gfc_conv_descriptor_ubound_set (&loop.pre, parm,
bb033c9a 7758 gfc_rank_cst[n], to);
a3935ffc
TB
7759 }
7760
ad5dd90d 7761 if (se->data_not_needed)
568e8e1e
PT
7762 gfc_conv_descriptor_data_set (&loop.pre, parm,
7763 gfc_index_zero_node);
ad5dd90d 7764 else
568e8e1e 7765 /* Point the data pointer at the 1st element in the section. */
1d6b7f39
PT
7766 gfc_get_dataptr_offset (&loop.pre, parm, desc, offset,
7767 subref_array_target, expr);
6de9cd9a 7768
f3b0bb7a
AV
7769 /* Force the offset to be -1, when the lower bound of the highest
7770 dimension is one and the symbol is present and is not a
7771 pointer/allocatable or associated. */
3244f4cd
AV
7772 if (((se->direct_byref || GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
7773 && !se->data_not_needed)
7774 || (se->use_offset && base != NULL_TREE))
7775 {
7776 /* Set the offset depending on base. */
7777 tmp = rank_remap && !se->direct_byref ?
7778 fold_build2_loc (input_location, PLUS_EXPR,
7779 gfc_array_index_type, base,
7780 offset)
7781 : base;
7782 gfc_conv_descriptor_offset_set (&loop.pre, parm, tmp);
7783 }
950ab3f1
PT
7784 else if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc))
7785 && !se->data_not_needed
7786 && (!rank_remap || se->use_offset))
574284e9
AV
7787 {
7788 gfc_conv_descriptor_offset_set (&loop.pre, parm,
7789 gfc_conv_descriptor_offset_get (desc));
7790 }
70570ec1
PT
7791 else if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc))
7792 && !se->data_not_needed
7793 && gfc_expr_attr (expr).select_rank_temporary)
7794 {
7795 gfc_conv_descriptor_offset_set (&loop.pre, parm, gfc_index_zero_node);
7796 }
3244f4cd 7797 else if (onebased && (!rank_remap || se->use_offset)
f3b0bb7a
AV
7798 && expr->symtree
7799 && !(expr->symtree->n.sym && expr->symtree->n.sym->ts.type == BT_CLASS
7800 && !CLASS_DATA (expr->symtree->n.sym)->attr.class_pointer)
7801 && !expr->symtree->n.sym->attr.allocatable
7802 && !expr->symtree->n.sym->attr.pointer
7803 && !expr->symtree->n.sym->attr.host_assoc
7804 && !expr->symtree->n.sym->attr.use_assoc)
6de9cd9a 7805 {
f3b0bb7a
AV
7806 /* Set the offset to -1. */
7807 mpz_t minus_one;
7808 mpz_init_set_si (minus_one, -1);
7809 tmp = gfc_conv_mpz_to_tree (minus_one, gfc_index_integer_kind);
7810 gfc_conv_descriptor_offset_set (&loop.pre, parm, tmp);
6de9cd9a
DN
7811 }
7812 else
7813 {
7814 /* Only the callee knows what the correct offset it, so just set
7815 it to zero here. */
568e8e1e 7816 gfc_conv_descriptor_offset_set (&loop.pre, parm, gfc_index_zero_node);
6de9cd9a 7817 }
7a70c12d
RS
7818 desc = parm;
7819 }
6de9cd9a 7820
1792349b
AV
7821 /* For class arrays add the class tree into the saved descriptor to
7822 enable getting of _vptr and the like. */
7823 if (expr->expr_type == EXPR_VARIABLE && VAR_P (desc)
b8ac4f3b 7824 && IS_CLASS_ARRAY (expr->symtree->n.sym))
1792349b
AV
7825 {
7826 gfc_allocate_lang_decl (desc);
7827 GFC_DECL_SAVED_DESCRIPTOR (desc) =
b8ac4f3b
AV
7828 DECL_LANG_SPECIFIC (expr->symtree->n.sym->backend_decl) ?
7829 GFC_DECL_SAVED_DESCRIPTOR (expr->symtree->n.sym->backend_decl)
7830 : expr->symtree->n.sym->backend_decl;
1792349b 7831 }
574284e9
AV
7832 else if (expr->expr_type == EXPR_ARRAY && VAR_P (desc)
7833 && IS_CLASS_ARRAY (expr))
7834 {
7835 tree vtype;
7836 gfc_allocate_lang_decl (desc);
7837 tmp = gfc_create_var (expr->ts.u.derived->backend_decl, "class");
7838 GFC_DECL_SAVED_DESCRIPTOR (desc) = tmp;
7839 vtype = gfc_class_vptr_get (tmp);
7840 gfc_add_modify (&se->pre, vtype,
7841 gfc_build_addr_expr (TREE_TYPE (vtype),
7842 gfc_find_vtab (&expr->ts)->backend_decl));
7843 }
99d821c0 7844 if (!se->direct_byref || se->byref_noassign)
7a70c12d
RS
7845 {
7846 /* Get a pointer to the new descriptor. */
7847 if (se->want_pointer)
628c189e 7848 se->expr = gfc_build_addr_expr (NULL_TREE, desc);
7a70c12d
RS
7849 else
7850 se->expr = desc;
6de9cd9a
DN
7851 }
7852
7853 gfc_add_block_to_block (&se->pre, &loop.pre);
7854 gfc_add_block_to_block (&se->post, &loop.post);
7855
7856 /* Cleanup the scalarizer. */
7857 gfc_cleanup_loop (&loop);
7858}
7859
7e279142
JJ
7860/* Helper function for gfc_conv_array_parameter if array size needs to be
7861 computed. */
7862
7863static void
7864array_parameter_size (tree desc, gfc_expr *expr, tree *size)
7865{
7866 tree elem;
7867 if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
7868 *size = GFC_TYPE_ARRAY_SIZE (TREE_TYPE (desc));
7869 else if (expr->rank > 1)
db3927fb
AH
7870 *size = build_call_expr_loc (input_location,
7871 gfor_fndecl_size0, 1,
7e279142
JJ
7872 gfc_build_addr_expr (NULL, desc));
7873 else
7874 {
568e8e1e
PT
7875 tree ubound = gfc_conv_descriptor_ubound_get (desc, gfc_index_zero_node);
7876 tree lbound = gfc_conv_descriptor_lbound_get (desc, gfc_index_zero_node);
7e279142 7877
94471a56
TB
7878 *size = fold_build2_loc (input_location, MINUS_EXPR,
7879 gfc_array_index_type, ubound, lbound);
7880 *size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
7881 *size, gfc_index_one_node);
7882 *size = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
7883 *size, gfc_index_zero_node);
7e279142
JJ
7884 }
7885 elem = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
94471a56
TB
7886 *size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
7887 *size, fold_convert (gfc_array_index_type, elem));
7e279142 7888}
6de9cd9a 7889
bf09e559 7890/* Helper function - return true if the argument is a pointer. */
94f3d11c 7891
bf09e559
TK
7892static bool
7893is_pointer (gfc_expr *e)
7894{
7895 gfc_symbol *sym;
7896
7897 if (e->expr_type != EXPR_VARIABLE || e->symtree == NULL)
7898 return false;
7899
7900 sym = e->symtree->n.sym;
7901 if (sym == NULL)
7902 return false;
7903
7904 return sym->attr.pointer || sym->attr.proc_pointer;
7905}
7906
6de9cd9a 7907/* Convert an array for passing as an actual parameter. */
6de9cd9a
DN
7908
7909void
2960a368 7910gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, bool g77,
7e279142
JJ
7911 const gfc_symbol *fsym, const char *proc_name,
7912 tree *size)
6de9cd9a
DN
7913{
7914 tree ptr;
7915 tree desc;
bd075cf2 7916 tree tmp = NULL_TREE;
6de9cd9a 7917 tree stmt;
b2b247f9 7918 tree parent = DECL_CONTEXT (current_function_decl);
17555e7e
PT
7919 bool full_array_var;
7920 bool this_array_result;
7921 bool contiguous;
f7172b55 7922 bool no_pack;
2542496c
PT
7923 bool array_constructor;
7924 bool good_allocatable;
ba461991
PT
7925 bool ultimate_ptr_comp;
7926 bool ultimate_alloc_comp;
6de9cd9a
DN
7927 gfc_symbol *sym;
7928 stmtblock_t block;
17555e7e
PT
7929 gfc_ref *ref;
7930
ba461991
PT
7931 ultimate_ptr_comp = false;
7932 ultimate_alloc_comp = false;
fe4e525c 7933
17555e7e 7934 for (ref = expr->ref; ref; ref = ref->next)
ba461991
PT
7935 {
7936 if (ref->next == NULL)
7937 break;
7938
7939 if (ref->type == REF_COMPONENT)
7940 {
7941 ultimate_ptr_comp = ref->u.c.component->attr.pointer;
7942 ultimate_alloc_comp = ref->u.c.component->attr.allocatable;
7943 }
7944 }
17555e7e
PT
7945
7946 full_array_var = false;
7947 contiguous = false;
7948
ba461991 7949 if (expr->expr_type == EXPR_VARIABLE && ref && !ultimate_ptr_comp)
17555e7e 7950 full_array_var = gfc_full_array_ref_p (ref, &contiguous);
6de9cd9a 7951
b2b247f9
PT
7952 sym = full_array_var ? expr->symtree->n.sym : NULL;
7953
18b0679f 7954 /* The symbol should have an array specification. */
17555e7e 7955 gcc_assert (!sym || sym->as || ref->u.ar.as);
18b0679f 7956
0ee8e250
PT
7957 if (expr->expr_type == EXPR_ARRAY && expr->ts.type == BT_CHARACTER)
7958 {
7959 get_array_ctor_strlen (&se->pre, expr->value.constructor, &tmp);
bc21d315 7960 expr->ts.u.cl->backend_decl = tmp;
f2d3cb25 7961 se->string_length = tmp;
0ee8e250
PT
7962 }
7963
b2b247f9
PT
7964 /* Is this the result of the enclosing procedure? */
7965 this_array_result = (full_array_var && sym->attr.flavor == FL_PROCEDURE);
7966 if (this_array_result
7967 && (sym->backend_decl != current_function_decl)
7968 && (sym->backend_decl != parent))
7969 this_array_result = false;
7970
6de9cd9a 7971 /* Passing address of the array if it is not pointer or assumed-shape. */
ea73447a
JW
7972 if (full_array_var && g77 && !this_array_result
7973 && sym->ts.type != BT_DERIVED && sym->ts.type != BT_CLASS)
6de9cd9a 7974 {
b122dc6a 7975 tmp = gfc_get_symbol_decl (sym);
83d890b9 7976
20c9dc8a 7977 if (sym->ts.type == BT_CHARACTER)
bc21d315 7978 se->string_length = sym->ts.u.cl->backend_decl;
17555e7e 7979
f7172b55 7980 if (!sym->attr.pointer
c62c6622 7981 && sym->as
f04986a9 7982 && sym->as->type != AS_ASSUMED_SHAPE
2d98d2b4 7983 && sym->as->type != AS_DEFERRED
f04986a9 7984 && sym->as->type != AS_ASSUMED_RANK
c62c6622 7985 && !sym->attr.allocatable)
6de9cd9a 7986 {
346d5977 7987 /* Some variables are declared directly, others are declared as
841b0c1f
PB
7988 pointers and allocated on the heap. */
7989 if (sym->attr.dummy || POINTER_TYPE_P (TREE_TYPE (tmp)))
7990 se->expr = tmp;
6de9cd9a 7991 else
628c189e 7992 se->expr = gfc_build_addr_expr (NULL_TREE, tmp);
7e279142
JJ
7993 if (size)
7994 array_parameter_size (tmp, expr, size);
6de9cd9a
DN
7995 return;
7996 }
17555e7e 7997
6de9cd9a
DN
7998 if (sym->attr.allocatable)
7999 {
237b2f1b 8000 if (sym->attr.dummy || sym->attr.result)
7f0d6da9 8001 {
2960a368 8002 gfc_conv_expr_descriptor (se, expr);
7e279142 8003 tmp = se->expr;
7f0d6da9 8004 }
7e279142
JJ
8005 if (size)
8006 array_parameter_size (tmp, expr, size);
8007 se->expr = gfc_conv_array_data (tmp);
6de9cd9a
DN
8008 return;
8009 }
8010 }
8011
ba461991
PT
8012 /* A convenient reduction in scope. */
8013 contiguous = g77 && !this_array_result && contiguous;
8014
2542496c 8015 /* There is no need to pack and unpack the array, if it is contiguous
fe4e525c
TB
8016 and not a deferred- or assumed-shape array, or if it is simply
8017 contiguous. */
f7172b55
PT
8018 no_pack = ((sym && sym->as
8019 && !sym->attr.pointer
8020 && sym->as->type != AS_DEFERRED
c62c6622 8021 && sym->as->type != AS_ASSUMED_RANK
f7172b55
PT
8022 && sym->as->type != AS_ASSUMED_SHAPE)
8023 ||
8024 (ref && ref->u.ar.as
8025 && ref->u.ar.as->type != AS_DEFERRED
c62c6622 8026 && ref->u.ar.as->type != AS_ASSUMED_RANK
fe4e525c
TB
8027 && ref->u.ar.as->type != AS_ASSUMED_SHAPE)
8028 ||
460263d0 8029 gfc_is_simply_contiguous (expr, false, true));
f7172b55 8030
ba461991 8031 no_pack = contiguous && no_pack;
f7172b55 8032
5f8865c3
TK
8033 /* If we have an EXPR_OP or a function returning an explicit-shaped
8034 or allocatable array, an array temporary will be generated which
8035 does not need to be packed / unpacked if passed to an
8036 explicit-shape dummy array. */
7dc3df08 8037
5f8865c3
TK
8038 if (g77)
8039 {
8040 if (expr->expr_type == EXPR_OP)
8041 no_pack = 1;
8042 else if (expr->expr_type == EXPR_FUNCTION && expr->value.function.esym)
8043 {
8044 gfc_symbol *result = expr->value.function.esym->result;
8045 if (result->attr.dimension
8ef8fa9a
TK
8046 && (result->as->type == AS_EXPLICIT
8047 || result->attr.allocatable
8048 || result->attr.contiguous))
5f8865c3
TK
8049 no_pack = 1;
8050 }
8051 }
7dc3df08 8052
2542496c
PT
8053 /* Array constructors are always contiguous and do not need packing. */
8054 array_constructor = g77 && !this_array_result && expr->expr_type == EXPR_ARRAY;
8055
8056 /* Same is true of contiguous sections from allocatable variables. */
ba461991
PT
8057 good_allocatable = contiguous
8058 && expr->symtree
8059 && expr->symtree->n.sym->attr.allocatable;
8060
8061 /* Or ultimate allocatable components. */
f04986a9 8062 ultimate_alloc_comp = contiguous && ultimate_alloc_comp;
f7172b55 8063
ba461991 8064 if (no_pack || array_constructor || good_allocatable || ultimate_alloc_comp)
17555e7e 8065 {
2960a368 8066 gfc_conv_expr_descriptor (se, expr);
1b961de9
PT
8067 /* Deallocate the allocatable components of structures that are
8068 not variable. */
8069 if ((expr->ts.type == BT_DERIVED || expr->ts.type == BT_CLASS)
8070 && expr->ts.u.derived->attr.alloc_comp
8071 && expr->expr_type != EXPR_VARIABLE)
8072 {
8073 tmp = gfc_deallocate_alloc_comp (expr->ts.u.derived, se->expr, expr->rank);
8074
8075 /* The components shall be deallocated before their containing entity. */
8076 gfc_prepend_expr_to_block (&se->post, tmp);
8077 }
6b7a9826 8078 if (expr->ts.type == BT_CHARACTER && expr->expr_type != EXPR_FUNCTION)
17555e7e
PT
8079 se->string_length = expr->ts.u.cl->backend_decl;
8080 if (size)
8081 array_parameter_size (se->expr, expr, size);
8082 se->expr = gfc_conv_array_data (se->expr);
8083 return;
8084 }
8085
b2b247f9
PT
8086 if (this_array_result)
8087 {
8088 /* Result of the enclosing function. */
2960a368 8089 gfc_conv_expr_descriptor (se, expr);
7e279142
JJ
8090 if (size)
8091 array_parameter_size (se->expr, expr, size);
628c189e 8092 se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
b2b247f9
PT
8093
8094 if (g77 && TREE_TYPE (TREE_TYPE (se->expr)) != NULL_TREE
8095 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (se->expr))))
db3927fb
AH
8096 se->expr = gfc_conv_array_data (build_fold_indirect_ref_loc (input_location,
8097 se->expr));
b2b247f9
PT
8098
8099 return;
8100 }
8101 else
8102 {
8103 /* Every other type of array. */
8104 se->want_pointer = 1;
2960a368 8105 gfc_conv_expr_descriptor (se, expr);
ff3598bc 8106
7e279142 8107 if (size)
db3927fb
AH
8108 array_parameter_size (build_fold_indirect_ref_loc (input_location,
8109 se->expr),
7e279142 8110 expr, size);
b2b247f9
PT
8111 }
8112
5046aff5 8113 /* Deallocate the allocatable components of structures that are
0e1f8c6a
MM
8114 not variable, for descriptorless arguments.
8115 Arguments with a descriptor are handled in gfc_conv_procedure_call. */
8116 if (g77 && (expr->ts.type == BT_DERIVED || expr->ts.type == BT_CLASS)
8117 && expr->ts.u.derived->attr.alloc_comp
8118 && expr->expr_type != EXPR_VARIABLE)
5046aff5 8119 {
46b2c440 8120 tmp = build_fold_indirect_ref_loc (input_location, se->expr);
bc21d315 8121 tmp = gfc_deallocate_alloc_comp (expr->ts.u.derived, tmp, expr->rank);
46b2c440
MM
8122
8123 /* The components shall be deallocated before their containing entity. */
8124 gfc_prepend_expr_to_block (&se->post, tmp);
5046aff5
PT
8125 }
8126
fe4e525c 8127 if (g77 || (fsym && fsym->attr.contiguous
460263d0 8128 && !gfc_is_simply_contiguous (expr, false, true)))
6de9cd9a 8129 {
fe4e525c
TB
8130 tree origptr = NULL_TREE;
8131
6de9cd9a 8132 desc = se->expr;
fe4e525c
TB
8133
8134 /* For contiguous arrays, save the original value of the descriptor. */
8135 if (!g77)
8136 {
8137 origptr = gfc_create_var (pvoid_type_node, "origptr");
8138 tmp = build_fold_indirect_ref_loc (input_location, desc);
8139 tmp = gfc_conv_array_data (tmp);
94471a56
TB
8140 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
8141 TREE_TYPE (origptr), origptr,
8142 fold_convert (TREE_TYPE (origptr), tmp));
fe4e525c
TB
8143 gfc_add_expr_to_block (&se->pre, tmp);
8144 }
8145
6de9cd9a 8146 /* Repack the array. */
73e42eef 8147 if (warn_array_temporaries)
0d52899f
TB
8148 {
8149 if (fsym)
48749dbc
MLI
8150 gfc_warning (OPT_Warray_temporaries,
8151 "Creating array temporary at %L for argument %qs",
0d52899f
TB
8152 &expr->where, fsym->name);
8153 else
48749dbc
MLI
8154 gfc_warning (OPT_Warray_temporaries,
8155 "Creating array temporary at %L", &expr->where);
0d52899f 8156 }
bdfd2ff0 8157
bf09e559
TK
8158 /* When optmizing, we can use gfc_conv_subref_array_arg for
8159 making the packing and unpacking operation visible to the
8160 optimizers. */
8161
95d27703 8162 if (g77 && flag_inline_arg_packing && expr->expr_type == EXPR_VARIABLE
1585b483 8163 && !is_pointer (expr) && ! gfc_has_dimen_vector_ref (expr)
0cc063af
TK
8164 && !(expr->symtree->n.sym->as
8165 && expr->symtree->n.sym->as->type == AS_ASSUMED_RANK)
1585b483 8166 && (fsym == NULL || fsym->ts.type != BT_ASSUMED))
bf09e559
TK
8167 {
8168 gfc_conv_subref_array_arg (se, expr, g77,
8169 fsym ? fsym->attr.intent : INTENT_INOUT,
1585b483 8170 false, fsym, proc_name, sym, true);
bf09e559
TK
8171 return;
8172 }
8173
db3927fb
AH
8174 ptr = build_call_expr_loc (input_location,
8175 gfor_fndecl_in_pack, 1, desc);
0d52899f
TB
8176
8177 if (fsym && fsym->attr.optional && sym && sym->attr.optional)
8178 {
8179 tmp = gfc_conv_expr_present (sym);
5d44e5c8
TB
8180 ptr = build3_loc (input_location, COND_EXPR, TREE_TYPE (se->expr),
8181 tmp, fold_convert (TREE_TYPE (se->expr), ptr),
6e1b67b3 8182 fold_convert (TREE_TYPE (se->expr), null_pointer_node));
0d52899f
TB
8183 }
8184
6de9cd9a 8185 ptr = gfc_evaluate_now (ptr, &se->pre);
0d52899f 8186
fe4e525c
TB
8187 /* Use the packed data for the actual argument, except for contiguous arrays,
8188 where the descriptor's data component is set. */
8189 if (g77)
8190 se->expr = ptr;
8191 else
8192 {
8193 tmp = build_fold_indirect_ref_loc (input_location, desc);
88719f2d
MM
8194
8195 gfc_ss * ss = gfc_walk_expr (expr);
8196 if (!transposed_dims (ss))
8197 gfc_conv_descriptor_data_set (&se->pre, tmp, ptr);
8198 else
8199 {
8200 tree old_field, new_field;
8201
8202 /* The original descriptor has transposed dims so we can't reuse
8203 it directly; we have to create a new one. */
8204 tree old_desc = tmp;
8205 tree new_desc = gfc_create_var (TREE_TYPE (old_desc), "arg_desc");
8206
8207 old_field = gfc_conv_descriptor_dtype (old_desc);
8208 new_field = gfc_conv_descriptor_dtype (new_desc);
8209 gfc_add_modify (&se->pre, new_field, old_field);
8210
8211 old_field = gfc_conv_descriptor_offset (old_desc);
8212 new_field = gfc_conv_descriptor_offset (new_desc);
8213 gfc_add_modify (&se->pre, new_field, old_field);
8214
8215 for (int i = 0; i < expr->rank; i++)
8216 {
8217 old_field = gfc_conv_descriptor_dimension (old_desc,
8218 gfc_rank_cst[get_array_ref_dim_for_loop_dim (ss, i)]);
8219 new_field = gfc_conv_descriptor_dimension (new_desc,
8220 gfc_rank_cst[i]);
8221 gfc_add_modify (&se->pre, new_field, old_field);
8222 }
8223
f19626cf 8224 if (flag_coarray == GFC_FCOARRAY_LIB
88719f2d
MM
8225 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (old_desc))
8226 && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (old_desc))
8227 == GFC_ARRAY_ALLOCATABLE)
8228 {
8229 old_field = gfc_conv_descriptor_token (old_desc);
8230 new_field = gfc_conv_descriptor_token (new_desc);
8231 gfc_add_modify (&se->pre, new_field, old_field);
8232 }
8233
8234 gfc_conv_descriptor_data_set (&se->pre, new_desc, ptr);
8235 se->expr = gfc_build_addr_expr (NULL_TREE, new_desc);
8236 }
8237 gfc_free_ss (ss);
fe4e525c 8238 }
6de9cd9a 8239
d3d3011f 8240 if (gfc_option.rtcheck & GFC_RTCHECK_ARRAY_TEMPS)
0d52899f
TB
8241 {
8242 char * msg;
8243
8244 if (fsym && proc_name)
1a33dc9e
UB
8245 msg = xasprintf ("An array temporary was created for argument "
8246 "'%s' of procedure '%s'", fsym->name, proc_name);
0d52899f 8247 else
1a33dc9e 8248 msg = xasprintf ("An array temporary was created");
0d52899f 8249
db3927fb
AH
8250 tmp = build_fold_indirect_ref_loc (input_location,
8251 desc);
0d52899f 8252 tmp = gfc_conv_array_data (tmp);
63ee5404 8253 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
94471a56 8254 fold_convert (TREE_TYPE (tmp), ptr), tmp);
0d52899f
TB
8255
8256 if (fsym && fsym->attr.optional && sym && sym->attr.optional)
94471a56 8257 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
63ee5404 8258 logical_type_node,
94471a56 8259 gfc_conv_expr_present (sym), tmp);
0d52899f
TB
8260
8261 gfc_trans_runtime_check (false, true, tmp, &se->pre,
8262 &expr->where, msg);
cede9502 8263 free (msg);
0d52899f
TB
8264 }
8265
6de9cd9a
DN
8266 gfc_start_block (&block);
8267
8268 /* Copy the data back. */
0d52899f
TB
8269 if (fsym == NULL || fsym->attr.intent != INTENT_IN)
8270 {
db3927fb
AH
8271 tmp = build_call_expr_loc (input_location,
8272 gfor_fndecl_in_unpack, 2, desc, ptr);
0d52899f
TB
8273 gfc_add_expr_to_block (&block, tmp);
8274 }
6de9cd9a
DN
8275
8276 /* Free the temporary. */
107051a5 8277 tmp = gfc_call_free (ptr);
6de9cd9a
DN
8278 gfc_add_expr_to_block (&block, tmp);
8279
8280 stmt = gfc_finish_block (&block);
8281
8282 gfc_init_block (&block);
8283 /* Only if it was repacked. This code needs to be executed before the
8284 loop cleanup code. */
db3927fb
AH
8285 tmp = build_fold_indirect_ref_loc (input_location,
8286 desc);
6de9cd9a 8287 tmp = gfc_conv_array_data (tmp);
63ee5404 8288 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
94471a56 8289 fold_convert (TREE_TYPE (tmp), ptr), tmp);
0d52899f
TB
8290
8291 if (fsym && fsym->attr.optional && sym && sym->attr.optional)
94471a56 8292 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
63ee5404 8293 logical_type_node,
94471a56 8294 gfc_conv_expr_present (sym), tmp);
0d52899f 8295
c2255bc4 8296 tmp = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt (input_location));
6de9cd9a
DN
8297
8298 gfc_add_expr_to_block (&block, tmp);
8299 gfc_add_block_to_block (&block, &se->post);
8300
8301 gfc_init_block (&se->post);
fe4e525c
TB
8302
8303 /* Reset the descriptor pointer. */
8304 if (!g77)
8305 {
8306 tmp = build_fold_indirect_ref_loc (input_location, desc);
8307 gfc_conv_descriptor_data_set (&se->post, tmp, origptr);
8308 }
8309
6de9cd9a
DN
8310 gfc_add_block_to_block (&se->post, &block);
8311 }
8312}
8313
8314
5046aff5
PT
8315/* This helper function calculates the size in words of a full array. */
8316
92d28cbb
JJ
8317tree
8318gfc_full_array_size (stmtblock_t *block, tree decl, int rank)
5046aff5
PT
8319{
8320 tree idx;
8321 tree nelems;
8322 tree tmp;
8323 idx = gfc_rank_cst[rank - 1];
568e8e1e
PT
8324 nelems = gfc_conv_descriptor_ubound_get (decl, idx);
8325 tmp = gfc_conv_descriptor_lbound_get (decl, idx);
94471a56
TB
8326 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
8327 nelems, tmp);
8328 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
8329 tmp, gfc_index_one_node);
5046aff5
PT
8330 tmp = gfc_evaluate_now (tmp, block);
8331
568e8e1e 8332 nelems = gfc_conv_descriptor_stride_get (decl, idx);
94471a56
TB
8333 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
8334 nelems, tmp);
5046aff5
PT
8335 return gfc_evaluate_now (tmp, block);
8336}
42a0e16c 8337
5046aff5 8338
40c32948
PT
8339/* Allocate dest to the same size as src, and copy src -> dest.
8340 If no_malloc is set, only the copy is done. */
5046aff5 8341
40c32948 8342static tree
94471a56 8343duplicate_allocatable (tree dest, tree src, tree type, int rank,
fc7d0afb
AV
8344 bool no_malloc, bool no_memcpy, tree str_sz,
8345 tree add_when_allocated)
5046aff5
PT
8346{
8347 tree tmp;
8348 tree size;
8349 tree nelems;
5046aff5
PT
8350 tree null_cond;
8351 tree null_data;
8352 stmtblock_t block;
8353
40c32948
PT
8354 /* If the source is null, set the destination to null. Then,
8355 allocate memory to the destination. */
5046aff5 8356 gfc_init_block (&block);
5046aff5 8357
14c96bca 8358 if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (dest)))
40c32948 8359 {
ba85c8c3 8360 gfc_add_modify (&block, dest, fold_convert (type, null_pointer_node));
40c32948
PT
8361 null_data = gfc_finish_block (&block);
8362
8363 gfc_init_block (&block);
2b3dc0db
PT
8364 if (str_sz != NULL_TREE)
8365 size = str_sz;
8366 else
8367 size = TYPE_SIZE_UNIT (TREE_TYPE (type));
8368
40c32948
PT
8369 if (!no_malloc)
8370 {
8371 tmp = gfc_call_malloc (&block, type, size);
ba85c8c3 8372 gfc_add_modify (&block, dest, fold_convert (type, tmp));
40c32948
PT
8373 }
8374
92d28cbb
JJ
8375 if (!no_memcpy)
8376 {
8377 tmp = builtin_decl_explicit (BUILT_IN_MEMCPY);
8378 tmp = build_call_expr_loc (input_location, tmp, 3, dest, src,
8379 fold_convert (size_type_node, size));
8380 gfc_add_expr_to_block (&block, tmp);
8381 }
40c32948
PT
8382 }
8383 else
8384 {
8385 gfc_conv_descriptor_data_set (&block, dest, null_pointer_node);
8386 null_data = gfc_finish_block (&block);
8387
8388 gfc_init_block (&block);
14c96bca 8389 if (rank)
92d28cbb 8390 nelems = gfc_full_array_size (&block, src, rank);
14c96bca
TB
8391 else
8392 nelems = gfc_index_one_node;
8393
2b3dc0db
PT
8394 if (str_sz != NULL_TREE)
8395 tmp = fold_convert (gfc_array_index_type, str_sz);
8396 else
8397 tmp = fold_convert (gfc_array_index_type,
8398 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
94471a56
TB
8399 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
8400 nelems, tmp);
40c32948
PT
8401 if (!no_malloc)
8402 {
8403 tmp = TREE_TYPE (gfc_conv_descriptor_data_get (src));
8404 tmp = gfc_call_malloc (&block, tmp, size);
8405 gfc_conv_descriptor_data_set (&block, dest, tmp);
8406 }
8407
8408 /* We know the temporary and the value will be the same length,
8409 so can use memcpy. */
92d28cbb
JJ
8410 if (!no_memcpy)
8411 {
8412 tmp = builtin_decl_explicit (BUILT_IN_MEMCPY);
8413 tmp = build_call_expr_loc (input_location, tmp, 3,
8414 gfc_conv_descriptor_data_get (dest),
8415 gfc_conv_descriptor_data_get (src),
8416 fold_convert (size_type_node, size));
8417 gfc_add_expr_to_block (&block, tmp);
8418 }
40c32948 8419 }
5046aff5 8420
fc7d0afb 8421 gfc_add_expr_to_block (&block, add_when_allocated);
42a0e16c
PT
8422 tmp = gfc_finish_block (&block);
8423
5046aff5
PT
8424 /* Null the destination if the source is null; otherwise do
8425 the allocate and copy. */
14c96bca 8426 if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (src)))
40c32948
PT
8427 null_cond = src;
8428 else
8429 null_cond = gfc_conv_descriptor_data_get (src);
8430
5046aff5 8431 null_cond = convert (pvoid_type_node, null_cond);
63ee5404 8432 null_cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
94471a56 8433 null_cond, null_pointer_node);
5046aff5
PT
8434 return build3_v (COND_EXPR, null_cond, tmp, null_data);
8435}
8436
8437
40c32948
PT
8438/* Allocate dest to the same size as src, and copy data src -> dest. */
8439
8440tree
fc7d0afb
AV
8441gfc_duplicate_allocatable (tree dest, tree src, tree type, int rank,
8442 tree add_when_allocated)
40c32948 8443{
92d28cbb 8444 return duplicate_allocatable (dest, src, type, rank, false, false,
fc7d0afb 8445 NULL_TREE, add_when_allocated);
40c32948
PT
8446}
8447
8448
8449/* Copy data src -> dest. */
8450
8451tree
8452gfc_copy_allocatable_data (tree dest, tree src, tree type, int rank)
8453{
92d28cbb 8454 return duplicate_allocatable (dest, src, type, rank, true, false,
fc7d0afb 8455 NULL_TREE, NULL_TREE);
92d28cbb
JJ
8456}
8457
8458/* Allocate dest to the same size as src, but don't copy anything. */
8459
8460tree
8461gfc_duplicate_allocatable_nocopy (tree dest, tree src, tree type, int rank)
8462{
fc7d0afb
AV
8463 return duplicate_allocatable (dest, src, type, rank, false, true,
8464 NULL_TREE, NULL_TREE);
40c32948
PT
8465}
8466
8467
ba85c8c3
AV
8468static tree
8469duplicate_allocatable_coarray (tree dest, tree dest_tok, tree src,
8470 tree type, int rank)
8471{
8472 tree tmp;
8473 tree size;
8474 tree nelems;
8475 tree null_cond;
8476 tree null_data;
8477 stmtblock_t block, globalblock;
8478
8479 /* If the source is null, set the destination to null. Then,
8480 allocate memory to the destination. */
8481 gfc_init_block (&block);
8482 gfc_init_block (&globalblock);
8483
8484 if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (dest)))
8485 {
8486 gfc_se se;
8487 symbol_attribute attr;
8488 tree dummy_desc;
8489
8490 gfc_init_se (&se, NULL);
e0396d77
AV
8491 gfc_clear_attr (&attr);
8492 attr.allocatable = 1;
ba85c8c3
AV
8493 dummy_desc = gfc_conv_scalar_to_descriptor (&se, dest, attr);
8494 gfc_add_block_to_block (&globalblock, &se.pre);
8495 size = TYPE_SIZE_UNIT (TREE_TYPE (type));
8496
8497 gfc_add_modify (&block, dest, fold_convert (type, null_pointer_node));
8498 gfc_allocate_using_caf_lib (&block, dummy_desc, size,
8499 gfc_build_addr_expr (NULL_TREE, dest_tok),
8500 NULL_TREE, NULL_TREE, NULL_TREE,
8501 GFC_CAF_COARRAY_ALLOC_REGISTER_ONLY);
8502 null_data = gfc_finish_block (&block);
8503
8504 gfc_init_block (&block);
8505
8506 gfc_allocate_using_caf_lib (&block, dummy_desc,
8507 fold_convert (size_type_node, size),
8508 gfc_build_addr_expr (NULL_TREE, dest_tok),
8509 NULL_TREE, NULL_TREE, NULL_TREE,
8510 GFC_CAF_COARRAY_ALLOC);
8511
8512 tmp = builtin_decl_explicit (BUILT_IN_MEMCPY);
8513 tmp = build_call_expr_loc (input_location, tmp, 3, dest, src,
8514 fold_convert (size_type_node, size));
8515 gfc_add_expr_to_block (&block, tmp);
8516 }
8517 else
8518 {
8519 /* Set the rank or unitialized memory access may be reported. */
7fb43006 8520 tmp = gfc_conv_descriptor_rank (dest);
ba85c8c3
AV
8521 gfc_add_modify (&globalblock, tmp, build_int_cst (TREE_TYPE (tmp), rank));
8522
8523 if (rank)
8524 nelems = gfc_full_array_size (&block, src, rank);
8525 else
8526 nelems = integer_one_node;
8527
8528 tmp = fold_convert (size_type_node,
8529 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
8530 size = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
8531 fold_convert (size_type_node, nelems), tmp);
8532
8533 gfc_conv_descriptor_data_set (&block, dest, null_pointer_node);
8534 gfc_allocate_using_caf_lib (&block, dest, fold_convert (size_type_node,
8535 size),
8536 gfc_build_addr_expr (NULL_TREE, dest_tok),
8537 NULL_TREE, NULL_TREE, NULL_TREE,
8538 GFC_CAF_COARRAY_ALLOC_REGISTER_ONLY);
8539 null_data = gfc_finish_block (&block);
8540
8541 gfc_init_block (&block);
8542 gfc_allocate_using_caf_lib (&block, dest,
8543 fold_convert (size_type_node, size),
8544 gfc_build_addr_expr (NULL_TREE, dest_tok),
8545 NULL_TREE, NULL_TREE, NULL_TREE,
8546 GFC_CAF_COARRAY_ALLOC);
8547
8548 tmp = builtin_decl_explicit (BUILT_IN_MEMCPY);
8549 tmp = build_call_expr_loc (input_location, tmp, 3,
8550 gfc_conv_descriptor_data_get (dest),
8551 gfc_conv_descriptor_data_get (src),
8552 fold_convert (size_type_node, size));
8553 gfc_add_expr_to_block (&block, tmp);
8554 }
8555
8556 tmp = gfc_finish_block (&block);
8557
8558 /* Null the destination if the source is null; otherwise do
8559 the register and copy. */
8560 if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (src)))
8561 null_cond = src;
8562 else
8563 null_cond = gfc_conv_descriptor_data_get (src);
8564
8565 null_cond = convert (pvoid_type_node, null_cond);
63ee5404 8566 null_cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
ba85c8c3
AV
8567 null_cond, null_pointer_node);
8568 gfc_add_expr_to_block (&globalblock, build3_v (COND_EXPR, null_cond, tmp,
8569 null_data));
8570 return gfc_finish_block (&globalblock);
8571}
8572
8573
8574/* Helper function to abstract whether coarray processing is enabled. */
8575
8576static bool
8577caf_enabled (int caf_mode)
8578{
8579 return (caf_mode & GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY)
8580 == GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY;
8581}
8582
8583
8584/* Helper function to abstract whether coarray processing is enabled
8585 and we are in a derived type coarray. */
8586
8587static bool
8588caf_in_coarray (int caf_mode)
8589{
8590 static const int pat = GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY
8591 | GFC_STRUCTURE_CAF_MODE_IN_COARRAY;
8592 return (caf_mode & pat) == pat;
8593}
8594
8595
8596/* Helper function to abstract whether coarray is to deallocate only. */
8597
8598bool
8599gfc_caf_is_dealloc_only (int caf_mode)
8600{
8601 return (caf_mode & GFC_STRUCTURE_CAF_MODE_DEALLOC_ONLY)
8602 == GFC_STRUCTURE_CAF_MODE_DEALLOC_ONLY;
8603}
8604
8605
5046aff5
PT
8606/* Recursively traverse an object of derived type, generating code to
8607 deallocate, nullify or copy allocatable components. This is the work horse
8608 function for the functions named in this enum. */
8609
ba85c8c3 8610enum {DEALLOCATE_ALLOC_COMP = 1, NULLIFY_ALLOC_COMP,
5bab4c96 8611 COPY_ALLOC_COMP, COPY_ONLY_ALLOC_COMP, REASSIGN_CAF_COMP,
c78d3425
AF
8612 ALLOCATE_PDT_COMP, DEALLOCATE_PDT_COMP, CHECK_PDT_DUMMY,
8613 BCAST_ALLOC_COMP};
5bab4c96
PT
8614
8615static gfc_actual_arglist *pdt_param_list;
5046aff5
PT
8616
8617static tree
8618structure_alloc_comps (gfc_symbol * der_type, tree decl,
c78d3425
AF
8619 tree dest, int rank, int purpose, int caf_mode,
8620 gfc_co_subroutines_args *args)
5046aff5
PT
8621{
8622 gfc_component *c;
8623 gfc_loopinfo loop;
8624 stmtblock_t fnblock;
8625 stmtblock_t loopbody;
d6430d9a 8626 stmtblock_t tmpblock;
546a65d9 8627 tree decl_type;
5046aff5
PT
8628 tree tmp;
8629 tree comp;
8630 tree dcmp;
8631 tree nelems;
8632 tree index;
8633 tree var;
8634 tree cdecl;
8635 tree ctype;
8636 tree vref, dref;
8637 tree null_cond = NULL_TREE;
fc7d0afb 8638 tree add_when_allocated;
bf9f15ee 8639 tree dealloc_fndecl;
39da5866 8640 tree caf_token;
bf9f15ee 8641 gfc_symbol *vtab;
39da5866
AV
8642 int caf_dereg_mode;
8643 symbol_attribute *attr;
8644 bool deallocate_called;
5046aff5
PT
8645
8646 gfc_init_block (&fnblock);
8647
546a65d9
PT
8648 decl_type = TREE_TYPE (decl);
8649
fc7d0afb 8650 if ((POINTER_TYPE_P (decl_type))
546a65d9 8651 || (TREE_CODE (decl_type) == REFERENCE_TYPE && rank == 0))
fc7d0afb
AV
8652 {
8653 decl = build_fold_indirect_ref_loc (input_location, decl);
8654 /* Deref dest in sync with decl, but only when it is not NULL. */
8655 if (dest)
8656 dest = build_fold_indirect_ref_loc (input_location, dest);
7114edca 8657
ba85c8c3
AV
8658 /* Update the decl_type because it got dereferenced. */
8659 decl_type = TREE_TYPE (decl);
8660 }
546a65d9 8661
fc7d0afb 8662 /* If this is an array of derived types with allocatable components
5046aff5 8663 build a loop and recursively call this function. */
546a65d9 8664 if (TREE_CODE (decl_type) == ARRAY_TYPE
2be13164 8665 || (GFC_DESCRIPTOR_TYPE_P (decl_type) && rank != 0))
5046aff5
PT
8666 {
8667 tmp = gfc_conv_array_data (decl);
fc7d0afb 8668 var = build_fold_indirect_ref_loc (input_location, tmp);
f04986a9 8669
5046aff5 8670 /* Get the number of elements - 1 and set the counter. */
546a65d9 8671 if (GFC_DESCRIPTOR_TYPE_P (decl_type))
5046aff5
PT
8672 {
8673 /* Use the descriptor for an allocatable array. Since this
8674 is a full array reference, we only need the descriptor
8675 information from dimension = rank. */
92d28cbb 8676 tmp = gfc_full_array_size (&fnblock, decl, rank);
94471a56
TB
8677 tmp = fold_build2_loc (input_location, MINUS_EXPR,
8678 gfc_array_index_type, tmp,
8679 gfc_index_one_node);
5046aff5
PT
8680
8681 null_cond = gfc_conv_descriptor_data_get (decl);
94471a56 8682 null_cond = fold_build2_loc (input_location, NE_EXPR,
63ee5404 8683 logical_type_node, null_cond,
94471a56 8684 build_int_cst (TREE_TYPE (null_cond), 0));
5046aff5
PT
8685 }
8686 else
8687 {
8688 /* Otherwise use the TYPE_DOMAIN information. */
fc7d0afb 8689 tmp = array_type_nelts (decl_type);
5046aff5
PT
8690 tmp = fold_convert (gfc_array_index_type, tmp);
8691 }
8692
8693 /* Remember that this is, in fact, the no. of elements - 1. */
8694 nelems = gfc_evaluate_now (tmp, &fnblock);
8695 index = gfc_create_var (gfc_array_index_type, "S");
8696
8697 /* Build the body of the loop. */
8698 gfc_init_block (&loopbody);
8699
1d6b7f39 8700 vref = gfc_build_array_ref (var, index, NULL);
5046aff5 8701
ba85c8c3
AV
8702 if ((purpose == COPY_ALLOC_COMP || purpose == COPY_ONLY_ALLOC_COMP)
8703 && !caf_enabled (caf_mode))
8704 {
40c32948 8705 tmp = build_fold_indirect_ref_loc (input_location,
c78d3425 8706 gfc_conv_array_data (dest));
40c32948
PT
8707 dref = gfc_build_array_ref (tmp, index, NULL);
8708 tmp = structure_alloc_comps (der_type, vref, dref, rank,
c78d3425 8709 COPY_ALLOC_COMP, 0, args);
40c32948 8710 }
5046aff5 8711 else
ba85c8c3 8712 tmp = structure_alloc_comps (der_type, vref, NULL_TREE, rank, purpose,
c78d3425 8713 caf_mode, args);
5046aff5
PT
8714
8715 gfc_add_expr_to_block (&loopbody, tmp);
8716
66e4ab31 8717 /* Build the loop and return. */
5046aff5
PT
8718 gfc_init_loopinfo (&loop);
8719 loop.dimen = 1;
8720 loop.from[0] = gfc_index_zero_node;
8721 loop.loopvar[0] = index;
8722 loop.to[0] = nelems;
8723 gfc_trans_scalarizing_loops (&loop, &loopbody);
8724 gfc_add_block_to_block (&fnblock, &loop.pre);
8725
8726 tmp = gfc_finish_block (&fnblock);
fc7d0afb
AV
8727 /* When copying allocateable components, the above implements the
8728 deep copy. Nevertheless is a deep copy only allowed, when the current
8729 component is allocated, for which code will be generated in
8730 gfc_duplicate_allocatable (), where the deep copy code is just added
8731 into the if's body, by adding tmp (the deep copy code) as last
8732 argument to gfc_duplicate_allocatable (). */
8733 if (purpose == COPY_ALLOC_COMP
8734 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (dest)))
8735 tmp = gfc_duplicate_allocatable (dest, decl, decl_type, rank,
8736 tmp);
8737 else if (null_cond != NULL_TREE)
c2255bc4
AH
8738 tmp = build3_v (COND_EXPR, null_cond, tmp,
8739 build_empty_stmt (input_location));
5046aff5
PT
8740
8741 return tmp;
8742 }
8743
2fcd5884
PT
8744 if (purpose == DEALLOCATE_ALLOC_COMP && der_type->attr.pdt_type)
8745 {
8746 tmp = structure_alloc_comps (der_type, decl, NULL_TREE, rank,
c78d3425 8747 DEALLOCATE_PDT_COMP, 0, args);
2fcd5884
PT
8748 gfc_add_expr_to_block (&fnblock, tmp);
8749 }
8750 else if (purpose == ALLOCATE_PDT_COMP && der_type->attr.alloc_comp)
8751 {
8752 tmp = structure_alloc_comps (der_type, decl, NULL_TREE, rank,
c78d3425 8753 NULLIFY_ALLOC_COMP, 0, args);
2fcd5884
PT
8754 gfc_add_expr_to_block (&fnblock, tmp);
8755 }
8756
5046aff5 8757 /* Otherwise, act on the components or recursively call self to
66e4ab31 8758 act on a chain of components. */
5046aff5
PT
8759 for (c = der_type->components; c; c = c->next)
8760 {
272cec5d
TK
8761 bool cmp_has_alloc_comps = (c->ts.type == BT_DERIVED
8762 || c->ts.type == BT_CLASS)
bc21d315 8763 && c->ts.u.derived->attr.alloc_comp;
39da5866
AV
8764 bool same_type = (c->ts.type == BT_DERIVED && der_type == c->ts.u.derived)
8765 || (c->ts.type == BT_CLASS && der_type == CLASS_DATA (c)->ts.u.derived);
bf9f15ee 8766
0b627b58
PT
8767 bool is_pdt_type = c->ts.type == BT_DERIVED
8768 && c->ts.u.derived->attr.pdt_type;
8769
5046aff5
PT
8770 cdecl = c->backend_decl;
8771 ctype = TREE_TYPE (cdecl);
8772
8773 switch (purpose)
8774 {
c78d3425
AF
8775
8776 case BCAST_ALLOC_COMP:
8777
8778 tree ubound;
8779 tree cdesc;
8780 stmtblock_t derived_type_block;
8781
8782 gfc_init_block (&tmpblock);
8783
8784 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
8785 decl, cdecl, NULL_TREE);
8786
8787 /* Shortcut to get the attributes of the component. */
8788 if (c->ts.type == BT_CLASS)
8789 {
8790 attr = &CLASS_DATA (c)->attr;
8791 if (attr->class_pointer)
8792 continue;
8793 }
8794 else
8795 {
8796 attr = &c->attr;
8797 if (attr->pointer)
8798 continue;
8799 }
8800
8801 add_when_allocated = NULL_TREE;
8802 if (cmp_has_alloc_comps
8803 && !c->attr.pointer && !c->attr.proc_pointer)
8804 {
8805 if (c->ts.type == BT_CLASS)
8806 {
8807 rank = CLASS_DATA (c)->as ? CLASS_DATA (c)->as->rank : 0;
8808 add_when_allocated
8809 = structure_alloc_comps (CLASS_DATA (c)->ts.u.derived,
8810 comp, NULL_TREE, rank, purpose,
8811 caf_mode, args);
8812 }
8813 else
8814 {
8815 rank = c->as ? c->as->rank : 0;
8816 add_when_allocated = structure_alloc_comps (c->ts.u.derived,
8817 comp, NULL_TREE,
8818 rank, purpose,
8819 caf_mode, args);
8820 }
8821 }
8822
8823 gfc_init_block (&derived_type_block);
8824 if (add_when_allocated)
8825 gfc_add_expr_to_block (&derived_type_block, add_when_allocated);
8826 tmp = gfc_finish_block (&derived_type_block);
8827 gfc_add_expr_to_block (&tmpblock, tmp);
8828
8829 /* Convert the component into a rank 1 descriptor type. */
8830 if (attr->dimension)
8831 {
8832 tmp = gfc_get_element_type (TREE_TYPE (comp));
8833 ubound = gfc_full_array_size (&tmpblock, comp,
8834 c->ts.type == BT_CLASS
8835 ? CLASS_DATA (c)->as->rank
8836 : c->as->rank);
8837 }
8838 else
8839 {
8840 tmp = TREE_TYPE (comp);
8841 ubound = build_int_cst (gfc_array_index_type, 1);
8842 }
8843
8844 cdesc = gfc_get_array_type_bounds (tmp, 1, 0, &gfc_index_one_node,
8845 &ubound, 1,
8846 GFC_ARRAY_ALLOCATABLE, false);
8847
8848 cdesc = gfc_create_var (cdesc, "cdesc");
8849 DECL_ARTIFICIAL (cdesc) = 1;
61c8d9e4 8850
c78d3425
AF
8851 gfc_add_modify (&tmpblock, gfc_conv_descriptor_dtype (cdesc),
8852 gfc_get_dtype_rank_type (1, tmp));
8853 gfc_conv_descriptor_lbound_set (&tmpblock, cdesc,
8854 gfc_index_zero_node,
8855 gfc_index_one_node);
8856 gfc_conv_descriptor_stride_set (&tmpblock, cdesc,
8857 gfc_index_zero_node,
8858 gfc_index_one_node);
8859 gfc_conv_descriptor_ubound_set (&tmpblock, cdesc,
8860 gfc_index_zero_node, ubound);
61c8d9e4 8861
c78d3425
AF
8862 if (attr->dimension)
8863 comp = gfc_conv_descriptor_data_get (comp);
8864 else
8865 {
8866 gfc_se se;
8867
8868 gfc_init_se (&se, NULL);
8869
8870 comp = gfc_conv_scalar_to_descriptor (&se, comp,
8871 c->ts.type == BT_CLASS
8872 ? CLASS_DATA (c)->attr
8873 : c->attr);
8874 comp = gfc_build_addr_expr (NULL_TREE, comp);
8875 gfc_add_block_to_block (&tmpblock, &se.pre);
8876 }
8877
8878 gfc_conv_descriptor_data_set (&tmpblock, cdesc, comp);
8879
8880 tree fndecl;
8881
8882 fndecl = build_call_expr_loc (input_location,
8883 gfor_fndecl_co_broadcast, 5,
8884 gfc_build_addr_expr (pvoid_type_node,cdesc),
8885 args->image_index,
8886 null_pointer_node, null_pointer_node,
8887 null_pointer_node);
8888
8889 gfc_add_expr_to_block (&tmpblock, fndecl);
8890 gfc_add_block_to_block (&fnblock, &tmpblock);
8891
8892 break;
8893
5046aff5 8894 case DEALLOCATE_ALLOC_COMP:
d6430d9a 8895
d6430d9a 8896 gfc_init_block (&tmpblock);
dbb7247b 8897
39da5866
AV
8898 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
8899 decl, cdecl, NULL_TREE);
8900
8901 /* Shortcut to get the attributes of the component. */
8902 if (c->ts.type == BT_CLASS)
4b9c80d8
AV
8903 {
8904 attr = &CLASS_DATA (c)->attr;
8905 if (attr->class_pointer)
8906 continue;
8907 }
39da5866 8908 else
4b9c80d8
AV
8909 {
8910 attr = &c->attr;
8911 if (attr->pointer)
8912 continue;
8913 }
39da5866 8914
895a0c2d 8915 if ((c->ts.type == BT_DERIVED && !c->attr.pointer)
39da5866
AV
8916 || (c->ts.type == BT_CLASS && !CLASS_DATA (c)->attr.class_pointer))
8917 /* Call the finalizer, which will free the memory and nullify the
8918 pointer of an array. */
8919 deallocate_called = gfc_add_comp_finalizer_call (&tmpblock, comp, c,
8920 caf_enabled (caf_mode))
8921 && attr->dimension;
8922 else
8923 deallocate_called = false;
8924
8925 /* Add the _class ref for classes. */
8926 if (c->ts.type == BT_CLASS && attr->allocatable)
8927 comp = gfc_class_data_get (comp);
895a0c2d 8928
39da5866
AV
8929 add_when_allocated = NULL_TREE;
8930 if (cmp_has_alloc_comps
8931 && !c->attr.pointer && !c->attr.proc_pointer
8932 && !same_type
8933 && !deallocate_called)
8934 {
8935 /* Add checked deallocation of the components. This code is
8936 obviously added because the finalizer is not trusted to free
8937 all memory. */
8938 if (c->ts.type == BT_CLASS)
8939 {
8940 rank = CLASS_DATA (c)->as ? CLASS_DATA (c)->as->rank : 0;
8941 add_when_allocated
8942 = structure_alloc_comps (CLASS_DATA (c)->ts.u.derived,
8943 comp, NULL_TREE, rank, purpose,
c78d3425 8944 caf_mode, args);
39da5866
AV
8945 }
8946 else
8947 {
8948 rank = c->as ? c->as->rank : 0;
8949 add_when_allocated = structure_alloc_comps (c->ts.u.derived,
8950 comp, NULL_TREE,
8951 rank, purpose,
c78d3425 8952 caf_mode, args);
39da5866 8953 }
895a0c2d 8954 }
895a0c2d 8955
39da5866
AV
8956 if (attr->allocatable && !same_type
8957 && (!attr->codimension || caf_enabled (caf_mode)))
895a0c2d 8958 {
39da5866
AV
8959 /* Handle all types of components besides components of the
8960 same_type as the current one, because those would create an
8961 endless loop. */
8962 caf_dereg_mode
8963 = (caf_in_coarray (caf_mode) || attr->codimension)
ba85c8c3
AV
8964 ? (gfc_caf_is_dealloc_only (caf_mode)
8965 ? GFC_CAF_COARRAY_DEALLOCATE_ONLY
8966 : GFC_CAF_COARRAY_DEREGISTER)
8967 : GFC_CAF_COARRAY_NOCOARRAY;
ba85c8c3 8968
39da5866
AV
8969 caf_token = NULL_TREE;
8970 /* Coarray components are handled directly by
8971 deallocate_with_status. */
8972 if (!attr->codimension
8973 && caf_dereg_mode != GFC_CAF_COARRAY_NOCOARRAY)
ba85c8c3 8974 {
39da5866
AV
8975 if (c->caf_token)
8976 caf_token = fold_build3_loc (input_location, COMPONENT_REF,
8977 TREE_TYPE (c->caf_token),
8978 decl, c->caf_token, NULL_TREE);
8979 else if (attr->dimension && !attr->proc_pointer)
8980 caf_token = gfc_conv_descriptor_token (comp);
ba85c8c3 8981 }
39da5866
AV
8982 if (attr->dimension && !attr->codimension && !attr->proc_pointer)
8983 /* When this is an array but not in conjunction with a coarray
8984 then add the data-ref. For coarray'ed arrays the data-ref
8985 is added by deallocate_with_status. */
8986 comp = gfc_conv_descriptor_data_get (comp);
ba85c8c3 8987
39da5866
AV
8988 tmp = gfc_deallocate_with_status (comp, NULL_TREE, NULL_TREE,
8989 NULL_TREE, NULL_TREE, true,
8990 NULL, caf_dereg_mode,
8991 add_when_allocated, caf_token);
1517fd57 8992
d6430d9a 8993 gfc_add_expr_to_block (&tmpblock, tmp);
1517fd57 8994 }
39da5866
AV
8995 else if (attr->allocatable && !attr->codimension
8996 && !deallocate_called)
bf9f15ee
PT
8997 {
8998 /* Case of recursive allocatable derived types. */
8999 tree is_allocated;
9000 tree ubound;
9001 tree cdesc;
bf9f15ee
PT
9002 stmtblock_t dealloc_block;
9003
9004 gfc_init_block (&dealloc_block);
39da5866
AV
9005 if (add_when_allocated)
9006 gfc_add_expr_to_block (&dealloc_block, add_when_allocated);
bf9f15ee
PT
9007
9008 /* Convert the component into a rank 1 descriptor type. */
39da5866 9009 if (attr->dimension)
bf9f15ee
PT
9010 {
9011 tmp = gfc_get_element_type (TREE_TYPE (comp));
39da5866
AV
9012 ubound = gfc_full_array_size (&dealloc_block, comp,
9013 c->ts.type == BT_CLASS
9014 ? CLASS_DATA (c)->as->rank
9015 : c->as->rank);
bf9f15ee
PT
9016 }
9017 else
9018 {
9019 tmp = TREE_TYPE (comp);
9020 ubound = build_int_cst (gfc_array_index_type, 1);
9021 }
9022
ba85c8c3
AV
9023 cdesc = gfc_get_array_type_bounds (tmp, 1, 0, &gfc_index_one_node,
9024 &ubound, 1,
bf9f15ee
PT
9025 GFC_ARRAY_ALLOCATABLE, false);
9026
9027 cdesc = gfc_create_var (cdesc, "cdesc");
9028 DECL_ARTIFICIAL (cdesc) = 1;
9029
9030 gfc_add_modify (&dealloc_block, gfc_conv_descriptor_dtype (cdesc),
9031 gfc_get_dtype_rank_type (1, tmp));
9032 gfc_conv_descriptor_lbound_set (&dealloc_block, cdesc,
ba85c8c3
AV
9033 gfc_index_zero_node,
9034 gfc_index_one_node);
bf9f15ee 9035 gfc_conv_descriptor_stride_set (&dealloc_block, cdesc,
ba85c8c3
AV
9036 gfc_index_zero_node,
9037 gfc_index_one_node);
bf9f15ee 9038 gfc_conv_descriptor_ubound_set (&dealloc_block, cdesc,
ba85c8c3 9039 gfc_index_zero_node, ubound);
bf9f15ee 9040
39da5866
AV
9041 if (attr->dimension)
9042 comp = gfc_conv_descriptor_data_get (comp);
bf9f15ee 9043
39da5866 9044 gfc_conv_descriptor_data_set (&dealloc_block, cdesc, comp);
bf9f15ee
PT
9045
9046 /* Now call the deallocator. */
9047 vtab = gfc_find_vtab (&c->ts);
9048 if (vtab->backend_decl == NULL)
9049 gfc_get_symbol_decl (vtab);
9050 tmp = gfc_build_addr_expr (NULL_TREE, vtab->backend_decl);
9051 dealloc_fndecl = gfc_vptr_deallocate_get (tmp);
9052 dealloc_fndecl = build_fold_indirect_ref_loc (input_location,
9053 dealloc_fndecl);
39da5866 9054 tmp = build_int_cst (TREE_TYPE (comp), 0);
bf9f15ee 9055 is_allocated = fold_build2_loc (input_location, NE_EXPR,
63ee5404 9056 logical_type_node, tmp,
39da5866 9057 comp);
bf9f15ee
PT
9058 cdesc = gfc_build_addr_expr (NULL_TREE, cdesc);
9059
9060 tmp = build_call_expr_loc (input_location,
9061 dealloc_fndecl, 1,
9062 cdesc);
9063 gfc_add_expr_to_block (&dealloc_block, tmp);
9064
9065 tmp = gfc_finish_block (&dealloc_block);
9066
9067 tmp = fold_build3_loc (input_location, COND_EXPR,
9068 void_type_node, is_allocated, tmp,
9069 build_empty_stmt (input_location));
9070
9071 gfc_add_expr_to_block (&tmpblock, tmp);
bf9f15ee 9072 }
39da5866
AV
9073 else if (add_when_allocated)
9074 gfc_add_expr_to_block (&tmpblock, add_when_allocated);
bf9f15ee 9075
39da5866
AV
9076 if (c->ts.type == BT_CLASS && attr->allocatable
9077 && (!attr->codimension || !caf_enabled (caf_mode)))
1517fd57 9078 {
6a4236ce
PT
9079 /* Finally, reset the vptr to the declared type vtable and, if
9080 necessary reset the _len field.
9081
9082 First recover the reference to the component and obtain
9083 the vptr. */
9084 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
39da5866 9085 decl, cdecl, NULL_TREE);
6a4236ce
PT
9086 tmp = gfc_class_vptr_get (comp);
9087
9088 if (UNLIMITED_POLY (c))
9089 {
9090 /* Both vptr and _len field should be nulled. */
9091 gfc_add_modify (&tmpblock, tmp,
9092 build_int_cst (TREE_TYPE (tmp), 0));
9093 tmp = gfc_class_len_get (comp);
9094 gfc_add_modify (&tmpblock, tmp,
9095 build_int_cst (TREE_TYPE (tmp), 0));
9096 }
9097 else
9098 {
9099 /* Build the vtable address and set the vptr with it. */
9100 tree vtab;
9101 gfc_symbol *vtable;
9102 vtable = gfc_find_derived_vtab (c->ts.u.derived);
9103 vtab = vtable->backend_decl;
9104 if (vtab == NULL_TREE)
9105 vtab = gfc_get_symbol_decl (vtable);
9106 vtab = gfc_build_addr_expr (NULL, vtab);
9107 vtab = fold_convert (TREE_TYPE (tmp), vtab);
9108 gfc_add_modify (&tmpblock, tmp, vtab);
9109 }
d6430d9a
PT
9110 }
9111
d6430d9a
PT
9112 /* Now add the deallocation of this component. */
9113 gfc_add_block_to_block (&fnblock, &tmpblock);
5046aff5
PT
9114 break;
9115
9116 case NULLIFY_ALLOC_COMP:
de91486c
AV
9117 /* Nullify
9118 - allocatable components (regular or in class)
9119 - components that have allocatable components
9120 - pointer components when in a coarray.
9121 Skip everything else especially proc_pointers, which may come
9122 coupled with the regular pointer attribute. */
9123 if (c->attr.proc_pointer
ba85c8c3
AV
9124 || !(c->attr.allocatable || (c->ts.type == BT_CLASS
9125 && CLASS_DATA (c)->attr.allocatable)
de91486c
AV
9126 || (cmp_has_alloc_comps
9127 && ((c->ts.type == BT_DERIVED && !c->attr.pointer)
9128 || (c->ts.type == BT_CLASS
9129 && !CLASS_DATA (c)->attr.class_pointer)))
9130 || (caf_in_coarray (caf_mode) && c->attr.pointer)))
5046aff5 9131 continue;
ba85c8c3 9132
de91486c
AV
9133 /* Process class components first, because they always have the
9134 pointer-attribute set which would be caught wrong else. */
9135 if (c->ts.type == BT_CLASS
9136 && (CLASS_DATA (c)->attr.allocatable
9137 || CLASS_DATA (c)->attr.class_pointer))
1517fd57 9138 {
61c8d9e4
PT
9139 tree vptr_decl;
9140
de91486c 9141 /* Allocatable CLASS components. */
94471a56
TB
9142 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
9143 decl, cdecl, NULL_TREE);
de91486c 9144
61c8d9e4
PT
9145 vptr_decl = gfc_class_vptr_get (comp);
9146
de91486c
AV
9147 comp = gfc_class_data_get (comp);
9148 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (comp)))
9149 gfc_conv_descriptor_data_set (&fnblock, comp,
9150 null_pointer_node);
9151 else
2b3dc0db 9152 {
2b3dc0db 9153 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
de91486c 9154 void_type_node, comp,
2b3dc0db
PT
9155 build_int_cst (TREE_TYPE (comp), 0));
9156 gfc_add_expr_to_block (&fnblock, tmp);
9157 }
61c8d9e4
PT
9158
9159 /* The dynamic type of a disassociated pointer or unallocated
9160 allocatable variable is its declared type. An unlimited
9161 polymorphic entity has no declared type. */
9162 if (!UNLIMITED_POLY (c))
9163 {
9164 vtab = gfc_find_derived_vtab (c->ts.u.derived);
9165 if (!vtab->backend_decl)
9166 gfc_get_symbol_decl (vtab);
9167 tmp = gfc_build_addr_expr (NULL_TREE, vtab->backend_decl);
9168 }
9169 else
9170 tmp = build_int_cst (TREE_TYPE (vptr_decl), 0);
9171
9172 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
9173 void_type_node, vptr_decl, tmp);
9174 gfc_add_expr_to_block (&fnblock, tmp);
9175
ba85c8c3 9176 cmp_has_alloc_comps = false;
1517fd57 9177 }
de91486c
AV
9178 /* Coarrays need the component to be nulled before the api-call
9179 is made. */
9180 else if (c->attr.pointer || c->attr.allocatable)
1517fd57 9181 {
94471a56
TB
9182 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
9183 decl, cdecl, NULL_TREE);
de91486c
AV
9184 if (c->attr.dimension || c->attr.codimension)
9185 gfc_conv_descriptor_data_set (&fnblock, comp,
9186 null_pointer_node);
c49ea23d 9187 else
de91486c
AV
9188 gfc_add_modify (&fnblock, comp,
9189 build_int_cst (TREE_TYPE (comp), 0));
9190 if (gfc_deferred_strlen (c, &comp))
c49ea23d 9191 {
de91486c
AV
9192 comp = fold_build3_loc (input_location, COMPONENT_REF,
9193 TREE_TYPE (comp),
9194 decl, comp, NULL_TREE);
c49ea23d 9195 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
de91486c 9196 TREE_TYPE (comp), comp,
c49ea23d
PT
9197 build_int_cst (TREE_TYPE (comp), 0));
9198 gfc_add_expr_to_block (&fnblock, tmp);
9199 }
ba85c8c3
AV
9200 cmp_has_alloc_comps = false;
9201 }
9202
61fad608 9203 if (flag_coarray == GFC_FCOARRAY_LIB && caf_in_coarray (caf_mode))
ba85c8c3 9204 {
61fad608
AV
9205 /* Register a component of a derived type coarray with the
9206 coarray library. Do not register ultimate component
9207 coarrays here. They are treated like regular coarrays and
9208 are either allocated on all images or on none. */
ba85c8c3
AV
9209 tree token;
9210
9211 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
9212 decl, cdecl, NULL_TREE);
61fad608 9213 if (c->attr.dimension)
ba85c8c3 9214 {
de91486c
AV
9215 /* Set the dtype, because caf_register needs it. */
9216 gfc_add_modify (&fnblock, gfc_conv_descriptor_dtype (comp),
9217 gfc_get_dtype (TREE_TYPE (comp)));
ba85c8c3
AV
9218 tmp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
9219 decl, cdecl, NULL_TREE);
9220 token = gfc_conv_descriptor_token (tmp);
9221 }
9222 else
9223 {
9224 gfc_se se;
ba85c8c3
AV
9225
9226 gfc_init_se (&se, NULL);
ba85c8c3
AV
9227 token = fold_build3_loc (input_location, COMPONENT_REF,
9228 pvoid_type_node, decl, c->caf_token,
9229 NULL_TREE);
e0396d77
AV
9230 comp = gfc_conv_scalar_to_descriptor (&se, comp,
9231 c->ts.type == BT_CLASS
9232 ? CLASS_DATA (c)->attr
9233 : c->attr);
ba85c8c3
AV
9234 gfc_add_block_to_block (&fnblock, &se.pre);
9235 }
9236
ba85c8c3
AV
9237 gfc_allocate_using_caf_lib (&fnblock, comp, size_zero_node,
9238 gfc_build_addr_expr (NULL_TREE,
9239 token),
9240 NULL_TREE, NULL_TREE, NULL_TREE,
9241 GFC_CAF_COARRAY_ALLOC_REGISTER_ONLY);
1517fd57 9242 }
ba85c8c3
AV
9243
9244 if (cmp_has_alloc_comps)
5046aff5 9245 {
94471a56
TB
9246 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
9247 decl, cdecl, NULL_TREE);
5046aff5 9248 rank = c->as ? c->as->rank : 0;
bc21d315 9249 tmp = structure_alloc_comps (c->ts.u.derived, comp, NULL_TREE,
c78d3425 9250 rank, purpose, caf_mode, args);
5046aff5
PT
9251 gfc_add_expr_to_block (&fnblock, tmp);
9252 }
9253 break;
9254
ba85c8c3
AV
9255 case REASSIGN_CAF_COMP:
9256 if (caf_enabled (caf_mode)
9257 && (c->attr.codimension
9258 || (c->ts.type == BT_CLASS
9259 && (CLASS_DATA (c)->attr.coarray_comp
9260 || caf_in_coarray (caf_mode)))
9261 || (c->ts.type == BT_DERIVED
9262 && (c->ts.u.derived->attr.coarray_comp
9263 || caf_in_coarray (caf_mode))))
9264 && !same_type)
558f3755 9265 {
ba85c8c3
AV
9266 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
9267 decl, cdecl, NULL_TREE);
9268 dcmp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
9269 dest, cdecl, NULL_TREE);
9270
9271 if (c->attr.codimension)
558f3755 9272 {
ba85c8c3
AV
9273 if (c->ts.type == BT_CLASS)
9274 {
9275 comp = gfc_class_data_get (comp);
9276 dcmp = gfc_class_data_get (dcmp);
9277 }
9278 gfc_conv_descriptor_data_set (&fnblock, dcmp,
558f3755 9279 gfc_conv_descriptor_data_get (comp));
ba85c8c3
AV
9280 }
9281 else
9282 {
9283 tmp = structure_alloc_comps (c->ts.u.derived, comp, dcmp,
9284 rank, purpose, caf_mode
c78d3425
AF
9285 | GFC_STRUCTURE_CAF_MODE_IN_COARRAY,
9286 args);
ba85c8c3
AV
9287 gfc_add_expr_to_block (&fnblock, tmp);
9288 }
abc2d807
TB
9289 }
9290 break;
9291
5046aff5 9292 case COPY_ALLOC_COMP:
e057d3e5 9293 if (c->attr.pointer || c->attr.proc_pointer)
5046aff5
PT
9294 continue;
9295
9296 /* We need source and destination components. */
94471a56
TB
9297 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype, decl,
9298 cdecl, NULL_TREE);
9299 dcmp = fold_build3_loc (input_location, COMPONENT_REF, ctype, dest,
9300 cdecl, NULL_TREE);
5046aff5
PT
9301 dcmp = fold_convert (TREE_TYPE (comp), dcmp);
9302
4ed1b019
TB
9303 if (c->ts.type == BT_CLASS && CLASS_DATA (c)->attr.allocatable)
9304 {
9305 tree ftn_tree;
9306 tree size;
9307 tree dst_data;
9308 tree src_data;
9309 tree null_data;
9310
9311 dst_data = gfc_class_data_get (dcmp);
9312 src_data = gfc_class_data_get (comp);
34d9d749
AV
9313 size = fold_convert (size_type_node,
9314 gfc_class_vtab_size_get (comp));
4ed1b019
TB
9315
9316 if (CLASS_DATA (c)->attr.dimension)
9317 {
9318 nelems = gfc_conv_descriptor_size (src_data,
9319 CLASS_DATA (c)->as->rank);
16023efc
TB
9320 size = fold_build2_loc (input_location, MULT_EXPR,
9321 size_type_node, size,
9322 fold_convert (size_type_node,
9323 nelems));
4ed1b019
TB
9324 }
9325 else
9326 nelems = build_int_cst (size_type_node, 1);
9327
abc2d807
TB
9328 if (CLASS_DATA (c)->attr.dimension
9329 || CLASS_DATA (c)->attr.codimension)
9330 {
9331 src_data = gfc_conv_descriptor_data_get (src_data);
9332 dst_data = gfc_conv_descriptor_data_get (dst_data);
9333 }
9334
4ed1b019
TB
9335 gfc_init_block (&tmpblock);
9336
26219cee
PT
9337 gfc_add_modify (&tmpblock, gfc_class_vptr_get (dcmp),
9338 gfc_class_vptr_get (comp));
9339
9340 /* Copy the unlimited '_len' field. If it is greater than zero
9341 (ie. a character(_len)), multiply it by size and use this
9342 for the malloc call. */
9343 if (UNLIMITED_POLY (c))
9344 {
9345 tree ctmp;
9346 gfc_add_modify (&tmpblock, gfc_class_len_get (dcmp),
9347 gfc_class_len_get (comp));
9348
9349 size = gfc_evaluate_now (size, &tmpblock);
9350 tmp = gfc_class_len_get (comp);
9351 ctmp = fold_build2_loc (input_location, MULT_EXPR,
9352 size_type_node, size,
9353 fold_convert (size_type_node, tmp));
9354 tmp = fold_build2_loc (input_location, GT_EXPR,
9355 logical_type_node, tmp,
9356 build_zero_cst (TREE_TYPE (tmp)));
9357 size = fold_build3_loc (input_location, COND_EXPR,
9358 size_type_node, tmp, ctmp, size);
9359 size = gfc_evaluate_now (size, &tmpblock);
9360 }
9361
abc2d807
TB
9362 /* Coarray component have to have the same allocation status and
9363 shape/type-parameter/effective-type on the LHS and RHS of an
9364 intrinsic assignment. Hence, we did not deallocated them - and
9365 do not allocate them here. */
9366 if (!CLASS_DATA (c)->attr.codimension)
9367 {
9368 ftn_tree = builtin_decl_explicit (BUILT_IN_MALLOC);
9369 tmp = build_call_expr_loc (input_location, ftn_tree, 1, size);
9370 gfc_add_modify (&tmpblock, dst_data,
9371 fold_convert (TREE_TYPE (dst_data), tmp));
9372 }
4ed1b019 9373
34d9d749
AV
9374 tmp = gfc_copy_class_to_class (comp, dcmp, nelems,
9375 UNLIMITED_POLY (c));
4ed1b019
TB
9376 gfc_add_expr_to_block (&tmpblock, tmp);
9377 tmp = gfc_finish_block (&tmpblock);
9378
9379 gfc_init_block (&tmpblock);
9380 gfc_add_modify (&tmpblock, dst_data,
9381 fold_convert (TREE_TYPE (dst_data),
9382 null_pointer_node));
9383 null_data = gfc_finish_block (&tmpblock);
9384
9385 null_cond = fold_build2_loc (input_location, NE_EXPR,
63ee5404 9386 logical_type_node, src_data,
f04986a9 9387 null_pointer_node);
4ed1b019
TB
9388
9389 gfc_add_expr_to_block (&fnblock, build3_v (COND_EXPR, null_cond,
9390 tmp, null_data));
9391 continue;
9392 }
9393
fc7d0afb
AV
9394 /* To implement guarded deep copy, i.e., deep copy only allocatable
9395 components that are really allocated, the deep copy code has to
9396 be generated first and then added to the if-block in
9397 gfc_duplicate_allocatable (). */
0b627b58 9398 if (cmp_has_alloc_comps && !c->attr.proc_pointer && !same_type)
fc7d0afb
AV
9399 {
9400 rank = c->as ? c->as->rank : 0;
9401 tmp = fold_convert (TREE_TYPE (dcmp), comp);
9402 gfc_add_modify (&fnblock, dcmp, tmp);
9403 add_when_allocated = structure_alloc_comps (c->ts.u.derived,
9404 comp, dcmp,
ba85c8c3 9405 rank, purpose,
c78d3425 9406 caf_mode, args);
fc7d0afb
AV
9407 }
9408 else
9409 add_when_allocated = NULL_TREE;
9410
2b3dc0db
PT
9411 if (gfc_deferred_strlen (c, &tmp))
9412 {
9413 tree len, size;
9414 len = tmp;
9415 tmp = fold_build3_loc (input_location, COMPONENT_REF,
9416 TREE_TYPE (len),
9417 decl, len, NULL_TREE);
9418 len = fold_build3_loc (input_location, COMPONENT_REF,
9419 TREE_TYPE (len),
9420 dest, len, NULL_TREE);
9421 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
9422 TREE_TYPE (len), len, tmp);
9423 gfc_add_expr_to_block (&fnblock, tmp);
9424 size = size_of_string_in_bytes (c->ts.kind, len);
67914693 9425 /* This component cannot have allocatable components,
fc7d0afb
AV
9426 therefore add_when_allocated of duplicate_allocatable ()
9427 is always NULL. */
2b3dc0db 9428 tmp = duplicate_allocatable (dcmp, comp, ctype, rank,
fc7d0afb 9429 false, false, size, NULL_TREE);
2b3dc0db
PT
9430 gfc_add_expr_to_block (&fnblock, tmp);
9431 }
0b627b58
PT
9432 else if (c->attr.pdt_array)
9433 {
9434 tmp = duplicate_allocatable (dcmp, comp, ctype,
9435 c->as ? c->as->rank : 0,
9436 false, false, NULL_TREE, NULL_TREE);
9437 gfc_add_expr_to_block (&fnblock, tmp);
9438 }
9439 else if ((c->attr.allocatable)
9440 && !c->attr.proc_pointer && !same_type
9441 && (!(cmp_has_alloc_comps && c->as) || c->attr.codimension
9442 || caf_in_coarray (caf_mode)))
5046aff5 9443 {
40c32948 9444 rank = c->as ? c->as->rank : 0;
abc2d807
TB
9445 if (c->attr.codimension)
9446 tmp = gfc_copy_allocatable_data (dcmp, comp, ctype, rank);
ba85c8c3
AV
9447 else if (flag_coarray == GFC_FCOARRAY_LIB
9448 && caf_in_coarray (caf_mode))
9449 {
9450 tree dst_tok = c->as ? gfc_conv_descriptor_token (dcmp)
9451 : fold_build3_loc (input_location,
9452 COMPONENT_REF,
9453 pvoid_type_node, dest,
9454 c->caf_token,
9455 NULL_TREE);
9456 tmp = duplicate_allocatable_coarray (dcmp, dst_tok, comp,
9457 ctype, rank);
9458 }
abc2d807 9459 else
fc7d0afb
AV
9460 tmp = gfc_duplicate_allocatable (dcmp, comp, ctype, rank,
9461 add_when_allocated);
5046aff5
PT
9462 gfc_add_expr_to_block (&fnblock, tmp);
9463 }
fc7d0afb 9464 else
0b627b58 9465 if (cmp_has_alloc_comps || is_pdt_type)
fc7d0afb 9466 gfc_add_expr_to_block (&fnblock, add_when_allocated);
5046aff5 9467
5046aff5
PT
9468 break;
9469
5bab4c96
PT
9470 case ALLOCATE_PDT_COMP:
9471
9472 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
9473 decl, cdecl, NULL_TREE);
9474
9475 /* Set the PDT KIND and LEN fields. */
9476 if (c->attr.pdt_kind || c->attr.pdt_len)
9477 {
9478 gfc_se tse;
9479 gfc_expr *c_expr = NULL;
9480 gfc_actual_arglist *param = pdt_param_list;
9481 gfc_init_se (&tse, NULL);
9482 for (; param; param = param->next)
276515e6 9483 if (param->name && !strcmp (c->name, param->name))
5bab4c96
PT
9484 c_expr = param->expr;
9485
9486 if (!c_expr)
9487 c_expr = c->initializer;
9488
9489 if (c_expr)
9490 {
9491 gfc_conv_expr_type (&tse, c_expr, TREE_TYPE (comp));
9492 gfc_add_modify (&fnblock, comp, tse.expr);
9493 }
9494 }
9495
9496 if (c->attr.pdt_string)
9497 {
9498 gfc_se tse;
9499 gfc_init_se (&tse, NULL);
276515e6
PT
9500 tree strlen = NULL_TREE;
9501 gfc_expr *e = gfc_copy_expr (c->ts.u.cl->length);
5bab4c96
PT
9502 /* Convert the parameterized string length to its value. The
9503 string length is stored in a hidden field in the same way as
9504 deferred string lengths. */
276515e6 9505 gfc_insert_parameter_exprs (e, pdt_param_list);
5bab4c96
PT
9506 if (gfc_deferred_strlen (c, &strlen) && strlen != NULL_TREE)
9507 {
276515e6 9508 gfc_conv_expr_type (&tse, e,
5bab4c96
PT
9509 TREE_TYPE (strlen));
9510 strlen = fold_build3_loc (input_location, COMPONENT_REF,
9511 TREE_TYPE (strlen),
9512 decl, strlen, NULL_TREE);
9513 gfc_add_modify (&fnblock, strlen, tse.expr);
9514 c->ts.u.cl->backend_decl = strlen;
9515 }
276515e6
PT
9516 gfc_free_expr (e);
9517
0b627b58 9518 /* Scalar parameterized strings can be allocated now. */
5bab4c96
PT
9519 if (!c->as)
9520 {
9521 tmp = fold_convert (gfc_array_index_type, strlen);
9522 tmp = size_of_string_in_bytes (c->ts.kind, tmp);
9523 tmp = gfc_evaluate_now (tmp, &fnblock);
9524 tmp = gfc_call_malloc (&fnblock, TREE_TYPE (comp), tmp);
9525 gfc_add_modify (&fnblock, comp, tmp);
9526 }
9527 }
9528
0b627b58 9529 /* Allocate parameterized arrays of parameterized derived types. */
5bab4c96
PT
9530 if (!(c->attr.pdt_array && c->as && c->as->type == AS_EXPLICIT)
9531 && !((c->ts.type == BT_DERIVED || c->ts.type == BT_CLASS)
9532 && (c->ts.u.derived && c->ts.u.derived->attr.pdt_type)))
9533 continue;
9534
9535 if (c->ts.type == BT_CLASS)
9536 comp = gfc_class_data_get (comp);
9537
9538 if (c->attr.pdt_array)
9539 {
9540 gfc_se tse;
9541 int i;
9542 tree size = gfc_index_one_node;
9543 tree offset = gfc_index_zero_node;
9544 tree lower, upper;
9545 gfc_expr *e;
9546
9547 /* This chunk takes the expressions for 'lower' and 'upper'
9548 in the arrayspec and substitutes in the expressions for
9549 the parameters from 'pdt_param_list'. The descriptor
9550 fields can then be filled from the values so obtained. */
9551 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (comp)));
9552 for (i = 0; i < c->as->rank; i++)
9553 {
9554 gfc_init_se (&tse, NULL);
9555 e = gfc_copy_expr (c->as->lower[i]);
9556 gfc_insert_parameter_exprs (e, pdt_param_list);
9557 gfc_conv_expr_type (&tse, e, gfc_array_index_type);
9558 gfc_free_expr (e);
9559 lower = tse.expr;
9560 gfc_conv_descriptor_lbound_set (&fnblock, comp,
9561 gfc_rank_cst[i],
9562 lower);
9563 e = gfc_copy_expr (c->as->upper[i]);
9564 gfc_insert_parameter_exprs (e, pdt_param_list);
9565 gfc_conv_expr_type (&tse, e, gfc_array_index_type);
9566 gfc_free_expr (e);
9567 upper = tse.expr;
9568 gfc_conv_descriptor_ubound_set (&fnblock, comp,
9569 gfc_rank_cst[i],
9570 upper);
9571 gfc_conv_descriptor_stride_set (&fnblock, comp,
9572 gfc_rank_cst[i],
9573 size);
9574 size = gfc_evaluate_now (size, &fnblock);
9575 offset = fold_build2_loc (input_location,
9576 MINUS_EXPR,
9577 gfc_array_index_type,
9578 offset, size);
9579 offset = gfc_evaluate_now (offset, &fnblock);
9580 tmp = fold_build2_loc (input_location, MINUS_EXPR,
9581 gfc_array_index_type,
9582 upper, lower);
9583 tmp = fold_build2_loc (input_location, PLUS_EXPR,
9584 gfc_array_index_type,
9585 tmp, gfc_index_one_node);
9586 size = fold_build2_loc (input_location, MULT_EXPR,
9587 gfc_array_index_type, size, tmp);
9588 }
9589 gfc_conv_descriptor_offset_set (&fnblock, comp, offset);
9590 if (c->ts.type == BT_CLASS)
9591 {
9592 tmp = gfc_get_vptr_from_expr (comp);
9593 if (POINTER_TYPE_P (TREE_TYPE (tmp)))
9594 tmp = build_fold_indirect_ref_loc (input_location, tmp);
9595 tmp = gfc_vptr_size_get (tmp);
9596 }
9597 else
9598 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (ctype));
9599 tmp = fold_convert (gfc_array_index_type, tmp);
9600 size = fold_build2_loc (input_location, MULT_EXPR,
9601 gfc_array_index_type, size, tmp);
9602 size = gfc_evaluate_now (size, &fnblock);
9603 tmp = gfc_call_malloc (&fnblock, NULL, size);
9604 gfc_conv_descriptor_data_set (&fnblock, comp, tmp);
9605 tmp = gfc_conv_descriptor_dtype (comp);
9606 gfc_add_modify (&fnblock, tmp, gfc_get_dtype (ctype));
0b627b58
PT
9607
9608 if (c->initializer && c->initializer->rank)
9609 {
9610 gfc_init_se (&tse, NULL);
9611 e = gfc_copy_expr (c->initializer);
9612 gfc_insert_parameter_exprs (e, pdt_param_list);
9613 gfc_conv_expr_descriptor (&tse, e);
9614 gfc_add_block_to_block (&fnblock, &tse.pre);
9615 gfc_free_expr (e);
9616 tmp = builtin_decl_explicit (BUILT_IN_MEMCPY);
9617 tmp = build_call_expr_loc (input_location, tmp, 3,
9618 gfc_conv_descriptor_data_get (comp),
9619 gfc_conv_descriptor_data_get (tse.expr),
9620 fold_convert (size_type_node, size));
9621 gfc_add_expr_to_block (&fnblock, tmp);
9622 gfc_add_block_to_block (&fnblock, &tse.post);
9623 }
5bab4c96
PT
9624 }
9625
9626 /* Recurse in to PDT components. */
9627 if ((c->ts.type == BT_DERIVED || c->ts.type == BT_CLASS)
2fcd5884
PT
9628 && c->ts.u.derived && c->ts.u.derived->attr.pdt_type
9629 && !(c->attr.pointer || c->attr.allocatable))
5bab4c96
PT
9630 {
9631 bool is_deferred = false;
9632 gfc_actual_arglist *tail = c->param_list;
9633
9634 for (; tail; tail = tail->next)
9635 if (!tail->expr)
9636 is_deferred = true;
9637
9638 tail = is_deferred ? pdt_param_list : c->param_list;
9639 tmp = gfc_allocate_pdt_comp (c->ts.u.derived, comp,
9640 c->as ? c->as->rank : 0,
9641 tail);
9642 gfc_add_expr_to_block (&fnblock, tmp);
9643 }
9644
9645 break;
9646
9647 case DEALLOCATE_PDT_COMP:
9648 /* Deallocate array or parameterized string length components
9649 of parameterized derived types. */
9650 if (!(c->attr.pdt_array && c->as && c->as->type == AS_EXPLICIT)
9651 && !c->attr.pdt_string
9652 && !((c->ts.type == BT_DERIVED || c->ts.type == BT_CLASS)
9653 && (c->ts.u.derived && c->ts.u.derived->attr.pdt_type)))
9654 continue;
9655
9656 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
9657 decl, cdecl, NULL_TREE);
9658 if (c->ts.type == BT_CLASS)
9659 comp = gfc_class_data_get (comp);
9660
9661 /* Recurse in to PDT components. */
9662 if ((c->ts.type == BT_DERIVED || c->ts.type == BT_CLASS)
2fcd5884
PT
9663 && c->ts.u.derived && c->ts.u.derived->attr.pdt_type
9664 && (!c->attr.pointer && !c->attr.allocatable))
5bab4c96
PT
9665 {
9666 tmp = gfc_deallocate_pdt_comp (c->ts.u.derived, comp,
9667 c->as ? c->as->rank : 0);
9668 gfc_add_expr_to_block (&fnblock, tmp);
9669 }
9670
9671 if (c->attr.pdt_array)
9672 {
9673 tmp = gfc_conv_descriptor_data_get (comp);
2fcd5884 9674 null_cond = fold_build2_loc (input_location, NE_EXPR,
63ee5404 9675 logical_type_node, tmp,
2fcd5884 9676 build_int_cst (TREE_TYPE (tmp), 0));
5bab4c96 9677 tmp = gfc_call_free (tmp);
2fcd5884
PT
9678 tmp = build3_v (COND_EXPR, null_cond, tmp,
9679 build_empty_stmt (input_location));
5bab4c96
PT
9680 gfc_add_expr_to_block (&fnblock, tmp);
9681 gfc_conv_descriptor_data_set (&fnblock, comp, null_pointer_node);
9682 }
9683 else if (c->attr.pdt_string)
9684 {
2fcd5884 9685 null_cond = fold_build2_loc (input_location, NE_EXPR,
63ee5404 9686 logical_type_node, comp,
2fcd5884 9687 build_int_cst (TREE_TYPE (comp), 0));
5bab4c96 9688 tmp = gfc_call_free (comp);
2fcd5884
PT
9689 tmp = build3_v (COND_EXPR, null_cond, tmp,
9690 build_empty_stmt (input_location));
5bab4c96
PT
9691 gfc_add_expr_to_block (&fnblock, tmp);
9692 tmp = fold_convert (TREE_TYPE (comp), null_pointer_node);
9693 gfc_add_modify (&fnblock, comp, tmp);
9694 }
9695
9696 break;
9697
9698 case CHECK_PDT_DUMMY:
9699
9700 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
9701 decl, cdecl, NULL_TREE);
9702 if (c->ts.type == BT_CLASS)
9703 comp = gfc_class_data_get (comp);
9704
9705 /* Recurse in to PDT components. */
9706 if ((c->ts.type == BT_DERIVED || c->ts.type == BT_CLASS)
9707 && c->ts.u.derived && c->ts.u.derived->attr.pdt_type)
9708 {
9709 tmp = gfc_check_pdt_dummy (c->ts.u.derived, comp,
9710 c->as ? c->as->rank : 0,
9711 pdt_param_list);
9712 gfc_add_expr_to_block (&fnblock, tmp);
9713 }
9714
9715 if (!c->attr.pdt_len)
9716 continue;
9717 else
9718 {
9719 gfc_se tse;
9720 gfc_expr *c_expr = NULL;
9721 gfc_actual_arglist *param = pdt_param_list;
9722
9723 gfc_init_se (&tse, NULL);
9724 for (; param; param = param->next)
0b627b58
PT
9725 if (!strcmp (c->name, param->name)
9726 && param->spec_type == SPEC_EXPLICIT)
5bab4c96
PT
9727 c_expr = param->expr;
9728
9729 if (c_expr)
9730 {
9731 tree error, cond, cname;
9732 gfc_conv_expr_type (&tse, c_expr, TREE_TYPE (comp));
9733 cond = fold_build2_loc (input_location, NE_EXPR,
63ee5404 9734 logical_type_node,
5bab4c96
PT
9735 comp, tse.expr);
9736 cname = gfc_build_cstring_const (c->name);
9737 cname = gfc_build_addr_expr (pchar_type_node, cname);
9738 error = gfc_trans_runtime_error (true, NULL,
9739 "The value of the PDT LEN "
9740 "parameter '%s' does not "
9741 "agree with that in the "
9742 "dummy declaration",
9743 cname);
9744 tmp = fold_build3_loc (input_location, COND_EXPR,
9745 void_type_node, cond, error,
9746 build_empty_stmt (input_location));
9747 gfc_add_expr_to_block (&fnblock, tmp);
9748 }
9749 }
9750 break;
9751
5046aff5
PT
9752 default:
9753 gcc_unreachable ();
9754 break;
9755 }
9756 }
9757
9758 return gfc_finish_block (&fnblock);
9759}
9760
9761/* Recursively traverse an object of derived type, generating code to
9762 nullify allocatable components. */
9763
9764tree
de91486c
AV
9765gfc_nullify_alloc_comp (gfc_symbol * der_type, tree decl, int rank,
9766 int caf_mode)
5046aff5
PT
9767{
9768 return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
ba85c8c3 9769 NULLIFY_ALLOC_COMP,
c78d3425 9770 GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY | caf_mode, NULL);
42a0e16c
PT
9771}
9772
9773
5046aff5
PT
9774/* Recursively traverse an object of derived type, generating code to
9775 deallocate allocatable components. */
9776
9777tree
ba85c8c3
AV
9778gfc_deallocate_alloc_comp (gfc_symbol * der_type, tree decl, int rank,
9779 int caf_mode)
5046aff5
PT
9780{
9781 return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
ba85c8c3 9782 DEALLOCATE_ALLOC_COMP,
c78d3425 9783 GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY | caf_mode, NULL);
5046aff5
PT
9784}
9785
c78d3425
AF
9786tree
9787gfc_bcast_alloc_comp (gfc_symbol *derived, gfc_expr *expr, int rank,
9788 tree image_index, tree stat, tree errmsg,
9789 tree errmsg_len)
9790{
9791 tree tmp, array;
9792 gfc_se argse;
9793 stmtblock_t block, post_block;
9794 gfc_co_subroutines_args args;
9795
9796 args.image_index = image_index;
9797 args.stat = stat;
9798 args.errmsg = errmsg;
9799 args.errmsg = errmsg_len;
9800
9801 if (rank == 0)
9802 {
9803 gfc_start_block (&block);
9804 gfc_init_block (&post_block);
9805 gfc_init_se (&argse, NULL);
9806 gfc_conv_expr (&argse, expr);
9807 gfc_add_block_to_block (&block, &argse.pre);
9808 gfc_add_block_to_block (&post_block, &argse.post);
9809 array = argse.expr;
9810 }
9811 else
9812 {
9813 gfc_init_se (&argse, NULL);
9814 argse.want_pointer = 1;
9815 gfc_conv_expr_descriptor (&argse, expr);
9816 array = argse.expr;
9817 }
9818
9819 tmp = structure_alloc_comps (derived, array, NULL_TREE, rank,
9820 BCAST_ALLOC_COMP,
9821 GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY, &args);
9822 return tmp;
9823}
5046aff5 9824
abc2d807
TB
9825/* Recursively traverse an object of derived type, generating code to
9826 deallocate allocatable components. But do not deallocate coarrays.
9827 To be used for intrinsic assignment, which may not change the allocation
9828 status of coarrays. */
9829
9830tree
9831gfc_deallocate_alloc_comp_no_caf (gfc_symbol * der_type, tree decl, int rank)
9832{
9833 return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
c78d3425 9834 DEALLOCATE_ALLOC_COMP, 0, NULL);
abc2d807
TB
9835}
9836
9837
9838tree
9839gfc_reassign_alloc_comp_caf (gfc_symbol *der_type, tree decl, tree dest)
9840{
ba85c8c3 9841 return structure_alloc_comps (der_type, decl, dest, 0, REASSIGN_CAF_COMP,
c78d3425 9842 GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY, NULL);
abc2d807
TB
9843}
9844
9845
5046aff5 9846/* Recursively traverse an object of derived type, generating code to
40c32948 9847 copy it and its allocatable components. */
5046aff5
PT
9848
9849tree
ba85c8c3
AV
9850gfc_copy_alloc_comp (gfc_symbol * der_type, tree decl, tree dest, int rank,
9851 int caf_mode)
5046aff5 9852{
ba85c8c3 9853 return structure_alloc_comps (der_type, decl, dest, rank, COPY_ALLOC_COMP,
c78d3425 9854 caf_mode, NULL);
5046aff5
PT
9855}
9856
9857
40c32948
PT
9858/* Recursively traverse an object of derived type, generating code to
9859 copy only its allocatable components. */
9860
9861tree
9862gfc_copy_only_alloc_comp (gfc_symbol * der_type, tree decl, tree dest, int rank)
9863{
ba85c8c3 9864 return structure_alloc_comps (der_type, decl, dest, rank,
c78d3425 9865 COPY_ONLY_ALLOC_COMP, 0, NULL);
40c32948
PT
9866}
9867
9868
71837f64 9869/* Recursively traverse an object of parameterized derived type, generating
5bab4c96
PT
9870 code to allocate parameterized components. */
9871
9872tree
9873gfc_allocate_pdt_comp (gfc_symbol * der_type, tree decl, int rank,
9874 gfc_actual_arglist *param_list)
9875{
9876 tree res;
9877 gfc_actual_arglist *old_param_list = pdt_param_list;
9878 pdt_param_list = param_list;
9879 res = structure_alloc_comps (der_type, decl, NULL_TREE, rank,
c78d3425 9880 ALLOCATE_PDT_COMP, 0, NULL);
5bab4c96
PT
9881 pdt_param_list = old_param_list;
9882 return res;
9883}
9884
71837f64 9885/* Recursively traverse an object of parameterized derived type, generating
5bab4c96
PT
9886 code to deallocate parameterized components. */
9887
9888tree
9889gfc_deallocate_pdt_comp (gfc_symbol * der_type, tree decl, int rank)
9890{
9891 return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
c78d3425 9892 DEALLOCATE_PDT_COMP, 0, NULL);
5bab4c96
PT
9893}
9894
9895
71837f64 9896/* Recursively traverse a dummy of parameterized derived type to check the
5bab4c96
PT
9897 values of LEN parameters. */
9898
9899tree
9900gfc_check_pdt_dummy (gfc_symbol * der_type, tree decl, int rank,
9901 gfc_actual_arglist *param_list)
9902{
9903 tree res;
9904 gfc_actual_arglist *old_param_list = pdt_param_list;
9905 pdt_param_list = param_list;
9906 res = structure_alloc_comps (der_type, decl, NULL_TREE, rank,
c78d3425 9907 CHECK_PDT_DUMMY, 0, NULL);
5bab4c96
PT
9908 pdt_param_list = old_param_list;
9909 return res;
9910}
9911
9912
597553ab
PT
9913/* Returns the value of LBOUND for an expression. This could be broken out
9914 from gfc_conv_intrinsic_bound but this seemed to be simpler. This is
9915 called by gfc_alloc_allocatable_for_assignment. */
9916static tree
9917get_std_lbound (gfc_expr *expr, tree desc, int dim, bool assumed_size)
9918{
9919 tree lbound;
9920 tree ubound;
9921 tree stride;
9922 tree cond, cond1, cond3, cond4;
9923 tree tmp;
99ee0251
PT
9924 gfc_ref *ref;
9925
597553ab
PT
9926 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
9927 {
9928 tmp = gfc_rank_cst[dim];
9929 lbound = gfc_conv_descriptor_lbound_get (desc, tmp);
9930 ubound = gfc_conv_descriptor_ubound_get (desc, tmp);
9931 stride = gfc_conv_descriptor_stride_get (desc, tmp);
63ee5404 9932 cond1 = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
597553ab 9933 ubound, lbound);
63ee5404 9934 cond3 = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
597553ab
PT
9935 stride, gfc_index_zero_node);
9936 cond3 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
63ee5404
JB
9937 logical_type_node, cond3, cond1);
9938 cond4 = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
597553ab
PT
9939 stride, gfc_index_zero_node);
9940 if (assumed_size)
63ee5404 9941 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
597553ab
PT
9942 tmp, build_int_cst (gfc_array_index_type,
9943 expr->rank - 1));
9944 else
63ee5404 9945 cond = logical_false_node;
597553ab
PT
9946
9947 cond1 = fold_build2_loc (input_location, TRUTH_OR_EXPR,
63ee5404 9948 logical_type_node, cond3, cond4);
597553ab 9949 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
63ee5404 9950 logical_type_node, cond, cond1);
597553ab
PT
9951
9952 return fold_build3_loc (input_location, COND_EXPR,
9953 gfc_array_index_type, cond,
9954 lbound, gfc_index_one_node);
9955 }
e48cc391
TB
9956
9957 if (expr->expr_type == EXPR_FUNCTION)
9958 {
9959 /* A conversion function, so use the argument. */
9960 gcc_assert (expr->value.function.isym
9961 && expr->value.function.isym->conversion);
9962 expr = expr->value.function.actual->expr;
9963 }
9964
9965 if (expr->expr_type == EXPR_VARIABLE)
597553ab
PT
9966 {
9967 tmp = TREE_TYPE (expr->symtree->n.sym->backend_decl);
99ee0251
PT
9968 for (ref = expr->ref; ref; ref = ref->next)
9969 {
9970 if (ref->type == REF_COMPONENT
9971 && ref->u.c.component->as
9972 && ref->next
9973 && ref->next->u.ar.type == AR_FULL)
9974 tmp = TREE_TYPE (ref->u.c.component->backend_decl);
9975 }
597553ab
PT
9976 return GFC_TYPE_ARRAY_LBOUND(tmp, dim);
9977 }
597553ab
PT
9978
9979 return gfc_index_one_node;
9980}
9981
9982
9983/* Returns true if an expression represents an lhs that can be reallocated
9984 on assignment. */
9985
9986bool
9987gfc_is_reallocatable_lhs (gfc_expr *expr)
9988{
9989 gfc_ref * ref;
a8399af8 9990 gfc_symbol *sym;
597553ab
PT
9991
9992 if (!expr->ref)
9993 return false;
9994
a8399af8
PT
9995 sym = expr->symtree->n.sym;
9996
a086078b 9997 if (sym->attr.associate_var && !expr->ref)
ca32d61b
PT
9998 return false;
9999
574284e9 10000 /* An allocatable class variable with no reference. */
a8399af8 10001 if (sym->ts.type == BT_CLASS
a086078b 10002 && !sym->attr.associate_var
a8399af8 10003 && CLASS_DATA (sym)->attr.allocatable
d0477233
TB
10004 && expr->ref
10005 && ((expr->ref->type == REF_ARRAY && expr->ref->u.ar.type == AR_FULL
10006 && expr->ref->next == NULL)
10007 || (expr->ref->type == REF_COMPONENT
10008 && strcmp (expr->ref->u.c.component->name, "_data") == 0
10009 && (expr->ref->next == NULL
10010 || (expr->ref->next->type == REF_ARRAY
10011 && expr->ref->next->u.ar.type == AR_FULL
10012 && expr->ref->next->next == NULL)))))
574284e9
AV
10013 return true;
10014
597553ab 10015 /* An allocatable variable. */
a8399af8 10016 if (sym->attr.allocatable
a086078b
PT
10017 && !sym->attr.associate_var
10018 && expr->ref
10019 && expr->ref->type == REF_ARRAY
10020 && expr->ref->u.ar.type == AR_FULL)
597553ab
PT
10021 return true;
10022
10023 /* All that can be left are allocatable components. */
a8399af8
PT
10024 if ((sym->ts.type != BT_DERIVED
10025 && sym->ts.type != BT_CLASS)
10026 || !sym->ts.u.derived->attr.alloc_comp)
597553ab
PT
10027 return false;
10028
10029 /* Find a component ref followed by an array reference. */
10030 for (ref = expr->ref; ref; ref = ref->next)
10031 if (ref->next
10032 && ref->type == REF_COMPONENT
10033 && ref->next->type == REF_ARRAY
10034 && !ref->next->next)
10035 break;
10036
10037 if (!ref)
10038 return false;
10039
10040 /* Return true if valid reallocatable lhs. */
10041 if (ref->u.c.component->attr.allocatable
10042 && ref->next->u.ar.type == AR_FULL)
10043 return true;
10044
10045 return false;
10046}
10047
10048
78ab5260
PT
10049static tree
10050concat_str_length (gfc_expr* expr)
10051{
10052 tree type;
10053 tree len1;
10054 tree len2;
10055 gfc_se se;
10056
10057 type = gfc_typenode_for_spec (&expr->value.op.op1->ts);
10058 len1 = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
10059 if (len1 == NULL_TREE)
10060 {
10061 if (expr->value.op.op1->expr_type == EXPR_OP)
10062 len1 = concat_str_length (expr->value.op.op1);
10063 else if (expr->value.op.op1->expr_type == EXPR_CONSTANT)
10064 len1 = build_int_cst (gfc_charlen_type_node,
10065 expr->value.op.op1->value.character.length);
10066 else if (expr->value.op.op1->ts.u.cl->length)
10067 {
10068 gfc_init_se (&se, NULL);
10069 gfc_conv_expr (&se, expr->value.op.op1->ts.u.cl->length);
10070 len1 = se.expr;
10071 }
10072 else
10073 {
10074 /* Last resort! */
10075 gfc_init_se (&se, NULL);
10076 se.want_pointer = 1;
10077 se.descriptor_only = 1;
10078 gfc_conv_expr (&se, expr->value.op.op1);
10079 len1 = se.string_length;
10080 }
10081 }
10082
10083 type = gfc_typenode_for_spec (&expr->value.op.op2->ts);
10084 len2 = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
10085 if (len2 == NULL_TREE)
10086 {
10087 if (expr->value.op.op2->expr_type == EXPR_OP)
10088 len2 = concat_str_length (expr->value.op.op2);
10089 else if (expr->value.op.op2->expr_type == EXPR_CONSTANT)
10090 len2 = build_int_cst (gfc_charlen_type_node,
10091 expr->value.op.op2->value.character.length);
10092 else if (expr->value.op.op2->ts.u.cl->length)
10093 {
10094 gfc_init_se (&se, NULL);
10095 gfc_conv_expr (&se, expr->value.op.op2->ts.u.cl->length);
10096 len2 = se.expr;
10097 }
10098 else
10099 {
10100 /* Last resort! */
10101 gfc_init_se (&se, NULL);
10102 se.want_pointer = 1;
10103 se.descriptor_only = 1;
10104 gfc_conv_expr (&se, expr->value.op.op2);
10105 len2 = se.string_length;
10106 }
10107 }
10108
10109 gcc_assert(len1 && len2);
10110 len1 = fold_convert (gfc_charlen_type_node, len1);
10111 len2 = fold_convert (gfc_charlen_type_node, len2);
10112
10113 return fold_build2_loc (input_location, PLUS_EXPR,
10114 gfc_charlen_type_node, len1, len2);
10115}
10116
10117
597553ab
PT
10118/* Allocate the lhs of an assignment to an allocatable array, otherwise
10119 reallocate it. */
10120
10121tree
10122gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
10123 gfc_expr *expr1,
10124 gfc_expr *expr2)
10125{
10126 stmtblock_t realloc_block;
10127 stmtblock_t alloc_block;
10128 stmtblock_t fblock;
10129 gfc_ss *rss;
10130 gfc_ss *lss;
1838afec 10131 gfc_array_info *linfo;
597553ab
PT
10132 tree realloc_expr;
10133 tree alloc_expr;
10134 tree size1;
10135 tree size2;
10136 tree array1;
d700518b 10137 tree cond_null;
597553ab
PT
10138 tree cond;
10139 tree tmp;
10140 tree tmp2;
10141 tree lbound;
10142 tree ubound;
10143 tree desc;
16e24756 10144 tree old_desc;
597553ab
PT
10145 tree desc2;
10146 tree offset;
10147 tree jump_label1;
10148 tree jump_label2;
10149 tree neq_size;
10150 tree lbd;
10151 int n;
10152 int dim;
10153 gfc_array_spec * as;
3c9f5092
AV
10154 bool coarray = (flag_coarray == GFC_FCOARRAY_LIB
10155 && gfc_caf_attr (expr1, true).codimension);
10156 tree token;
10157 gfc_se caf_se;
597553ab
PT
10158
10159 /* x = f(...) with x allocatable. In this case, expr1 is the rhs.
10160 Find the lhs expression in the loop chain and set expr1 and
10161 expr2 accordingly. */
10162 if (expr1->expr_type == EXPR_FUNCTION && expr2 == NULL)
10163 {
10164 expr2 = expr1;
10165 /* Find the ss for the lhs. */
10166 lss = loop->ss;
10167 for (; lss && lss != gfc_ss_terminator; lss = lss->loop_chain)
f98cfd3c 10168 if (lss->info->expr && lss->info->expr->expr_type == EXPR_VARIABLE)
597553ab
PT
10169 break;
10170 if (lss == gfc_ss_terminator)
10171 return NULL_TREE;
f98cfd3c 10172 expr1 = lss->info->expr;
597553ab
PT
10173 }
10174
10175 /* Bail out if this is not a valid allocate on assignment. */
10176 if (!gfc_is_reallocatable_lhs (expr1)
10177 || (expr2 && !expr2->rank))
10178 return NULL_TREE;
10179
10180 /* Find the ss for the lhs. */
10181 lss = loop->ss;
10182 for (; lss && lss != gfc_ss_terminator; lss = lss->loop_chain)
f98cfd3c 10183 if (lss->info->expr == expr1)
597553ab
PT
10184 break;
10185
10186 if (lss == gfc_ss_terminator)
10187 return NULL_TREE;
10188
1838afec
MM
10189 linfo = &lss->info->data.array;
10190
597553ab
PT
10191 /* Find an ss for the rhs. For operator expressions, we see the
10192 ss's for the operands. Any one of these will do. */
10193 rss = loop->ss;
10194 for (; rss && rss != gfc_ss_terminator; rss = rss->loop_chain)
f98cfd3c 10195 if (rss->info->expr != expr1 && rss != loop->temp_ss)
597553ab
PT
10196 break;
10197
10198 if (expr2 && rss == gfc_ss_terminator)
10199 return NULL_TREE;
10200
dc32bc72
PT
10201 /* Ensure that the string length from the current scope is used. */
10202 if (expr2->ts.type == BT_CHARACTER
10203 && expr2->expr_type == EXPR_FUNCTION
10204 && !expr2->value.function.isym)
10205 expr2->ts.u.cl->backend_decl = rss->info->string_length;
10206
597553ab
PT
10207 gfc_start_block (&fblock);
10208
10209 /* Since the lhs is allocatable, this must be a descriptor type.
10210 Get the data and array size. */
1838afec 10211 desc = linfo->descriptor;
597553ab
PT
10212 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)));
10213 array1 = gfc_conv_descriptor_data_get (desc);
597553ab 10214
93c3bf47
PT
10215 /* 7.4.1.3 "If variable is an allocated allocatable variable, it is
10216 deallocated if expr is an array of different shape or any of the
10217 corresponding length type parameter values of variable and expr
10218 differ." This assures F95 compatibility. */
597553ab
PT
10219 jump_label1 = gfc_build_label_decl (NULL_TREE);
10220 jump_label2 = gfc_build_label_decl (NULL_TREE);
10221
10222 /* Allocate if data is NULL. */
63ee5404 10223 cond_null = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
597553ab 10224 array1, build_int_cst (TREE_TYPE (array1), 0));
78ab5260 10225
9d44426f
PT
10226 if (expr1->ts.type == BT_CHARACTER && expr1->ts.deferred)
10227 {
10228 tmp = fold_build2_loc (input_location, NE_EXPR,
10229 logical_type_node,
10230 lss->info->string_length,
10231 rss->info->string_length);
10232 cond_null = fold_build2_loc (input_location, TRUTH_OR_EXPR,
10233 logical_type_node, tmp, cond_null);
10234 }
78ab5260
PT
10235 else
10236 cond_null= gfc_evaluate_now (cond_null, &fblock);
10237
d700518b 10238 tmp = build3_v (COND_EXPR, cond_null,
597553ab
PT
10239 build1_v (GOTO_EXPR, jump_label1),
10240 build_empty_stmt (input_location));
10241 gfc_add_expr_to_block (&fblock, tmp);
10242
93c3bf47 10243 /* Get arrayspec if expr is a full array. */
597553ab
PT
10244 if (expr2 && expr2->expr_type == EXPR_FUNCTION
10245 && expr2->value.function.isym
10246 && expr2->value.function.isym->conversion)
10247 {
10248 /* For conversion functions, take the arg. */
10249 gfc_expr *arg = expr2->value.function.actual->expr;
10250 as = gfc_get_full_arrayspec_from_expr (arg);
10251 }
10252 else if (expr2)
10253 as = gfc_get_full_arrayspec_from_expr (expr2);
10254 else
10255 as = NULL;
10256
93c3bf47 10257 /* If the lhs shape is not the same as the rhs jump to setting the
f04986a9 10258 bounds and doing the reallocation....... */
93c3bf47 10259 for (n = 0; n < expr1->rank; n++)
597553ab 10260 {
93c3bf47
PT
10261 /* Check the shape. */
10262 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[n]);
10263 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[n]);
10264 tmp = fold_build2_loc (input_location, MINUS_EXPR,
10265 gfc_array_index_type,
10266 loop->to[n], loop->from[n]);
10267 tmp = fold_build2_loc (input_location, PLUS_EXPR,
10268 gfc_array_index_type,
10269 tmp, lbound);
10270 tmp = fold_build2_loc (input_location, MINUS_EXPR,
10271 gfc_array_index_type,
10272 tmp, ubound);
10273 cond = fold_build2_loc (input_location, NE_EXPR,
63ee5404 10274 logical_type_node,
93c3bf47
PT
10275 tmp, gfc_index_zero_node);
10276 tmp = build3_v (COND_EXPR, cond,
10277 build1_v (GOTO_EXPR, jump_label1),
10278 build_empty_stmt (input_location));
f04986a9 10279 gfc_add_expr_to_block (&fblock, tmp);
93c3bf47
PT
10280 }
10281
10282 /* ....else jump past the (re)alloc code. */
10283 tmp = build1_v (GOTO_EXPR, jump_label2);
10284 gfc_add_expr_to_block (&fblock, tmp);
f04986a9 10285
93c3bf47
PT
10286 /* Add the label to start automatic (re)allocation. */
10287 tmp = build1_v (LABEL_EXPR, jump_label1);
10288 gfc_add_expr_to_block (&fblock, tmp);
597553ab 10289
d700518b
PT
10290 /* If the lhs has not been allocated, its bounds will not have been
10291 initialized and so its size is set to zero. */
10292 size1 = gfc_create_var (gfc_array_index_type, NULL);
10293 gfc_init_block (&alloc_block);
10294 gfc_add_modify (&alloc_block, size1, gfc_index_zero_node);
10295 gfc_init_block (&realloc_block);
10296 gfc_add_modify (&realloc_block, size1,
10297 gfc_conv_descriptor_size (desc, expr1->rank));
10298 tmp = build3_v (COND_EXPR, cond_null,
10299 gfc_finish_block (&alloc_block),
10300 gfc_finish_block (&realloc_block));
10301 gfc_add_expr_to_block (&fblock, tmp);
93c3bf47 10302
d700518b 10303 /* Get the rhs size and fix it. */
93c3bf47 10304 if (expr2)
1838afec 10305 desc2 = rss->info->data.array.descriptor;
93c3bf47
PT
10306 else
10307 desc2 = NULL_TREE;
d700518b 10308
93c3bf47
PT
10309 size2 = gfc_index_one_node;
10310 for (n = 0; n < expr2->rank; n++)
10311 {
10312 tmp = fold_build2_loc (input_location, MINUS_EXPR,
10313 gfc_array_index_type,
10314 loop->to[n], loop->from[n]);
10315 tmp = fold_build2_loc (input_location, PLUS_EXPR,
10316 gfc_array_index_type,
10317 tmp, gfc_index_one_node);
10318 size2 = fold_build2_loc (input_location, MULT_EXPR,
10319 gfc_array_index_type,
10320 tmp, size2);
597553ab 10321 }
93c3bf47
PT
10322 size2 = gfc_evaluate_now (size2, &fblock);
10323
63ee5404 10324 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
93c3bf47 10325 size1, size2);
78ab5260
PT
10326
10327 /* If the lhs is deferred length, assume that the element size
10328 changes and force a reallocation. */
10329 if (expr1->ts.deferred)
63ee5404 10330 neq_size = gfc_evaluate_now (logical_true_node, &fblock);
78ab5260
PT
10331 else
10332 neq_size = gfc_evaluate_now (cond, &fblock);
93c3bf47 10333
16e24756
PT
10334 /* Deallocation of allocatable components will have to occur on
10335 reallocation. Fix the old descriptor now. */
10336 if ((expr1->ts.type == BT_DERIVED)
10337 && expr1->ts.u.derived->attr.alloc_comp)
10338 old_desc = gfc_evaluate_now (desc, &fblock);
10339 else
10340 old_desc = NULL_TREE;
597553ab
PT
10341
10342 /* Now modify the lhs descriptor and the associated scalarizer
93c3bf47
PT
10343 variables. F2003 7.4.1.3: "If variable is or becomes an
10344 unallocated allocatable variable, then it is allocated with each
10345 deferred type parameter equal to the corresponding type parameters
10346 of expr , with the shape of expr , and with each lower bound equal
f04986a9 10347 to the corresponding element of LBOUND(expr)."
93c3bf47
PT
10348 Reuse size1 to keep a dimension-by-dimension track of the
10349 stride of the new array. */
597553ab
PT
10350 size1 = gfc_index_one_node;
10351 offset = gfc_index_zero_node;
10352
10353 for (n = 0; n < expr2->rank; n++)
10354 {
10355 tmp = fold_build2_loc (input_location, MINUS_EXPR,
10356 gfc_array_index_type,
10357 loop->to[n], loop->from[n]);
10358 tmp = fold_build2_loc (input_location, PLUS_EXPR,
10359 gfc_array_index_type,
10360 tmp, gfc_index_one_node);
10361
10362 lbound = gfc_index_one_node;
10363 ubound = tmp;
10364
10365 if (as)
10366 {
10367 lbd = get_std_lbound (expr2, desc2, n,
10368 as->type == AS_ASSUMED_SIZE);
10369 ubound = fold_build2_loc (input_location,
10370 MINUS_EXPR,
10371 gfc_array_index_type,
10372 ubound, lbound);
10373 ubound = fold_build2_loc (input_location,
10374 PLUS_EXPR,
10375 gfc_array_index_type,
10376 ubound, lbd);
10377 lbound = lbd;
10378 }
10379
10380 gfc_conv_descriptor_lbound_set (&fblock, desc,
10381 gfc_rank_cst[n],
10382 lbound);
10383 gfc_conv_descriptor_ubound_set (&fblock, desc,
10384 gfc_rank_cst[n],
10385 ubound);
10386 gfc_conv_descriptor_stride_set (&fblock, desc,
10387 gfc_rank_cst[n],
10388 size1);
10389 lbound = gfc_conv_descriptor_lbound_get (desc,
10390 gfc_rank_cst[n]);
10391 tmp2 = fold_build2_loc (input_location, MULT_EXPR,
10392 gfc_array_index_type,
10393 lbound, size1);
10394 offset = fold_build2_loc (input_location, MINUS_EXPR,
10395 gfc_array_index_type,
10396 offset, tmp2);
10397 size1 = fold_build2_loc (input_location, MULT_EXPR,
10398 gfc_array_index_type,
10399 tmp, size1);
10400 }
10401
10402 /* Set the lhs descriptor and scalarizer offsets. For rank > 1,
10403 the array offset is saved and the info.offset is used for a
10404 running offset. Use the saved_offset instead. */
10405 tmp = gfc_conv_descriptor_offset (desc);
10406 gfc_add_modify (&fblock, tmp, offset);
1838afec 10407 if (linfo->saved_offset
d168c883 10408 && VAR_P (linfo->saved_offset))
1838afec 10409 gfc_add_modify (&fblock, linfo->saved_offset, tmp);
597553ab
PT
10410
10411 /* Now set the deltas for the lhs. */
10412 for (n = 0; n < expr1->rank; n++)
10413 {
10414 tmp = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[n]);
cb4b9eae 10415 dim = lss->dim[n];
597553ab
PT
10416 tmp = fold_build2_loc (input_location, MINUS_EXPR,
10417 gfc_array_index_type, tmp,
10418 loop->from[dim]);
d168c883 10419 if (linfo->delta[dim] && VAR_P (linfo->delta[dim]))
1838afec 10420 gfc_add_modify (&fblock, linfo->delta[dim], tmp);
597553ab
PT
10421 }
10422
10423 /* Get the new lhs size in bytes. */
10424 if (expr1->ts.type == BT_CHARACTER && expr1->ts.deferred)
10425 {
2b3dc0db
PT
10426 if (expr2->ts.deferred)
10427 {
204d4630
PT
10428 if (expr2->ts.u.cl->backend_decl
10429 && VAR_P (expr2->ts.u.cl->backend_decl))
2b3dc0db
PT
10430 tmp = expr2->ts.u.cl->backend_decl;
10431 else
10432 tmp = rss->info->string_length;
10433 }
10434 else
10435 {
10436 tmp = expr2->ts.u.cl->backend_decl;
78ab5260
PT
10437 if (!tmp && expr2->expr_type == EXPR_OP
10438 && expr2->value.op.op == INTRINSIC_CONCAT)
10439 {
10440 tmp = concat_str_length (expr2);
10441 expr2->ts.u.cl->backend_decl = gfc_evaluate_now (tmp, &fblock);
10442 }
5b4dd015
PT
10443 else if (!tmp && expr2->ts.u.cl->length)
10444 {
10445 gfc_se tmpse;
10446 gfc_init_se (&tmpse, NULL);
10447 gfc_conv_expr_type (&tmpse, expr2->ts.u.cl->length,
10448 gfc_charlen_type_node);
10449 tmp = tmpse.expr;
10450 expr2->ts.u.cl->backend_decl = gfc_evaluate_now (tmp, &fblock);
10451 }
2b3dc0db
PT
10452 tmp = fold_convert (TREE_TYPE (expr1->ts.u.cl->backend_decl), tmp);
10453 }
10454
10455 if (expr1->ts.u.cl->backend_decl
d168c883 10456 && VAR_P (expr1->ts.u.cl->backend_decl))
2b3dc0db
PT
10457 gfc_add_modify (&fblock, expr1->ts.u.cl->backend_decl, tmp);
10458 else
10459 gfc_add_modify (&fblock, lss->info->string_length, tmp);
9d44426f
PT
10460
10461 if (expr1->ts.kind > 1)
10462 tmp = fold_build2_loc (input_location, MULT_EXPR,
10463 TREE_TYPE (tmp),
10464 tmp, build_int_cst (TREE_TYPE (tmp),
10465 expr1->ts.kind));
597553ab
PT
10466 }
10467 else if (expr1->ts.type == BT_CHARACTER && expr1->ts.u.cl->backend_decl)
10468 {
10469 tmp = TYPE_SIZE_UNIT (TREE_TYPE (gfc_typenode_for_spec (&expr1->ts)));
10470 tmp = fold_build2_loc (input_location, MULT_EXPR,
10471 gfc_array_index_type, tmp,
10472 expr1->ts.u.cl->backend_decl);
10473 }
75382a96
PT
10474 else if (UNLIMITED_POLY (expr1) && expr2->ts.type != BT_CLASS)
10475 tmp = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&expr2->ts));
597553ab
PT
10476 else
10477 tmp = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&expr1->ts));
10478 tmp = fold_convert (gfc_array_index_type, tmp);
9d44426f
PT
10479
10480 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
10481 gfc_conv_descriptor_span_set (&fblock, desc, tmp);
10482
597553ab
PT
10483 size2 = fold_build2_loc (input_location, MULT_EXPR,
10484 gfc_array_index_type,
10485 tmp, size2);
10486 size2 = fold_convert (size_type_node, size2);
6f556b07
TB
10487 size2 = fold_build2_loc (input_location, MAX_EXPR, size_type_node,
10488 size2, size_one_node);
597553ab
PT
10489 size2 = gfc_evaluate_now (size2, &fblock);
10490
78ab5260
PT
10491 /* For deferred character length, the 'size' field of the dtype might
10492 have changed so set the dtype. */
10493 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc))
10494 && expr1->ts.type == BT_CHARACTER && expr1->ts.deferred)
10495 {
10496 tree type;
10497 tmp = gfc_conv_descriptor_dtype (desc);
10498 if (expr2->ts.u.cl->backend_decl)
10499 type = gfc_typenode_for_spec (&expr2->ts);
10500 else
10501 type = gfc_typenode_for_spec (&expr1->ts);
10502
10503 gfc_add_modify (&fblock, tmp,
10504 gfc_get_dtype_rank_type (expr1->rank,type));
10505 }
75382a96
PT
10506 else if (UNLIMITED_POLY (expr1) && expr2->ts.type != BT_CLASS)
10507 {
10508 tree type;
10509 tmp = gfc_conv_descriptor_dtype (desc);
10510 type = gfc_typenode_for_spec (&expr2->ts);
10511 gfc_add_modify (&fblock, tmp,
10512 gfc_get_dtype_rank_type (expr2->rank,type));
10513 /* Set the _len field as well... */
10514 tmp = gfc_class_len_get (TREE_OPERAND (desc, 0));
10515 if (expr2->ts.type == BT_CHARACTER)
10516 gfc_add_modify (&fblock, tmp,
10517 fold_convert (TREE_TYPE (tmp),
10518 TYPE_SIZE_UNIT (type)));
10519 else
10520 gfc_add_modify (&fblock, tmp,
10521 build_int_cst (TREE_TYPE (tmp), 0));
10522 /* ...and the vptr. */
10523 tmp = gfc_class_vptr_get (TREE_OPERAND (desc, 0));
10524 tmp2 = gfc_get_symbol_decl (gfc_find_vtab (&expr2->ts));
10525 tmp2 = gfc_build_addr_expr (TREE_TYPE (tmp), tmp2);
10526 gfc_add_modify (&fblock, tmp, tmp2);
10527 }
3c9f5092
AV
10528 else if (coarray && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
10529 {
10530 gfc_add_modify (&fblock, gfc_conv_descriptor_dtype (desc),
10531 gfc_get_dtype (TREE_TYPE (desc)));
10532 }
78ab5260 10533
597553ab 10534 /* Realloc expression. Note that the scalarizer uses desc.data
1cc0e193 10535 in the array reference - (*desc.data)[<element>]. */
597553ab 10536 gfc_init_block (&realloc_block);
3c9f5092 10537 gfc_init_se (&caf_se, NULL);
16e24756 10538
3c9f5092
AV
10539 if (coarray)
10540 {
10541 token = gfc_get_ultimate_alloc_ptr_comps_caf_token (&caf_se, expr1);
10542 if (token == NULL_TREE)
10543 {
10544 tmp = gfc_get_tree_for_caf_expr (expr1);
6479f45b
AV
10545 if (POINTER_TYPE_P (TREE_TYPE (tmp)))
10546 tmp = build_fold_indirect_ref (tmp);
3c9f5092
AV
10547 gfc_get_caf_token_offset (&caf_se, &token, NULL, tmp, NULL_TREE,
10548 expr1);
10549 token = gfc_build_addr_expr (NULL_TREE, token);
10550 }
10551
10552 gfc_add_block_to_block (&realloc_block, &caf_se.pre);
10553 }
16e24756
PT
10554 if ((expr1->ts.type == BT_DERIVED)
10555 && expr1->ts.u.derived->attr.alloc_comp)
10556 {
abc2d807
TB
10557 tmp = gfc_deallocate_alloc_comp_no_caf (expr1->ts.u.derived, old_desc,
10558 expr1->rank);
16e24756
PT
10559 gfc_add_expr_to_block (&realloc_block, tmp);
10560 }
10561
3c9f5092
AV
10562 if (!coarray)
10563 {
10564 tmp = build_call_expr_loc (input_location,
10565 builtin_decl_explicit (BUILT_IN_REALLOC), 2,
10566 fold_convert (pvoid_type_node, array1),
10567 size2);
10568 gfc_conv_descriptor_data_set (&realloc_block,
10569 desc, tmp);
10570 }
10571 else
10572 {
10573 tmp = build_call_expr_loc (input_location,
ba85c8c3
AV
10574 gfor_fndecl_caf_deregister, 5, token,
10575 build_int_cst (integer_type_node,
10576 GFC_CAF_COARRAY_DEALLOCATE_ONLY),
10577 null_pointer_node, null_pointer_node,
10578 integer_zero_node);
3c9f5092
AV
10579 gfc_add_expr_to_block (&realloc_block, tmp);
10580 tmp = build_call_expr_loc (input_location,
10581 gfor_fndecl_caf_register,
10582 7, size2,
10583 build_int_cst (integer_type_node,
ba85c8c3 10584 GFC_CAF_COARRAY_ALLOC_ALLOCATE_ONLY),
3c9f5092
AV
10585 token, gfc_build_addr_expr (NULL_TREE, desc),
10586 null_pointer_node, null_pointer_node,
10587 integer_zero_node);
10588 gfc_add_expr_to_block (&realloc_block, tmp);
10589 }
16e24756
PT
10590
10591 if ((expr1->ts.type == BT_DERIVED)
10592 && expr1->ts.u.derived->attr.alloc_comp)
10593 {
10594 tmp = gfc_nullify_alloc_comp (expr1->ts.u.derived, desc,
10595 expr1->rank);
10596 gfc_add_expr_to_block (&realloc_block, tmp);
10597 }
10598
3c9f5092 10599 gfc_add_block_to_block (&realloc_block, &caf_se.post);
597553ab
PT
10600 realloc_expr = gfc_finish_block (&realloc_block);
10601
10602 /* Only reallocate if sizes are different. */
10603 tmp = build3_v (COND_EXPR, neq_size, realloc_expr,
10604 build_empty_stmt (input_location));
10605 realloc_expr = tmp;
10606
10607
10608 /* Malloc expression. */
10609 gfc_init_block (&alloc_block);
3c9f5092
AV
10610 if (!coarray)
10611 {
10612 tmp = build_call_expr_loc (input_location,
10613 builtin_decl_explicit (BUILT_IN_MALLOC),
10614 1, size2);
10615 gfc_conv_descriptor_data_set (&alloc_block,
10616 desc, tmp);
10617 }
10618 else
10619 {
10620 tmp = build_call_expr_loc (input_location,
10621 gfor_fndecl_caf_register,
10622 7, size2,
10623 build_int_cst (integer_type_node,
10624 GFC_CAF_COARRAY_ALLOC),
10625 token, gfc_build_addr_expr (NULL_TREE, desc),
10626 null_pointer_node, null_pointer_node,
10627 integer_zero_node);
10628 gfc_add_expr_to_block (&alloc_block, tmp);
10629 }
10630
78ab5260
PT
10631
10632 /* We already set the dtype in the case of deferred character
75382a96 10633 length arrays and unlimited polymorphic arrays. */
78ab5260 10634 if (!(GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc))
3c9f5092 10635 && ((expr1->ts.type == BT_CHARACTER && expr1->ts.deferred)
75382a96
PT
10636 || coarray))
10637 && !UNLIMITED_POLY (expr1))
78ab5260
PT
10638 {
10639 tmp = gfc_conv_descriptor_dtype (desc);
10640 gfc_add_modify (&alloc_block, tmp, gfc_get_dtype (TREE_TYPE (desc)));
10641 }
10642
16e24756
PT
10643 if ((expr1->ts.type == BT_DERIVED)
10644 && expr1->ts.u.derived->attr.alloc_comp)
10645 {
10646 tmp = gfc_nullify_alloc_comp (expr1->ts.u.derived, desc,
10647 expr1->rank);
10648 gfc_add_expr_to_block (&alloc_block, tmp);
10649 }
597553ab
PT
10650 alloc_expr = gfc_finish_block (&alloc_block);
10651
10652 /* Malloc if not allocated; realloc otherwise. */
10653 tmp = build_int_cst (TREE_TYPE (array1), 0);
10654 cond = fold_build2_loc (input_location, EQ_EXPR,
63ee5404 10655 logical_type_node,
597553ab
PT
10656 array1, tmp);
10657 tmp = build3_v (COND_EXPR, cond, alloc_expr, realloc_expr);
10658 gfc_add_expr_to_block (&fblock, tmp);
10659
10660 /* Make sure that the scalarizer data pointer is updated. */
d168c883 10661 if (linfo->data && VAR_P (linfo->data))
597553ab
PT
10662 {
10663 tmp = gfc_conv_descriptor_data_get (desc);
1838afec 10664 gfc_add_modify (&fblock, linfo->data, tmp);
597553ab
PT
10665 }
10666
10667 /* Add the exit label. */
10668 tmp = build1_v (LABEL_EXPR, jump_label2);
10669 gfc_add_expr_to_block (&fblock, tmp);
10670
10671 return gfc_finish_block (&fblock);
10672}
10673
10674
5046aff5
PT
10675/* NULLIFY an allocatable/pointer array on function entry, free it on exit.
10676 Do likewise, recursively if necessary, with the allocatable components of
62ede14d
TB
10677 derived types. This function is also called for assumed-rank arrays, which
10678 are always dummy arguments. */
6de9cd9a 10679
0019d498
DK
10680void
10681gfc_trans_deferred_array (gfc_symbol * sym, gfc_wrapped_block * block)
6de9cd9a
DN
10682{
10683 tree type;
10684 tree tmp;
10685 tree descriptor;
0019d498
DK
10686 stmtblock_t init;
10687 stmtblock_t cleanup;
6de9cd9a 10688 locus loc;
5046aff5 10689 int rank;
ef292537 10690 bool sym_has_alloc_comp, has_finalizer;
5046aff5 10691
272cec5d
TK
10692 sym_has_alloc_comp = (sym->ts.type == BT_DERIVED
10693 || sym->ts.type == BT_CLASS)
bc21d315 10694 && sym->ts.u.derived->attr.alloc_comp;
ea8b72e6
TB
10695 has_finalizer = sym->ts.type == BT_CLASS || sym->ts.type == BT_DERIVED
10696 ? gfc_is_finalizable (sym->ts.u.derived, NULL) : false;
6de9cd9a
DN
10697
10698 /* Make sure the frontend gets these right. */
ea8b72e6 10699 gcc_assert (sym->attr.pointer || sym->attr.allocatable || sym_has_alloc_comp
62ede14d
TB
10700 || has_finalizer
10701 || (sym->as->type == AS_ASSUMED_RANK && sym->attr.dummy));
6de9cd9a 10702
ceccaacf
TB
10703 gfc_save_backend_locus (&loc);
10704 gfc_set_backend_locus (&sym->declared_at);
0019d498 10705 gfc_init_block (&init);
6de9cd9a 10706
d168c883
JJ
10707 gcc_assert (VAR_P (sym->backend_decl)
10708 || TREE_CODE (sym->backend_decl) == PARM_DECL);
99c7ab42 10709
6de9cd9a 10710 if (sym->ts.type == BT_CHARACTER
bc21d315 10711 && !INTEGER_CST_P (sym->ts.u.cl->backend_decl))
417ab240 10712 {
0019d498
DK
10713 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
10714 gfc_trans_vla_type_sizes (sym, &init);
417ab240 10715 }
6de9cd9a 10716
bafc96b4
PT
10717 /* Dummy, use associated and result variables don't need anything special. */
10718 if (sym->attr.dummy || sym->attr.use_assoc || sym->attr.result)
6de9cd9a 10719 {
0019d498 10720 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
ceccaacf 10721 gfc_restore_backend_locus (&loc);
0019d498 10722 return;
6de9cd9a
DN
10723 }
10724
6de9cd9a
DN
10725 descriptor = sym->backend_decl;
10726
b2a43373 10727 /* Although static, derived types with default initializers and
5046aff5
PT
10728 allocatable components must not be nulled wholesale; instead they
10729 are treated component by component. */
ea8b72e6 10730 if (TREE_STATIC (descriptor) && !sym_has_alloc_comp && !has_finalizer)
6de9cd9a
DN
10731 {
10732 /* SAVEd variables are not freed on exit. */
10733 gfc_trans_static_array_pointer (sym);
0019d498
DK
10734
10735 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
363aab21 10736 gfc_restore_backend_locus (&loc);
0019d498 10737 return;
6de9cd9a
DN
10738 }
10739
10740 /* Get the descriptor type. */
10741 type = TREE_TYPE (sym->backend_decl);
2b56d6a4 10742
ea8b72e6
TB
10743 if ((sym_has_alloc_comp || (has_finalizer && sym->ts.type != BT_CLASS))
10744 && !(sym->attr.pointer || sym->attr.allocatable))
5046aff5 10745 {
2b56d6a4
TB
10746 if (!sym->attr.save
10747 && !(TREE_STATIC (sym->backend_decl) && sym->attr.is_main_program))
36d3fb4c 10748 {
16e520b6
DF
10749 if (sym->value == NULL
10750 || !gfc_has_default_initializer (sym->ts.u.derived))
2b56d6a4
TB
10751 {
10752 rank = sym->as ? sym->as->rank : 0;
0019d498
DK
10753 tmp = gfc_nullify_alloc_comp (sym->ts.u.derived,
10754 descriptor, rank);
10755 gfc_add_expr_to_block (&init, tmp);
2b56d6a4
TB
10756 }
10757 else
0019d498 10758 gfc_init_default_dt (sym, &init, false);
36d3fb4c 10759 }
5046aff5
PT
10760 }
10761 else if (!GFC_DESCRIPTOR_TYPE_P (type))
f5f701ad
PT
10762 {
10763 /* If the backend_decl is not a descriptor, we must have a pointer
10764 to one. */
db3927fb 10765 descriptor = build_fold_indirect_ref_loc (input_location,
0019d498 10766 sym->backend_decl);
f5f701ad 10767 type = TREE_TYPE (descriptor);
f5f701ad 10768 }
f04986a9 10769
727dc121
JV
10770 /* NULLIFY the data pointer, for non-saved allocatables. */
10771 if (GFC_DESCRIPTOR_TYPE_P (type) && !sym->attr.save && sym->attr.allocatable)
ba85c8c3
AV
10772 {
10773 gfc_conv_descriptor_data_set (&init, descriptor, null_pointer_node);
10774 if (flag_coarray == GFC_FCOARRAY_LIB && sym->attr.codimension)
10775 {
10776 /* Declare the variable static so its array descriptor stays present
10777 after leaving the scope. It may still be accessed through another
10778 image. This may happen, for example, with the caf_mpi
10779 implementation. */
10780 TREE_STATIC (descriptor) = 1;
10781 tmp = gfc_conv_descriptor_token (descriptor);
10782 gfc_add_modify (&init, tmp, fold_convert (TREE_TYPE (tmp),
10783 null_pointer_node));
10784 }
10785 }
6de9cd9a 10786
363aab21 10787 gfc_restore_backend_locus (&loc);
ceccaacf 10788 gfc_init_block (&cleanup);
5046aff5
PT
10789
10790 /* Allocatable arrays need to be freed when they go out of scope.
10791 The allocatable components of pointers must not be touched. */
ea8b72e6
TB
10792 if (!sym->attr.allocatable && has_finalizer && sym->ts.type != BT_CLASS
10793 && !sym->attr.pointer && !sym->attr.artificial && !sym->attr.save
10794 && !sym->ns->proc_name->attr.is_main_program)
10795 {
10796 gfc_expr *e;
10797 sym->attr.referenced = 1;
10798 e = gfc_lval_expr_from_sym (sym);
10799 gfc_add_finalizer_call (&cleanup, e);
10800 gfc_free_expr (e);
10801 }
10802 else if ((!sym->attr.allocatable || !has_finalizer)
ef292537
TB
10803 && sym_has_alloc_comp && !(sym->attr.function || sym->attr.result)
10804 && !sym->attr.pointer && !sym->attr.save
10805 && !sym->ns->proc_name->attr.is_main_program)
5046aff5
PT
10806 {
10807 int rank;
10808 rank = sym->as ? sym->as->rank : 0;
bc21d315 10809 tmp = gfc_deallocate_alloc_comp (sym->ts.u.derived, descriptor, rank);
0019d498 10810 gfc_add_expr_to_block (&cleanup, tmp);
5046aff5
PT
10811 }
10812
badd9e69 10813 if (sym->attr.allocatable && (sym->attr.dimension || sym->attr.codimension)
ef292537
TB
10814 && !sym->attr.save && !sym->attr.result
10815 && !sym->ns->proc_name->attr.is_main_program)
6de9cd9a 10816 {
6a2bf10f
TB
10817 gfc_expr *e;
10818 e = has_finalizer ? gfc_lval_expr_from_sym (sym) : NULL;
39da5866
AV
10819 tmp = gfc_deallocate_with_status (sym->backend_decl, NULL_TREE, NULL_TREE,
10820 NULL_TREE, NULL_TREE, true, e,
10821 sym->attr.codimension
10822 ? GFC_CAF_COARRAY_DEREGISTER
10823 : GFC_CAF_COARRAY_NOCOARRAY);
6a2bf10f
TB
10824 if (e)
10825 gfc_free_expr (e);
0019d498 10826 gfc_add_expr_to_block (&cleanup, tmp);
6de9cd9a
DN
10827 }
10828
0019d498
DK
10829 gfc_add_init_cleanup (block, gfc_finish_block (&init),
10830 gfc_finish_block (&cleanup));
6de9cd9a
DN
10831}
10832
10833/************ Expression Walking Functions ******************/
10834
10835/* Walk a variable reference.
10836
10837 Possible extension - multiple component subscripts.
10838 x(:,:) = foo%a(:)%b(:)
10839 Transforms to
10840 forall (i=..., j=...)
10841 x(i,j) = foo%a(j)%b(i)
10842 end forall
735dfed7 10843 This adds a fair amount of complexity because you need to deal with more
6de9cd9a
DN
10844 than one ref. Maybe handle in a similar manner to vector subscripts.
10845 Maybe not worth the effort. */
10846
10847
10848static gfc_ss *
10849gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
10850{
10851 gfc_ref *ref;
6de9cd9a 10852
4932364b
TK
10853 gfc_fix_class_refs (expr);
10854
6de9cd9a 10855 for (ref = expr->ref; ref; ref = ref->next)
068e7338
RS
10856 if (ref->type == REF_ARRAY && ref->u.ar.type != AR_ELEMENT)
10857 break;
10858
42ac5ee1
MM
10859 return gfc_walk_array_ref (ss, expr, ref);
10860}
10861
10862
10863gfc_ss *
10864gfc_walk_array_ref (gfc_ss * ss, gfc_expr * expr, gfc_ref * ref)
10865{
10866 gfc_array_ref *ar;
10867 gfc_ss *newss;
10868 int n;
10869
068e7338 10870 for (; ref; ref = ref->next)
6de9cd9a 10871 {
068e7338
RS
10872 if (ref->type == REF_SUBSTRING)
10873 {
26f77530
MM
10874 ss = gfc_get_scalar_ss (ss, ref->u.ss.start);
10875 ss = gfc_get_scalar_ss (ss, ref->u.ss.end);
068e7338
RS
10876 }
10877
10878 /* We're only interested in array sections from now on. */
6de9cd9a
DN
10879 if (ref->type != REF_ARRAY)
10880 continue;
10881
10882 ar = &ref->u.ar;
d3a9eea2 10883
6de9cd9a
DN
10884 switch (ar->type)
10885 {
10886 case AR_ELEMENT:
a7c61416 10887 for (n = ar->dimen - 1; n >= 0; n--)
26f77530 10888 ss = gfc_get_scalar_ss (ss, ar->start[n]);
6de9cd9a
DN
10889 break;
10890
10891 case AR_FULL:
66877276 10892 newss = gfc_get_array_ss (ss, expr, ar->as->rank, GFC_SS_SECTION);
1838afec 10893 newss->info->data.array.ref = ref;
6de9cd9a
DN
10894
10895 /* Make sure array is the same as array(:,:), this way
10896 we don't need to special case all the time. */
10897 ar->dimen = ar->as->rank;
10898 for (n = 0; n < ar->dimen; n++)
10899 {
6de9cd9a
DN
10900 ar->dimen_type[n] = DIMEN_RANGE;
10901
6e45f57b
PB
10902 gcc_assert (ar->start[n] == NULL);
10903 gcc_assert (ar->end[n] == NULL);
10904 gcc_assert (ar->stride[n] == NULL);
6de9cd9a 10905 }
068e7338
RS
10906 ss = newss;
10907 break;
6de9cd9a
DN
10908
10909 case AR_SECTION:
66877276 10910 newss = gfc_get_array_ss (ss, expr, 0, GFC_SS_SECTION);
1838afec 10911 newss->info->data.array.ref = ref;
6de9cd9a 10912
66877276 10913 /* We add SS chains for all the subscripts in the section. */
d7baf647 10914 for (n = 0; n < ar->dimen; n++)
6de9cd9a
DN
10915 {
10916 gfc_ss *indexss;
10917
10918 switch (ar->dimen_type[n])
10919 {
10920 case DIMEN_ELEMENT:
10921 /* Add SS for elemental (scalar) subscripts. */
6e45f57b 10922 gcc_assert (ar->start[n]);
26f77530 10923 indexss = gfc_get_scalar_ss (gfc_ss_terminator, ar->start[n]);
6de9cd9a 10924 indexss->loop_chain = gfc_ss_terminator;
1838afec 10925 newss->info->data.array.subscript[n] = indexss;
6de9cd9a
DN
10926 break;
10927
10928 case DIMEN_RANGE:
10929 /* We don't add anything for sections, just remember this
10930 dimension for later. */
cb4b9eae
MM
10931 newss->dim[newss->dimen] = n;
10932 newss->dimen++;
6de9cd9a
DN
10933 break;
10934
10935 case DIMEN_VECTOR:
7a70c12d
RS
10936 /* Create a GFC_SS_VECTOR index in which we can store
10937 the vector's descriptor. */
66877276
MM
10938 indexss = gfc_get_array_ss (gfc_ss_terminator, ar->start[n],
10939 1, GFC_SS_VECTOR);
7a70c12d 10940 indexss->loop_chain = gfc_ss_terminator;
1838afec 10941 newss->info->data.array.subscript[n] = indexss;
cb4b9eae
MM
10942 newss->dim[newss->dimen] = n;
10943 newss->dimen++;
6de9cd9a
DN
10944 break;
10945
10946 default:
10947 /* We should know what sort of section it is by now. */
6e45f57b 10948 gcc_unreachable ();
6de9cd9a
DN
10949 }
10950 }
6b81e94d
MM
10951 /* We should have at least one non-elemental dimension,
10952 unless we are creating a descriptor for a (scalar) coarray. */
cb4b9eae 10953 gcc_assert (newss->dimen > 0
1838afec 10954 || newss->info->data.array.ref->u.ar.as->corank > 0);
068e7338 10955 ss = newss;
6de9cd9a
DN
10956 break;
10957
10958 default:
10959 /* We should know what sort of section it is by now. */
6e45f57b 10960 gcc_unreachable ();
6de9cd9a
DN
10961 }
10962
10963 }
10964 return ss;
10965}
10966
10967
10968/* Walk an expression operator. If only one operand of a binary expression is
10969 scalar, we must also add the scalar term to the SS chain. */
10970
10971static gfc_ss *
10972gfc_walk_op_expr (gfc_ss * ss, gfc_expr * expr)
10973{
10974 gfc_ss *head;
10975 gfc_ss *head2;
6de9cd9a 10976
58b03ab2
TS
10977 head = gfc_walk_subexpr (ss, expr->value.op.op1);
10978 if (expr->value.op.op2 == NULL)
6de9cd9a
DN
10979 head2 = head;
10980 else
58b03ab2 10981 head2 = gfc_walk_subexpr (head, expr->value.op.op2);
6de9cd9a
DN
10982
10983 /* All operands are scalar. Pass back and let the caller deal with it. */
10984 if (head2 == ss)
10985 return head2;
10986
f7b529fa 10987 /* All operands require scalarization. */
58b03ab2 10988 if (head != ss && (expr->value.op.op2 == NULL || head2 != head))
6de9cd9a
DN
10989 return head2;
10990
10991 /* One of the operands needs scalarization, the other is scalar.
10992 Create a gfc_ss for the scalar expression. */
6de9cd9a
DN
10993 if (head == ss)
10994 {
10995 /* First operand is scalar. We build the chain in reverse order, so
df2fba9e 10996 add the scalar SS after the second operand. */
6de9cd9a
DN
10997 head = head2;
10998 while (head && head->next != ss)
10999 head = head->next;
11000 /* Check we haven't somehow broken the chain. */
6e45f57b 11001 gcc_assert (head);
26f77530 11002 head->next = gfc_get_scalar_ss (ss, expr->value.op.op1);
6de9cd9a
DN
11003 }
11004 else /* head2 == head */
11005 {
6e45f57b 11006 gcc_assert (head2 == head);
6de9cd9a 11007 /* Second operand is scalar. */
26f77530 11008 head2 = gfc_get_scalar_ss (head2, expr->value.op.op2);
6de9cd9a
DN
11009 }
11010
11011 return head2;
11012}
11013
11014
11015/* Reverse a SS chain. */
11016
48474141 11017gfc_ss *
6de9cd9a
DN
11018gfc_reverse_ss (gfc_ss * ss)
11019{
11020 gfc_ss *next;
11021 gfc_ss *head;
11022
6e45f57b 11023 gcc_assert (ss != NULL);
6de9cd9a
DN
11024
11025 head = gfc_ss_terminator;
11026 while (ss != gfc_ss_terminator)
11027 {
11028 next = ss->next;
6e45f57b
PB
11029 /* Check we didn't somehow break the chain. */
11030 gcc_assert (next != NULL);
6de9cd9a
DN
11031 ss->next = head;
11032 head = ss;
11033 ss = next;
11034 }
11035
11036 return (head);
11037}
11038
11039
eea58adb 11040/* Given an expression referring to a procedure, return the symbol of its
58b29fa3
MM
11041 interface. We can't get the procedure symbol directly as we have to handle
11042 the case of (deferred) type-bound procedures. */
11043
11044gfc_symbol *
11045gfc_get_proc_ifc_for_expr (gfc_expr *procedure_ref)
11046{
11047 gfc_symbol *sym;
11048 gfc_ref *ref;
11049
11050 if (procedure_ref == NULL)
11051 return NULL;
11052
11053 /* Normal procedure case. */
252207bd
MM
11054 if (procedure_ref->expr_type == EXPR_FUNCTION
11055 && procedure_ref->value.function.esym)
11056 sym = procedure_ref->value.function.esym;
11057 else
11058 sym = procedure_ref->symtree->n.sym;
58b29fa3
MM
11059
11060 /* Typebound procedure case. */
11061 for (ref = procedure_ref->ref; ref; ref = ref->next)
11062 {
11063 if (ref->type == REF_COMPONENT
11064 && ref->u.c.component->attr.proc_pointer)
11065 sym = ref->u.c.component->ts.interface;
11066 else
11067 sym = NULL;
11068 }
11069
11070 return sym;
11071}
11072
11073
17d038cd
MM
11074/* Walk the arguments of an elemental function.
11075 PROC_EXPR is used to check whether an argument is permitted to be absent. If
11076 it is NULL, we don't do the check and the argument is assumed to be present.
11077*/
6de9cd9a
DN
11078
11079gfc_ss *
48474141 11080gfc_walk_elemental_function_args (gfc_ss * ss, gfc_actual_arglist *arg,
dec131b6 11081 gfc_symbol *proc_ifc, gfc_ss_type type)
6de9cd9a 11082{
17d038cd 11083 gfc_formal_arglist *dummy_arg;
6de9cd9a
DN
11084 int scalar;
11085 gfc_ss *head;
11086 gfc_ss *tail;
11087 gfc_ss *newss;
11088
11089 head = gfc_ss_terminator;
11090 tail = NULL;
17d038cd 11091
58b29fa3 11092 if (proc_ifc)
4cbc9039 11093 dummy_arg = gfc_sym_get_dummy_args (proc_ifc);
17d038cd
MM
11094 else
11095 dummy_arg = NULL;
11096
6de9cd9a 11097 scalar = 1;
48474141 11098 for (; arg; arg = arg->next)
6de9cd9a 11099 {
80508c49 11100 if (!arg->expr || arg->expr->expr_type == EXPR_NULL)
4a8108f0 11101 goto loop_continue;
6de9cd9a
DN
11102
11103 newss = gfc_walk_subexpr (head, arg->expr);
11104 if (newss == head)
11105 {
1f2959f0 11106 /* Scalar argument. */
26f77530
MM
11107 gcc_assert (type == GFC_SS_SCALAR || type == GFC_SS_REFERENCE);
11108 newss = gfc_get_scalar_ss (head, arg->expr);
bcc4d4e0 11109 newss->info->type = type;
14aeb3cd
MM
11110 if (dummy_arg)
11111 newss->info->data.scalar.dummy_arg = dummy_arg->sym;
6de9cd9a
DN
11112 }
11113 else
11114 scalar = 0;
11115
9bcf7121
MM
11116 if (dummy_arg != NULL
11117 && dummy_arg->sym->attr.optional
11118 && arg->expr->expr_type == EXPR_VARIABLE
11119 && (gfc_expr_attr (arg->expr).optional
11120 || gfc_expr_attr (arg->expr).allocatable
11121 || gfc_expr_attr (arg->expr).pointer))
11122 newss->info->can_be_null_ref = true;
11123
6de9cd9a
DN
11124 head = newss;
11125 if (!tail)
11126 {
11127 tail = head;
11128 while (tail->next != gfc_ss_terminator)
11129 tail = tail->next;
11130 }
17d038cd 11131
4a8108f0 11132loop_continue:
17d038cd
MM
11133 if (dummy_arg != NULL)
11134 dummy_arg = dummy_arg->next;
6de9cd9a
DN
11135 }
11136
11137 if (scalar)
11138 {
11139 /* If all the arguments are scalar we don't need the argument SS. */
11140 gfc_free_ss_chain (head);
11141 /* Pass it back. */
11142 return ss;
11143 }
11144
11145 /* Add it onto the existing chain. */
11146 tail->next = ss;
11147 return head;
11148}
11149
11150
11151/* Walk a function call. Scalar functions are passed back, and taken out of
11152 scalarization loops. For elemental functions we walk their arguments.
11153 The result of functions returning arrays is stored in a temporary outside
11154 the loop, so that the function is only called once. Hence we do not need
11155 to walk their arguments. */
11156
11157static gfc_ss *
11158gfc_walk_function_expr (gfc_ss * ss, gfc_expr * expr)
11159{
6de9cd9a
DN
11160 gfc_intrinsic_sym *isym;
11161 gfc_symbol *sym;
c74b74a8 11162 gfc_component *comp = NULL;
6de9cd9a
DN
11163
11164 isym = expr->value.function.isym;
11165
13413760 11166 /* Handle intrinsic functions separately. */
6de9cd9a
DN
11167 if (isym)
11168 return gfc_walk_intrinsic_function (ss, expr, isym);
11169
11170 sym = expr->value.function.esym;
11171 if (!sym)
1b26c26b 11172 sym = expr->symtree->n.sym;
6de9cd9a 11173
a6b22eea 11174 if (gfc_is_class_array_function (expr))
43a68a9d
PT
11175 return gfc_get_array_ss (ss, expr,
11176 CLASS_DATA (expr->value.function.esym->result)->as->rank,
11177 GFC_SS_FUNCTION);
11178
6de9cd9a 11179 /* A function that returns arrays. */
2a573572 11180 comp = gfc_get_proc_ptr_comp (expr);
c74b74a8
JW
11181 if ((!comp && gfc_return_by_reference (sym) && sym->result->attr.dimension)
11182 || (comp && comp->attr.dimension))
66877276 11183 return gfc_get_array_ss (ss, expr, expr->rank, GFC_SS_FUNCTION);
6de9cd9a
DN
11184
11185 /* Walk the parameters of an elemental function. For now we always pass
11186 by reference. */
1b26c26b 11187 if (sym->attr.elemental || (comp && comp->attr.elemental))
30c931de
PT
11188 {
11189 gfc_ss *old_ss = ss;
11190
11191 ss = gfc_walk_elemental_function_args (old_ss,
11192 expr->value.function.actual,
dec131b6
MM
11193 gfc_get_proc_ifc_for_expr (expr),
11194 GFC_SS_REFERENCE);
30c931de
PT
11195 if (ss != old_ss
11196 && (comp
11197 || sym->attr.proc_pointer
11198 || sym->attr.if_source != IFSRC_DECL
11199 || sym->attr.array_outer_dependency))
11200 ss->info->array_outer_dependency = 1;
11201 }
6de9cd9a 11202
e7dc5b4f 11203 /* Scalar functions are OK as these are evaluated outside the scalarization
6de9cd9a
DN
11204 loop. Pass back and let the caller deal with it. */
11205 return ss;
11206}
11207
11208
11209/* An array temporary is constructed for array constructors. */
11210
11211static gfc_ss *
11212gfc_walk_array_constructor (gfc_ss * ss, gfc_expr * expr)
11213{
66877276 11214 return gfc_get_array_ss (ss, expr, expr->rank, GFC_SS_CONSTRUCTOR);
6de9cd9a
DN
11215}
11216
11217
1f2959f0 11218/* Walk an expression. Add walked expressions to the head of the SS chain.
aa9c57ec 11219 A wholly scalar expression will not be added. */
6de9cd9a 11220
712efae1 11221gfc_ss *
6de9cd9a
DN
11222gfc_walk_subexpr (gfc_ss * ss, gfc_expr * expr)
11223{
11224 gfc_ss *head;
11225
11226 switch (expr->expr_type)
11227 {
11228 case EXPR_VARIABLE:
11229 head = gfc_walk_variable_expr (ss, expr);
11230 return head;
11231
11232 case EXPR_OP:
11233 head = gfc_walk_op_expr (ss, expr);
11234 return head;
11235
11236 case EXPR_FUNCTION:
11237 head = gfc_walk_function_expr (ss, expr);
11238 return head;
11239
11240 case EXPR_CONSTANT:
11241 case EXPR_NULL:
11242 case EXPR_STRUCTURE:
11243 /* Pass back and let the caller deal with it. */
11244 break;
11245
11246 case EXPR_ARRAY:
11247 head = gfc_walk_array_constructor (ss, expr);
11248 return head;
11249
11250 case EXPR_SUBSTRING:
11251 /* Pass back and let the caller deal with it. */
11252 break;
11253
11254 default:
17d5d49f 11255 gfc_internal_error ("bad expression type during walk (%d)",
6de9cd9a
DN
11256 expr->expr_type);
11257 }
11258 return ss;
11259}
11260
11261
11262/* Entry point for expression walking.
11263 A return value equal to the passed chain means this is
11264 a scalar expression. It is up to the caller to take whatever action is
1f2959f0 11265 necessary to translate these. */
6de9cd9a
DN
11266
11267gfc_ss *
11268gfc_walk_expr (gfc_expr * expr)
11269{
11270 gfc_ss *res;
11271
11272 res = gfc_walk_subexpr (gfc_ss_terminator, expr);
11273 return gfc_reverse_ss (res);
11274}