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