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