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