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