hppa: Fix pr110279-1.c on hppa
[official-gcc.git] / gcc / fortran / trans-array.cc
blob633f2af09c11c9913b0ba73f5a47b505980476aa
1 /* Array translation routines
2 Copyright (C) 2002-2023 Free Software Foundation, Inc.
3 Contributed by Paul Brook <paul@nowt.org>
4 and Steven Bosscher <s.bosscher@student.tudelft.nl>
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
22 /* trans-array.cc-- Various array related code, including scalarization,
23 allocation, initialization and other support routines. */
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.
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.
37 If the expression is an assignment, we must then resolve any dependencies.
38 In Fortran all the rhs values of an assignment must be evaluated before
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
41 or vector subscripts as procedure parameters.
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.
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.
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.
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
62 values are automatically substituted. Note that gfc_advance_se_ss_chain
63 must be used, rather than changing the se->ss directly.
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.
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.
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. */
78 #include "config.h"
79 #include "system.h"
80 #include "coretypes.h"
81 #include "options.h"
82 #include "tree.h"
83 #include "gfortran.h"
84 #include "gimple-expr.h"
85 #include "tree-iterator.h"
86 #include "stringpool.h" /* Required by "attribs.h". */
87 #include "attribs.h" /* For lookup_attribute. */
88 #include "trans.h"
89 #include "fold-const.h"
90 #include "constructor.h"
91 #include "trans-types.h"
92 #include "trans-array.h"
93 #include "trans-const.h"
94 #include "dependency.h"
96 static bool gfc_get_array_constructor_size (mpz_t *, gfc_constructor_base);
98 /* The contents of this structure aren't actually used, just the address. */
99 static gfc_ss gfc_ss_terminator_var;
100 gfc_ss * const gfc_ss_terminator = &gfc_ss_terminator_var;
103 static tree
104 gfc_array_dataptr_type (tree desc)
106 return (GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc)));
109 /* Build expressions to access members of the CFI descriptor. */
110 #define CFI_FIELD_BASE_ADDR 0
111 #define CFI_FIELD_ELEM_LEN 1
112 #define CFI_FIELD_VERSION 2
113 #define CFI_FIELD_RANK 3
114 #define CFI_FIELD_ATTRIBUTE 4
115 #define CFI_FIELD_TYPE 5
116 #define CFI_FIELD_DIM 6
118 #define CFI_DIM_FIELD_LOWER_BOUND 0
119 #define CFI_DIM_FIELD_EXTENT 1
120 #define CFI_DIM_FIELD_SM 2
122 static tree
123 gfc_get_cfi_descriptor_field (tree desc, unsigned field_idx)
125 tree type = TREE_TYPE (desc);
126 gcc_assert (TREE_CODE (type) == RECORD_TYPE
127 && TYPE_FIELDS (type)
128 && (strcmp ("base_addr",
129 IDENTIFIER_POINTER (DECL_NAME (TYPE_FIELDS (type))))
130 == 0));
131 tree field = gfc_advance_chain (TYPE_FIELDS (type), field_idx);
132 gcc_assert (field != NULL_TREE);
134 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
135 desc, field, NULL_TREE);
138 tree
139 gfc_get_cfi_desc_base_addr (tree desc)
141 return gfc_get_cfi_descriptor_field (desc, CFI_FIELD_BASE_ADDR);
144 tree
145 gfc_get_cfi_desc_elem_len (tree desc)
147 return gfc_get_cfi_descriptor_field (desc, CFI_FIELD_ELEM_LEN);
150 tree
151 gfc_get_cfi_desc_version (tree desc)
153 return gfc_get_cfi_descriptor_field (desc, CFI_FIELD_VERSION);
156 tree
157 gfc_get_cfi_desc_rank (tree desc)
159 return gfc_get_cfi_descriptor_field (desc, CFI_FIELD_RANK);
162 tree
163 gfc_get_cfi_desc_type (tree desc)
165 return gfc_get_cfi_descriptor_field (desc, CFI_FIELD_TYPE);
168 tree
169 gfc_get_cfi_desc_attribute (tree desc)
171 return gfc_get_cfi_descriptor_field (desc, CFI_FIELD_ATTRIBUTE);
174 static tree
175 gfc_get_cfi_dim_item (tree desc, tree idx, unsigned field_idx)
177 tree tmp = gfc_get_cfi_descriptor_field (desc, CFI_FIELD_DIM);
178 tmp = gfc_build_array_ref (tmp, idx, NULL_TREE, true);
179 tree field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)), field_idx);
180 gcc_assert (field != NULL_TREE);
181 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
182 tmp, field, NULL_TREE);
185 tree
186 gfc_get_cfi_dim_lbound (tree desc, tree idx)
188 return gfc_get_cfi_dim_item (desc, idx, CFI_DIM_FIELD_LOWER_BOUND);
191 tree
192 gfc_get_cfi_dim_extent (tree desc, tree idx)
194 return gfc_get_cfi_dim_item (desc, idx, CFI_DIM_FIELD_EXTENT);
197 tree
198 gfc_get_cfi_dim_sm (tree desc, tree idx)
200 return gfc_get_cfi_dim_item (desc, idx, CFI_DIM_FIELD_SM);
203 #undef CFI_FIELD_BASE_ADDR
204 #undef CFI_FIELD_ELEM_LEN
205 #undef CFI_FIELD_VERSION
206 #undef CFI_FIELD_RANK
207 #undef CFI_FIELD_ATTRIBUTE
208 #undef CFI_FIELD_TYPE
209 #undef CFI_FIELD_DIM
211 #undef CFI_DIM_FIELD_LOWER_BOUND
212 #undef CFI_DIM_FIELD_EXTENT
213 #undef CFI_DIM_FIELD_SM
215 /* Build expressions to access the members of an array descriptor.
216 It's surprisingly easy to mess up here, so never access
217 an array descriptor by "brute force", always use these
218 functions. This also avoids problems if we change the format
219 of an array descriptor.
221 To understand these magic numbers, look at the comments
222 before gfc_build_array_type() in trans-types.cc.
224 The code within these defines should be the only code which knows the format
225 of an array descriptor.
227 Any code just needing to read obtain the bounds of an array should use
228 gfc_conv_array_* rather than the following functions as these will return
229 know constant values, and work with arrays which do not have descriptors.
231 Don't forget to #undef these! */
233 #define DATA_FIELD 0
234 #define OFFSET_FIELD 1
235 #define DTYPE_FIELD 2
236 #define SPAN_FIELD 3
237 #define DIMENSION_FIELD 4
238 #define CAF_TOKEN_FIELD 5
240 #define STRIDE_SUBFIELD 0
241 #define LBOUND_SUBFIELD 1
242 #define UBOUND_SUBFIELD 2
244 static tree
245 gfc_get_descriptor_field (tree desc, unsigned field_idx)
247 tree type = TREE_TYPE (desc);
248 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
250 tree field = gfc_advance_chain (TYPE_FIELDS (type), field_idx);
251 gcc_assert (field != NULL_TREE);
253 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
254 desc, field, NULL_TREE);
257 /* This provides READ-ONLY access to the data field. The field itself
258 doesn't have the proper type. */
260 tree
261 gfc_conv_descriptor_data_get (tree desc)
263 tree type = TREE_TYPE (desc);
264 if (TREE_CODE (type) == REFERENCE_TYPE)
265 gcc_unreachable ();
267 tree field = gfc_get_descriptor_field (desc, DATA_FIELD);
268 return fold_convert (GFC_TYPE_ARRAY_DATAPTR_TYPE (type), field);
271 /* This provides WRITE access to the data field.
273 TUPLES_P is true if we are generating tuples.
275 This function gets called through the following macros:
276 gfc_conv_descriptor_data_set
277 gfc_conv_descriptor_data_set. */
279 void
280 gfc_conv_descriptor_data_set (stmtblock_t *block, tree desc, tree value)
282 tree field = gfc_get_descriptor_field (desc, DATA_FIELD);
283 gfc_add_modify (block, field, fold_convert (TREE_TYPE (field), value));
287 /* This provides address access to the data field. This should only be
288 used by array allocation, passing this on to the runtime. */
290 tree
291 gfc_conv_descriptor_data_addr (tree desc)
293 tree field = gfc_get_descriptor_field (desc, DATA_FIELD);
294 return gfc_build_addr_expr (NULL_TREE, field);
297 static tree
298 gfc_conv_descriptor_offset (tree desc)
300 tree field = gfc_get_descriptor_field (desc, OFFSET_FIELD);
301 gcc_assert (TREE_TYPE (field) == gfc_array_index_type);
302 return field;
305 tree
306 gfc_conv_descriptor_offset_get (tree desc)
308 return gfc_conv_descriptor_offset (desc);
311 void
312 gfc_conv_descriptor_offset_set (stmtblock_t *block, tree desc,
313 tree value)
315 tree t = gfc_conv_descriptor_offset (desc);
316 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
320 tree
321 gfc_conv_descriptor_dtype (tree desc)
323 tree field = gfc_get_descriptor_field (desc, DTYPE_FIELD);
324 gcc_assert (TREE_TYPE (field) == get_dtype_type_node ());
325 return field;
328 static tree
329 gfc_conv_descriptor_span (tree desc)
331 tree field = gfc_get_descriptor_field (desc, SPAN_FIELD);
332 gcc_assert (TREE_TYPE (field) == gfc_array_index_type);
333 return field;
336 tree
337 gfc_conv_descriptor_span_get (tree desc)
339 return gfc_conv_descriptor_span (desc);
342 void
343 gfc_conv_descriptor_span_set (stmtblock_t *block, tree desc,
344 tree value)
346 tree t = gfc_conv_descriptor_span (desc);
347 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
351 tree
352 gfc_conv_descriptor_rank (tree desc)
354 tree tmp;
355 tree dtype;
357 dtype = gfc_conv_descriptor_dtype (desc);
358 tmp = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (dtype)), GFC_DTYPE_RANK);
359 gcc_assert (tmp != NULL_TREE
360 && TREE_TYPE (tmp) == signed_char_type_node);
361 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (tmp),
362 dtype, tmp, NULL_TREE);
366 tree
367 gfc_conv_descriptor_version (tree desc)
369 tree tmp;
370 tree dtype;
372 dtype = gfc_conv_descriptor_dtype (desc);
373 tmp = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (dtype)), GFC_DTYPE_VERSION);
374 gcc_assert (tmp != NULL_TREE
375 && TREE_TYPE (tmp) == integer_type_node);
376 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (tmp),
377 dtype, tmp, NULL_TREE);
381 /* Return the element length from the descriptor dtype field. */
383 tree
384 gfc_conv_descriptor_elem_len (tree desc)
386 tree tmp;
387 tree dtype;
389 dtype = gfc_conv_descriptor_dtype (desc);
390 tmp = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (dtype)),
391 GFC_DTYPE_ELEM_LEN);
392 gcc_assert (tmp != NULL_TREE
393 && TREE_TYPE (tmp) == size_type_node);
394 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (tmp),
395 dtype, tmp, NULL_TREE);
399 tree
400 gfc_conv_descriptor_attribute (tree desc)
402 tree tmp;
403 tree dtype;
405 dtype = gfc_conv_descriptor_dtype (desc);
406 tmp = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (dtype)),
407 GFC_DTYPE_ATTRIBUTE);
408 gcc_assert (tmp!= NULL_TREE
409 && TREE_TYPE (tmp) == short_integer_type_node);
410 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (tmp),
411 dtype, tmp, NULL_TREE);
414 tree
415 gfc_conv_descriptor_type (tree desc)
417 tree tmp;
418 tree dtype;
420 dtype = gfc_conv_descriptor_dtype (desc);
421 tmp = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (dtype)), GFC_DTYPE_TYPE);
422 gcc_assert (tmp!= NULL_TREE
423 && TREE_TYPE (tmp) == signed_char_type_node);
424 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (tmp),
425 dtype, tmp, NULL_TREE);
428 tree
429 gfc_get_descriptor_dimension (tree desc)
431 tree field = gfc_get_descriptor_field (desc, DIMENSION_FIELD);
432 gcc_assert (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
433 && TREE_CODE (TREE_TYPE (TREE_TYPE (field))) == RECORD_TYPE);
434 return field;
438 static tree
439 gfc_conv_descriptor_dimension (tree desc, tree dim)
441 tree tmp;
443 tmp = gfc_get_descriptor_dimension (desc);
445 return gfc_build_array_ref (tmp, dim, NULL_TREE, true);
449 tree
450 gfc_conv_descriptor_token (tree desc)
452 gcc_assert (flag_coarray == GFC_FCOARRAY_LIB);
453 tree field = gfc_get_descriptor_field (desc, CAF_TOKEN_FIELD);
454 /* Should be a restricted pointer - except in the finalization wrapper. */
455 gcc_assert (TREE_TYPE (field) == prvoid_type_node
456 || TREE_TYPE (field) == pvoid_type_node);
457 return field;
460 static tree
461 gfc_conv_descriptor_subfield (tree desc, tree dim, unsigned field_idx)
463 tree tmp = gfc_conv_descriptor_dimension (desc, dim);
464 tree field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)), field_idx);
465 gcc_assert (field != NULL_TREE);
467 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
468 tmp, field, NULL_TREE);
471 static tree
472 gfc_conv_descriptor_stride (tree desc, tree dim)
474 tree field = gfc_conv_descriptor_subfield (desc, dim, STRIDE_SUBFIELD);
475 gcc_assert (TREE_TYPE (field) == gfc_array_index_type);
476 return field;
479 tree
480 gfc_conv_descriptor_stride_get (tree desc, tree dim)
482 tree type = TREE_TYPE (desc);
483 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
484 if (integer_zerop (dim)
485 && (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE
486 ||GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_SHAPE_CONT
487 ||GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_RANK_CONT
488 ||GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER_CONT))
489 return gfc_index_one_node;
491 return gfc_conv_descriptor_stride (desc, dim);
494 void
495 gfc_conv_descriptor_stride_set (stmtblock_t *block, tree desc,
496 tree dim, tree value)
498 tree t = gfc_conv_descriptor_stride (desc, dim);
499 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
502 static tree
503 gfc_conv_descriptor_lbound (tree desc, tree dim)
505 tree field = gfc_conv_descriptor_subfield (desc, dim, LBOUND_SUBFIELD);
506 gcc_assert (TREE_TYPE (field) == gfc_array_index_type);
507 return field;
510 tree
511 gfc_conv_descriptor_lbound_get (tree desc, tree dim)
513 return gfc_conv_descriptor_lbound (desc, dim);
516 void
517 gfc_conv_descriptor_lbound_set (stmtblock_t *block, tree desc,
518 tree dim, tree value)
520 tree t = gfc_conv_descriptor_lbound (desc, dim);
521 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
524 static tree
525 gfc_conv_descriptor_ubound (tree desc, tree dim)
527 tree field = gfc_conv_descriptor_subfield (desc, dim, UBOUND_SUBFIELD);
528 gcc_assert (TREE_TYPE (field) == gfc_array_index_type);
529 return field;
532 tree
533 gfc_conv_descriptor_ubound_get (tree desc, tree dim)
535 return gfc_conv_descriptor_ubound (desc, dim);
538 void
539 gfc_conv_descriptor_ubound_set (stmtblock_t *block, tree desc,
540 tree dim, tree value)
542 tree t = gfc_conv_descriptor_ubound (desc, dim);
543 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
546 /* Build a null array descriptor constructor. */
548 tree
549 gfc_build_null_descriptor (tree type)
551 tree field;
552 tree tmp;
554 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
555 gcc_assert (DATA_FIELD == 0);
556 field = TYPE_FIELDS (type);
558 /* Set a NULL data pointer. */
559 tmp = build_constructor_single (type, field, null_pointer_node);
560 TREE_CONSTANT (tmp) = 1;
561 /* All other fields are ignored. */
563 return tmp;
567 /* Modify a descriptor such that the lbound of a given dimension is the value
568 specified. This also updates ubound and offset accordingly. */
570 void
571 gfc_conv_shift_descriptor_lbound (stmtblock_t* block, tree desc,
572 int dim, tree new_lbound)
574 tree offs, ubound, lbound, stride;
575 tree diff, offs_diff;
577 new_lbound = fold_convert (gfc_array_index_type, new_lbound);
579 offs = gfc_conv_descriptor_offset_get (desc);
580 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[dim]);
581 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[dim]);
582 stride = gfc_conv_descriptor_stride_get (desc, gfc_rank_cst[dim]);
584 /* Get difference (new - old) by which to shift stuff. */
585 diff = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
586 new_lbound, lbound);
588 /* Shift ubound and offset accordingly. This has to be done before
589 updating the lbound, as they depend on the lbound expression! */
590 ubound = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
591 ubound, diff);
592 gfc_conv_descriptor_ubound_set (block, desc, gfc_rank_cst[dim], ubound);
593 offs_diff = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
594 diff, stride);
595 offs = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
596 offs, offs_diff);
597 gfc_conv_descriptor_offset_set (block, desc, offs);
599 /* Finally set lbound to value we want. */
600 gfc_conv_descriptor_lbound_set (block, desc, gfc_rank_cst[dim], new_lbound);
604 /* Obtain offsets for trans-types.cc(gfc_get_array_descr_info). */
606 void
607 gfc_get_descriptor_offsets_for_info (const_tree desc_type, tree *data_off,
608 tree *dtype_off, tree *span_off,
609 tree *dim_off, tree *dim_size,
610 tree *stride_suboff, tree *lower_suboff,
611 tree *upper_suboff)
613 tree field;
614 tree type;
616 type = TYPE_MAIN_VARIANT (desc_type);
617 field = gfc_advance_chain (TYPE_FIELDS (type), DATA_FIELD);
618 *data_off = byte_position (field);
619 field = gfc_advance_chain (TYPE_FIELDS (type), DTYPE_FIELD);
620 *dtype_off = byte_position (field);
621 field = gfc_advance_chain (TYPE_FIELDS (type), SPAN_FIELD);
622 *span_off = byte_position (field);
623 field = gfc_advance_chain (TYPE_FIELDS (type), DIMENSION_FIELD);
624 *dim_off = byte_position (field);
625 type = TREE_TYPE (TREE_TYPE (field));
626 *dim_size = TYPE_SIZE_UNIT (type);
627 field = gfc_advance_chain (TYPE_FIELDS (type), STRIDE_SUBFIELD);
628 *stride_suboff = byte_position (field);
629 field = gfc_advance_chain (TYPE_FIELDS (type), LBOUND_SUBFIELD);
630 *lower_suboff = byte_position (field);
631 field = gfc_advance_chain (TYPE_FIELDS (type), UBOUND_SUBFIELD);
632 *upper_suboff = byte_position (field);
636 /* Cleanup those #defines. */
638 #undef DATA_FIELD
639 #undef OFFSET_FIELD
640 #undef DTYPE_FIELD
641 #undef SPAN_FIELD
642 #undef DIMENSION_FIELD
643 #undef CAF_TOKEN_FIELD
644 #undef STRIDE_SUBFIELD
645 #undef LBOUND_SUBFIELD
646 #undef UBOUND_SUBFIELD
649 /* Mark a SS chain as used. Flags specifies in which loops the SS is used.
650 flags & 1 = Main loop body.
651 flags & 2 = temp copy loop. */
653 void
654 gfc_mark_ss_chain_used (gfc_ss * ss, unsigned flags)
656 for (; ss != gfc_ss_terminator; ss = ss->next)
657 ss->info->useflags = flags;
661 /* Free a gfc_ss chain. */
663 void
664 gfc_free_ss_chain (gfc_ss * ss)
666 gfc_ss *next;
668 while (ss != gfc_ss_terminator)
670 gcc_assert (ss != NULL);
671 next = ss->next;
672 gfc_free_ss (ss);
673 ss = next;
678 static void
679 free_ss_info (gfc_ss_info *ss_info)
681 int n;
683 ss_info->refcount--;
684 if (ss_info->refcount > 0)
685 return;
687 gcc_assert (ss_info->refcount == 0);
689 switch (ss_info->type)
691 case GFC_SS_SECTION:
692 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
693 if (ss_info->data.array.subscript[n])
694 gfc_free_ss_chain (ss_info->data.array.subscript[n]);
695 break;
697 default:
698 break;
701 free (ss_info);
705 /* Free a SS. */
707 void
708 gfc_free_ss (gfc_ss * ss)
710 free_ss_info (ss->info);
711 free (ss);
715 /* Creates and initializes an array type gfc_ss struct. */
717 gfc_ss *
718 gfc_get_array_ss (gfc_ss *next, gfc_expr *expr, int dimen, gfc_ss_type type)
720 gfc_ss *ss;
721 gfc_ss_info *ss_info;
722 int i;
724 ss_info = gfc_get_ss_info ();
725 ss_info->refcount++;
726 ss_info->type = type;
727 ss_info->expr = expr;
729 ss = gfc_get_ss ();
730 ss->info = ss_info;
731 ss->next = next;
732 ss->dimen = dimen;
733 for (i = 0; i < ss->dimen; i++)
734 ss->dim[i] = i;
736 return ss;
740 /* Creates and initializes a temporary type gfc_ss struct. */
742 gfc_ss *
743 gfc_get_temp_ss (tree type, tree string_length, int dimen)
745 gfc_ss *ss;
746 gfc_ss_info *ss_info;
747 int i;
749 ss_info = gfc_get_ss_info ();
750 ss_info->refcount++;
751 ss_info->type = GFC_SS_TEMP;
752 ss_info->string_length = string_length;
753 ss_info->data.temp.type = type;
755 ss = gfc_get_ss ();
756 ss->info = ss_info;
757 ss->next = gfc_ss_terminator;
758 ss->dimen = dimen;
759 for (i = 0; i < ss->dimen; i++)
760 ss->dim[i] = i;
762 return ss;
766 /* Creates and initializes a scalar type gfc_ss struct. */
768 gfc_ss *
769 gfc_get_scalar_ss (gfc_ss *next, gfc_expr *expr)
771 gfc_ss *ss;
772 gfc_ss_info *ss_info;
774 ss_info = gfc_get_ss_info ();
775 ss_info->refcount++;
776 ss_info->type = GFC_SS_SCALAR;
777 ss_info->expr = expr;
779 ss = gfc_get_ss ();
780 ss->info = ss_info;
781 ss->next = next;
783 return ss;
787 /* Free all the SS associated with a loop. */
789 void
790 gfc_cleanup_loop (gfc_loopinfo * loop)
792 gfc_loopinfo *loop_next, **ploop;
793 gfc_ss *ss;
794 gfc_ss *next;
796 ss = loop->ss;
797 while (ss != gfc_ss_terminator)
799 gcc_assert (ss != NULL);
800 next = ss->loop_chain;
801 gfc_free_ss (ss);
802 ss = next;
805 /* Remove reference to self in the parent loop. */
806 if (loop->parent)
807 for (ploop = &loop->parent->nested; *ploop; ploop = &(*ploop)->next)
808 if (*ploop == loop)
810 *ploop = loop->next;
811 break;
814 /* Free non-freed nested loops. */
815 for (loop = loop->nested; loop; loop = loop_next)
817 loop_next = loop->next;
818 gfc_cleanup_loop (loop);
819 free (loop);
824 static void
825 set_ss_loop (gfc_ss *ss, gfc_loopinfo *loop)
827 int n;
829 for (; ss != gfc_ss_terminator; ss = ss->next)
831 ss->loop = loop;
833 if (ss->info->type == GFC_SS_SCALAR
834 || ss->info->type == GFC_SS_REFERENCE
835 || ss->info->type == GFC_SS_TEMP)
836 continue;
838 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
839 if (ss->info->data.array.subscript[n] != NULL)
840 set_ss_loop (ss->info->data.array.subscript[n], loop);
845 /* Associate a SS chain with a loop. */
847 void
848 gfc_add_ss_to_loop (gfc_loopinfo * loop, gfc_ss * head)
850 gfc_ss *ss;
851 gfc_loopinfo *nested_loop;
853 if (head == gfc_ss_terminator)
854 return;
856 set_ss_loop (head, loop);
858 ss = head;
859 for (; ss && ss != gfc_ss_terminator; ss = ss->next)
861 if (ss->nested_ss)
863 nested_loop = ss->nested_ss->loop;
865 /* More than one ss can belong to the same loop. Hence, we add the
866 loop to the chain only if it is different from the previously
867 added one, to avoid duplicate nested loops. */
868 if (nested_loop != loop->nested)
870 gcc_assert (nested_loop->parent == NULL);
871 nested_loop->parent = loop;
873 gcc_assert (nested_loop->next == NULL);
874 nested_loop->next = loop->nested;
875 loop->nested = nested_loop;
877 else
878 gcc_assert (nested_loop->parent == loop);
881 if (ss->next == gfc_ss_terminator)
882 ss->loop_chain = loop->ss;
883 else
884 ss->loop_chain = ss->next;
886 gcc_assert (ss == gfc_ss_terminator);
887 loop->ss = head;
891 /* Returns true if the expression is an array pointer. */
893 static bool
894 is_pointer_array (tree expr)
896 if (expr == NULL_TREE
897 || !GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (expr))
898 || GFC_CLASS_TYPE_P (TREE_TYPE (expr)))
899 return false;
901 if (VAR_P (expr)
902 && GFC_DECL_PTR_ARRAY_P (expr))
903 return true;
905 if (TREE_CODE (expr) == PARM_DECL
906 && GFC_DECL_PTR_ARRAY_P (expr))
907 return true;
909 if (INDIRECT_REF_P (expr)
910 && GFC_DECL_PTR_ARRAY_P (TREE_OPERAND (expr, 0)))
911 return true;
913 /* The field declaration is marked as an pointer array. */
914 if (TREE_CODE (expr) == COMPONENT_REF
915 && GFC_DECL_PTR_ARRAY_P (TREE_OPERAND (expr, 1))
916 && !GFC_CLASS_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 1))))
917 return true;
919 return false;
923 /* If the symbol or expression reference a CFI descriptor, return the
924 pointer to the converted gfc descriptor. If an array reference is
925 present as the last argument, check that it is the one applied to
926 the CFI descriptor in the expression. Note that the CFI object is
927 always the symbol in the expression! */
929 static bool
930 get_CFI_desc (gfc_symbol *sym, gfc_expr *expr,
931 tree *desc, gfc_array_ref *ar)
933 tree tmp;
935 if (!is_CFI_desc (sym, expr))
936 return false;
938 if (expr && ar)
940 if (!(expr->ref && expr->ref->type == REF_ARRAY)
941 || (&expr->ref->u.ar != ar))
942 return false;
945 if (sym == NULL)
946 tmp = expr->symtree->n.sym->backend_decl;
947 else
948 tmp = sym->backend_decl;
950 if (tmp && DECL_LANG_SPECIFIC (tmp) && GFC_DECL_SAVED_DESCRIPTOR (tmp))
951 tmp = GFC_DECL_SAVED_DESCRIPTOR (tmp);
953 *desc = tmp;
954 return true;
958 /* Return the span of an array. */
960 tree
961 gfc_get_array_span (tree desc, gfc_expr *expr)
963 tree tmp;
965 if (is_pointer_array (desc)
966 || (get_CFI_desc (NULL, expr, &desc, NULL)
967 && (POINTER_TYPE_P (TREE_TYPE (desc))
968 ? GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (desc)))
969 : GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))))
971 if (POINTER_TYPE_P (TREE_TYPE (desc)))
972 desc = build_fold_indirect_ref_loc (input_location, desc);
974 /* This will have the span field set. */
975 tmp = gfc_conv_descriptor_span_get (desc);
977 else if (expr->ts.type == BT_ASSUMED)
979 if (DECL_LANG_SPECIFIC (desc) && GFC_DECL_SAVED_DESCRIPTOR (desc))
980 desc = GFC_DECL_SAVED_DESCRIPTOR (desc);
981 if (POINTER_TYPE_P (TREE_TYPE (desc)))
982 desc = build_fold_indirect_ref_loc (input_location, desc);
983 tmp = gfc_conv_descriptor_span_get (desc);
985 else if (TREE_CODE (desc) == COMPONENT_REF
986 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc))
987 && GFC_CLASS_TYPE_P (TREE_TYPE (TREE_OPERAND (desc, 0))))
989 /* The descriptor is a class _data field and so use the vtable
990 size for the receiving span field. */
991 tmp = gfc_get_vptr_from_expr (desc);
992 tmp = gfc_vptr_size_get (tmp);
994 else if (expr && expr->expr_type == EXPR_VARIABLE
995 && expr->symtree->n.sym->ts.type == BT_CLASS
996 && expr->ref->type == REF_COMPONENT
997 && expr->ref->next->type == REF_ARRAY
998 && expr->ref->next->next == NULL
999 && CLASS_DATA (expr->symtree->n.sym)->attr.dimension)
1001 /* Dummys come in sometimes with the descriptor detached from
1002 the class field or declaration. */
1003 tmp = gfc_class_vptr_get (expr->symtree->n.sym->backend_decl);
1004 tmp = gfc_vptr_size_get (tmp);
1006 else
1008 /* If none of the fancy stuff works, the span is the element
1009 size of the array. Attempt to deal with unbounded character
1010 types if possible. Otherwise, return NULL_TREE. */
1011 tmp = gfc_get_element_type (TREE_TYPE (desc));
1012 if (tmp && TREE_CODE (tmp) == ARRAY_TYPE && TYPE_STRING_FLAG (tmp))
1014 gcc_assert (expr->ts.type == BT_CHARACTER);
1016 tmp = gfc_get_character_len_in_bytes (tmp);
1018 if (tmp == NULL_TREE || integer_zerop (tmp))
1020 tree bs;
1022 tmp = gfc_get_expr_charlen (expr);
1023 tmp = fold_convert (gfc_array_index_type, tmp);
1024 bs = build_int_cst (gfc_array_index_type, expr->ts.kind);
1025 tmp = fold_build2_loc (input_location, MULT_EXPR,
1026 gfc_array_index_type, tmp, bs);
1029 tmp = (tmp && !integer_zerop (tmp))
1030 ? (fold_convert (gfc_array_index_type, tmp)) : (NULL_TREE);
1032 else
1033 tmp = fold_convert (gfc_array_index_type,
1034 size_in_bytes (tmp));
1036 return tmp;
1040 /* Generate an initializer for a static pointer or allocatable array. */
1042 void
1043 gfc_trans_static_array_pointer (gfc_symbol * sym)
1045 tree type;
1047 gcc_assert (TREE_STATIC (sym->backend_decl));
1048 /* Just zero the data member. */
1049 type = TREE_TYPE (sym->backend_decl);
1050 DECL_INITIAL (sym->backend_decl) = gfc_build_null_descriptor (type);
1054 /* If the bounds of SE's loop have not yet been set, see if they can be
1055 determined from array spec AS, which is the array spec of a called
1056 function. MAPPING maps the callee's dummy arguments to the values
1057 that the caller is passing. Add any initialization and finalization
1058 code to SE. */
1060 void
1061 gfc_set_loop_bounds_from_array_spec (gfc_interface_mapping * mapping,
1062 gfc_se * se, gfc_array_spec * as)
1064 int n, dim, total_dim;
1065 gfc_se tmpse;
1066 gfc_ss *ss;
1067 tree lower;
1068 tree upper;
1069 tree tmp;
1071 total_dim = 0;
1073 if (!as || as->type != AS_EXPLICIT)
1074 return;
1076 for (ss = se->ss; ss; ss = ss->parent)
1078 total_dim += ss->loop->dimen;
1079 for (n = 0; n < ss->loop->dimen; n++)
1081 /* The bound is known, nothing to do. */
1082 if (ss->loop->to[n] != NULL_TREE)
1083 continue;
1085 dim = ss->dim[n];
1086 gcc_assert (dim < as->rank);
1087 gcc_assert (ss->loop->dimen <= as->rank);
1089 /* Evaluate the lower bound. */
1090 gfc_init_se (&tmpse, NULL);
1091 gfc_apply_interface_mapping (mapping, &tmpse, as->lower[dim]);
1092 gfc_add_block_to_block (&se->pre, &tmpse.pre);
1093 gfc_add_block_to_block (&se->post, &tmpse.post);
1094 lower = fold_convert (gfc_array_index_type, tmpse.expr);
1096 /* ...and the upper bound. */
1097 gfc_init_se (&tmpse, NULL);
1098 gfc_apply_interface_mapping (mapping, &tmpse, as->upper[dim]);
1099 gfc_add_block_to_block (&se->pre, &tmpse.pre);
1100 gfc_add_block_to_block (&se->post, &tmpse.post);
1101 upper = fold_convert (gfc_array_index_type, tmpse.expr);
1103 /* Set the upper bound of the loop to UPPER - LOWER. */
1104 tmp = fold_build2_loc (input_location, MINUS_EXPR,
1105 gfc_array_index_type, upper, lower);
1106 tmp = gfc_evaluate_now (tmp, &se->pre);
1107 ss->loop->to[n] = tmp;
1111 gcc_assert (total_dim == as->rank);
1115 /* Generate code to allocate an array temporary, or create a variable to
1116 hold the data. If size is NULL, zero the descriptor so that the
1117 callee will allocate the array. If DEALLOC is true, also generate code to
1118 free the array afterwards.
1120 If INITIAL is not NULL, it is packed using internal_pack and the result used
1121 as data instead of allocating a fresh, unitialized area of memory.
1123 Initialization code is added to PRE and finalization code to POST.
1124 DYNAMIC is true if the caller may want to extend the array later
1125 using realloc. This prevents us from putting the array on the stack. */
1127 static void
1128 gfc_trans_allocate_array_storage (stmtblock_t * pre, stmtblock_t * post,
1129 gfc_array_info * info, tree size, tree nelem,
1130 tree initial, bool dynamic, bool dealloc)
1132 tree tmp;
1133 tree desc;
1134 bool onstack;
1136 desc = info->descriptor;
1137 info->offset = gfc_index_zero_node;
1138 if (size == NULL_TREE || (dynamic && integer_zerop (size)))
1140 /* A callee allocated array. */
1141 gfc_conv_descriptor_data_set (pre, desc, null_pointer_node);
1142 onstack = false;
1144 else
1146 /* Allocate the temporary. */
1147 onstack = !dynamic && initial == NULL_TREE
1148 && (flag_stack_arrays
1149 || gfc_can_put_var_on_stack (size));
1151 if (onstack)
1153 /* Make a temporary variable to hold the data. */
1154 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (nelem),
1155 nelem, gfc_index_one_node);
1156 tmp = gfc_evaluate_now (tmp, pre);
1157 tmp = build_range_type (gfc_array_index_type, gfc_index_zero_node,
1158 tmp);
1159 tmp = build_array_type (gfc_get_element_type (TREE_TYPE (desc)),
1160 tmp);
1161 tmp = gfc_create_var (tmp, "A");
1162 /* If we're here only because of -fstack-arrays we have to
1163 emit a DECL_EXPR to make the gimplifier emit alloca calls. */
1164 if (!gfc_can_put_var_on_stack (size))
1165 gfc_add_expr_to_block (pre,
1166 fold_build1_loc (input_location,
1167 DECL_EXPR, TREE_TYPE (tmp),
1168 tmp));
1169 tmp = gfc_build_addr_expr (NULL_TREE, tmp);
1170 gfc_conv_descriptor_data_set (pre, desc, tmp);
1172 else
1174 /* Allocate memory to hold the data or call internal_pack. */
1175 if (initial == NULL_TREE)
1177 tmp = gfc_call_malloc (pre, NULL, size);
1178 tmp = gfc_evaluate_now (tmp, pre);
1180 else
1182 tree packed;
1183 tree source_data;
1184 tree was_packed;
1185 stmtblock_t do_copying;
1187 tmp = TREE_TYPE (initial); /* Pointer to descriptor. */
1188 gcc_assert (TREE_CODE (tmp) == POINTER_TYPE);
1189 tmp = TREE_TYPE (tmp); /* The descriptor itself. */
1190 tmp = gfc_get_element_type (tmp);
1191 packed = gfc_create_var (build_pointer_type (tmp), "data");
1193 tmp = build_call_expr_loc (input_location,
1194 gfor_fndecl_in_pack, 1, initial);
1195 tmp = fold_convert (TREE_TYPE (packed), tmp);
1196 gfc_add_modify (pre, packed, tmp);
1198 tmp = build_fold_indirect_ref_loc (input_location,
1199 initial);
1200 source_data = gfc_conv_descriptor_data_get (tmp);
1202 /* internal_pack may return source->data without any allocation
1203 or copying if it is already packed. If that's the case, we
1204 need to allocate and copy manually. */
1206 gfc_start_block (&do_copying);
1207 tmp = gfc_call_malloc (&do_copying, NULL, size);
1208 tmp = fold_convert (TREE_TYPE (packed), tmp);
1209 gfc_add_modify (&do_copying, packed, tmp);
1210 tmp = gfc_build_memcpy_call (packed, source_data, size);
1211 gfc_add_expr_to_block (&do_copying, tmp);
1213 was_packed = fold_build2_loc (input_location, EQ_EXPR,
1214 logical_type_node, packed,
1215 source_data);
1216 tmp = gfc_finish_block (&do_copying);
1217 tmp = build3_v (COND_EXPR, was_packed, tmp,
1218 build_empty_stmt (input_location));
1219 gfc_add_expr_to_block (pre, tmp);
1221 tmp = fold_convert (pvoid_type_node, packed);
1224 gfc_conv_descriptor_data_set (pre, desc, tmp);
1227 info->data = gfc_conv_descriptor_data_get (desc);
1229 /* The offset is zero because we create temporaries with a zero
1230 lower bound. */
1231 gfc_conv_descriptor_offset_set (pre, desc, gfc_index_zero_node);
1233 if (dealloc && !onstack)
1235 /* Free the temporary. */
1236 tmp = gfc_conv_descriptor_data_get (desc);
1237 tmp = gfc_call_free (tmp);
1238 gfc_add_expr_to_block (post, tmp);
1243 /* Get the scalarizer array dimension corresponding to actual array dimension
1244 given by ARRAY_DIM.
1246 For example, if SS represents the array ref a(1,:,:,1), it is a
1247 bidimensional scalarizer array, and the result would be 0 for ARRAY_DIM=1,
1248 and 1 for ARRAY_DIM=2.
1249 If SS represents transpose(a(:,1,1,:)), it is again a bidimensional
1250 scalarizer array, and the result would be 1 for ARRAY_DIM=0 and 0 for
1251 ARRAY_DIM=3.
1252 If SS represents sum(a(:,:,:,1), dim=1), it is a 2+1-dimensional scalarizer
1253 array. If called on the inner ss, the result would be respectively 0,1,2 for
1254 ARRAY_DIM=0,1,2. If called on the outer ss, the result would be 0,1
1255 for ARRAY_DIM=1,2. */
1257 static int
1258 get_scalarizer_dim_for_array_dim (gfc_ss *ss, int array_dim)
1260 int array_ref_dim;
1261 int n;
1263 array_ref_dim = 0;
1265 for (; ss; ss = ss->parent)
1266 for (n = 0; n < ss->dimen; n++)
1267 if (ss->dim[n] < array_dim)
1268 array_ref_dim++;
1270 return array_ref_dim;
1274 static gfc_ss *
1275 innermost_ss (gfc_ss *ss)
1277 while (ss->nested_ss != NULL)
1278 ss = ss->nested_ss;
1280 return ss;
1285 /* Get the array reference dimension corresponding to the given loop dimension.
1286 It is different from the true array dimension given by the dim array in
1287 the case of a partial array reference (i.e. a(:,:,1,:) for example)
1288 It is different from the loop dimension in the case of a transposed array.
1291 static int
1292 get_array_ref_dim_for_loop_dim (gfc_ss *ss, int loop_dim)
1294 return get_scalarizer_dim_for_array_dim (innermost_ss (ss),
1295 ss->dim[loop_dim]);
1299 /* Use the information in the ss to obtain the required information about
1300 the type and size of an array temporary, when the lhs in an assignment
1301 is a class expression. */
1303 static tree
1304 get_class_info_from_ss (stmtblock_t * pre, gfc_ss *ss, tree *eltype)
1306 gfc_ss *lhs_ss;
1307 gfc_ss *rhs_ss;
1308 tree tmp;
1309 tree tmp2;
1310 tree vptr;
1311 tree rhs_class_expr = NULL_TREE;
1312 tree lhs_class_expr = NULL_TREE;
1313 bool unlimited_rhs = false;
1314 bool unlimited_lhs = false;
1315 bool rhs_function = false;
1316 gfc_symbol *vtab;
1318 /* The second element in the loop chain contains the source for the
1319 temporary; ie. the rhs of the assignment. */
1320 rhs_ss = ss->loop->ss->loop_chain;
1322 if (rhs_ss != gfc_ss_terminator
1323 && rhs_ss->info
1324 && rhs_ss->info->expr
1325 && rhs_ss->info->expr->ts.type == BT_CLASS
1326 && rhs_ss->info->data.array.descriptor)
1328 if (rhs_ss->info->expr->expr_type != EXPR_VARIABLE)
1329 rhs_class_expr
1330 = gfc_get_class_from_expr (rhs_ss->info->data.array.descriptor);
1331 else
1332 rhs_class_expr = gfc_get_class_from_gfc_expr (rhs_ss->info->expr);
1333 unlimited_rhs = UNLIMITED_POLY (rhs_ss->info->expr);
1334 if (rhs_ss->info->expr->expr_type == EXPR_FUNCTION)
1335 rhs_function = true;
1338 /* For an assignment the lhs is the next element in the loop chain.
1339 If we have a class rhs, this had better be a class variable
1340 expression! */
1341 lhs_ss = rhs_ss->loop_chain;
1342 if (lhs_ss != gfc_ss_terminator
1343 && lhs_ss->info
1344 && lhs_ss->info->expr
1345 && lhs_ss->info->expr->expr_type ==EXPR_VARIABLE
1346 && lhs_ss->info->expr->ts.type == BT_CLASS)
1348 tmp = lhs_ss->info->data.array.descriptor;
1349 unlimited_lhs = UNLIMITED_POLY (rhs_ss->info->expr);
1351 else
1352 tmp = NULL_TREE;
1354 /* Get the lhs class expression. */
1355 if (tmp != NULL_TREE && lhs_ss->loop_chain == gfc_ss_terminator)
1356 lhs_class_expr = gfc_get_class_from_expr (tmp);
1357 else
1358 return rhs_class_expr;
1360 gcc_assert (GFC_CLASS_TYPE_P (TREE_TYPE (lhs_class_expr)));
1362 /* Set the lhs vptr and, if necessary, the _len field. */
1363 if (rhs_class_expr)
1365 /* Both lhs and rhs are class expressions. */
1366 tmp = gfc_class_vptr_get (lhs_class_expr);
1367 gfc_add_modify (pre, tmp,
1368 fold_convert (TREE_TYPE (tmp),
1369 gfc_class_vptr_get (rhs_class_expr)));
1370 if (unlimited_lhs)
1372 tmp = gfc_class_len_get (lhs_class_expr);
1373 if (unlimited_rhs)
1374 tmp2 = gfc_class_len_get (rhs_class_expr);
1375 else
1376 tmp2 = build_int_cst (TREE_TYPE (tmp), 0);
1377 gfc_add_modify (pre, tmp, tmp2);
1380 if (rhs_function)
1382 tmp = gfc_class_data_get (rhs_class_expr);
1383 gfc_conv_descriptor_offset_set (pre, tmp, gfc_index_zero_node);
1386 else
1388 /* lhs is class and rhs is intrinsic or derived type. */
1389 *eltype = TREE_TYPE (rhs_ss->info->data.array.descriptor);
1390 *eltype = gfc_get_element_type (*eltype);
1391 vtab = gfc_find_vtab (&rhs_ss->info->expr->ts);
1392 vptr = vtab->backend_decl;
1393 if (vptr == NULL_TREE)
1394 vptr = gfc_get_symbol_decl (vtab);
1395 vptr = gfc_build_addr_expr (NULL_TREE, vptr);
1396 tmp = gfc_class_vptr_get (lhs_class_expr);
1397 gfc_add_modify (pre, tmp,
1398 fold_convert (TREE_TYPE (tmp), vptr));
1400 if (unlimited_lhs)
1402 tmp = gfc_class_len_get (lhs_class_expr);
1403 if (rhs_ss->info
1404 && rhs_ss->info->expr
1405 && rhs_ss->info->expr->ts.type == BT_CHARACTER)
1406 tmp2 = build_int_cst (TREE_TYPE (tmp),
1407 rhs_ss->info->expr->ts.kind);
1408 else
1409 tmp2 = build_int_cst (TREE_TYPE (tmp), 0);
1410 gfc_add_modify (pre, tmp, tmp2);
1414 return rhs_class_expr;
1419 /* Generate code to create and initialize the descriptor for a temporary
1420 array. This is used for both temporaries needed by the scalarizer, and
1421 functions returning arrays. Adjusts the loop variables to be
1422 zero-based, and calculates the loop bounds for callee allocated arrays.
1423 Allocate the array unless it's callee allocated (we have a callee
1424 allocated array if 'callee_alloc' is true, or if loop->to[n] is
1425 NULL_TREE for any n). Also fills in the descriptor, data and offset
1426 fields of info if known. Returns the size of the array, or NULL for a
1427 callee allocated array.
1429 'eltype' == NULL signals that the temporary should be a class object.
1430 The 'initial' expression is used to obtain the size of the dynamic
1431 type; otherwise the allocation and initialization proceeds as for any
1432 other expression
1434 PRE, POST, INITIAL, DYNAMIC and DEALLOC are as for
1435 gfc_trans_allocate_array_storage. */
1437 tree
1438 gfc_trans_create_temp_array (stmtblock_t * pre, stmtblock_t * post, gfc_ss * ss,
1439 tree eltype, tree initial, bool dynamic,
1440 bool dealloc, bool callee_alloc, locus * where)
1442 gfc_loopinfo *loop;
1443 gfc_ss *s;
1444 gfc_array_info *info;
1445 tree from[GFC_MAX_DIMENSIONS], to[GFC_MAX_DIMENSIONS];
1446 tree type;
1447 tree desc;
1448 tree tmp;
1449 tree size;
1450 tree nelem;
1451 tree cond;
1452 tree or_expr;
1453 tree elemsize;
1454 tree class_expr = NULL_TREE;
1455 int n, dim, tmp_dim;
1456 int total_dim = 0;
1458 /* This signals a class array for which we need the size of the
1459 dynamic type. Generate an eltype and then the class expression. */
1460 if (eltype == NULL_TREE && initial)
1462 gcc_assert (POINTER_TYPE_P (TREE_TYPE (initial)));
1463 class_expr = build_fold_indirect_ref_loc (input_location, initial);
1464 /* Obtain the structure (class) expression. */
1465 class_expr = gfc_get_class_from_expr (class_expr);
1466 gcc_assert (class_expr);
1469 /* Otherwise, some expressions, such as class functions, arising from
1470 dependency checking in assignments come here with class element type.
1471 The descriptor can be obtained from the ss->info and then converted
1472 to the class object. */
1473 if (class_expr == NULL_TREE && GFC_CLASS_TYPE_P (eltype))
1474 class_expr = get_class_info_from_ss (pre, ss, &eltype);
1476 /* If the dynamic type is not available, use the declared type. */
1477 if (eltype && GFC_CLASS_TYPE_P (eltype))
1478 eltype = gfc_get_element_type (TREE_TYPE (TYPE_FIELDS (eltype)));
1480 if (class_expr == NULL_TREE)
1481 elemsize = fold_convert (gfc_array_index_type,
1482 TYPE_SIZE_UNIT (eltype));
1483 else
1485 /* Unlimited polymorphic entities are initialised with NULL vptr. They
1486 can be tested for by checking if the len field is present. If so
1487 test the vptr before using the vtable size. */
1488 tmp = gfc_class_vptr_get (class_expr);
1489 tmp = fold_build2_loc (input_location, NE_EXPR,
1490 logical_type_node,
1491 tmp, build_int_cst (TREE_TYPE (tmp), 0));
1492 elemsize = fold_build3_loc (input_location, COND_EXPR,
1493 gfc_array_index_type,
1494 tmp,
1495 gfc_class_vtab_size_get (class_expr),
1496 gfc_index_zero_node);
1497 elemsize = gfc_evaluate_now (elemsize, pre);
1498 elemsize = gfc_resize_class_size_with_len (pre, class_expr, elemsize);
1499 /* Casting the data as a character of the dynamic length ensures that
1500 assignment of elements works when needed. */
1501 eltype = gfc_get_character_type_len (1, elemsize);
1504 memset (from, 0, sizeof (from));
1505 memset (to, 0, sizeof (to));
1507 info = &ss->info->data.array;
1509 gcc_assert (ss->dimen > 0);
1510 gcc_assert (ss->loop->dimen == ss->dimen);
1512 if (warn_array_temporaries && where)
1513 gfc_warning (OPT_Warray_temporaries,
1514 "Creating array temporary at %L", where);
1516 /* Set the lower bound to zero. */
1517 for (s = ss; s; s = s->parent)
1519 loop = s->loop;
1521 total_dim += loop->dimen;
1522 for (n = 0; n < loop->dimen; n++)
1524 dim = s->dim[n];
1526 /* Callee allocated arrays may not have a known bound yet. */
1527 if (loop->to[n])
1528 loop->to[n] = gfc_evaluate_now (
1529 fold_build2_loc (input_location, MINUS_EXPR,
1530 gfc_array_index_type,
1531 loop->to[n], loop->from[n]),
1532 pre);
1533 loop->from[n] = gfc_index_zero_node;
1535 /* We have just changed the loop bounds, we must clear the
1536 corresponding specloop, so that delta calculation is not skipped
1537 later in gfc_set_delta. */
1538 loop->specloop[n] = NULL;
1540 /* We are constructing the temporary's descriptor based on the loop
1541 dimensions. As the dimensions may be accessed in arbitrary order
1542 (think of transpose) the size taken from the n'th loop may not map
1543 to the n'th dimension of the array. We need to reconstruct loop
1544 infos in the right order before using it to set the descriptor
1545 bounds. */
1546 tmp_dim = get_scalarizer_dim_for_array_dim (ss, dim);
1547 from[tmp_dim] = loop->from[n];
1548 to[tmp_dim] = loop->to[n];
1550 info->delta[dim] = gfc_index_zero_node;
1551 info->start[dim] = gfc_index_zero_node;
1552 info->end[dim] = gfc_index_zero_node;
1553 info->stride[dim] = gfc_index_one_node;
1557 /* Initialize the descriptor. */
1558 type =
1559 gfc_get_array_type_bounds (eltype, total_dim, 0, from, to, 1,
1560 GFC_ARRAY_UNKNOWN, true);
1561 desc = gfc_create_var (type, "atmp");
1562 GFC_DECL_PACKED_ARRAY (desc) = 1;
1564 /* Emit a DECL_EXPR for the variable sized array type in
1565 GFC_TYPE_ARRAY_DATAPTR_TYPE so the gimplification of its type
1566 sizes works correctly. */
1567 tree arraytype = TREE_TYPE (GFC_TYPE_ARRAY_DATAPTR_TYPE (type));
1568 if (! TYPE_NAME (arraytype))
1569 TYPE_NAME (arraytype) = build_decl (UNKNOWN_LOCATION, TYPE_DECL,
1570 NULL_TREE, arraytype);
1571 gfc_add_expr_to_block (pre, build1 (DECL_EXPR,
1572 arraytype, TYPE_NAME (arraytype)));
1574 if (class_expr != NULL_TREE)
1576 tree class_data;
1577 tree dtype;
1579 /* Create a class temporary. */
1580 tmp = gfc_create_var (TREE_TYPE (class_expr), "ctmp");
1581 gfc_add_modify (pre, tmp, class_expr);
1583 /* Assign the new descriptor to the _data field. This allows the
1584 vptr _copy to be used for scalarized assignment since the class
1585 temporary can be found from the descriptor. */
1586 class_data = gfc_class_data_get (tmp);
1587 tmp = fold_build1_loc (input_location, VIEW_CONVERT_EXPR,
1588 TREE_TYPE (desc), desc);
1589 gfc_add_modify (pre, class_data, tmp);
1591 /* Take the dtype from the class expression. */
1592 dtype = gfc_conv_descriptor_dtype (gfc_class_data_get (class_expr));
1593 tmp = gfc_conv_descriptor_dtype (class_data);
1594 gfc_add_modify (pre, tmp, dtype);
1596 /* Point desc to the class _data field. */
1597 desc = class_data;
1599 else
1601 /* Fill in the array dtype. */
1602 tmp = gfc_conv_descriptor_dtype (desc);
1603 gfc_add_modify (pre, tmp, gfc_get_dtype (TREE_TYPE (desc)));
1606 info->descriptor = desc;
1607 size = gfc_index_one_node;
1610 Fill in the bounds and stride. This is a packed array, so:
1612 size = 1;
1613 for (n = 0; n < rank; n++)
1615 stride[n] = size
1616 delta = ubound[n] + 1 - lbound[n];
1617 size = size * delta;
1619 size = size * sizeof(element);
1622 or_expr = NULL_TREE;
1624 /* If there is at least one null loop->to[n], it is a callee allocated
1625 array. */
1626 for (n = 0; n < total_dim; n++)
1627 if (to[n] == NULL_TREE)
1629 size = NULL_TREE;
1630 break;
1633 if (size == NULL_TREE)
1634 for (s = ss; s; s = s->parent)
1635 for (n = 0; n < s->loop->dimen; n++)
1637 dim = get_scalarizer_dim_for_array_dim (ss, s->dim[n]);
1639 /* For a callee allocated array express the loop bounds in terms
1640 of the descriptor fields. */
1641 tmp = fold_build2_loc (input_location,
1642 MINUS_EXPR, gfc_array_index_type,
1643 gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[dim]),
1644 gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[dim]));
1645 s->loop->to[n] = tmp;
1647 else
1649 for (n = 0; n < total_dim; n++)
1651 /* Store the stride and bound components in the descriptor. */
1652 gfc_conv_descriptor_stride_set (pre, desc, gfc_rank_cst[n], size);
1654 gfc_conv_descriptor_lbound_set (pre, desc, gfc_rank_cst[n],
1655 gfc_index_zero_node);
1657 gfc_conv_descriptor_ubound_set (pre, desc, gfc_rank_cst[n], to[n]);
1659 tmp = fold_build2_loc (input_location, PLUS_EXPR,
1660 gfc_array_index_type,
1661 to[n], gfc_index_one_node);
1663 /* Check whether the size for this dimension is negative. */
1664 cond = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
1665 tmp, gfc_index_zero_node);
1666 cond = gfc_evaluate_now (cond, pre);
1668 if (n == 0)
1669 or_expr = cond;
1670 else
1671 or_expr = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1672 logical_type_node, or_expr, cond);
1674 size = fold_build2_loc (input_location, MULT_EXPR,
1675 gfc_array_index_type, size, tmp);
1676 size = gfc_evaluate_now (size, pre);
1680 /* Get the size of the array. */
1681 if (size && !callee_alloc)
1683 /* If or_expr is true, then the extent in at least one
1684 dimension is zero and the size is set to zero. */
1685 size = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
1686 or_expr, gfc_index_zero_node, size);
1688 nelem = size;
1689 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
1690 size, elemsize);
1692 else
1694 nelem = size;
1695 size = NULL_TREE;
1698 /* Set the span. */
1699 tmp = fold_convert (gfc_array_index_type, elemsize);
1700 gfc_conv_descriptor_span_set (pre, desc, tmp);
1702 gfc_trans_allocate_array_storage (pre, post, info, size, nelem, initial,
1703 dynamic, dealloc);
1705 while (ss->parent)
1706 ss = ss->parent;
1708 if (ss->dimen > ss->loop->temp_dim)
1709 ss->loop->temp_dim = ss->dimen;
1711 return size;
1715 /* Return the number of iterations in a loop that starts at START,
1716 ends at END, and has step STEP. */
1718 static tree
1719 gfc_get_iteration_count (tree start, tree end, tree step)
1721 tree tmp;
1722 tree type;
1724 type = TREE_TYPE (step);
1725 tmp = fold_build2_loc (input_location, MINUS_EXPR, type, end, start);
1726 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR, type, tmp, step);
1727 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp,
1728 build_int_cst (type, 1));
1729 tmp = fold_build2_loc (input_location, MAX_EXPR, type, tmp,
1730 build_int_cst (type, 0));
1731 return fold_convert (gfc_array_index_type, tmp);
1735 /* Extend the data in array DESC by EXTRA elements. */
1737 static void
1738 gfc_grow_array (stmtblock_t * pblock, tree desc, tree extra)
1740 tree arg0, arg1;
1741 tree tmp;
1742 tree size;
1743 tree ubound;
1745 if (integer_zerop (extra))
1746 return;
1748 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[0]);
1750 /* Add EXTRA to the upper bound. */
1751 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1752 ubound, extra);
1753 gfc_conv_descriptor_ubound_set (pblock, desc, gfc_rank_cst[0], tmp);
1755 /* Get the value of the current data pointer. */
1756 arg0 = gfc_conv_descriptor_data_get (desc);
1758 /* Calculate the new array size. */
1759 size = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
1760 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1761 ubound, gfc_index_one_node);
1762 arg1 = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
1763 fold_convert (size_type_node, tmp),
1764 fold_convert (size_type_node, size));
1766 /* Call the realloc() function. */
1767 tmp = gfc_call_realloc (pblock, arg0, arg1);
1768 gfc_conv_descriptor_data_set (pblock, desc, tmp);
1772 /* Return true if the bounds of iterator I can only be determined
1773 at run time. */
1775 static inline bool
1776 gfc_iterator_has_dynamic_bounds (gfc_iterator * i)
1778 return (i->start->expr_type != EXPR_CONSTANT
1779 || i->end->expr_type != EXPR_CONSTANT
1780 || i->step->expr_type != EXPR_CONSTANT);
1784 /* Split the size of constructor element EXPR into the sum of two terms,
1785 one of which can be determined at compile time and one of which must
1786 be calculated at run time. Set *SIZE to the former and return true
1787 if the latter might be nonzero. */
1789 static bool
1790 gfc_get_array_constructor_element_size (mpz_t * size, gfc_expr * expr)
1792 if (expr->expr_type == EXPR_ARRAY)
1793 return gfc_get_array_constructor_size (size, expr->value.constructor);
1794 else if (expr->rank > 0)
1796 /* Calculate everything at run time. */
1797 mpz_set_ui (*size, 0);
1798 return true;
1800 else
1802 /* A single element. */
1803 mpz_set_ui (*size, 1);
1804 return false;
1809 /* Like gfc_get_array_constructor_element_size, but applied to the whole
1810 of array constructor C. */
1812 static bool
1813 gfc_get_array_constructor_size (mpz_t * size, gfc_constructor_base base)
1815 gfc_constructor *c;
1816 gfc_iterator *i;
1817 mpz_t val;
1818 mpz_t len;
1819 bool dynamic;
1821 mpz_set_ui (*size, 0);
1822 mpz_init (len);
1823 mpz_init (val);
1825 dynamic = false;
1826 for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
1828 i = c->iterator;
1829 if (i && gfc_iterator_has_dynamic_bounds (i))
1830 dynamic = true;
1831 else
1833 dynamic |= gfc_get_array_constructor_element_size (&len, c->expr);
1834 if (i)
1836 /* Multiply the static part of the element size by the
1837 number of iterations. */
1838 mpz_sub (val, i->end->value.integer, i->start->value.integer);
1839 mpz_fdiv_q (val, val, i->step->value.integer);
1840 mpz_add_ui (val, val, 1);
1841 if (mpz_sgn (val) > 0)
1842 mpz_mul (len, len, val);
1843 else
1844 mpz_set_ui (len, 0);
1846 mpz_add (*size, *size, len);
1849 mpz_clear (len);
1850 mpz_clear (val);
1851 return dynamic;
1855 /* Make sure offset is a variable. */
1857 static void
1858 gfc_put_offset_into_var (stmtblock_t * pblock, tree * poffset,
1859 tree * offsetvar)
1861 /* We should have already created the offset variable. We cannot
1862 create it here because we may be in an inner scope. */
1863 gcc_assert (*offsetvar != NULL_TREE);
1864 gfc_add_modify (pblock, *offsetvar, *poffset);
1865 *poffset = *offsetvar;
1866 TREE_USED (*offsetvar) = 1;
1870 /* Variables needed for bounds-checking. */
1871 static bool first_len;
1872 static tree first_len_val;
1873 static bool typespec_chararray_ctor;
1875 static void
1876 gfc_trans_array_ctor_element (stmtblock_t * pblock, tree desc,
1877 tree offset, gfc_se * se, gfc_expr * expr)
1879 tree tmp;
1881 gfc_conv_expr (se, expr);
1883 /* Store the value. */
1884 tmp = build_fold_indirect_ref_loc (input_location,
1885 gfc_conv_descriptor_data_get (desc));
1886 tmp = gfc_build_array_ref (tmp, offset, NULL);
1888 if (expr->ts.type == BT_CHARACTER)
1890 int i = gfc_validate_kind (BT_CHARACTER, expr->ts.kind, false);
1891 tree esize;
1893 esize = size_in_bytes (gfc_get_element_type (TREE_TYPE (desc)));
1894 esize = fold_convert (gfc_charlen_type_node, esize);
1895 esize = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
1896 TREE_TYPE (esize), esize,
1897 build_int_cst (TREE_TYPE (esize),
1898 gfc_character_kinds[i].bit_size / 8));
1900 gfc_conv_string_parameter (se);
1901 if (POINTER_TYPE_P (TREE_TYPE (tmp)))
1903 /* The temporary is an array of pointers. */
1904 se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
1905 gfc_add_modify (&se->pre, tmp, se->expr);
1907 else
1909 /* The temporary is an array of string values. */
1910 tmp = gfc_build_addr_expr (gfc_get_pchar_type (expr->ts.kind), tmp);
1911 /* We know the temporary and the value will be the same length,
1912 so can use memcpy. */
1913 gfc_trans_string_copy (&se->pre, esize, tmp, expr->ts.kind,
1914 se->string_length, se->expr, expr->ts.kind);
1916 if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS) && !typespec_chararray_ctor)
1918 if (first_len)
1920 gfc_add_modify (&se->pre, first_len_val,
1921 fold_convert (TREE_TYPE (first_len_val),
1922 se->string_length));
1923 first_len = false;
1925 else
1927 /* Verify that all constructor elements are of the same
1928 length. */
1929 tree rhs = fold_convert (TREE_TYPE (first_len_val),
1930 se->string_length);
1931 tree cond = fold_build2_loc (input_location, NE_EXPR,
1932 logical_type_node, first_len_val,
1933 rhs);
1934 gfc_trans_runtime_check
1935 (true, false, cond, &se->pre, &expr->where,
1936 "Different CHARACTER lengths (%ld/%ld) in array constructor",
1937 fold_convert (long_integer_type_node, first_len_val),
1938 fold_convert (long_integer_type_node, se->string_length));
1942 else if (GFC_CLASS_TYPE_P (TREE_TYPE (se->expr))
1943 && !GFC_CLASS_TYPE_P (gfc_get_element_type (TREE_TYPE (desc))))
1945 /* Assignment of a CLASS array constructor to a derived type array. */
1946 if (expr->expr_type == EXPR_FUNCTION)
1947 se->expr = gfc_evaluate_now (se->expr, pblock);
1948 se->expr = gfc_class_data_get (se->expr);
1949 se->expr = build_fold_indirect_ref_loc (input_location, se->expr);
1950 se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
1951 gfc_add_modify (&se->pre, tmp, se->expr);
1953 else
1955 /* TODO: Should the frontend already have done this conversion? */
1956 se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
1957 gfc_add_modify (&se->pre, tmp, se->expr);
1960 gfc_add_block_to_block (pblock, &se->pre);
1961 gfc_add_block_to_block (pblock, &se->post);
1965 /* Add the contents of an array to the constructor. DYNAMIC is as for
1966 gfc_trans_array_constructor_value. */
1968 static void
1969 gfc_trans_array_constructor_subarray (stmtblock_t * pblock,
1970 tree type ATTRIBUTE_UNUSED,
1971 tree desc, gfc_expr * expr,
1972 tree * poffset, tree * offsetvar,
1973 bool dynamic)
1975 gfc_se se;
1976 gfc_ss *ss;
1977 gfc_loopinfo loop;
1978 stmtblock_t body;
1979 tree tmp;
1980 tree size;
1981 int n;
1983 /* We need this to be a variable so we can increment it. */
1984 gfc_put_offset_into_var (pblock, poffset, offsetvar);
1986 gfc_init_se (&se, NULL);
1988 /* Walk the array expression. */
1989 ss = gfc_walk_expr (expr);
1990 gcc_assert (ss != gfc_ss_terminator);
1992 /* Initialize the scalarizer. */
1993 gfc_init_loopinfo (&loop);
1994 gfc_add_ss_to_loop (&loop, ss);
1996 /* Initialize the loop. */
1997 gfc_conv_ss_startstride (&loop);
1998 gfc_conv_loop_setup (&loop, &expr->where);
2000 /* Make sure the constructed array has room for the new data. */
2001 if (dynamic)
2003 /* Set SIZE to the total number of elements in the subarray. */
2004 size = gfc_index_one_node;
2005 for (n = 0; n < loop.dimen; n++)
2007 tmp = gfc_get_iteration_count (loop.from[n], loop.to[n],
2008 gfc_index_one_node);
2009 size = fold_build2_loc (input_location, MULT_EXPR,
2010 gfc_array_index_type, size, tmp);
2013 /* Grow the constructed array by SIZE elements. */
2014 gfc_grow_array (&loop.pre, desc, size);
2017 /* Make the loop body. */
2018 gfc_mark_ss_chain_used (ss, 1);
2019 gfc_start_scalarized_body (&loop, &body);
2020 gfc_copy_loopinfo_to_se (&se, &loop);
2021 se.ss = ss;
2023 gfc_trans_array_ctor_element (&body, desc, *poffset, &se, expr);
2024 gcc_assert (se.ss == gfc_ss_terminator);
2026 /* Increment the offset. */
2027 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
2028 *poffset, gfc_index_one_node);
2029 gfc_add_modify (&body, *poffset, tmp);
2031 /* Finish the loop. */
2032 gfc_trans_scalarizing_loops (&loop, &body);
2033 gfc_add_block_to_block (&loop.pre, &loop.post);
2034 tmp = gfc_finish_block (&loop.pre);
2035 gfc_add_expr_to_block (pblock, tmp);
2037 gfc_cleanup_loop (&loop);
2041 /* Assign the values to the elements of an array constructor. DYNAMIC
2042 is true if descriptor DESC only contains enough data for the static
2043 size calculated by gfc_get_array_constructor_size. When true, memory
2044 for the dynamic parts must be allocated using realloc. */
2046 static void
2047 gfc_trans_array_constructor_value (stmtblock_t * pblock,
2048 stmtblock_t * finalblock,
2049 tree type, tree desc,
2050 gfc_constructor_base base, tree * poffset,
2051 tree * offsetvar, bool dynamic)
2053 tree tmp;
2054 tree start = NULL_TREE;
2055 tree end = NULL_TREE;
2056 tree step = NULL_TREE;
2057 stmtblock_t body;
2058 gfc_se se;
2059 mpz_t size;
2060 gfc_constructor *c;
2061 gfc_typespec ts;
2062 int ctr = 0;
2064 tree shadow_loopvar = NULL_TREE;
2065 gfc_saved_var saved_loopvar;
2067 ts.type = BT_UNKNOWN;
2068 mpz_init (size);
2069 for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
2071 ctr++;
2072 /* If this is an iterator or an array, the offset must be a variable. */
2073 if ((c->iterator || c->expr->rank > 0) && INTEGER_CST_P (*poffset))
2074 gfc_put_offset_into_var (pblock, poffset, offsetvar);
2076 /* Shadowing the iterator avoids changing its value and saves us from
2077 keeping track of it. Further, it makes sure that there's always a
2078 backend-decl for the symbol, even if there wasn't one before,
2079 e.g. in the case of an iterator that appears in a specification
2080 expression in an interface mapping. */
2081 if (c->iterator)
2083 gfc_symbol *sym;
2084 tree type;
2086 /* Evaluate loop bounds before substituting the loop variable
2087 in case they depend on it. Such a case is invalid, but it is
2088 not more expensive to do the right thing here.
2089 See PR 44354. */
2090 gfc_init_se (&se, NULL);
2091 gfc_conv_expr_val (&se, c->iterator->start);
2092 gfc_add_block_to_block (pblock, &se.pre);
2093 start = gfc_evaluate_now (se.expr, pblock);
2095 gfc_init_se (&se, NULL);
2096 gfc_conv_expr_val (&se, c->iterator->end);
2097 gfc_add_block_to_block (pblock, &se.pre);
2098 end = gfc_evaluate_now (se.expr, pblock);
2100 gfc_init_se (&se, NULL);
2101 gfc_conv_expr_val (&se, c->iterator->step);
2102 gfc_add_block_to_block (pblock, &se.pre);
2103 step = gfc_evaluate_now (se.expr, pblock);
2105 sym = c->iterator->var->symtree->n.sym;
2106 type = gfc_typenode_for_spec (&sym->ts);
2108 shadow_loopvar = gfc_create_var (type, "shadow_loopvar");
2109 gfc_shadow_sym (sym, shadow_loopvar, &saved_loopvar);
2112 gfc_start_block (&body);
2114 if (c->expr->expr_type == EXPR_ARRAY)
2116 /* Array constructors can be nested. */
2117 gfc_trans_array_constructor_value (&body, finalblock, type,
2118 desc, c->expr->value.constructor,
2119 poffset, offsetvar, dynamic);
2121 else if (c->expr->rank > 0)
2123 gfc_trans_array_constructor_subarray (&body, type, desc, c->expr,
2124 poffset, offsetvar, dynamic);
2126 else
2128 /* This code really upsets the gimplifier so don't bother for now. */
2129 gfc_constructor *p;
2130 HOST_WIDE_INT n;
2131 HOST_WIDE_INT size;
2133 p = c;
2134 n = 0;
2135 while (p && !(p->iterator || p->expr->expr_type != EXPR_CONSTANT))
2137 p = gfc_constructor_next (p);
2138 n++;
2140 if (n < 4)
2142 /* Scalar values. */
2143 gfc_init_se (&se, NULL);
2144 gfc_trans_array_ctor_element (&body, desc, *poffset,
2145 &se, c->expr);
2147 *poffset = fold_build2_loc (input_location, PLUS_EXPR,
2148 gfc_array_index_type,
2149 *poffset, gfc_index_one_node);
2151 else
2153 /* Collect multiple scalar constants into a constructor. */
2154 vec<constructor_elt, va_gc> *v = NULL;
2155 tree init;
2156 tree bound;
2157 tree tmptype;
2158 HOST_WIDE_INT idx = 0;
2160 p = c;
2161 /* Count the number of consecutive scalar constants. */
2162 while (p && !(p->iterator
2163 || p->expr->expr_type != EXPR_CONSTANT))
2165 gfc_init_se (&se, NULL);
2166 gfc_conv_constant (&se, p->expr);
2168 if (c->expr->ts.type != BT_CHARACTER)
2169 se.expr = fold_convert (type, se.expr);
2170 /* For constant character array constructors we build
2171 an array of pointers. */
2172 else if (POINTER_TYPE_P (type))
2173 se.expr = gfc_build_addr_expr
2174 (gfc_get_pchar_type (p->expr->ts.kind),
2175 se.expr);
2177 CONSTRUCTOR_APPEND_ELT (v,
2178 build_int_cst (gfc_array_index_type,
2179 idx++),
2180 se.expr);
2181 c = p;
2182 p = gfc_constructor_next (p);
2185 bound = size_int (n - 1);
2186 /* Create an array type to hold them. */
2187 tmptype = build_range_type (gfc_array_index_type,
2188 gfc_index_zero_node, bound);
2189 tmptype = build_array_type (type, tmptype);
2191 init = build_constructor (tmptype, v);
2192 TREE_CONSTANT (init) = 1;
2193 TREE_STATIC (init) = 1;
2194 /* Create a static variable to hold the data. */
2195 tmp = gfc_create_var (tmptype, "data");
2196 TREE_STATIC (tmp) = 1;
2197 TREE_CONSTANT (tmp) = 1;
2198 TREE_READONLY (tmp) = 1;
2199 DECL_INITIAL (tmp) = init;
2200 init = tmp;
2202 /* Use BUILTIN_MEMCPY to assign the values. */
2203 tmp = gfc_conv_descriptor_data_get (desc);
2204 tmp = build_fold_indirect_ref_loc (input_location,
2205 tmp);
2206 tmp = gfc_build_array_ref (tmp, *poffset, NULL);
2207 tmp = gfc_build_addr_expr (NULL_TREE, tmp);
2208 init = gfc_build_addr_expr (NULL_TREE, init);
2210 size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type));
2211 bound = build_int_cst (size_type_node, n * size);
2212 tmp = build_call_expr_loc (input_location,
2213 builtin_decl_explicit (BUILT_IN_MEMCPY),
2214 3, tmp, init, bound);
2215 gfc_add_expr_to_block (&body, tmp);
2217 *poffset = fold_build2_loc (input_location, PLUS_EXPR,
2218 gfc_array_index_type, *poffset,
2219 build_int_cst (gfc_array_index_type, n));
2221 if (!INTEGER_CST_P (*poffset))
2223 gfc_add_modify (&body, *offsetvar, *poffset);
2224 *poffset = *offsetvar;
2227 if (!c->iterator)
2228 ts = c->expr->ts;
2231 /* The frontend should already have done any expansions
2232 at compile-time. */
2233 if (!c->iterator)
2235 /* Pass the code as is. */
2236 tmp = gfc_finish_block (&body);
2237 gfc_add_expr_to_block (pblock, tmp);
2239 else
2241 /* Build the implied do-loop. */
2242 stmtblock_t implied_do_block;
2243 tree cond;
2244 tree exit_label;
2245 tree loopbody;
2246 tree tmp2;
2248 loopbody = gfc_finish_block (&body);
2250 /* Create a new block that holds the implied-do loop. A temporary
2251 loop-variable is used. */
2252 gfc_start_block(&implied_do_block);
2254 /* Initialize the loop. */
2255 gfc_add_modify (&implied_do_block, shadow_loopvar, start);
2257 /* If this array expands dynamically, and the number of iterations
2258 is not constant, we won't have allocated space for the static
2259 part of C->EXPR's size. Do that now. */
2260 if (dynamic && gfc_iterator_has_dynamic_bounds (c->iterator))
2262 /* Get the number of iterations. */
2263 tmp = gfc_get_iteration_count (shadow_loopvar, end, step);
2265 /* Get the static part of C->EXPR's size. */
2266 gfc_get_array_constructor_element_size (&size, c->expr);
2267 tmp2 = gfc_conv_mpz_to_tree (size, gfc_index_integer_kind);
2269 /* Grow the array by TMP * TMP2 elements. */
2270 tmp = fold_build2_loc (input_location, MULT_EXPR,
2271 gfc_array_index_type, tmp, tmp2);
2272 gfc_grow_array (&implied_do_block, desc, tmp);
2275 /* Generate the loop body. */
2276 exit_label = gfc_build_label_decl (NULL_TREE);
2277 gfc_start_block (&body);
2279 /* Generate the exit condition. Depending on the sign of
2280 the step variable we have to generate the correct
2281 comparison. */
2282 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
2283 step, build_int_cst (TREE_TYPE (step), 0));
2284 cond = fold_build3_loc (input_location, COND_EXPR,
2285 logical_type_node, tmp,
2286 fold_build2_loc (input_location, GT_EXPR,
2287 logical_type_node, shadow_loopvar, end),
2288 fold_build2_loc (input_location, LT_EXPR,
2289 logical_type_node, shadow_loopvar, end));
2290 tmp = build1_v (GOTO_EXPR, exit_label);
2291 TREE_USED (exit_label) = 1;
2292 tmp = build3_v (COND_EXPR, cond, tmp,
2293 build_empty_stmt (input_location));
2294 gfc_add_expr_to_block (&body, tmp);
2296 /* The main loop body. */
2297 gfc_add_expr_to_block (&body, loopbody);
2299 /* Increase loop variable by step. */
2300 tmp = fold_build2_loc (input_location, PLUS_EXPR,
2301 TREE_TYPE (shadow_loopvar), shadow_loopvar,
2302 step);
2303 gfc_add_modify (&body, shadow_loopvar, tmp);
2305 /* Finish the loop. */
2306 tmp = gfc_finish_block (&body);
2307 tmp = build1_v (LOOP_EXPR, tmp);
2308 gfc_add_expr_to_block (&implied_do_block, tmp);
2310 /* Add the exit label. */
2311 tmp = build1_v (LABEL_EXPR, exit_label);
2312 gfc_add_expr_to_block (&implied_do_block, tmp);
2314 /* Finish the implied-do loop. */
2315 tmp = gfc_finish_block(&implied_do_block);
2316 gfc_add_expr_to_block(pblock, tmp);
2318 gfc_restore_sym (c->iterator->var->symtree->n.sym, &saved_loopvar);
2322 /* F2008 4.5.6.3 para 5: If an executable construct references a structure
2323 constructor or array constructor, the entity created by the constructor is
2324 finalized after execution of the innermost executable construct containing
2325 the reference. This, in fact, was later deleted by the Combined Techical
2326 Corrigenda 1 TO 4 for fortran 2008 (f08/0011).
2328 Transmit finalization of this constructor through 'finalblock'. */
2329 if ((gfc_option.allow_std & (GFC_STD_F2008 | GFC_STD_F2003))
2330 && !(gfc_option.allow_std & GFC_STD_GNU)
2331 && finalblock != NULL
2332 && gfc_may_be_finalized (ts)
2333 && ctr > 0 && desc != NULL_TREE
2334 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
2336 symbol_attribute attr;
2337 gfc_se fse;
2338 gfc_warning (0, "The structure constructor at %C has been"
2339 " finalized. This feature was removed by f08/0011."
2340 " Use -std=f2018 or -std=gnu to eliminate the"
2341 " finalization.");
2342 attr.pointer = attr.allocatable = 0;
2343 gfc_init_se (&fse, NULL);
2344 fse.expr = desc;
2345 gfc_finalize_tree_expr (&fse, ts.u.derived, attr, 1);
2346 gfc_add_block_to_block (finalblock, &fse.pre);
2347 gfc_add_block_to_block (finalblock, &fse.finalblock);
2348 gfc_add_block_to_block (finalblock, &fse.post);
2351 mpz_clear (size);
2355 /* The array constructor code can create a string length with an operand
2356 in the form of a temporary variable. This variable will retain its
2357 context (current_function_decl). If we store this length tree in a
2358 gfc_charlen structure which is shared by a variable in another
2359 context, the resulting gfc_charlen structure with a variable in a
2360 different context, we could trip the assertion in expand_expr_real_1
2361 when it sees that a variable has been created in one context and
2362 referenced in another.
2364 If this might be the case, we create a new gfc_charlen structure and
2365 link it into the current namespace. */
2367 static void
2368 store_backend_decl (gfc_charlen **clp, tree len, bool force_new_cl)
2370 if (force_new_cl)
2372 gfc_charlen *new_cl = gfc_new_charlen (gfc_current_ns, *clp);
2373 *clp = new_cl;
2375 (*clp)->backend_decl = len;
2378 /* A catch-all to obtain the string length for anything that is not
2379 a substring of non-constant length, a constant, array or variable. */
2381 static void
2382 get_array_ctor_all_strlen (stmtblock_t *block, gfc_expr *e, tree *len)
2384 gfc_se se;
2386 /* Don't bother if we already know the length is a constant. */
2387 if (*len && INTEGER_CST_P (*len))
2388 return;
2390 if (!e->ref && e->ts.u.cl && e->ts.u.cl->length
2391 && e->ts.u.cl->length->expr_type == EXPR_CONSTANT)
2393 /* This is easy. */
2394 gfc_conv_const_charlen (e->ts.u.cl);
2395 *len = e->ts.u.cl->backend_decl;
2397 else
2399 /* Otherwise, be brutal even if inefficient. */
2400 gfc_init_se (&se, NULL);
2402 /* No function call, in case of side effects. */
2403 se.no_function_call = 1;
2404 if (e->rank == 0)
2405 gfc_conv_expr (&se, e);
2406 else
2407 gfc_conv_expr_descriptor (&se, e);
2409 /* Fix the value. */
2410 *len = gfc_evaluate_now (se.string_length, &se.pre);
2412 gfc_add_block_to_block (block, &se.pre);
2413 gfc_add_block_to_block (block, &se.post);
2415 store_backend_decl (&e->ts.u.cl, *len, true);
2420 /* Figure out the string length of a variable reference expression.
2421 Used by get_array_ctor_strlen. */
2423 static void
2424 get_array_ctor_var_strlen (stmtblock_t *block, gfc_expr * expr, tree * len)
2426 gfc_ref *ref;
2427 gfc_typespec *ts;
2428 mpz_t char_len;
2429 gfc_se se;
2431 /* Don't bother if we already know the length is a constant. */
2432 if (*len && INTEGER_CST_P (*len))
2433 return;
2435 ts = &expr->symtree->n.sym->ts;
2436 for (ref = expr->ref; ref; ref = ref->next)
2438 switch (ref->type)
2440 case REF_ARRAY:
2441 /* Array references don't change the string length. */
2442 if (ts->deferred)
2443 get_array_ctor_all_strlen (block, expr, len);
2444 break;
2446 case REF_COMPONENT:
2447 /* Use the length of the component. */
2448 ts = &ref->u.c.component->ts;
2449 break;
2451 case REF_SUBSTRING:
2452 if (ref->u.ss.end == NULL
2453 || ref->u.ss.start->expr_type != EXPR_CONSTANT
2454 || ref->u.ss.end->expr_type != EXPR_CONSTANT)
2456 /* Note that this might evaluate expr. */
2457 get_array_ctor_all_strlen (block, expr, len);
2458 return;
2460 mpz_init_set_ui (char_len, 1);
2461 mpz_add (char_len, char_len, ref->u.ss.end->value.integer);
2462 mpz_sub (char_len, char_len, ref->u.ss.start->value.integer);
2463 *len = gfc_conv_mpz_to_tree_type (char_len, gfc_charlen_type_node);
2464 mpz_clear (char_len);
2465 return;
2467 case REF_INQUIRY:
2468 break;
2470 default:
2471 gcc_unreachable ();
2475 /* A last ditch attempt that is sometimes needed for deferred characters. */
2476 if (!ts->u.cl->backend_decl)
2478 gfc_init_se (&se, NULL);
2479 if (expr->rank)
2480 gfc_conv_expr_descriptor (&se, expr);
2481 else
2482 gfc_conv_expr (&se, expr);
2483 gcc_assert (se.string_length != NULL_TREE);
2484 gfc_add_block_to_block (block, &se.pre);
2485 ts->u.cl->backend_decl = se.string_length;
2488 *len = ts->u.cl->backend_decl;
2492 /* Figure out the string length of a character array constructor.
2493 If len is NULL, don't calculate the length; this happens for recursive calls
2494 when a sub-array-constructor is an element but not at the first position,
2495 so when we're not interested in the length.
2496 Returns TRUE if all elements are character constants. */
2498 bool
2499 get_array_ctor_strlen (stmtblock_t *block, gfc_constructor_base base, tree * len)
2501 gfc_constructor *c;
2502 bool is_const;
2504 is_const = true;
2506 if (gfc_constructor_first (base) == NULL)
2508 if (len)
2509 *len = build_int_cstu (gfc_charlen_type_node, 0);
2510 return is_const;
2513 /* Loop over all constructor elements to find out is_const, but in len we
2514 want to store the length of the first, not the last, element. We can
2515 of course exit the loop as soon as is_const is found to be false. */
2516 for (c = gfc_constructor_first (base);
2517 c && is_const; c = gfc_constructor_next (c))
2519 switch (c->expr->expr_type)
2521 case EXPR_CONSTANT:
2522 if (len && !(*len && INTEGER_CST_P (*len)))
2523 *len = build_int_cstu (gfc_charlen_type_node,
2524 c->expr->value.character.length);
2525 break;
2527 case EXPR_ARRAY:
2528 if (!get_array_ctor_strlen (block, c->expr->value.constructor, len))
2529 is_const = false;
2530 break;
2532 case EXPR_VARIABLE:
2533 is_const = false;
2534 if (len)
2535 get_array_ctor_var_strlen (block, c->expr, len);
2536 break;
2538 default:
2539 is_const = false;
2540 if (len)
2541 get_array_ctor_all_strlen (block, c->expr, len);
2542 break;
2545 /* After the first iteration, we don't want the length modified. */
2546 len = NULL;
2549 return is_const;
2552 /* Check whether the array constructor C consists entirely of constant
2553 elements, and if so returns the number of those elements, otherwise
2554 return zero. Note, an empty or NULL array constructor returns zero. */
2556 unsigned HOST_WIDE_INT
2557 gfc_constant_array_constructor_p (gfc_constructor_base base)
2559 unsigned HOST_WIDE_INT nelem = 0;
2561 gfc_constructor *c = gfc_constructor_first (base);
2562 while (c)
2564 if (c->iterator
2565 || c->expr->rank > 0
2566 || c->expr->expr_type != EXPR_CONSTANT)
2567 return 0;
2568 c = gfc_constructor_next (c);
2569 nelem++;
2571 return nelem;
2575 /* Given EXPR, the constant array constructor specified by an EXPR_ARRAY,
2576 and the tree type of it's elements, TYPE, return a static constant
2577 variable that is compile-time initialized. */
2579 tree
2580 gfc_build_constant_array_constructor (gfc_expr * expr, tree type)
2582 tree tmptype, init, tmp;
2583 HOST_WIDE_INT nelem;
2584 gfc_constructor *c;
2585 gfc_array_spec as;
2586 gfc_se se;
2587 int i;
2588 vec<constructor_elt, va_gc> *v = NULL;
2590 /* First traverse the constructor list, converting the constants
2591 to tree to build an initializer. */
2592 nelem = 0;
2593 c = gfc_constructor_first (expr->value.constructor);
2594 while (c)
2596 gfc_init_se (&se, NULL);
2597 gfc_conv_constant (&se, c->expr);
2598 if (c->expr->ts.type != BT_CHARACTER)
2599 se.expr = fold_convert (type, se.expr);
2600 else if (POINTER_TYPE_P (type))
2601 se.expr = gfc_build_addr_expr (gfc_get_pchar_type (c->expr->ts.kind),
2602 se.expr);
2603 CONSTRUCTOR_APPEND_ELT (v, build_int_cst (gfc_array_index_type, nelem),
2604 se.expr);
2605 c = gfc_constructor_next (c);
2606 nelem++;
2609 /* Next determine the tree type for the array. We use the gfortran
2610 front-end's gfc_get_nodesc_array_type in order to create a suitable
2611 GFC_ARRAY_TYPE_P that may be used by the scalarizer. */
2613 memset (&as, 0, sizeof (gfc_array_spec));
2615 as.rank = expr->rank;
2616 as.type = AS_EXPLICIT;
2617 if (!expr->shape)
2619 as.lower[0] = gfc_get_int_expr (gfc_default_integer_kind, NULL, 0);
2620 as.upper[0] = gfc_get_int_expr (gfc_default_integer_kind,
2621 NULL, nelem - 1);
2623 else
2624 for (i = 0; i < expr->rank; i++)
2626 int tmp = (int) mpz_get_si (expr->shape[i]);
2627 as.lower[i] = gfc_get_int_expr (gfc_default_integer_kind, NULL, 0);
2628 as.upper[i] = gfc_get_int_expr (gfc_default_integer_kind,
2629 NULL, tmp - 1);
2632 tmptype = gfc_get_nodesc_array_type (type, &as, PACKED_STATIC, true);
2634 /* as is not needed anymore. */
2635 for (i = 0; i < as.rank + as.corank; i++)
2637 gfc_free_expr (as.lower[i]);
2638 gfc_free_expr (as.upper[i]);
2641 init = build_constructor (tmptype, v);
2643 TREE_CONSTANT (init) = 1;
2644 TREE_STATIC (init) = 1;
2646 tmp = build_decl (input_location, VAR_DECL, create_tmp_var_name ("A"),
2647 tmptype);
2648 DECL_ARTIFICIAL (tmp) = 1;
2649 DECL_IGNORED_P (tmp) = 1;
2650 TREE_STATIC (tmp) = 1;
2651 TREE_CONSTANT (tmp) = 1;
2652 TREE_READONLY (tmp) = 1;
2653 DECL_INITIAL (tmp) = init;
2654 pushdecl (tmp);
2656 return tmp;
2660 /* Translate a constant EXPR_ARRAY array constructor for the scalarizer.
2661 This mostly initializes the scalarizer state info structure with the
2662 appropriate values to directly use the array created by the function
2663 gfc_build_constant_array_constructor. */
2665 static void
2666 trans_constant_array_constructor (gfc_ss * ss, tree type)
2668 gfc_array_info *info;
2669 tree tmp;
2670 int i;
2672 tmp = gfc_build_constant_array_constructor (ss->info->expr, type);
2674 info = &ss->info->data.array;
2676 info->descriptor = tmp;
2677 info->data = gfc_build_addr_expr (NULL_TREE, tmp);
2678 info->offset = gfc_index_zero_node;
2680 for (i = 0; i < ss->dimen; i++)
2682 info->delta[i] = gfc_index_zero_node;
2683 info->start[i] = gfc_index_zero_node;
2684 info->end[i] = gfc_index_zero_node;
2685 info->stride[i] = gfc_index_one_node;
2690 static int
2691 get_rank (gfc_loopinfo *loop)
2693 int rank;
2695 rank = 0;
2696 for (; loop; loop = loop->parent)
2697 rank += loop->dimen;
2699 return rank;
2703 /* Helper routine of gfc_trans_array_constructor to determine if the
2704 bounds of the loop specified by LOOP are constant and simple enough
2705 to use with trans_constant_array_constructor. Returns the
2706 iteration count of the loop if suitable, and NULL_TREE otherwise. */
2708 static tree
2709 constant_array_constructor_loop_size (gfc_loopinfo * l)
2711 gfc_loopinfo *loop;
2712 tree size = gfc_index_one_node;
2713 tree tmp;
2714 int i, total_dim;
2716 total_dim = get_rank (l);
2718 for (loop = l; loop; loop = loop->parent)
2720 for (i = 0; i < loop->dimen; i++)
2722 /* If the bounds aren't constant, return NULL_TREE. */
2723 if (!INTEGER_CST_P (loop->from[i]) || !INTEGER_CST_P (loop->to[i]))
2724 return NULL_TREE;
2725 if (!integer_zerop (loop->from[i]))
2727 /* Only allow nonzero "from" in one-dimensional arrays. */
2728 if (total_dim != 1)
2729 return NULL_TREE;
2730 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2731 gfc_array_index_type,
2732 loop->to[i], loop->from[i]);
2734 else
2735 tmp = loop->to[i];
2736 tmp = fold_build2_loc (input_location, PLUS_EXPR,
2737 gfc_array_index_type, tmp, gfc_index_one_node);
2738 size = fold_build2_loc (input_location, MULT_EXPR,
2739 gfc_array_index_type, size, tmp);
2743 return size;
2747 static tree *
2748 get_loop_upper_bound_for_array (gfc_ss *array, int array_dim)
2750 gfc_ss *ss;
2751 int n;
2753 gcc_assert (array->nested_ss == NULL);
2755 for (ss = array; ss; ss = ss->parent)
2756 for (n = 0; n < ss->loop->dimen; n++)
2757 if (array_dim == get_array_ref_dim_for_loop_dim (ss, n))
2758 return &(ss->loop->to[n]);
2760 gcc_unreachable ();
2764 static gfc_loopinfo *
2765 outermost_loop (gfc_loopinfo * loop)
2767 while (loop->parent != NULL)
2768 loop = loop->parent;
2770 return loop;
2774 /* Array constructors are handled by constructing a temporary, then using that
2775 within the scalarization loop. This is not optimal, but seems by far the
2776 simplest method. */
2778 static void
2779 trans_array_constructor (gfc_ss * ss, locus * where)
2781 gfc_constructor_base c;
2782 tree offset;
2783 tree offsetvar;
2784 tree desc;
2785 tree type;
2786 tree tmp;
2787 tree *loop_ubound0;
2788 bool dynamic;
2789 bool old_first_len, old_typespec_chararray_ctor;
2790 tree old_first_len_val;
2791 gfc_loopinfo *loop, *outer_loop;
2792 gfc_ss_info *ss_info;
2793 gfc_expr *expr;
2794 gfc_ss *s;
2795 tree neg_len;
2796 char *msg;
2797 stmtblock_t finalblock;
2799 /* Save the old values for nested checking. */
2800 old_first_len = first_len;
2801 old_first_len_val = first_len_val;
2802 old_typespec_chararray_ctor = typespec_chararray_ctor;
2804 loop = ss->loop;
2805 outer_loop = outermost_loop (loop);
2806 ss_info = ss->info;
2807 expr = ss_info->expr;
2809 /* Do bounds-checking here and in gfc_trans_array_ctor_element only if no
2810 typespec was given for the array constructor. */
2811 typespec_chararray_ctor = (expr->ts.type == BT_CHARACTER
2812 && expr->ts.u.cl
2813 && expr->ts.u.cl->length_from_typespec);
2815 if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2816 && expr->ts.type == BT_CHARACTER && !typespec_chararray_ctor)
2818 first_len_val = gfc_create_var (gfc_charlen_type_node, "len");
2819 first_len = true;
2822 gcc_assert (ss->dimen == ss->loop->dimen);
2824 c = expr->value.constructor;
2825 if (expr->ts.type == BT_CHARACTER)
2827 bool const_string;
2828 bool force_new_cl = false;
2830 /* get_array_ctor_strlen walks the elements of the constructor, if a
2831 typespec was given, we already know the string length and want the one
2832 specified there. */
2833 if (typespec_chararray_ctor && expr->ts.u.cl->length
2834 && expr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
2836 gfc_se length_se;
2838 const_string = false;
2839 gfc_init_se (&length_se, NULL);
2840 gfc_conv_expr_type (&length_se, expr->ts.u.cl->length,
2841 gfc_charlen_type_node);
2842 ss_info->string_length = length_se.expr;
2844 /* Check if the character length is negative. If it is, then
2845 set LEN = 0. */
2846 neg_len = fold_build2_loc (input_location, LT_EXPR,
2847 logical_type_node, ss_info->string_length,
2848 build_zero_cst (TREE_TYPE
2849 (ss_info->string_length)));
2850 /* Print a warning if bounds checking is enabled. */
2851 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2853 msg = xasprintf ("Negative character length treated as LEN = 0");
2854 gfc_trans_runtime_check (false, true, neg_len, &length_se.pre,
2855 where, msg);
2856 free (msg);
2859 ss_info->string_length
2860 = fold_build3_loc (input_location, COND_EXPR,
2861 gfc_charlen_type_node, neg_len,
2862 build_zero_cst
2863 (TREE_TYPE (ss_info->string_length)),
2864 ss_info->string_length);
2865 ss_info->string_length = gfc_evaluate_now (ss_info->string_length,
2866 &length_se.pre);
2867 gfc_add_block_to_block (&outer_loop->pre, &length_se.pre);
2868 gfc_add_block_to_block (&outer_loop->post, &length_se.post);
2870 else
2872 const_string = get_array_ctor_strlen (&outer_loop->pre, c,
2873 &ss_info->string_length);
2874 force_new_cl = true;
2876 /* Initialize "len" with string length for bounds checking. */
2877 if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2878 && !typespec_chararray_ctor
2879 && ss_info->string_length)
2881 gfc_se length_se;
2883 gfc_init_se (&length_se, NULL);
2884 gfc_add_modify (&length_se.pre, first_len_val,
2885 fold_convert (TREE_TYPE (first_len_val),
2886 ss_info->string_length));
2887 ss_info->string_length = gfc_evaluate_now (ss_info->string_length,
2888 &length_se.pre);
2889 gfc_add_block_to_block (&outer_loop->pre, &length_se.pre);
2890 gfc_add_block_to_block (&outer_loop->post, &length_se.post);
2894 /* Complex character array constructors should have been taken care of
2895 and not end up here. */
2896 gcc_assert (ss_info->string_length);
2898 store_backend_decl (&expr->ts.u.cl, ss_info->string_length, force_new_cl);
2900 type = gfc_get_character_type_len (expr->ts.kind, ss_info->string_length);
2901 if (const_string)
2902 type = build_pointer_type (type);
2904 else
2905 type = gfc_typenode_for_spec (expr->ts.type == BT_CLASS
2906 ? &CLASS_DATA (expr)->ts : &expr->ts);
2908 /* See if the constructor determines the loop bounds. */
2909 dynamic = false;
2911 loop_ubound0 = get_loop_upper_bound_for_array (ss, 0);
2913 if (expr->shape && get_rank (loop) > 1 && *loop_ubound0 == NULL_TREE)
2915 /* We have a multidimensional parameter. */
2916 for (s = ss; s; s = s->parent)
2918 int n;
2919 for (n = 0; n < s->loop->dimen; n++)
2921 s->loop->from[n] = gfc_index_zero_node;
2922 s->loop->to[n] = gfc_conv_mpz_to_tree (expr->shape[s->dim[n]],
2923 gfc_index_integer_kind);
2924 s->loop->to[n] = fold_build2_loc (input_location, MINUS_EXPR,
2925 gfc_array_index_type,
2926 s->loop->to[n],
2927 gfc_index_one_node);
2932 if (*loop_ubound0 == NULL_TREE)
2934 mpz_t size;
2936 /* We should have a 1-dimensional, zero-based loop. */
2937 gcc_assert (loop->parent == NULL && loop->nested == NULL);
2938 gcc_assert (loop->dimen == 1);
2939 gcc_assert (integer_zerop (loop->from[0]));
2941 /* Split the constructor size into a static part and a dynamic part.
2942 Allocate the static size up-front and record whether the dynamic
2943 size might be nonzero. */
2944 mpz_init (size);
2945 dynamic = gfc_get_array_constructor_size (&size, c);
2946 mpz_sub_ui (size, size, 1);
2947 loop->to[0] = gfc_conv_mpz_to_tree (size, gfc_index_integer_kind);
2948 mpz_clear (size);
2951 /* Special case constant array constructors. */
2952 if (!dynamic)
2954 unsigned HOST_WIDE_INT nelem = gfc_constant_array_constructor_p (c);
2955 if (nelem > 0)
2957 tree size = constant_array_constructor_loop_size (loop);
2958 if (size && compare_tree_int (size, nelem) == 0)
2960 trans_constant_array_constructor (ss, type);
2961 goto finish;
2966 gfc_trans_create_temp_array (&outer_loop->pre, &outer_loop->post, ss, type,
2967 NULL_TREE, dynamic, true, false, where);
2969 desc = ss_info->data.array.descriptor;
2970 offset = gfc_index_zero_node;
2971 offsetvar = gfc_create_var_np (gfc_array_index_type, "offset");
2972 suppress_warning (offsetvar);
2973 TREE_USED (offsetvar) = 0;
2975 gfc_init_block (&finalblock);
2976 gfc_trans_array_constructor_value (&outer_loop->pre,
2977 expr->must_finalize ? &finalblock : NULL,
2978 type, desc, c, &offset, &offsetvar,
2979 dynamic);
2981 /* If the array grows dynamically, the upper bound of the loop variable
2982 is determined by the array's final upper bound. */
2983 if (dynamic)
2985 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2986 gfc_array_index_type,
2987 offsetvar, gfc_index_one_node);
2988 tmp = gfc_evaluate_now (tmp, &outer_loop->pre);
2989 gfc_conv_descriptor_ubound_set (&loop->pre, desc, gfc_rank_cst[0], tmp);
2990 if (*loop_ubound0 && VAR_P (*loop_ubound0))
2991 gfc_add_modify (&outer_loop->pre, *loop_ubound0, tmp);
2992 else
2993 *loop_ubound0 = tmp;
2996 if (TREE_USED (offsetvar))
2997 pushdecl (offsetvar);
2998 else
2999 gcc_assert (INTEGER_CST_P (offset));
3001 #if 0
3002 /* Disable bound checking for now because it's probably broken. */
3003 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
3005 gcc_unreachable ();
3007 #endif
3009 finish:
3010 /* Restore old values of globals. */
3011 first_len = old_first_len;
3012 first_len_val = old_first_len_val;
3013 typespec_chararray_ctor = old_typespec_chararray_ctor;
3015 /* F2008 4.5.6.3 para 5: If an executable construct references a structure
3016 constructor or array constructor, the entity created by the constructor is
3017 finalized after execution of the innermost executable construct containing
3018 the reference. */
3019 if ((expr->ts.type == BT_DERIVED || expr->ts.type == BT_CLASS)
3020 && finalblock.head != NULL_TREE)
3021 gfc_add_block_to_block (&loop->post, &finalblock);
3026 /* INFO describes a GFC_SS_SECTION in loop LOOP, and this function is
3027 called after evaluating all of INFO's vector dimensions. Go through
3028 each such vector dimension and see if we can now fill in any missing
3029 loop bounds. */
3031 static void
3032 set_vector_loop_bounds (gfc_ss * ss)
3034 gfc_loopinfo *loop, *outer_loop;
3035 gfc_array_info *info;
3036 gfc_se se;
3037 tree tmp;
3038 tree desc;
3039 tree zero;
3040 int n;
3041 int dim;
3043 outer_loop = outermost_loop (ss->loop);
3045 info = &ss->info->data.array;
3047 for (; ss; ss = ss->parent)
3049 loop = ss->loop;
3051 for (n = 0; n < loop->dimen; n++)
3053 dim = ss->dim[n];
3054 if (info->ref->u.ar.dimen_type[dim] != DIMEN_VECTOR
3055 || loop->to[n] != NULL)
3056 continue;
3058 /* Loop variable N indexes vector dimension DIM, and we don't
3059 yet know the upper bound of loop variable N. Set it to the
3060 difference between the vector's upper and lower bounds. */
3061 gcc_assert (loop->from[n] == gfc_index_zero_node);
3062 gcc_assert (info->subscript[dim]
3063 && info->subscript[dim]->info->type == GFC_SS_VECTOR);
3065 gfc_init_se (&se, NULL);
3066 desc = info->subscript[dim]->info->data.array.descriptor;
3067 zero = gfc_rank_cst[0];
3068 tmp = fold_build2_loc (input_location, MINUS_EXPR,
3069 gfc_array_index_type,
3070 gfc_conv_descriptor_ubound_get (desc, zero),
3071 gfc_conv_descriptor_lbound_get (desc, zero));
3072 tmp = gfc_evaluate_now (tmp, &outer_loop->pre);
3073 loop->to[n] = tmp;
3079 /* Tells whether a scalar argument to an elemental procedure is saved out
3080 of a scalarization loop as a value or as a reference. */
3082 bool
3083 gfc_scalar_elemental_arg_saved_as_reference (gfc_ss_info * ss_info)
3085 if (ss_info->type != GFC_SS_REFERENCE)
3086 return false;
3088 if (ss_info->data.scalar.needs_temporary)
3089 return false;
3091 /* If the actual argument can be absent (in other words, it can
3092 be a NULL reference), don't try to evaluate it; pass instead
3093 the reference directly. */
3094 if (ss_info->can_be_null_ref)
3095 return true;
3097 /* If the expression is of polymorphic type, it's actual size is not known,
3098 so we avoid copying it anywhere. */
3099 if (ss_info->data.scalar.dummy_arg
3100 && gfc_dummy_arg_get_typespec (*ss_info->data.scalar.dummy_arg).type
3101 == BT_CLASS
3102 && ss_info->expr->ts.type == BT_CLASS)
3103 return true;
3105 /* If the expression is a data reference of aggregate type,
3106 and the data reference is not used on the left hand side,
3107 avoid a copy by saving a reference to the content. */
3108 if (!ss_info->data.scalar.needs_temporary
3109 && (ss_info->expr->ts.type == BT_DERIVED
3110 || ss_info->expr->ts.type == BT_CLASS)
3111 && gfc_expr_is_variable (ss_info->expr))
3112 return true;
3114 /* Otherwise the expression is evaluated to a temporary variable before the
3115 scalarization loop. */
3116 return false;
3120 /* Add the pre and post chains for all the scalar expressions in a SS chain
3121 to loop. This is called after the loop parameters have been calculated,
3122 but before the actual scalarizing loops. */
3124 static void
3125 gfc_add_loop_ss_code (gfc_loopinfo * loop, gfc_ss * ss, bool subscript,
3126 locus * where)
3128 gfc_loopinfo *nested_loop, *outer_loop;
3129 gfc_se se;
3130 gfc_ss_info *ss_info;
3131 gfc_array_info *info;
3132 gfc_expr *expr;
3133 int n;
3135 /* Don't evaluate the arguments for realloc_lhs_loop_for_fcn_call; otherwise,
3136 arguments could get evaluated multiple times. */
3137 if (ss->is_alloc_lhs)
3138 return;
3140 outer_loop = outermost_loop (loop);
3142 /* TODO: This can generate bad code if there are ordering dependencies,
3143 e.g., a callee allocated function and an unknown size constructor. */
3144 gcc_assert (ss != NULL);
3146 for (; ss != gfc_ss_terminator; ss = ss->loop_chain)
3148 gcc_assert (ss);
3150 /* Cross loop arrays are handled from within the most nested loop. */
3151 if (ss->nested_ss != NULL)
3152 continue;
3154 ss_info = ss->info;
3155 expr = ss_info->expr;
3156 info = &ss_info->data.array;
3158 switch (ss_info->type)
3160 case GFC_SS_SCALAR:
3161 /* Scalar expression. Evaluate this now. This includes elemental
3162 dimension indices, but not array section bounds. */
3163 gfc_init_se (&se, NULL);
3164 gfc_conv_expr (&se, expr);
3165 gfc_add_block_to_block (&outer_loop->pre, &se.pre);
3167 if (expr->ts.type != BT_CHARACTER
3168 && !gfc_is_alloc_class_scalar_function (expr))
3170 /* Move the evaluation of scalar expressions outside the
3171 scalarization loop, except for WHERE assignments. */
3172 if (subscript)
3173 se.expr = convert(gfc_array_index_type, se.expr);
3174 if (!ss_info->where)
3175 se.expr = gfc_evaluate_now (se.expr, &outer_loop->pre);
3176 gfc_add_block_to_block (&outer_loop->pre, &se.post);
3178 else
3179 gfc_add_block_to_block (&outer_loop->post, &se.post);
3181 ss_info->data.scalar.value = se.expr;
3182 ss_info->string_length = se.string_length;
3183 break;
3185 case GFC_SS_REFERENCE:
3186 /* Scalar argument to elemental procedure. */
3187 gfc_init_se (&se, NULL);
3188 if (gfc_scalar_elemental_arg_saved_as_reference (ss_info))
3189 gfc_conv_expr_reference (&se, expr);
3190 else
3192 /* Evaluate the argument outside the loop and pass
3193 a reference to the value. */
3194 gfc_conv_expr (&se, expr);
3197 /* Ensure that a pointer to the string is stored. */
3198 if (expr->ts.type == BT_CHARACTER)
3199 gfc_conv_string_parameter (&se);
3201 gfc_add_block_to_block (&outer_loop->pre, &se.pre);
3202 gfc_add_block_to_block (&outer_loop->post, &se.post);
3203 if (gfc_is_class_scalar_expr (expr))
3204 /* This is necessary because the dynamic type will always be
3205 large than the declared type. In consequence, assigning
3206 the value to a temporary could segfault.
3207 OOP-TODO: see if this is generally correct or is the value
3208 has to be written to an allocated temporary, whose address
3209 is passed via ss_info. */
3210 ss_info->data.scalar.value = se.expr;
3211 else
3212 ss_info->data.scalar.value = gfc_evaluate_now (se.expr,
3213 &outer_loop->pre);
3215 ss_info->string_length = se.string_length;
3216 break;
3218 case GFC_SS_SECTION:
3219 /* Add the expressions for scalar and vector subscripts. */
3220 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
3221 if (info->subscript[n])
3222 gfc_add_loop_ss_code (loop, info->subscript[n], true, where);
3224 set_vector_loop_bounds (ss);
3225 break;
3227 case GFC_SS_VECTOR:
3228 /* Get the vector's descriptor and store it in SS. */
3229 gfc_init_se (&se, NULL);
3230 gfc_conv_expr_descriptor (&se, expr);
3231 gfc_add_block_to_block (&outer_loop->pre, &se.pre);
3232 gfc_add_block_to_block (&outer_loop->post, &se.post);
3233 info->descriptor = se.expr;
3234 break;
3236 case GFC_SS_INTRINSIC:
3237 gfc_add_intrinsic_ss_code (loop, ss);
3238 break;
3240 case GFC_SS_FUNCTION:
3241 /* Array function return value. We call the function and save its
3242 result in a temporary for use inside the loop. */
3243 gfc_init_se (&se, NULL);
3244 se.loop = loop;
3245 se.ss = ss;
3246 if (gfc_is_class_array_function (expr))
3247 expr->must_finalize = 1;
3248 gfc_conv_expr (&se, expr);
3249 gfc_add_block_to_block (&outer_loop->pre, &se.pre);
3250 gfc_add_block_to_block (&outer_loop->post, &se.post);
3251 gfc_add_block_to_block (&outer_loop->post, &se.finalblock);
3252 ss_info->string_length = se.string_length;
3253 break;
3255 case GFC_SS_CONSTRUCTOR:
3256 if (expr->ts.type == BT_CHARACTER
3257 && ss_info->string_length == NULL
3258 && expr->ts.u.cl
3259 && expr->ts.u.cl->length
3260 && expr->ts.u.cl->length->expr_type == EXPR_CONSTANT)
3262 gfc_init_se (&se, NULL);
3263 gfc_conv_expr_type (&se, expr->ts.u.cl->length,
3264 gfc_charlen_type_node);
3265 ss_info->string_length = se.expr;
3266 gfc_add_block_to_block (&outer_loop->pre, &se.pre);
3267 gfc_add_block_to_block (&outer_loop->post, &se.post);
3269 trans_array_constructor (ss, where);
3270 break;
3272 case GFC_SS_TEMP:
3273 case GFC_SS_COMPONENT:
3274 /* Do nothing. These are handled elsewhere. */
3275 break;
3277 default:
3278 gcc_unreachable ();
3282 if (!subscript)
3283 for (nested_loop = loop->nested; nested_loop;
3284 nested_loop = nested_loop->next)
3285 gfc_add_loop_ss_code (nested_loop, nested_loop->ss, subscript, where);
3289 /* Translate expressions for the descriptor and data pointer of a SS. */
3290 /*GCC ARRAYS*/
3292 static void
3293 gfc_conv_ss_descriptor (stmtblock_t * block, gfc_ss * ss, int base)
3295 gfc_se se;
3296 gfc_ss_info *ss_info;
3297 gfc_array_info *info;
3298 tree tmp;
3300 ss_info = ss->info;
3301 info = &ss_info->data.array;
3303 /* Get the descriptor for the array to be scalarized. */
3304 gcc_assert (ss_info->expr->expr_type == EXPR_VARIABLE);
3305 gfc_init_se (&se, NULL);
3306 se.descriptor_only = 1;
3307 gfc_conv_expr_lhs (&se, ss_info->expr);
3308 gfc_add_block_to_block (block, &se.pre);
3309 info->descriptor = se.expr;
3310 ss_info->string_length = se.string_length;
3311 ss_info->class_container = se.class_container;
3313 if (base)
3315 if (ss_info->expr->ts.type == BT_CHARACTER && !ss_info->expr->ts.deferred
3316 && ss_info->expr->ts.u.cl->length == NULL)
3318 /* Emit a DECL_EXPR for the variable sized array type in
3319 GFC_TYPE_ARRAY_DATAPTR_TYPE so the gimplification of its type
3320 sizes works correctly. */
3321 tree arraytype = TREE_TYPE (
3322 GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (info->descriptor)));
3323 if (! TYPE_NAME (arraytype))
3324 TYPE_NAME (arraytype) = build_decl (UNKNOWN_LOCATION, TYPE_DECL,
3325 NULL_TREE, arraytype);
3326 gfc_add_expr_to_block (block, build1 (DECL_EXPR, arraytype,
3327 TYPE_NAME (arraytype)));
3329 /* Also the data pointer. */
3330 tmp = gfc_conv_array_data (se.expr);
3331 /* If this is a variable or address or a class array, use it directly.
3332 Otherwise we must evaluate it now to avoid breaking dependency
3333 analysis by pulling the expressions for elemental array indices
3334 inside the loop. */
3335 if (!(DECL_P (tmp)
3336 || (TREE_CODE (tmp) == ADDR_EXPR
3337 && DECL_P (TREE_OPERAND (tmp, 0)))
3338 || (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr))
3339 && TREE_CODE (se.expr) == COMPONENT_REF
3340 && GFC_CLASS_TYPE_P (TREE_TYPE (TREE_OPERAND (se.expr, 0))))))
3341 tmp = gfc_evaluate_now (tmp, block);
3342 info->data = tmp;
3344 tmp = gfc_conv_array_offset (se.expr);
3345 info->offset = gfc_evaluate_now (tmp, block);
3347 /* Make absolutely sure that the saved_offset is indeed saved
3348 so that the variable is still accessible after the loops
3349 are translated. */
3350 info->saved_offset = info->offset;
3355 /* Initialize a gfc_loopinfo structure. */
3357 void
3358 gfc_init_loopinfo (gfc_loopinfo * loop)
3360 int n;
3362 memset (loop, 0, sizeof (gfc_loopinfo));
3363 gfc_init_block (&loop->pre);
3364 gfc_init_block (&loop->post);
3366 /* Initially scalarize in order and default to no loop reversal. */
3367 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
3369 loop->order[n] = n;
3370 loop->reverse[n] = GFC_INHIBIT_REVERSE;
3373 loop->ss = gfc_ss_terminator;
3377 /* Copies the loop variable info to a gfc_se structure. Does not copy the SS
3378 chain. */
3380 void
3381 gfc_copy_loopinfo_to_se (gfc_se * se, gfc_loopinfo * loop)
3383 se->loop = loop;
3387 /* Return an expression for the data pointer of an array. */
3389 tree
3390 gfc_conv_array_data (tree descriptor)
3392 tree type;
3394 type = TREE_TYPE (descriptor);
3395 if (GFC_ARRAY_TYPE_P (type))
3397 if (TREE_CODE (type) == POINTER_TYPE)
3398 return descriptor;
3399 else
3401 /* Descriptorless arrays. */
3402 return gfc_build_addr_expr (NULL_TREE, descriptor);
3405 else
3406 return gfc_conv_descriptor_data_get (descriptor);
3410 /* Return an expression for the base offset of an array. */
3412 tree
3413 gfc_conv_array_offset (tree descriptor)
3415 tree type;
3417 type = TREE_TYPE (descriptor);
3418 if (GFC_ARRAY_TYPE_P (type))
3419 return GFC_TYPE_ARRAY_OFFSET (type);
3420 else
3421 return gfc_conv_descriptor_offset_get (descriptor);
3425 /* Get an expression for the array stride. */
3427 tree
3428 gfc_conv_array_stride (tree descriptor, int dim)
3430 tree tmp;
3431 tree type;
3433 type = TREE_TYPE (descriptor);
3435 /* For descriptorless arrays use the array size. */
3436 tmp = GFC_TYPE_ARRAY_STRIDE (type, dim);
3437 if (tmp != NULL_TREE)
3438 return tmp;
3440 tmp = gfc_conv_descriptor_stride_get (descriptor, gfc_rank_cst[dim]);
3441 return tmp;
3445 /* Like gfc_conv_array_stride, but for the lower bound. */
3447 tree
3448 gfc_conv_array_lbound (tree descriptor, int dim)
3450 tree tmp;
3451 tree type;
3453 type = TREE_TYPE (descriptor);
3455 tmp = GFC_TYPE_ARRAY_LBOUND (type, dim);
3456 if (tmp != NULL_TREE)
3457 return tmp;
3459 tmp = gfc_conv_descriptor_lbound_get (descriptor, gfc_rank_cst[dim]);
3460 return tmp;
3464 /* Like gfc_conv_array_stride, but for the upper bound. */
3466 tree
3467 gfc_conv_array_ubound (tree descriptor, int dim)
3469 tree tmp;
3470 tree type;
3472 type = TREE_TYPE (descriptor);
3474 tmp = GFC_TYPE_ARRAY_UBOUND (type, dim);
3475 if (tmp != NULL_TREE)
3476 return tmp;
3478 /* This should only ever happen when passing an assumed shape array
3479 as an actual parameter. The value will never be used. */
3480 if (GFC_ARRAY_TYPE_P (TREE_TYPE (descriptor)))
3481 return gfc_index_zero_node;
3483 tmp = gfc_conv_descriptor_ubound_get (descriptor, gfc_rank_cst[dim]);
3484 return tmp;
3488 /* Generate code to perform an array index bound check. */
3490 static tree
3491 trans_array_bound_check (gfc_se * se, gfc_ss *ss, tree index, int n,
3492 locus * where, bool check_upper,
3493 const char *compname = NULL)
3495 tree fault;
3496 tree tmp_lo, tmp_up;
3497 tree descriptor;
3498 char *msg;
3499 const char * name = NULL;
3501 if (!(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS))
3502 return index;
3504 descriptor = ss->info->data.array.descriptor;
3506 index = gfc_evaluate_now (index, &se->pre);
3508 /* We find a name for the error message. */
3509 name = ss->info->expr->symtree->n.sym->name;
3510 gcc_assert (name != NULL);
3512 if (VAR_P (descriptor))
3513 name = IDENTIFIER_POINTER (DECL_NAME (descriptor));
3515 /* Use given (array component) name. */
3516 if (compname)
3517 name = compname;
3519 /* If upper bound is present, include both bounds in the error message. */
3520 if (check_upper)
3522 tmp_lo = gfc_conv_array_lbound (descriptor, n);
3523 tmp_up = gfc_conv_array_ubound (descriptor, n);
3525 if (name)
3526 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
3527 "outside of expected range (%%ld:%%ld)", n+1, name);
3528 else
3529 msg = xasprintf ("Index '%%ld' of dimension %d "
3530 "outside of expected range (%%ld:%%ld)", n+1);
3532 fault = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3533 index, tmp_lo);
3534 gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
3535 fold_convert (long_integer_type_node, index),
3536 fold_convert (long_integer_type_node, tmp_lo),
3537 fold_convert (long_integer_type_node, tmp_up));
3538 fault = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3539 index, tmp_up);
3540 gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
3541 fold_convert (long_integer_type_node, index),
3542 fold_convert (long_integer_type_node, tmp_lo),
3543 fold_convert (long_integer_type_node, tmp_up));
3544 free (msg);
3546 else
3548 tmp_lo = gfc_conv_array_lbound (descriptor, n);
3550 if (name)
3551 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
3552 "below lower bound of %%ld", n+1, name);
3553 else
3554 msg = xasprintf ("Index '%%ld' of dimension %d "
3555 "below lower bound of %%ld", n+1);
3557 fault = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3558 index, tmp_lo);
3559 gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
3560 fold_convert (long_integer_type_node, index),
3561 fold_convert (long_integer_type_node, tmp_lo));
3562 free (msg);
3565 return index;
3569 /* Generate code for bounds checking for elemental dimensions. */
3571 static void
3572 array_bound_check_elemental (gfc_se * se, gfc_ss * ss, gfc_expr * expr)
3574 gfc_array_ref *ar;
3575 gfc_ref *ref;
3576 gfc_symbol *sym;
3577 char *var_name = NULL;
3578 size_t len;
3579 int dim;
3581 if (expr->expr_type == EXPR_VARIABLE)
3583 sym = expr->symtree->n.sym;
3584 len = strlen (sym->name) + 1;
3586 for (ref = expr->ref; ref; ref = ref->next)
3587 if (ref->type == REF_COMPONENT)
3588 len += 2 + strlen (ref->u.c.component->name);
3590 var_name = XALLOCAVEC (char, len);
3591 strcpy (var_name, sym->name);
3593 for (ref = expr->ref; ref; ref = ref->next)
3595 /* Append component name. */
3596 if (ref->type == REF_COMPONENT)
3598 strcat (var_name, "%%");
3599 strcat (var_name, ref->u.c.component->name);
3600 continue;
3603 if (ref->type == REF_ARRAY && ref->u.ar.dimen > 0)
3605 ar = &ref->u.ar;
3606 for (dim = 0; dim < ar->dimen; dim++)
3608 if (ar->dimen_type[dim] == DIMEN_ELEMENT)
3610 gfc_se indexse;
3611 gfc_init_se (&indexse, NULL);
3612 gfc_conv_expr_type (&indexse, ar->start[dim],
3613 gfc_array_index_type);
3614 trans_array_bound_check (se, ss, indexse.expr, dim,
3615 &ar->where,
3616 ar->as->type != AS_ASSUMED_SIZE
3617 || dim < ar->dimen - 1,
3618 var_name);
3627 /* Return the offset for an index. Performs bound checking for elemental
3628 dimensions. Single element references are processed separately.
3629 DIM is the array dimension, I is the loop dimension. */
3631 static tree
3632 conv_array_index_offset (gfc_se * se, gfc_ss * ss, int dim, int i,
3633 gfc_array_ref * ar, tree stride)
3635 gfc_array_info *info;
3636 tree index;
3637 tree desc;
3638 tree data;
3640 info = &ss->info->data.array;
3642 /* Get the index into the array for this dimension. */
3643 if (ar)
3645 gcc_assert (ar->type != AR_ELEMENT);
3646 switch (ar->dimen_type[dim])
3648 case DIMEN_THIS_IMAGE:
3649 gcc_unreachable ();
3650 break;
3651 case DIMEN_ELEMENT:
3652 /* Elemental dimension. */
3653 gcc_assert (info->subscript[dim]
3654 && info->subscript[dim]->info->type == GFC_SS_SCALAR);
3655 /* We've already translated this value outside the loop. */
3656 index = info->subscript[dim]->info->data.scalar.value;
3658 index = trans_array_bound_check (se, ss, index, dim, &ar->where,
3659 ar->as->type != AS_ASSUMED_SIZE
3660 || dim < ar->dimen - 1);
3661 break;
3663 case DIMEN_VECTOR:
3664 gcc_assert (info && se->loop);
3665 gcc_assert (info->subscript[dim]
3666 && info->subscript[dim]->info->type == GFC_SS_VECTOR);
3667 desc = info->subscript[dim]->info->data.array.descriptor;
3669 /* Get a zero-based index into the vector. */
3670 index = fold_build2_loc (input_location, MINUS_EXPR,
3671 gfc_array_index_type,
3672 se->loop->loopvar[i], se->loop->from[i]);
3674 /* Multiply the index by the stride. */
3675 index = fold_build2_loc (input_location, MULT_EXPR,
3676 gfc_array_index_type,
3677 index, gfc_conv_array_stride (desc, 0));
3679 /* Read the vector to get an index into info->descriptor. */
3680 data = build_fold_indirect_ref_loc (input_location,
3681 gfc_conv_array_data (desc));
3682 index = gfc_build_array_ref (data, index, NULL);
3683 index = gfc_evaluate_now (index, &se->pre);
3684 index = fold_convert (gfc_array_index_type, index);
3686 /* Do any bounds checking on the final info->descriptor index. */
3687 index = trans_array_bound_check (se, ss, index, dim, &ar->where,
3688 ar->as->type != AS_ASSUMED_SIZE
3689 || dim < ar->dimen - 1);
3690 break;
3692 case DIMEN_RANGE:
3693 /* Scalarized dimension. */
3694 gcc_assert (info && se->loop);
3696 /* Multiply the loop variable by the stride and delta. */
3697 index = se->loop->loopvar[i];
3698 if (!integer_onep (info->stride[dim]))
3699 index = fold_build2_loc (input_location, MULT_EXPR,
3700 gfc_array_index_type, index,
3701 info->stride[dim]);
3702 if (!integer_zerop (info->delta[dim]))
3703 index = fold_build2_loc (input_location, PLUS_EXPR,
3704 gfc_array_index_type, index,
3705 info->delta[dim]);
3706 break;
3708 default:
3709 gcc_unreachable ();
3712 else
3714 /* Temporary array or derived type component. */
3715 gcc_assert (se->loop);
3716 index = se->loop->loopvar[se->loop->order[i]];
3718 /* Pointer functions can have stride[0] different from unity.
3719 Use the stride returned by the function call and stored in
3720 the descriptor for the temporary. */
3721 if (se->ss && se->ss->info->type == GFC_SS_FUNCTION
3722 && se->ss->info->expr
3723 && se->ss->info->expr->symtree
3724 && se->ss->info->expr->symtree->n.sym->result
3725 && se->ss->info->expr->symtree->n.sym->result->attr.pointer)
3726 stride = gfc_conv_descriptor_stride_get (info->descriptor,
3727 gfc_rank_cst[dim]);
3729 if (info->delta[dim] && !integer_zerop (info->delta[dim]))
3730 index = fold_build2_loc (input_location, PLUS_EXPR,
3731 gfc_array_index_type, index, info->delta[dim]);
3734 /* Multiply by the stride. */
3735 if (stride != NULL && !integer_onep (stride))
3736 index = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
3737 index, stride);
3739 return index;
3743 /* Build a scalarized array reference using the vptr 'size'. */
3745 static bool
3746 build_class_array_ref (gfc_se *se, tree base, tree index)
3748 tree size;
3749 tree decl = NULL_TREE;
3750 tree tmp;
3751 gfc_expr *expr = se->ss->info->expr;
3752 gfc_expr *class_expr;
3753 gfc_typespec *ts;
3754 gfc_symbol *sym;
3756 tmp = !VAR_P (base) ? gfc_get_class_from_expr (base) : NULL_TREE;
3758 if (tmp != NULL_TREE)
3759 decl = tmp;
3760 else
3762 /* The base expression does not contain a class component, either
3763 because it is a temporary array or array descriptor. Class
3764 array functions are correctly resolved above. */
3765 if (!expr
3766 || (expr->ts.type != BT_CLASS
3767 && !gfc_is_class_array_ref (expr, NULL)))
3768 return false;
3770 /* Obtain the expression for the class entity or component that is
3771 followed by an array reference, which is not an element, so that
3772 the span of the array can be obtained. */
3773 class_expr = gfc_find_and_cut_at_last_class_ref (expr, false, &ts);
3775 if (!ts)
3776 return false;
3778 sym = (!class_expr && expr) ? expr->symtree->n.sym : NULL;
3779 if (sym && sym->attr.function
3780 && sym == sym->result
3781 && sym->backend_decl == current_function_decl)
3782 /* The temporary is the data field of the class data component
3783 of the current function. */
3784 decl = gfc_get_fake_result_decl (sym, 0);
3785 else if (sym)
3787 if (decl == NULL_TREE)
3788 decl = expr->symtree->n.sym->backend_decl;
3789 /* For class arrays the tree containing the class is stored in
3790 GFC_DECL_SAVED_DESCRIPTOR of the sym's backend_decl.
3791 For all others it's sym's backend_decl directly. */
3792 if (DECL_LANG_SPECIFIC (decl) && GFC_DECL_SAVED_DESCRIPTOR (decl))
3793 decl = GFC_DECL_SAVED_DESCRIPTOR (decl);
3795 else
3796 decl = gfc_get_class_from_gfc_expr (class_expr);
3798 if (POINTER_TYPE_P (TREE_TYPE (decl)))
3799 decl = build_fold_indirect_ref_loc (input_location, decl);
3801 if (!GFC_CLASS_TYPE_P (TREE_TYPE (decl)))
3802 return false;
3805 se->class_vptr = gfc_evaluate_now (gfc_class_vptr_get (decl), &se->pre);
3807 size = gfc_class_vtab_size_get (decl);
3808 /* For unlimited polymorphic entities then _len component needs to be
3809 multiplied with the size. */
3810 size = gfc_resize_class_size_with_len (&se->pre, decl, size);
3811 size = fold_convert (TREE_TYPE (index), size);
3813 /* Return the element in the se expression. */
3814 se->expr = gfc_build_spanned_array_ref (base, index, size);
3815 return true;
3819 /* Indicates that the tree EXPR is a reference to an array that can’t
3820 have any negative stride. */
3822 static bool
3823 non_negative_strides_array_p (tree expr)
3825 if (expr == NULL_TREE)
3826 return false;
3828 tree type = TREE_TYPE (expr);
3829 if (POINTER_TYPE_P (type))
3830 type = TREE_TYPE (type);
3832 if (TYPE_LANG_SPECIFIC (type))
3834 gfc_array_kind array_kind = GFC_TYPE_ARRAY_AKIND (type);
3836 if (array_kind == GFC_ARRAY_ALLOCATABLE
3837 || array_kind == GFC_ARRAY_ASSUMED_SHAPE_CONT)
3838 return true;
3841 /* An array with descriptor can have negative strides.
3842 We try to be conservative and return false by default here
3843 if we don’t recognize a contiguous array instead of
3844 returning false if we can identify a non-contiguous one. */
3845 if (!GFC_ARRAY_TYPE_P (type))
3846 return false;
3848 /* If the array was originally a dummy with a descriptor, strides can be
3849 negative. */
3850 if (DECL_P (expr)
3851 && DECL_LANG_SPECIFIC (expr)
3852 && GFC_DECL_SAVED_DESCRIPTOR (expr)
3853 && GFC_DECL_SAVED_DESCRIPTOR (expr) != expr)
3854 return non_negative_strides_array_p (GFC_DECL_SAVED_DESCRIPTOR (expr));
3856 return true;
3860 /* Build a scalarized reference to an array. */
3862 static void
3863 gfc_conv_scalarized_array_ref (gfc_se * se, gfc_array_ref * ar,
3864 bool tmp_array = false)
3866 gfc_array_info *info;
3867 tree decl = NULL_TREE;
3868 tree index;
3869 tree base;
3870 gfc_ss *ss;
3871 gfc_expr *expr;
3872 int n;
3874 ss = se->ss;
3875 expr = ss->info->expr;
3876 info = &ss->info->data.array;
3877 if (ar)
3878 n = se->loop->order[0];
3879 else
3880 n = 0;
3882 index = conv_array_index_offset (se, ss, ss->dim[n], n, ar, info->stride0);
3883 /* Add the offset for this dimension to the stored offset for all other
3884 dimensions. */
3885 if (info->offset && !integer_zerop (info->offset))
3886 index = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3887 index, info->offset);
3889 base = build_fold_indirect_ref_loc (input_location, info->data);
3891 /* Use the vptr 'size' field to access the element of a class array. */
3892 if (build_class_array_ref (se, base, index))
3893 return;
3895 if (get_CFI_desc (NULL, expr, &decl, ar))
3896 decl = build_fold_indirect_ref_loc (input_location, decl);
3898 /* A pointer array component can be detected from its field decl. Fix
3899 the descriptor, mark the resulting variable decl and pass it to
3900 gfc_build_array_ref. */
3901 if (is_pointer_array (info->descriptor)
3902 || (expr && expr->ts.deferred && info->descriptor
3903 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (info->descriptor))))
3905 if (TREE_CODE (info->descriptor) == COMPONENT_REF)
3906 decl = info->descriptor;
3907 else if (INDIRECT_REF_P (info->descriptor))
3908 decl = TREE_OPERAND (info->descriptor, 0);
3910 if (decl == NULL_TREE)
3911 decl = info->descriptor;
3914 bool non_negative_stride = tmp_array
3915 || non_negative_strides_array_p (info->descriptor);
3916 se->expr = gfc_build_array_ref (base, index, decl,
3917 non_negative_stride);
3921 /* Translate access of temporary array. */
3923 void
3924 gfc_conv_tmp_array_ref (gfc_se * se)
3926 se->string_length = se->ss->info->string_length;
3927 gfc_conv_scalarized_array_ref (se, NULL, true);
3928 gfc_advance_se_ss_chain (se);
3931 /* Add T to the offset pair *OFFSET, *CST_OFFSET. */
3933 static void
3934 add_to_offset (tree *cst_offset, tree *offset, tree t)
3936 if (TREE_CODE (t) == INTEGER_CST)
3937 *cst_offset = int_const_binop (PLUS_EXPR, *cst_offset, t);
3938 else
3940 if (!integer_zerop (*offset))
3941 *offset = fold_build2_loc (input_location, PLUS_EXPR,
3942 gfc_array_index_type, *offset, t);
3943 else
3944 *offset = t;
3949 static tree
3950 build_array_ref (tree desc, tree offset, tree decl, tree vptr)
3952 tree tmp;
3953 tree type;
3954 tree cdesc;
3956 /* For class arrays the class declaration is stored in the saved
3957 descriptor. */
3958 if (INDIRECT_REF_P (desc)
3959 && DECL_LANG_SPECIFIC (TREE_OPERAND (desc, 0))
3960 && GFC_DECL_SAVED_DESCRIPTOR (TREE_OPERAND (desc, 0)))
3961 cdesc = gfc_class_data_get (GFC_DECL_SAVED_DESCRIPTOR (
3962 TREE_OPERAND (desc, 0)));
3963 else
3964 cdesc = desc;
3966 /* Class container types do not always have the GFC_CLASS_TYPE_P
3967 but the canonical type does. */
3968 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (cdesc))
3969 && TREE_CODE (cdesc) == COMPONENT_REF)
3971 type = TREE_TYPE (TREE_OPERAND (cdesc, 0));
3972 if (TYPE_CANONICAL (type)
3973 && GFC_CLASS_TYPE_P (TYPE_CANONICAL (type)))
3974 vptr = gfc_class_vptr_get (TREE_OPERAND (cdesc, 0));
3977 tmp = gfc_conv_array_data (desc);
3978 tmp = build_fold_indirect_ref_loc (input_location, tmp);
3979 tmp = gfc_build_array_ref (tmp, offset, decl,
3980 non_negative_strides_array_p (desc),
3981 vptr);
3982 return tmp;
3986 /* Build an array reference. se->expr already holds the array descriptor.
3987 This should be either a variable, indirect variable reference or component
3988 reference. For arrays which do not have a descriptor, se->expr will be
3989 the data pointer.
3990 a(i, j, k) = base[offset + i * stride[0] + j * stride[1] + k * stride[2]]*/
3992 void
3993 gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_expr *expr,
3994 locus * where)
3996 int n;
3997 tree offset, cst_offset;
3998 tree tmp;
3999 tree stride;
4000 tree decl = NULL_TREE;
4001 gfc_se indexse;
4002 gfc_se tmpse;
4003 gfc_symbol * sym = expr->symtree->n.sym;
4004 char *var_name = NULL;
4006 if (ar->dimen == 0)
4008 gcc_assert (ar->codimen || sym->attr.select_rank_temporary
4009 || (ar->as && ar->as->corank));
4011 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se->expr)))
4012 se->expr = build_fold_indirect_ref (gfc_conv_array_data (se->expr));
4013 else
4015 if (GFC_ARRAY_TYPE_P (TREE_TYPE (se->expr))
4016 && TREE_CODE (TREE_TYPE (se->expr)) == POINTER_TYPE)
4017 se->expr = build_fold_indirect_ref_loc (input_location, se->expr);
4019 /* Use the actual tree type and not the wrapped coarray. */
4020 if (!se->want_pointer)
4021 se->expr = fold_convert (TYPE_MAIN_VARIANT (TREE_TYPE (se->expr)),
4022 se->expr);
4025 return;
4028 /* Handle scalarized references separately. */
4029 if (ar->type != AR_ELEMENT)
4031 gfc_conv_scalarized_array_ref (se, ar);
4032 gfc_advance_se_ss_chain (se);
4033 return;
4036 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
4038 size_t len;
4039 gfc_ref *ref;
4041 len = strlen (sym->name) + 1;
4042 for (ref = expr->ref; ref; ref = ref->next)
4044 if (ref->type == REF_ARRAY && &ref->u.ar == ar)
4045 break;
4046 if (ref->type == REF_COMPONENT)
4047 len += 2 + strlen (ref->u.c.component->name);
4050 var_name = XALLOCAVEC (char, len);
4051 strcpy (var_name, sym->name);
4053 for (ref = expr->ref; ref; ref = ref->next)
4055 if (ref->type == REF_ARRAY && &ref->u.ar == ar)
4056 break;
4057 if (ref->type == REF_COMPONENT)
4059 strcat (var_name, "%%");
4060 strcat (var_name, ref->u.c.component->name);
4065 decl = se->expr;
4066 if (IS_CLASS_ARRAY (sym) && sym->attr.dummy && ar->as->type != AS_DEFERRED)
4067 decl = sym->backend_decl;
4069 cst_offset = offset = gfc_index_zero_node;
4070 add_to_offset (&cst_offset, &offset, gfc_conv_array_offset (decl));
4072 /* Calculate the offsets from all the dimensions. Make sure to associate
4073 the final offset so that we form a chain of loop invariant summands. */
4074 for (n = ar->dimen - 1; n >= 0; n--)
4076 /* Calculate the index for this dimension. */
4077 gfc_init_se (&indexse, se);
4078 gfc_conv_expr_type (&indexse, ar->start[n], gfc_array_index_type);
4079 gfc_add_block_to_block (&se->pre, &indexse.pre);
4081 if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS) && ! expr->no_bounds_check)
4083 /* Check array bounds. */
4084 tree cond;
4085 char *msg;
4087 /* Evaluate the indexse.expr only once. */
4088 indexse.expr = save_expr (indexse.expr);
4090 /* Lower bound. */
4091 tmp = gfc_conv_array_lbound (decl, n);
4092 if (sym->attr.temporary)
4094 gfc_init_se (&tmpse, se);
4095 gfc_conv_expr_type (&tmpse, ar->as->lower[n],
4096 gfc_array_index_type);
4097 gfc_add_block_to_block (&se->pre, &tmpse.pre);
4098 tmp = tmpse.expr;
4101 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
4102 indexse.expr, tmp);
4103 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
4104 "below lower bound of %%ld", n+1, var_name);
4105 gfc_trans_runtime_check (true, false, cond, &se->pre, where, msg,
4106 fold_convert (long_integer_type_node,
4107 indexse.expr),
4108 fold_convert (long_integer_type_node, tmp));
4109 free (msg);
4111 /* Upper bound, but not for the last dimension of assumed-size
4112 arrays. */
4113 if (n < ar->dimen - 1 || ar->as->type != AS_ASSUMED_SIZE)
4115 tmp = gfc_conv_array_ubound (decl, n);
4116 if (sym->attr.temporary)
4118 gfc_init_se (&tmpse, se);
4119 gfc_conv_expr_type (&tmpse, ar->as->upper[n],
4120 gfc_array_index_type);
4121 gfc_add_block_to_block (&se->pre, &tmpse.pre);
4122 tmp = tmpse.expr;
4125 cond = fold_build2_loc (input_location, GT_EXPR,
4126 logical_type_node, indexse.expr, tmp);
4127 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
4128 "above upper bound of %%ld", n+1, var_name);
4129 gfc_trans_runtime_check (true, false, cond, &se->pre, where, msg,
4130 fold_convert (long_integer_type_node,
4131 indexse.expr),
4132 fold_convert (long_integer_type_node, tmp));
4133 free (msg);
4137 /* Multiply the index by the stride. */
4138 stride = gfc_conv_array_stride (decl, n);
4139 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
4140 indexse.expr, stride);
4142 /* And add it to the total. */
4143 add_to_offset (&cst_offset, &offset, tmp);
4146 if (!integer_zerop (cst_offset))
4147 offset = fold_build2_loc (input_location, PLUS_EXPR,
4148 gfc_array_index_type, offset, cst_offset);
4150 /* A pointer array component can be detected from its field decl. Fix
4151 the descriptor, mark the resulting variable decl and pass it to
4152 build_array_ref. */
4153 decl = NULL_TREE;
4154 if (get_CFI_desc (sym, expr, &decl, ar))
4155 decl = build_fold_indirect_ref_loc (input_location, decl);
4156 if (!expr->ts.deferred && !sym->attr.codimension
4157 && is_pointer_array (se->expr))
4159 if (TREE_CODE (se->expr) == COMPONENT_REF)
4160 decl = se->expr;
4161 else if (INDIRECT_REF_P (se->expr))
4162 decl = TREE_OPERAND (se->expr, 0);
4163 else
4164 decl = se->expr;
4166 else if (expr->ts.deferred
4167 || (sym->ts.type == BT_CHARACTER
4168 && sym->attr.select_type_temporary))
4170 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se->expr)))
4172 decl = se->expr;
4173 if (INDIRECT_REF_P (decl))
4174 decl = TREE_OPERAND (decl, 0);
4176 else
4177 decl = sym->backend_decl;
4179 else if (sym->ts.type == BT_CLASS)
4181 if (UNLIMITED_POLY (sym))
4183 gfc_expr *class_expr = gfc_find_and_cut_at_last_class_ref (expr);
4184 gfc_init_se (&tmpse, NULL);
4185 gfc_conv_expr (&tmpse, class_expr);
4186 if (!se->class_vptr)
4187 se->class_vptr = gfc_class_vptr_get (tmpse.expr);
4188 gfc_free_expr (class_expr);
4189 decl = tmpse.expr;
4191 else
4192 decl = NULL_TREE;
4195 se->expr = build_array_ref (se->expr, offset, decl, se->class_vptr);
4199 /* Add the offset corresponding to array's ARRAY_DIM dimension and loop's
4200 LOOP_DIM dimension (if any) to array's offset. */
4202 static void
4203 add_array_offset (stmtblock_t *pblock, gfc_loopinfo *loop, gfc_ss *ss,
4204 gfc_array_ref *ar, int array_dim, int loop_dim)
4206 gfc_se se;
4207 gfc_array_info *info;
4208 tree stride, index;
4210 info = &ss->info->data.array;
4212 gfc_init_se (&se, NULL);
4213 se.loop = loop;
4214 se.expr = info->descriptor;
4215 stride = gfc_conv_array_stride (info->descriptor, array_dim);
4216 index = conv_array_index_offset (&se, ss, array_dim, loop_dim, ar, stride);
4217 gfc_add_block_to_block (pblock, &se.pre);
4219 info->offset = fold_build2_loc (input_location, PLUS_EXPR,
4220 gfc_array_index_type,
4221 info->offset, index);
4222 info->offset = gfc_evaluate_now (info->offset, pblock);
4226 /* Generate the code to be executed immediately before entering a
4227 scalarization loop. */
4229 static void
4230 gfc_trans_preloop_setup (gfc_loopinfo * loop, int dim, int flag,
4231 stmtblock_t * pblock)
4233 tree stride;
4234 gfc_ss_info *ss_info;
4235 gfc_array_info *info;
4236 gfc_ss_type ss_type;
4237 gfc_ss *ss, *pss;
4238 gfc_loopinfo *ploop;
4239 gfc_array_ref *ar;
4240 int i;
4242 /* This code will be executed before entering the scalarization loop
4243 for this dimension. */
4244 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
4246 ss_info = ss->info;
4248 if ((ss_info->useflags & flag) == 0)
4249 continue;
4251 ss_type = ss_info->type;
4252 if (ss_type != GFC_SS_SECTION
4253 && ss_type != GFC_SS_FUNCTION
4254 && ss_type != GFC_SS_CONSTRUCTOR
4255 && ss_type != GFC_SS_COMPONENT)
4256 continue;
4258 info = &ss_info->data.array;
4260 gcc_assert (dim < ss->dimen);
4261 gcc_assert (ss->dimen == loop->dimen);
4263 if (info->ref)
4264 ar = &info->ref->u.ar;
4265 else
4266 ar = NULL;
4268 if (dim == loop->dimen - 1 && loop->parent != NULL)
4270 /* If we are in the outermost dimension of this loop, the previous
4271 dimension shall be in the parent loop. */
4272 gcc_assert (ss->parent != NULL);
4274 pss = ss->parent;
4275 ploop = loop->parent;
4277 /* ss and ss->parent are about the same array. */
4278 gcc_assert (ss_info == pss->info);
4280 else
4282 ploop = loop;
4283 pss = ss;
4286 if (dim == loop->dimen - 1)
4287 i = 0;
4288 else
4289 i = dim + 1;
4291 /* For the time being, there is no loop reordering. */
4292 gcc_assert (i == ploop->order[i]);
4293 i = ploop->order[i];
4295 if (dim == loop->dimen - 1 && loop->parent == NULL)
4297 stride = gfc_conv_array_stride (info->descriptor,
4298 innermost_ss (ss)->dim[i]);
4300 /* Calculate the stride of the innermost loop. Hopefully this will
4301 allow the backend optimizers to do their stuff more effectively.
4303 info->stride0 = gfc_evaluate_now (stride, pblock);
4305 /* For the outermost loop calculate the offset due to any
4306 elemental dimensions. It will have been initialized with the
4307 base offset of the array. */
4308 if (info->ref)
4310 for (i = 0; i < ar->dimen; i++)
4312 if (ar->dimen_type[i] != DIMEN_ELEMENT)
4313 continue;
4315 add_array_offset (pblock, loop, ss, ar, i, /* unused */ -1);
4319 else
4320 /* Add the offset for the previous loop dimension. */
4321 add_array_offset (pblock, ploop, ss, ar, pss->dim[i], i);
4323 /* Remember this offset for the second loop. */
4324 if (dim == loop->temp_dim - 1 && loop->parent == NULL)
4325 info->saved_offset = info->offset;
4330 /* Start a scalarized expression. Creates a scope and declares loop
4331 variables. */
4333 void
4334 gfc_start_scalarized_body (gfc_loopinfo * loop, stmtblock_t * pbody)
4336 int dim;
4337 int n;
4338 int flags;
4340 gcc_assert (!loop->array_parameter);
4342 for (dim = loop->dimen - 1; dim >= 0; dim--)
4344 n = loop->order[dim];
4346 gfc_start_block (&loop->code[n]);
4348 /* Create the loop variable. */
4349 loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "S");
4351 if (dim < loop->temp_dim)
4352 flags = 3;
4353 else
4354 flags = 1;
4355 /* Calculate values that will be constant within this loop. */
4356 gfc_trans_preloop_setup (loop, dim, flags, &loop->code[n]);
4358 gfc_start_block (pbody);
4362 /* Generates the actual loop code for a scalarization loop. */
4364 static void
4365 gfc_trans_scalarized_loop_end (gfc_loopinfo * loop, int n,
4366 stmtblock_t * pbody)
4368 stmtblock_t block;
4369 tree cond;
4370 tree tmp;
4371 tree loopbody;
4372 tree exit_label;
4373 tree stmt;
4374 tree init;
4375 tree incr;
4377 if ((ompws_flags & (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_WS
4378 | OMPWS_SCALARIZER_BODY))
4379 == (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_WS)
4380 && n == loop->dimen - 1)
4382 /* We create an OMP_FOR construct for the outermost scalarized loop. */
4383 init = make_tree_vec (1);
4384 cond = make_tree_vec (1);
4385 incr = make_tree_vec (1);
4387 /* Cycle statement is implemented with a goto. Exit statement must not
4388 be present for this loop. */
4389 exit_label = gfc_build_label_decl (NULL_TREE);
4390 TREE_USED (exit_label) = 1;
4392 /* Label for cycle statements (if needed). */
4393 tmp = build1_v (LABEL_EXPR, exit_label);
4394 gfc_add_expr_to_block (pbody, tmp);
4396 stmt = make_node (OMP_FOR);
4398 TREE_TYPE (stmt) = void_type_node;
4399 OMP_FOR_BODY (stmt) = loopbody = gfc_finish_block (pbody);
4401 OMP_FOR_CLAUSES (stmt) = build_omp_clause (input_location,
4402 OMP_CLAUSE_SCHEDULE);
4403 OMP_CLAUSE_SCHEDULE_KIND (OMP_FOR_CLAUSES (stmt))
4404 = OMP_CLAUSE_SCHEDULE_STATIC;
4405 if (ompws_flags & OMPWS_NOWAIT)
4406 OMP_CLAUSE_CHAIN (OMP_FOR_CLAUSES (stmt))
4407 = build_omp_clause (input_location, OMP_CLAUSE_NOWAIT);
4409 /* Initialize the loopvar. */
4410 TREE_VEC_ELT (init, 0) = build2_v (MODIFY_EXPR, loop->loopvar[n],
4411 loop->from[n]);
4412 OMP_FOR_INIT (stmt) = init;
4413 /* The exit condition. */
4414 TREE_VEC_ELT (cond, 0) = build2_loc (input_location, LE_EXPR,
4415 logical_type_node,
4416 loop->loopvar[n], loop->to[n]);
4417 SET_EXPR_LOCATION (TREE_VEC_ELT (cond, 0), input_location);
4418 OMP_FOR_COND (stmt) = cond;
4419 /* Increment the loopvar. */
4420 tmp = build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4421 loop->loopvar[n], gfc_index_one_node);
4422 TREE_VEC_ELT (incr, 0) = fold_build2_loc (input_location, MODIFY_EXPR,
4423 void_type_node, loop->loopvar[n], tmp);
4424 OMP_FOR_INCR (stmt) = incr;
4426 ompws_flags &= ~OMPWS_CURR_SINGLEUNIT;
4427 gfc_add_expr_to_block (&loop->code[n], stmt);
4429 else
4431 bool reverse_loop = (loop->reverse[n] == GFC_REVERSE_SET)
4432 && (loop->temp_ss == NULL);
4434 loopbody = gfc_finish_block (pbody);
4436 if (reverse_loop)
4437 std::swap (loop->from[n], loop->to[n]);
4439 /* Initialize the loopvar. */
4440 if (loop->loopvar[n] != loop->from[n])
4441 gfc_add_modify (&loop->code[n], loop->loopvar[n], loop->from[n]);
4443 exit_label = gfc_build_label_decl (NULL_TREE);
4445 /* Generate the loop body. */
4446 gfc_init_block (&block);
4448 /* The exit condition. */
4449 cond = fold_build2_loc (input_location, reverse_loop ? LT_EXPR : GT_EXPR,
4450 logical_type_node, loop->loopvar[n], loop->to[n]);
4451 tmp = build1_v (GOTO_EXPR, exit_label);
4452 TREE_USED (exit_label) = 1;
4453 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
4454 gfc_add_expr_to_block (&block, tmp);
4456 /* The main body. */
4457 gfc_add_expr_to_block (&block, loopbody);
4459 /* Increment the loopvar. */
4460 tmp = fold_build2_loc (input_location,
4461 reverse_loop ? MINUS_EXPR : PLUS_EXPR,
4462 gfc_array_index_type, loop->loopvar[n],
4463 gfc_index_one_node);
4465 gfc_add_modify (&block, loop->loopvar[n], tmp);
4467 /* Build the loop. */
4468 tmp = gfc_finish_block (&block);
4469 tmp = build1_v (LOOP_EXPR, tmp);
4470 gfc_add_expr_to_block (&loop->code[n], tmp);
4472 /* Add the exit label. */
4473 tmp = build1_v (LABEL_EXPR, exit_label);
4474 gfc_add_expr_to_block (&loop->code[n], tmp);
4480 /* Finishes and generates the loops for a scalarized expression. */
4482 void
4483 gfc_trans_scalarizing_loops (gfc_loopinfo * loop, stmtblock_t * body)
4485 int dim;
4486 int n;
4487 gfc_ss *ss;
4488 stmtblock_t *pblock;
4489 tree tmp;
4491 pblock = body;
4492 /* Generate the loops. */
4493 for (dim = 0; dim < loop->dimen; dim++)
4495 n = loop->order[dim];
4496 gfc_trans_scalarized_loop_end (loop, n, pblock);
4497 loop->loopvar[n] = NULL_TREE;
4498 pblock = &loop->code[n];
4501 tmp = gfc_finish_block (pblock);
4502 gfc_add_expr_to_block (&loop->pre, tmp);
4504 /* Clear all the used flags. */
4505 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
4506 if (ss->parent == NULL)
4507 ss->info->useflags = 0;
4511 /* Finish the main body of a scalarized expression, and start the secondary
4512 copying body. */
4514 void
4515 gfc_trans_scalarized_loop_boundary (gfc_loopinfo * loop, stmtblock_t * body)
4517 int dim;
4518 int n;
4519 stmtblock_t *pblock;
4520 gfc_ss *ss;
4522 pblock = body;
4523 /* We finish as many loops as are used by the temporary. */
4524 for (dim = 0; dim < loop->temp_dim - 1; dim++)
4526 n = loop->order[dim];
4527 gfc_trans_scalarized_loop_end (loop, n, pblock);
4528 loop->loopvar[n] = NULL_TREE;
4529 pblock = &loop->code[n];
4532 /* We don't want to finish the outermost loop entirely. */
4533 n = loop->order[loop->temp_dim - 1];
4534 gfc_trans_scalarized_loop_end (loop, n, pblock);
4536 /* Restore the initial offsets. */
4537 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
4539 gfc_ss_type ss_type;
4540 gfc_ss_info *ss_info;
4542 ss_info = ss->info;
4544 if ((ss_info->useflags & 2) == 0)
4545 continue;
4547 ss_type = ss_info->type;
4548 if (ss_type != GFC_SS_SECTION
4549 && ss_type != GFC_SS_FUNCTION
4550 && ss_type != GFC_SS_CONSTRUCTOR
4551 && ss_type != GFC_SS_COMPONENT)
4552 continue;
4554 ss_info->data.array.offset = ss_info->data.array.saved_offset;
4557 /* Restart all the inner loops we just finished. */
4558 for (dim = loop->temp_dim - 2; dim >= 0; dim--)
4560 n = loop->order[dim];
4562 gfc_start_block (&loop->code[n]);
4564 loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "Q");
4566 gfc_trans_preloop_setup (loop, dim, 2, &loop->code[n]);
4569 /* Start a block for the secondary copying code. */
4570 gfc_start_block (body);
4574 /* Precalculate (either lower or upper) bound of an array section.
4575 BLOCK: Block in which the (pre)calculation code will go.
4576 BOUNDS[DIM]: Where the bound value will be stored once evaluated.
4577 VALUES[DIM]: Specified bound (NULL <=> unspecified).
4578 DESC: Array descriptor from which the bound will be picked if unspecified
4579 (either lower or upper bound according to LBOUND). */
4581 static void
4582 evaluate_bound (stmtblock_t *block, tree *bounds, gfc_expr ** values,
4583 tree desc, int dim, bool lbound, bool deferred)
4585 gfc_se se;
4586 gfc_expr * input_val = values[dim];
4587 tree *output = &bounds[dim];
4590 if (input_val)
4592 /* Specified section bound. */
4593 gfc_init_se (&se, NULL);
4594 gfc_conv_expr_type (&se, input_val, gfc_array_index_type);
4595 gfc_add_block_to_block (block, &se.pre);
4596 *output = se.expr;
4598 else if (deferred && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
4600 /* The gfc_conv_array_lbound () routine returns a constant zero for
4601 deferred length arrays, which in the scalarizer wreaks havoc, when
4602 copying to a (newly allocated) one-based array.
4603 Keep returning the actual result in sync for both bounds. */
4604 *output = lbound ? gfc_conv_descriptor_lbound_get (desc,
4605 gfc_rank_cst[dim]):
4606 gfc_conv_descriptor_ubound_get (desc,
4607 gfc_rank_cst[dim]);
4609 else
4611 /* No specific bound specified so use the bound of the array. */
4612 *output = lbound ? gfc_conv_array_lbound (desc, dim) :
4613 gfc_conv_array_ubound (desc, dim);
4615 *output = gfc_evaluate_now (*output, block);
4619 /* Calculate the lower bound of an array section. */
4621 static void
4622 gfc_conv_section_startstride (stmtblock_t * block, gfc_ss * ss, int dim)
4624 gfc_expr *stride = NULL;
4625 tree desc;
4626 gfc_se se;
4627 gfc_array_info *info;
4628 gfc_array_ref *ar;
4630 gcc_assert (ss->info->type == GFC_SS_SECTION);
4632 info = &ss->info->data.array;
4633 ar = &info->ref->u.ar;
4635 if (ar->dimen_type[dim] == DIMEN_VECTOR)
4637 /* We use a zero-based index to access the vector. */
4638 info->start[dim] = gfc_index_zero_node;
4639 info->end[dim] = NULL;
4640 info->stride[dim] = gfc_index_one_node;
4641 return;
4644 gcc_assert (ar->dimen_type[dim] == DIMEN_RANGE
4645 || ar->dimen_type[dim] == DIMEN_THIS_IMAGE);
4646 desc = info->descriptor;
4647 stride = ar->stride[dim];
4650 /* Calculate the start of the range. For vector subscripts this will
4651 be the range of the vector. */
4652 evaluate_bound (block, info->start, ar->start, desc, dim, true,
4653 ar->as->type == AS_DEFERRED);
4655 /* Similarly calculate the end. Although this is not used in the
4656 scalarizer, it is needed when checking bounds and where the end
4657 is an expression with side-effects. */
4658 evaluate_bound (block, info->end, ar->end, desc, dim, false,
4659 ar->as->type == AS_DEFERRED);
4662 /* Calculate the stride. */
4663 if (stride == NULL)
4664 info->stride[dim] = gfc_index_one_node;
4665 else
4667 gfc_init_se (&se, NULL);
4668 gfc_conv_expr_type (&se, stride, gfc_array_index_type);
4669 gfc_add_block_to_block (block, &se.pre);
4670 info->stride[dim] = gfc_evaluate_now (se.expr, block);
4675 /* Calculates the range start and stride for a SS chain. Also gets the
4676 descriptor and data pointer. The range of vector subscripts is the size
4677 of the vector. Array bounds are also checked. */
4679 void
4680 gfc_conv_ss_startstride (gfc_loopinfo * loop)
4682 int n;
4683 tree tmp;
4684 gfc_ss *ss;
4685 tree desc;
4687 gfc_loopinfo * const outer_loop = outermost_loop (loop);
4689 loop->dimen = 0;
4690 /* Determine the rank of the loop. */
4691 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
4693 switch (ss->info->type)
4695 case GFC_SS_SECTION:
4696 case GFC_SS_CONSTRUCTOR:
4697 case GFC_SS_FUNCTION:
4698 case GFC_SS_COMPONENT:
4699 loop->dimen = ss->dimen;
4700 goto done;
4702 /* As usual, lbound and ubound are exceptions!. */
4703 case GFC_SS_INTRINSIC:
4704 switch (ss->info->expr->value.function.isym->id)
4706 case GFC_ISYM_LBOUND:
4707 case GFC_ISYM_UBOUND:
4708 case GFC_ISYM_LCOBOUND:
4709 case GFC_ISYM_UCOBOUND:
4710 case GFC_ISYM_SHAPE:
4711 case GFC_ISYM_THIS_IMAGE:
4712 loop->dimen = ss->dimen;
4713 goto done;
4715 default:
4716 break;
4719 default:
4720 break;
4724 /* We should have determined the rank of the expression by now. If
4725 not, that's bad news. */
4726 gcc_unreachable ();
4728 done:
4729 /* Loop over all the SS in the chain. */
4730 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
4732 gfc_ss_info *ss_info;
4733 gfc_array_info *info;
4734 gfc_expr *expr;
4736 ss_info = ss->info;
4737 expr = ss_info->expr;
4738 info = &ss_info->data.array;
4740 if (expr && expr->shape && !info->shape)
4741 info->shape = expr->shape;
4743 switch (ss_info->type)
4745 case GFC_SS_SECTION:
4746 /* Get the descriptor for the array. If it is a cross loops array,
4747 we got the descriptor already in the outermost loop. */
4748 if (ss->parent == NULL)
4749 gfc_conv_ss_descriptor (&outer_loop->pre, ss,
4750 !loop->array_parameter);
4752 for (n = 0; n < ss->dimen; n++)
4753 gfc_conv_section_startstride (&outer_loop->pre, ss, ss->dim[n]);
4754 break;
4756 case GFC_SS_INTRINSIC:
4757 switch (expr->value.function.isym->id)
4759 /* Fall through to supply start and stride. */
4760 case GFC_ISYM_LBOUND:
4761 case GFC_ISYM_UBOUND:
4762 /* This is the variant without DIM=... */
4763 gcc_assert (expr->value.function.actual->next->expr == NULL);
4764 /* Fall through. */
4766 case GFC_ISYM_SHAPE:
4768 gfc_expr *arg;
4770 arg = expr->value.function.actual->expr;
4771 if (arg->rank == -1)
4773 gfc_se se;
4774 tree rank, tmp;
4776 /* The rank (hence the return value's shape) is unknown,
4777 we have to retrieve it. */
4778 gfc_init_se (&se, NULL);
4779 se.descriptor_only = 1;
4780 gfc_conv_expr (&se, arg);
4781 /* This is a bare variable, so there is no preliminary
4782 or cleanup code. */
4783 gcc_assert (se.pre.head == NULL_TREE
4784 && se.post.head == NULL_TREE);
4785 rank = gfc_conv_descriptor_rank (se.expr);
4786 tmp = fold_build2_loc (input_location, MINUS_EXPR,
4787 gfc_array_index_type,
4788 fold_convert (gfc_array_index_type,
4789 rank),
4790 gfc_index_one_node);
4791 info->end[0] = gfc_evaluate_now (tmp, &outer_loop->pre);
4792 info->start[0] = gfc_index_zero_node;
4793 info->stride[0] = gfc_index_one_node;
4794 continue;
4796 /* Otherwise fall through GFC_SS_FUNCTION. */
4797 gcc_fallthrough ();
4799 case GFC_ISYM_LCOBOUND:
4800 case GFC_ISYM_UCOBOUND:
4801 case GFC_ISYM_THIS_IMAGE:
4802 break;
4804 default:
4805 continue;
4808 /* FALLTHRU */
4809 case GFC_SS_CONSTRUCTOR:
4810 case GFC_SS_FUNCTION:
4811 for (n = 0; n < ss->dimen; n++)
4813 int dim = ss->dim[n];
4815 info->start[dim] = gfc_index_zero_node;
4816 info->end[dim] = gfc_index_zero_node;
4817 info->stride[dim] = gfc_index_one_node;
4819 break;
4821 default:
4822 break;
4826 /* The rest is just runtime bounds checking. */
4827 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
4829 stmtblock_t block;
4830 tree lbound, ubound;
4831 tree end;
4832 tree size[GFC_MAX_DIMENSIONS];
4833 tree stride_pos, stride_neg, non_zerosized, tmp2, tmp3;
4834 gfc_array_info *info;
4835 char *msg;
4836 int dim;
4838 gfc_start_block (&block);
4840 for (n = 0; n < loop->dimen; n++)
4841 size[n] = NULL_TREE;
4843 /* If there is a constructor involved, derive size[] from its shape. */
4844 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
4846 gfc_ss_info *ss_info;
4848 ss_info = ss->info;
4849 info = &ss_info->data.array;
4851 if (ss_info->type == GFC_SS_CONSTRUCTOR && info->shape)
4853 for (n = 0; n < loop->dimen; n++)
4855 if (size[n] == NULL)
4857 gcc_assert (info->shape[n]);
4858 size[n] = gfc_conv_mpz_to_tree (info->shape[n],
4859 gfc_index_integer_kind);
4862 break;
4866 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
4868 stmtblock_t inner;
4869 gfc_ss_info *ss_info;
4870 gfc_expr *expr;
4871 locus *expr_loc;
4872 const char *expr_name;
4874 ss_info = ss->info;
4875 if (ss_info->type != GFC_SS_SECTION)
4876 continue;
4878 /* Catch allocatable lhs in f2003. */
4879 if (flag_realloc_lhs && ss->no_bounds_check)
4880 continue;
4882 expr = ss_info->expr;
4883 expr_loc = &expr->where;
4884 expr_name = expr->symtree->name;
4886 gfc_start_block (&inner);
4888 /* TODO: range checking for mapped dimensions. */
4889 info = &ss_info->data.array;
4891 /* This code only checks ranges. Elemental and vector
4892 dimensions are checked later. */
4893 for (n = 0; n < loop->dimen; n++)
4895 bool check_upper;
4897 dim = ss->dim[n];
4898 if (info->ref->u.ar.dimen_type[dim] != DIMEN_RANGE)
4899 continue;
4901 if (dim == info->ref->u.ar.dimen - 1
4902 && info->ref->u.ar.as->type == AS_ASSUMED_SIZE)
4903 check_upper = false;
4904 else
4905 check_upper = true;
4907 /* Zero stride is not allowed. */
4908 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
4909 info->stride[dim], gfc_index_zero_node);
4910 msg = xasprintf ("Zero stride is not allowed, for dimension %d "
4911 "of array '%s'", dim + 1, expr_name);
4912 gfc_trans_runtime_check (true, false, tmp, &inner,
4913 expr_loc, msg);
4914 free (msg);
4916 desc = info->descriptor;
4918 /* This is the run-time equivalent of resolve.cc's
4919 check_dimension(). The logical is more readable there
4920 than it is here, with all the trees. */
4921 lbound = gfc_conv_array_lbound (desc, dim);
4922 end = info->end[dim];
4923 if (check_upper)
4924 ubound = gfc_conv_array_ubound (desc, dim);
4925 else
4926 ubound = NULL;
4928 /* non_zerosized is true when the selected range is not
4929 empty. */
4930 stride_pos = fold_build2_loc (input_location, GT_EXPR,
4931 logical_type_node, info->stride[dim],
4932 gfc_index_zero_node);
4933 tmp = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
4934 info->start[dim], end);
4935 stride_pos = fold_build2_loc (input_location, TRUTH_AND_EXPR,
4936 logical_type_node, stride_pos, tmp);
4938 stride_neg = fold_build2_loc (input_location, LT_EXPR,
4939 logical_type_node,
4940 info->stride[dim], gfc_index_zero_node);
4941 tmp = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
4942 info->start[dim], end);
4943 stride_neg = fold_build2_loc (input_location, TRUTH_AND_EXPR,
4944 logical_type_node,
4945 stride_neg, tmp);
4946 non_zerosized = fold_build2_loc (input_location, TRUTH_OR_EXPR,
4947 logical_type_node,
4948 stride_pos, stride_neg);
4950 /* Check the start of the range against the lower and upper
4951 bounds of the array, if the range is not empty.
4952 If upper bound is present, include both bounds in the
4953 error message. */
4954 if (check_upper)
4956 tmp = fold_build2_loc (input_location, LT_EXPR,
4957 logical_type_node,
4958 info->start[dim], lbound);
4959 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
4960 logical_type_node,
4961 non_zerosized, tmp);
4962 tmp2 = fold_build2_loc (input_location, GT_EXPR,
4963 logical_type_node,
4964 info->start[dim], ubound);
4965 tmp2 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
4966 logical_type_node,
4967 non_zerosized, tmp2);
4968 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
4969 "outside of expected range (%%ld:%%ld)",
4970 dim + 1, expr_name);
4971 gfc_trans_runtime_check (true, false, tmp, &inner,
4972 expr_loc, msg,
4973 fold_convert (long_integer_type_node, info->start[dim]),
4974 fold_convert (long_integer_type_node, lbound),
4975 fold_convert (long_integer_type_node, ubound));
4976 gfc_trans_runtime_check (true, false, tmp2, &inner,
4977 expr_loc, msg,
4978 fold_convert (long_integer_type_node, info->start[dim]),
4979 fold_convert (long_integer_type_node, lbound),
4980 fold_convert (long_integer_type_node, ubound));
4981 free (msg);
4983 else
4985 tmp = fold_build2_loc (input_location, LT_EXPR,
4986 logical_type_node,
4987 info->start[dim], lbound);
4988 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
4989 logical_type_node, non_zerosized, tmp);
4990 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
4991 "below lower bound of %%ld",
4992 dim + 1, expr_name);
4993 gfc_trans_runtime_check (true, false, tmp, &inner,
4994 expr_loc, msg,
4995 fold_convert (long_integer_type_node, info->start[dim]),
4996 fold_convert (long_integer_type_node, lbound));
4997 free (msg);
5000 /* Compute the last element of the range, which is not
5001 necessarily "end" (think 0:5:3, which doesn't contain 5)
5002 and check it against both lower and upper bounds. */
5004 tmp = fold_build2_loc (input_location, MINUS_EXPR,
5005 gfc_array_index_type, end,
5006 info->start[dim]);
5007 tmp = fold_build2_loc (input_location, TRUNC_MOD_EXPR,
5008 gfc_array_index_type, tmp,
5009 info->stride[dim]);
5010 tmp = fold_build2_loc (input_location, MINUS_EXPR,
5011 gfc_array_index_type, end, tmp);
5012 tmp2 = fold_build2_loc (input_location, LT_EXPR,
5013 logical_type_node, tmp, lbound);
5014 tmp2 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
5015 logical_type_node, non_zerosized, tmp2);
5016 if (check_upper)
5018 tmp3 = fold_build2_loc (input_location, GT_EXPR,
5019 logical_type_node, tmp, ubound);
5020 tmp3 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
5021 logical_type_node, non_zerosized, tmp3);
5022 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
5023 "outside of expected range (%%ld:%%ld)",
5024 dim + 1, expr_name);
5025 gfc_trans_runtime_check (true, false, tmp2, &inner,
5026 expr_loc, msg,
5027 fold_convert (long_integer_type_node, tmp),
5028 fold_convert (long_integer_type_node, ubound),
5029 fold_convert (long_integer_type_node, lbound));
5030 gfc_trans_runtime_check (true, false, tmp3, &inner,
5031 expr_loc, msg,
5032 fold_convert (long_integer_type_node, tmp),
5033 fold_convert (long_integer_type_node, ubound),
5034 fold_convert (long_integer_type_node, lbound));
5035 free (msg);
5037 else
5039 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
5040 "below lower bound of %%ld",
5041 dim + 1, expr_name);
5042 gfc_trans_runtime_check (true, false, tmp2, &inner,
5043 expr_loc, msg,
5044 fold_convert (long_integer_type_node, tmp),
5045 fold_convert (long_integer_type_node, lbound));
5046 free (msg);
5049 /* Check the section sizes match. */
5050 tmp = fold_build2_loc (input_location, MINUS_EXPR,
5051 gfc_array_index_type, end,
5052 info->start[dim]);
5053 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR,
5054 gfc_array_index_type, tmp,
5055 info->stride[dim]);
5056 tmp = fold_build2_loc (input_location, PLUS_EXPR,
5057 gfc_array_index_type,
5058 gfc_index_one_node, tmp);
5059 tmp = fold_build2_loc (input_location, MAX_EXPR,
5060 gfc_array_index_type, tmp,
5061 build_int_cst (gfc_array_index_type, 0));
5062 /* We remember the size of the first section, and check all the
5063 others against this. */
5064 if (size[n])
5066 tmp3 = fold_build2_loc (input_location, NE_EXPR,
5067 logical_type_node, tmp, size[n]);
5068 msg = xasprintf ("Array bound mismatch for dimension %d "
5069 "of array '%s' (%%ld/%%ld)",
5070 dim + 1, expr_name);
5072 gfc_trans_runtime_check (true, false, tmp3, &inner,
5073 expr_loc, msg,
5074 fold_convert (long_integer_type_node, tmp),
5075 fold_convert (long_integer_type_node, size[n]));
5077 free (msg);
5079 else
5080 size[n] = gfc_evaluate_now (tmp, &inner);
5083 tmp = gfc_finish_block (&inner);
5085 /* For optional arguments, only check bounds if the argument is
5086 present. */
5087 if ((expr->symtree->n.sym->attr.optional
5088 || expr->symtree->n.sym->attr.not_always_present)
5089 && expr->symtree->n.sym->attr.dummy)
5090 tmp = build3_v (COND_EXPR,
5091 gfc_conv_expr_present (expr->symtree->n.sym),
5092 tmp, build_empty_stmt (input_location));
5094 gfc_add_expr_to_block (&block, tmp);
5098 tmp = gfc_finish_block (&block);
5099 gfc_add_expr_to_block (&outer_loop->pre, tmp);
5102 for (loop = loop->nested; loop; loop = loop->next)
5103 gfc_conv_ss_startstride (loop);
5106 /* Return true if both symbols could refer to the same data object. Does
5107 not take account of aliasing due to equivalence statements. */
5109 static bool
5110 symbols_could_alias (gfc_symbol *lsym, gfc_symbol *rsym, bool lsym_pointer,
5111 bool lsym_target, bool rsym_pointer, bool rsym_target)
5113 /* Aliasing isn't possible if the symbols have different base types. */
5114 if (gfc_compare_types (&lsym->ts, &rsym->ts) == 0)
5115 return 0;
5117 /* Pointers can point to other pointers and target objects. */
5119 if ((lsym_pointer && (rsym_pointer || rsym_target))
5120 || (rsym_pointer && (lsym_pointer || lsym_target)))
5121 return 1;
5123 /* Special case: Argument association, cf. F90 12.4.1.6, F2003 12.4.1.7
5124 and F2008 12.5.2.13 items 3b and 4b. The pointer case (a) is already
5125 checked above. */
5126 if (lsym_target && rsym_target
5127 && ((lsym->attr.dummy && !lsym->attr.contiguous
5128 && (!lsym->attr.dimension || lsym->as->type == AS_ASSUMED_SHAPE))
5129 || (rsym->attr.dummy && !rsym->attr.contiguous
5130 && (!rsym->attr.dimension
5131 || rsym->as->type == AS_ASSUMED_SHAPE))))
5132 return 1;
5134 return 0;
5138 /* Return true if the two SS could be aliased, i.e. both point to the same data
5139 object. */
5140 /* TODO: resolve aliases based on frontend expressions. */
5142 static int
5143 gfc_could_be_alias (gfc_ss * lss, gfc_ss * rss)
5145 gfc_ref *lref;
5146 gfc_ref *rref;
5147 gfc_expr *lexpr, *rexpr;
5148 gfc_symbol *lsym;
5149 gfc_symbol *rsym;
5150 bool lsym_pointer, lsym_target, rsym_pointer, rsym_target;
5152 lexpr = lss->info->expr;
5153 rexpr = rss->info->expr;
5155 lsym = lexpr->symtree->n.sym;
5156 rsym = rexpr->symtree->n.sym;
5158 lsym_pointer = lsym->attr.pointer;
5159 lsym_target = lsym->attr.target;
5160 rsym_pointer = rsym->attr.pointer;
5161 rsym_target = rsym->attr.target;
5163 if (symbols_could_alias (lsym, rsym, lsym_pointer, lsym_target,
5164 rsym_pointer, rsym_target))
5165 return 1;
5167 if (rsym->ts.type != BT_DERIVED && rsym->ts.type != BT_CLASS
5168 && lsym->ts.type != BT_DERIVED && lsym->ts.type != BT_CLASS)
5169 return 0;
5171 /* For derived types we must check all the component types. We can ignore
5172 array references as these will have the same base type as the previous
5173 component ref. */
5174 for (lref = lexpr->ref; lref != lss->info->data.array.ref; lref = lref->next)
5176 if (lref->type != REF_COMPONENT)
5177 continue;
5179 lsym_pointer = lsym_pointer || lref->u.c.sym->attr.pointer;
5180 lsym_target = lsym_target || lref->u.c.sym->attr.target;
5182 if (symbols_could_alias (lref->u.c.sym, rsym, lsym_pointer, lsym_target,
5183 rsym_pointer, rsym_target))
5184 return 1;
5186 if ((lsym_pointer && (rsym_pointer || rsym_target))
5187 || (rsym_pointer && (lsym_pointer || lsym_target)))
5189 if (gfc_compare_types (&lref->u.c.component->ts,
5190 &rsym->ts))
5191 return 1;
5194 for (rref = rexpr->ref; rref != rss->info->data.array.ref;
5195 rref = rref->next)
5197 if (rref->type != REF_COMPONENT)
5198 continue;
5200 rsym_pointer = rsym_pointer || rref->u.c.sym->attr.pointer;
5201 rsym_target = lsym_target || rref->u.c.sym->attr.target;
5203 if (symbols_could_alias (lref->u.c.sym, rref->u.c.sym,
5204 lsym_pointer, lsym_target,
5205 rsym_pointer, rsym_target))
5206 return 1;
5208 if ((lsym_pointer && (rsym_pointer || rsym_target))
5209 || (rsym_pointer && (lsym_pointer || lsym_target)))
5211 if (gfc_compare_types (&lref->u.c.component->ts,
5212 &rref->u.c.sym->ts))
5213 return 1;
5214 if (gfc_compare_types (&lref->u.c.sym->ts,
5215 &rref->u.c.component->ts))
5216 return 1;
5217 if (gfc_compare_types (&lref->u.c.component->ts,
5218 &rref->u.c.component->ts))
5219 return 1;
5224 lsym_pointer = lsym->attr.pointer;
5225 lsym_target = lsym->attr.target;
5227 for (rref = rexpr->ref; rref != rss->info->data.array.ref; rref = rref->next)
5229 if (rref->type != REF_COMPONENT)
5230 break;
5232 rsym_pointer = rsym_pointer || rref->u.c.sym->attr.pointer;
5233 rsym_target = lsym_target || rref->u.c.sym->attr.target;
5235 if (symbols_could_alias (rref->u.c.sym, lsym,
5236 lsym_pointer, lsym_target,
5237 rsym_pointer, rsym_target))
5238 return 1;
5240 if ((lsym_pointer && (rsym_pointer || rsym_target))
5241 || (rsym_pointer && (lsym_pointer || lsym_target)))
5243 if (gfc_compare_types (&lsym->ts, &rref->u.c.component->ts))
5244 return 1;
5248 return 0;
5252 /* Resolve array data dependencies. Creates a temporary if required. */
5253 /* TODO: Calc dependencies with gfc_expr rather than gfc_ss, and move to
5254 dependency.cc. */
5256 void
5257 gfc_conv_resolve_dependencies (gfc_loopinfo * loop, gfc_ss * dest,
5258 gfc_ss * rss)
5260 gfc_ss *ss;
5261 gfc_ref *lref;
5262 gfc_ref *rref;
5263 gfc_ss_info *ss_info;
5264 gfc_expr *dest_expr;
5265 gfc_expr *ss_expr;
5266 int nDepend = 0;
5267 int i, j;
5269 loop->temp_ss = NULL;
5270 dest_expr = dest->info->expr;
5272 for (ss = rss; ss != gfc_ss_terminator; ss = ss->next)
5274 ss_info = ss->info;
5275 ss_expr = ss_info->expr;
5277 if (ss_info->array_outer_dependency)
5279 nDepend = 1;
5280 break;
5283 if (ss_info->type != GFC_SS_SECTION)
5285 if (flag_realloc_lhs
5286 && dest_expr != ss_expr
5287 && gfc_is_reallocatable_lhs (dest_expr)
5288 && ss_expr->rank)
5289 nDepend = gfc_check_dependency (dest_expr, ss_expr, true);
5291 /* Check for cases like c(:)(1:2) = c(2)(2:3) */
5292 if (!nDepend && dest_expr->rank > 0
5293 && dest_expr->ts.type == BT_CHARACTER
5294 && ss_expr->expr_type == EXPR_VARIABLE)
5296 nDepend = gfc_check_dependency (dest_expr, ss_expr, false);
5298 if (ss_info->type == GFC_SS_REFERENCE
5299 && gfc_check_dependency (dest_expr, ss_expr, false))
5300 ss_info->data.scalar.needs_temporary = 1;
5302 if (nDepend)
5303 break;
5304 else
5305 continue;
5308 if (dest_expr->symtree->n.sym != ss_expr->symtree->n.sym)
5310 if (gfc_could_be_alias (dest, ss)
5311 || gfc_are_equivalenced_arrays (dest_expr, ss_expr))
5313 nDepend = 1;
5314 break;
5317 else
5319 lref = dest_expr->ref;
5320 rref = ss_expr->ref;
5322 nDepend = gfc_dep_resolver (lref, rref, &loop->reverse[0]);
5324 if (nDepend == 1)
5325 break;
5327 for (i = 0; i < dest->dimen; i++)
5328 for (j = 0; j < ss->dimen; j++)
5329 if (i != j
5330 && dest->dim[i] == ss->dim[j])
5332 /* If we don't access array elements in the same order,
5333 there is a dependency. */
5334 nDepend = 1;
5335 goto temporary;
5337 #if 0
5338 /* TODO : loop shifting. */
5339 if (nDepend == 1)
5341 /* Mark the dimensions for LOOP SHIFTING */
5342 for (n = 0; n < loop->dimen; n++)
5344 int dim = dest->data.info.dim[n];
5346 if (lref->u.ar.dimen_type[dim] == DIMEN_VECTOR)
5347 depends[n] = 2;
5348 else if (! gfc_is_same_range (&lref->u.ar,
5349 &rref->u.ar, dim, 0))
5350 depends[n] = 1;
5353 /* Put all the dimensions with dependencies in the
5354 innermost loops. */
5355 dim = 0;
5356 for (n = 0; n < loop->dimen; n++)
5358 gcc_assert (loop->order[n] == n);
5359 if (depends[n])
5360 loop->order[dim++] = n;
5362 for (n = 0; n < loop->dimen; n++)
5364 if (! depends[n])
5365 loop->order[dim++] = n;
5368 gcc_assert (dim == loop->dimen);
5369 break;
5371 #endif
5375 temporary:
5377 if (nDepend == 1)
5379 tree base_type = gfc_typenode_for_spec (&dest_expr->ts);
5380 if (GFC_ARRAY_TYPE_P (base_type)
5381 || GFC_DESCRIPTOR_TYPE_P (base_type))
5382 base_type = gfc_get_element_type (base_type);
5383 loop->temp_ss = gfc_get_temp_ss (base_type, dest->info->string_length,
5384 loop->dimen);
5385 gfc_add_ss_to_loop (loop, loop->temp_ss);
5387 else
5388 loop->temp_ss = NULL;
5392 /* Browse through each array's information from the scalarizer and set the loop
5393 bounds according to the "best" one (per dimension), i.e. the one which
5394 provides the most information (constant bounds, shape, etc.). */
5396 static void
5397 set_loop_bounds (gfc_loopinfo *loop)
5399 int n, dim, spec_dim;
5400 gfc_array_info *info;
5401 gfc_array_info *specinfo;
5402 gfc_ss *ss;
5403 tree tmp;
5404 gfc_ss **loopspec;
5405 bool dynamic[GFC_MAX_DIMENSIONS];
5406 mpz_t *cshape;
5407 mpz_t i;
5408 bool nonoptional_arr;
5410 gfc_loopinfo * const outer_loop = outermost_loop (loop);
5412 loopspec = loop->specloop;
5414 mpz_init (i);
5415 for (n = 0; n < loop->dimen; n++)
5417 loopspec[n] = NULL;
5418 dynamic[n] = false;
5420 /* If there are both optional and nonoptional array arguments, scalarize
5421 over the nonoptional; otherwise, it does not matter as then all
5422 (optional) arrays have to be present per F2008, 125.2.12p3(6). */
5424 nonoptional_arr = false;
5426 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
5427 if (ss->info->type != GFC_SS_SCALAR && ss->info->type != GFC_SS_TEMP
5428 && ss->info->type != GFC_SS_REFERENCE && !ss->info->can_be_null_ref)
5430 nonoptional_arr = true;
5431 break;
5434 /* We use one SS term, and use that to determine the bounds of the
5435 loop for this dimension. We try to pick the simplest term. */
5436 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
5438 gfc_ss_type ss_type;
5440 ss_type = ss->info->type;
5441 if (ss_type == GFC_SS_SCALAR
5442 || ss_type == GFC_SS_TEMP
5443 || ss_type == GFC_SS_REFERENCE
5444 || (ss->info->can_be_null_ref && nonoptional_arr))
5445 continue;
5447 info = &ss->info->data.array;
5448 dim = ss->dim[n];
5450 if (loopspec[n] != NULL)
5452 specinfo = &loopspec[n]->info->data.array;
5453 spec_dim = loopspec[n]->dim[n];
5455 else
5457 /* Silence uninitialized warnings. */
5458 specinfo = NULL;
5459 spec_dim = 0;
5462 if (info->shape)
5464 /* The frontend has worked out the size for us. */
5465 if (!loopspec[n]
5466 || !specinfo->shape
5467 || !integer_zerop (specinfo->start[spec_dim]))
5468 /* Prefer zero-based descriptors if possible. */
5469 loopspec[n] = ss;
5470 continue;
5473 if (ss_type == GFC_SS_CONSTRUCTOR)
5475 gfc_constructor_base base;
5476 /* An unknown size constructor will always be rank one.
5477 Higher rank constructors will either have known shape,
5478 or still be wrapped in a call to reshape. */
5479 gcc_assert (loop->dimen == 1);
5481 /* Always prefer to use the constructor bounds if the size
5482 can be determined at compile time. Prefer not to otherwise,
5483 since the general case involves realloc, and it's better to
5484 avoid that overhead if possible. */
5485 base = ss->info->expr->value.constructor;
5486 dynamic[n] = gfc_get_array_constructor_size (&i, base);
5487 if (!dynamic[n] || !loopspec[n])
5488 loopspec[n] = ss;
5489 continue;
5492 /* Avoid using an allocatable lhs in an assignment, since
5493 there might be a reallocation coming. */
5494 if (loopspec[n] && ss->is_alloc_lhs)
5495 continue;
5497 if (!loopspec[n])
5498 loopspec[n] = ss;
5499 /* Criteria for choosing a loop specifier (most important first):
5500 doesn't need realloc
5501 stride of one
5502 known stride
5503 known lower bound
5504 known upper bound
5506 else if (loopspec[n]->info->type == GFC_SS_CONSTRUCTOR && dynamic[n])
5507 loopspec[n] = ss;
5508 else if (integer_onep (info->stride[dim])
5509 && !integer_onep (specinfo->stride[spec_dim]))
5510 loopspec[n] = ss;
5511 else if (INTEGER_CST_P (info->stride[dim])
5512 && !INTEGER_CST_P (specinfo->stride[spec_dim]))
5513 loopspec[n] = ss;
5514 else if (INTEGER_CST_P (info->start[dim])
5515 && !INTEGER_CST_P (specinfo->start[spec_dim])
5516 && integer_onep (info->stride[dim])
5517 == integer_onep (specinfo->stride[spec_dim])
5518 && INTEGER_CST_P (info->stride[dim])
5519 == INTEGER_CST_P (specinfo->stride[spec_dim]))
5520 loopspec[n] = ss;
5521 /* We don't work out the upper bound.
5522 else if (INTEGER_CST_P (info->finish[n])
5523 && ! INTEGER_CST_P (specinfo->finish[n]))
5524 loopspec[n] = ss; */
5527 /* We should have found the scalarization loop specifier. If not,
5528 that's bad news. */
5529 gcc_assert (loopspec[n]);
5531 info = &loopspec[n]->info->data.array;
5532 dim = loopspec[n]->dim[n];
5534 /* Set the extents of this range. */
5535 cshape = info->shape;
5536 if (cshape && INTEGER_CST_P (info->start[dim])
5537 && INTEGER_CST_P (info->stride[dim]))
5539 loop->from[n] = info->start[dim];
5540 mpz_set (i, cshape[get_array_ref_dim_for_loop_dim (loopspec[n], n)]);
5541 mpz_sub_ui (i, i, 1);
5542 /* To = from + (size - 1) * stride. */
5543 tmp = gfc_conv_mpz_to_tree (i, gfc_index_integer_kind);
5544 if (!integer_onep (info->stride[dim]))
5545 tmp = fold_build2_loc (input_location, MULT_EXPR,
5546 gfc_array_index_type, tmp,
5547 info->stride[dim]);
5548 loop->to[n] = fold_build2_loc (input_location, PLUS_EXPR,
5549 gfc_array_index_type,
5550 loop->from[n], tmp);
5552 else
5554 loop->from[n] = info->start[dim];
5555 switch (loopspec[n]->info->type)
5557 case GFC_SS_CONSTRUCTOR:
5558 /* The upper bound is calculated when we expand the
5559 constructor. */
5560 gcc_assert (loop->to[n] == NULL_TREE);
5561 break;
5563 case GFC_SS_SECTION:
5564 /* Use the end expression if it exists and is not constant,
5565 so that it is only evaluated once. */
5566 loop->to[n] = info->end[dim];
5567 break;
5569 case GFC_SS_FUNCTION:
5570 /* The loop bound will be set when we generate the call. */
5571 gcc_assert (loop->to[n] == NULL_TREE);
5572 break;
5574 case GFC_SS_INTRINSIC:
5576 gfc_expr *expr = loopspec[n]->info->expr;
5578 /* The {l,u}bound of an assumed rank. */
5579 if (expr->value.function.isym->id == GFC_ISYM_SHAPE)
5580 gcc_assert (expr->value.function.actual->expr->rank == -1);
5581 else
5582 gcc_assert ((expr->value.function.isym->id == GFC_ISYM_LBOUND
5583 || expr->value.function.isym->id == GFC_ISYM_UBOUND)
5584 && expr->value.function.actual->next->expr == NULL
5585 && expr->value.function.actual->expr->rank == -1);
5587 loop->to[n] = info->end[dim];
5588 break;
5591 case GFC_SS_COMPONENT:
5593 if (info->end[dim] != NULL_TREE)
5595 loop->to[n] = info->end[dim];
5596 break;
5598 else
5599 gcc_unreachable ();
5602 default:
5603 gcc_unreachable ();
5607 /* Transform everything so we have a simple incrementing variable. */
5608 if (integer_onep (info->stride[dim]))
5609 info->delta[dim] = gfc_index_zero_node;
5610 else
5612 /* Set the delta for this section. */
5613 info->delta[dim] = gfc_evaluate_now (loop->from[n], &outer_loop->pre);
5614 /* Number of iterations is (end - start + step) / step.
5615 with start = 0, this simplifies to
5616 last = end / step;
5617 for (i = 0; i<=last; i++){...}; */
5618 tmp = fold_build2_loc (input_location, MINUS_EXPR,
5619 gfc_array_index_type, loop->to[n],
5620 loop->from[n]);
5621 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR,
5622 gfc_array_index_type, tmp, info->stride[dim]);
5623 tmp = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
5624 tmp, build_int_cst (gfc_array_index_type, -1));
5625 loop->to[n] = gfc_evaluate_now (tmp, &outer_loop->pre);
5626 /* Make the loop variable start at 0. */
5627 loop->from[n] = gfc_index_zero_node;
5630 mpz_clear (i);
5632 for (loop = loop->nested; loop; loop = loop->next)
5633 set_loop_bounds (loop);
5637 /* Initialize the scalarization loop. Creates the loop variables. Determines
5638 the range of the loop variables. Creates a temporary if required.
5639 Also generates code for scalar expressions which have been
5640 moved outside the loop. */
5642 void
5643 gfc_conv_loop_setup (gfc_loopinfo * loop, locus * where)
5645 gfc_ss *tmp_ss;
5646 tree tmp;
5648 set_loop_bounds (loop);
5650 /* Add all the scalar code that can be taken out of the loops.
5651 This may include calculating the loop bounds, so do it before
5652 allocating the temporary. */
5653 gfc_add_loop_ss_code (loop, loop->ss, false, where);
5655 tmp_ss = loop->temp_ss;
5656 /* If we want a temporary then create it. */
5657 if (tmp_ss != NULL)
5659 gfc_ss_info *tmp_ss_info;
5661 tmp_ss_info = tmp_ss->info;
5662 gcc_assert (tmp_ss_info->type == GFC_SS_TEMP);
5663 gcc_assert (loop->parent == NULL);
5665 /* Make absolutely sure that this is a complete type. */
5666 if (tmp_ss_info->string_length)
5667 tmp_ss_info->data.temp.type
5668 = gfc_get_character_type_len_for_eltype
5669 (TREE_TYPE (tmp_ss_info->data.temp.type),
5670 tmp_ss_info->string_length);
5672 tmp = tmp_ss_info->data.temp.type;
5673 memset (&tmp_ss_info->data.array, 0, sizeof (gfc_array_info));
5674 tmp_ss_info->type = GFC_SS_SECTION;
5676 gcc_assert (tmp_ss->dimen != 0);
5678 gfc_trans_create_temp_array (&loop->pre, &loop->post, tmp_ss, tmp,
5679 NULL_TREE, false, true, false, where);
5682 /* For array parameters we don't have loop variables, so don't calculate the
5683 translations. */
5684 if (!loop->array_parameter)
5685 gfc_set_delta (loop);
5689 /* Calculates how to transform from loop variables to array indices for each
5690 array: once loop bounds are chosen, sets the difference (DELTA field) between
5691 loop bounds and array reference bounds, for each array info. */
5693 void
5694 gfc_set_delta (gfc_loopinfo *loop)
5696 gfc_ss *ss, **loopspec;
5697 gfc_array_info *info;
5698 tree tmp;
5699 int n, dim;
5701 gfc_loopinfo * const outer_loop = outermost_loop (loop);
5703 loopspec = loop->specloop;
5705 /* Calculate the translation from loop variables to array indices. */
5706 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
5708 gfc_ss_type ss_type;
5710 ss_type = ss->info->type;
5711 if (ss_type != GFC_SS_SECTION
5712 && ss_type != GFC_SS_COMPONENT
5713 && ss_type != GFC_SS_CONSTRUCTOR)
5714 continue;
5716 info = &ss->info->data.array;
5718 for (n = 0; n < ss->dimen; n++)
5720 /* If we are specifying the range the delta is already set. */
5721 if (loopspec[n] != ss)
5723 dim = ss->dim[n];
5725 /* Calculate the offset relative to the loop variable.
5726 First multiply by the stride. */
5727 tmp = loop->from[n];
5728 if (!integer_onep (info->stride[dim]))
5729 tmp = fold_build2_loc (input_location, MULT_EXPR,
5730 gfc_array_index_type,
5731 tmp, info->stride[dim]);
5733 /* Then subtract this from our starting value. */
5734 tmp = fold_build2_loc (input_location, MINUS_EXPR,
5735 gfc_array_index_type,
5736 info->start[dim], tmp);
5738 info->delta[dim] = gfc_evaluate_now (tmp, &outer_loop->pre);
5743 for (loop = loop->nested; loop; loop = loop->next)
5744 gfc_set_delta (loop);
5748 /* Calculate the size of a given array dimension from the bounds. This
5749 is simply (ubound - lbound + 1) if this expression is positive
5750 or 0 if it is negative (pick either one if it is zero). Optionally
5751 (if or_expr is present) OR the (expression != 0) condition to it. */
5753 tree
5754 gfc_conv_array_extent_dim (tree lbound, tree ubound, tree* or_expr)
5756 tree res;
5757 tree cond;
5759 /* Calculate (ubound - lbound + 1). */
5760 res = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
5761 ubound, lbound);
5762 res = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type, res,
5763 gfc_index_one_node);
5765 /* Check whether the size for this dimension is negative. */
5766 cond = fold_build2_loc (input_location, LE_EXPR, logical_type_node, res,
5767 gfc_index_zero_node);
5768 res = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type, cond,
5769 gfc_index_zero_node, res);
5771 /* Build OR expression. */
5772 if (or_expr)
5773 *or_expr = fold_build2_loc (input_location, TRUTH_OR_EXPR,
5774 logical_type_node, *or_expr, cond);
5776 return res;
5780 /* For an array descriptor, get the total number of elements. This is just
5781 the product of the extents along from_dim to to_dim. */
5783 static tree
5784 gfc_conv_descriptor_size_1 (tree desc, int from_dim, int to_dim)
5786 tree res;
5787 int dim;
5789 res = gfc_index_one_node;
5791 for (dim = from_dim; dim < to_dim; ++dim)
5793 tree lbound;
5794 tree ubound;
5795 tree extent;
5797 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[dim]);
5798 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[dim]);
5800 extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
5801 res = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
5802 res, extent);
5805 return res;
5809 /* Full size of an array. */
5811 tree
5812 gfc_conv_descriptor_size (tree desc, int rank)
5814 return gfc_conv_descriptor_size_1 (desc, 0, rank);
5818 /* Size of a coarray for all dimensions but the last. */
5820 tree
5821 gfc_conv_descriptor_cosize (tree desc, int rank, int corank)
5823 return gfc_conv_descriptor_size_1 (desc, rank, rank + corank - 1);
5827 /* Fills in an array descriptor, and returns the size of the array.
5828 The size will be a simple_val, ie a variable or a constant. Also
5829 calculates the offset of the base. The pointer argument overflow,
5830 which should be of integer type, will increase in value if overflow
5831 occurs during the size calculation. Returns the size of the array.
5833 stride = 1;
5834 offset = 0;
5835 for (n = 0; n < rank; n++)
5837 a.lbound[n] = specified_lower_bound;
5838 offset = offset + a.lbond[n] * stride;
5839 size = 1 - lbound;
5840 a.ubound[n] = specified_upper_bound;
5841 a.stride[n] = stride;
5842 size = size >= 0 ? ubound + size : 0; //size = ubound + 1 - lbound
5843 overflow += size == 0 ? 0: (MAX/size < stride ? 1: 0);
5844 stride = stride * size;
5846 for (n = rank; n < rank+corank; n++)
5847 (Set lcobound/ucobound as above.)
5848 element_size = sizeof (array element);
5849 if (!rank)
5850 return element_size
5851 stride = (size_t) stride;
5852 overflow += element_size == 0 ? 0: (MAX/element_size < stride ? 1: 0);
5853 stride = stride * element_size;
5854 return (stride);
5855 } */
5856 /*GCC ARRAYS*/
5858 static tree
5859 gfc_array_init_size (tree descriptor, int rank, int corank, tree * poffset,
5860 gfc_expr ** lower, gfc_expr ** upper, stmtblock_t * pblock,
5861 stmtblock_t * descriptor_block, tree * overflow,
5862 tree expr3_elem_size, tree *nelems, gfc_expr *expr3,
5863 tree expr3_desc, bool e3_has_nodescriptor, gfc_expr *expr,
5864 tree *element_size)
5866 tree type;
5867 tree tmp;
5868 tree size;
5869 tree offset;
5870 tree stride;
5871 tree or_expr;
5872 tree thencase;
5873 tree elsecase;
5874 tree cond;
5875 tree var;
5876 stmtblock_t thenblock;
5877 stmtblock_t elseblock;
5878 gfc_expr *ubound;
5879 gfc_se se;
5880 int n;
5882 type = TREE_TYPE (descriptor);
5884 stride = gfc_index_one_node;
5885 offset = gfc_index_zero_node;
5887 /* Set the dtype before the alloc, because registration of coarrays needs
5888 it initialized. */
5889 if (expr->ts.type == BT_CHARACTER
5890 && expr->ts.deferred
5891 && VAR_P (expr->ts.u.cl->backend_decl))
5893 type = gfc_typenode_for_spec (&expr->ts);
5894 tmp = gfc_conv_descriptor_dtype (descriptor);
5895 gfc_add_modify (pblock, tmp, gfc_get_dtype_rank_type (rank, type));
5897 else if (expr->ts.type == BT_CHARACTER
5898 && expr->ts.deferred
5899 && TREE_CODE (descriptor) == COMPONENT_REF)
5901 /* Deferred character components have their string length tucked away
5902 in a hidden field of the derived type. Obtain that and use it to
5903 set the dtype. The charlen backend decl is zero because the field
5904 type is zero length. */
5905 gfc_ref *ref;
5906 tmp = NULL_TREE;
5907 for (ref = expr->ref; ref; ref = ref->next)
5908 if (ref->type == REF_COMPONENT
5909 && gfc_deferred_strlen (ref->u.c.component, &tmp))
5910 break;
5911 gcc_assert (tmp != NULL_TREE);
5912 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (tmp),
5913 TREE_OPERAND (descriptor, 0), tmp, NULL_TREE);
5914 tmp = fold_convert (gfc_charlen_type_node, tmp);
5915 type = gfc_get_character_type_len (expr->ts.kind, tmp);
5916 tmp = gfc_conv_descriptor_dtype (descriptor);
5917 gfc_add_modify (pblock, tmp, gfc_get_dtype_rank_type (rank, type));
5919 else
5921 tmp = gfc_conv_descriptor_dtype (descriptor);
5922 gfc_add_modify (pblock, tmp, gfc_get_dtype (type));
5925 or_expr = logical_false_node;
5927 for (n = 0; n < rank; n++)
5929 tree conv_lbound;
5930 tree conv_ubound;
5932 /* We have 3 possibilities for determining the size of the array:
5933 lower == NULL => lbound = 1, ubound = upper[n]
5934 upper[n] = NULL => lbound = 1, ubound = lower[n]
5935 upper[n] != NULL => lbound = lower[n], ubound = upper[n] */
5936 ubound = upper[n];
5938 /* Set lower bound. */
5939 gfc_init_se (&se, NULL);
5940 if (expr3_desc != NULL_TREE)
5942 if (e3_has_nodescriptor)
5943 /* The lbound of nondescriptor arrays like array constructors,
5944 nonallocatable/nonpointer function results/variables,
5945 start at zero, but when allocating it, the standard expects
5946 the array to start at one. */
5947 se.expr = gfc_index_one_node;
5948 else
5949 se.expr = gfc_conv_descriptor_lbound_get (expr3_desc,
5950 gfc_rank_cst[n]);
5952 else if (lower == NULL)
5953 se.expr = gfc_index_one_node;
5954 else
5956 gcc_assert (lower[n]);
5957 if (ubound)
5959 gfc_conv_expr_type (&se, lower[n], gfc_array_index_type);
5960 gfc_add_block_to_block (pblock, &se.pre);
5962 else
5964 se.expr = gfc_index_one_node;
5965 ubound = lower[n];
5968 gfc_conv_descriptor_lbound_set (descriptor_block, descriptor,
5969 gfc_rank_cst[n], se.expr);
5970 conv_lbound = se.expr;
5972 /* Work out the offset for this component. */
5973 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
5974 se.expr, stride);
5975 offset = fold_build2_loc (input_location, MINUS_EXPR,
5976 gfc_array_index_type, offset, tmp);
5978 /* Set upper bound. */
5979 gfc_init_se (&se, NULL);
5980 if (expr3_desc != NULL_TREE)
5982 if (e3_has_nodescriptor)
5984 /* The lbound of nondescriptor arrays like array constructors,
5985 nonallocatable/nonpointer function results/variables,
5986 start at zero, but when allocating it, the standard expects
5987 the array to start at one. Therefore fix the upper bound to be
5988 (desc.ubound - desc.lbound) + 1. */
5989 tmp = fold_build2_loc (input_location, MINUS_EXPR,
5990 gfc_array_index_type,
5991 gfc_conv_descriptor_ubound_get (
5992 expr3_desc, gfc_rank_cst[n]),
5993 gfc_conv_descriptor_lbound_get (
5994 expr3_desc, gfc_rank_cst[n]));
5995 tmp = fold_build2_loc (input_location, PLUS_EXPR,
5996 gfc_array_index_type, tmp,
5997 gfc_index_one_node);
5998 se.expr = gfc_evaluate_now (tmp, pblock);
6000 else
6001 se.expr = gfc_conv_descriptor_ubound_get (expr3_desc,
6002 gfc_rank_cst[n]);
6004 else
6006 gcc_assert (ubound);
6007 gfc_conv_expr_type (&se, ubound, gfc_array_index_type);
6008 gfc_add_block_to_block (pblock, &se.pre);
6009 if (ubound->expr_type == EXPR_FUNCTION)
6010 se.expr = gfc_evaluate_now (se.expr, pblock);
6012 gfc_conv_descriptor_ubound_set (descriptor_block, descriptor,
6013 gfc_rank_cst[n], se.expr);
6014 conv_ubound = se.expr;
6016 /* Store the stride. */
6017 gfc_conv_descriptor_stride_set (descriptor_block, descriptor,
6018 gfc_rank_cst[n], stride);
6020 /* Calculate size and check whether extent is negative. */
6021 size = gfc_conv_array_extent_dim (conv_lbound, conv_ubound, &or_expr);
6022 size = gfc_evaluate_now (size, pblock);
6024 /* Check whether multiplying the stride by the number of
6025 elements in this dimension would overflow. We must also check
6026 whether the current dimension has zero size in order to avoid
6027 division by zero.
6029 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
6030 gfc_array_index_type,
6031 fold_convert (gfc_array_index_type,
6032 TYPE_MAX_VALUE (gfc_array_index_type)),
6033 size);
6034 cond = gfc_unlikely (fold_build2_loc (input_location, LT_EXPR,
6035 logical_type_node, tmp, stride),
6036 PRED_FORTRAN_OVERFLOW);
6037 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node, cond,
6038 integer_one_node, integer_zero_node);
6039 cond = gfc_unlikely (fold_build2_loc (input_location, EQ_EXPR,
6040 logical_type_node, size,
6041 gfc_index_zero_node),
6042 PRED_FORTRAN_SIZE_ZERO);
6043 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node, cond,
6044 integer_zero_node, tmp);
6045 tmp = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
6046 *overflow, tmp);
6047 *overflow = gfc_evaluate_now (tmp, pblock);
6049 /* Multiply the stride by the number of elements in this dimension. */
6050 stride = fold_build2_loc (input_location, MULT_EXPR,
6051 gfc_array_index_type, stride, size);
6052 stride = gfc_evaluate_now (stride, pblock);
6055 for (n = rank; n < rank + corank; n++)
6057 ubound = upper[n];
6059 /* Set lower bound. */
6060 gfc_init_se (&se, NULL);
6061 if (lower == NULL || lower[n] == NULL)
6063 gcc_assert (n == rank + corank - 1);
6064 se.expr = gfc_index_one_node;
6066 else
6068 if (ubound || n == rank + corank - 1)
6070 gfc_conv_expr_type (&se, lower[n], gfc_array_index_type);
6071 gfc_add_block_to_block (pblock, &se.pre);
6073 else
6075 se.expr = gfc_index_one_node;
6076 ubound = lower[n];
6079 gfc_conv_descriptor_lbound_set (descriptor_block, descriptor,
6080 gfc_rank_cst[n], se.expr);
6082 if (n < rank + corank - 1)
6084 gfc_init_se (&se, NULL);
6085 gcc_assert (ubound);
6086 gfc_conv_expr_type (&se, ubound, gfc_array_index_type);
6087 gfc_add_block_to_block (pblock, &se.pre);
6088 gfc_conv_descriptor_ubound_set (descriptor_block, descriptor,
6089 gfc_rank_cst[n], se.expr);
6093 /* The stride is the number of elements in the array, so multiply by the
6094 size of an element to get the total size. Obviously, if there is a
6095 SOURCE expression (expr3) we must use its element size. */
6096 if (expr3_elem_size != NULL_TREE)
6097 tmp = expr3_elem_size;
6098 else if (expr3 != NULL)
6100 if (expr3->ts.type == BT_CLASS)
6102 gfc_se se_sz;
6103 gfc_expr *sz = gfc_copy_expr (expr3);
6104 gfc_add_vptr_component (sz);
6105 gfc_add_size_component (sz);
6106 gfc_init_se (&se_sz, NULL);
6107 gfc_conv_expr (&se_sz, sz);
6108 gfc_free_expr (sz);
6109 tmp = se_sz.expr;
6111 else
6113 tmp = gfc_typenode_for_spec (&expr3->ts);
6114 tmp = TYPE_SIZE_UNIT (tmp);
6117 else
6118 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
6120 /* Convert to size_t. */
6121 *element_size = fold_convert (size_type_node, tmp);
6123 if (rank == 0)
6124 return *element_size;
6126 *nelems = gfc_evaluate_now (stride, pblock);
6127 stride = fold_convert (size_type_node, stride);
6129 /* First check for overflow. Since an array of type character can
6130 have zero element_size, we must check for that before
6131 dividing. */
6132 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
6133 size_type_node,
6134 TYPE_MAX_VALUE (size_type_node), *element_size);
6135 cond = gfc_unlikely (fold_build2_loc (input_location, LT_EXPR,
6136 logical_type_node, tmp, stride),
6137 PRED_FORTRAN_OVERFLOW);
6138 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node, cond,
6139 integer_one_node, integer_zero_node);
6140 cond = gfc_unlikely (fold_build2_loc (input_location, EQ_EXPR,
6141 logical_type_node, *element_size,
6142 build_int_cst (size_type_node, 0)),
6143 PRED_FORTRAN_SIZE_ZERO);
6144 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node, cond,
6145 integer_zero_node, tmp);
6146 tmp = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
6147 *overflow, tmp);
6148 *overflow = gfc_evaluate_now (tmp, pblock);
6150 size = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
6151 stride, *element_size);
6153 if (poffset != NULL)
6155 offset = gfc_evaluate_now (offset, pblock);
6156 *poffset = offset;
6159 if (integer_zerop (or_expr))
6160 return size;
6161 if (integer_onep (or_expr))
6162 return build_int_cst (size_type_node, 0);
6164 var = gfc_create_var (TREE_TYPE (size), "size");
6165 gfc_start_block (&thenblock);
6166 gfc_add_modify (&thenblock, var, build_int_cst (size_type_node, 0));
6167 thencase = gfc_finish_block (&thenblock);
6169 gfc_start_block (&elseblock);
6170 gfc_add_modify (&elseblock, var, size);
6171 elsecase = gfc_finish_block (&elseblock);
6173 tmp = gfc_evaluate_now (or_expr, pblock);
6174 tmp = build3_v (COND_EXPR, tmp, thencase, elsecase);
6175 gfc_add_expr_to_block (pblock, tmp);
6177 return var;
6181 /* Retrieve the last ref from the chain. This routine is specific to
6182 gfc_array_allocate ()'s needs. */
6184 bool
6185 retrieve_last_ref (gfc_ref **ref_in, gfc_ref **prev_ref_in)
6187 gfc_ref *ref, *prev_ref;
6189 ref = *ref_in;
6190 /* Prevent warnings for uninitialized variables. */
6191 prev_ref = *prev_ref_in;
6192 while (ref && ref->next != NULL)
6194 gcc_assert (ref->type != REF_ARRAY || ref->u.ar.type == AR_ELEMENT
6195 || (ref->u.ar.dimen == 0 && ref->u.ar.codimen > 0));
6196 prev_ref = ref;
6197 ref = ref->next;
6200 if (ref == NULL || ref->type != REF_ARRAY)
6201 return false;
6203 *ref_in = ref;
6204 *prev_ref_in = prev_ref;
6205 return true;
6208 /* Initializes the descriptor and generates a call to _gfor_allocate. Does
6209 the work for an ALLOCATE statement. */
6210 /*GCC ARRAYS*/
6212 bool
6213 gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree status, tree errmsg,
6214 tree errlen, tree label_finish, tree expr3_elem_size,
6215 tree *nelems, gfc_expr *expr3, tree e3_arr_desc,
6216 bool e3_has_nodescriptor, gfc_omp_namelist *omp_alloc)
6218 tree tmp;
6219 tree pointer;
6220 tree offset = NULL_TREE;
6221 tree token = NULL_TREE;
6222 tree size;
6223 tree msg;
6224 tree error = NULL_TREE;
6225 tree overflow; /* Boolean storing whether size calculation overflows. */
6226 tree var_overflow = NULL_TREE;
6227 tree cond;
6228 tree set_descriptor;
6229 tree not_prev_allocated = NULL_TREE;
6230 tree element_size = NULL_TREE;
6231 stmtblock_t set_descriptor_block;
6232 stmtblock_t elseblock;
6233 gfc_expr **lower;
6234 gfc_expr **upper;
6235 gfc_ref *ref, *prev_ref = NULL, *coref;
6236 bool allocatable, coarray, dimension, alloc_w_e3_arr_spec = false,
6237 non_ulimate_coarray_ptr_comp;
6238 tree omp_cond = NULL_TREE, omp_alt_alloc = NULL_TREE;
6240 ref = expr->ref;
6242 /* Find the last reference in the chain. */
6243 if (!retrieve_last_ref (&ref, &prev_ref))
6244 return false;
6246 /* Take the allocatable and coarray properties solely from the expr-ref's
6247 attributes and not from source=-expression. */
6248 if (!prev_ref)
6250 allocatable = expr->symtree->n.sym->attr.allocatable;
6251 dimension = expr->symtree->n.sym->attr.dimension;
6252 non_ulimate_coarray_ptr_comp = false;
6254 else
6256 allocatable = prev_ref->u.c.component->attr.allocatable;
6257 /* Pointer components in coarrayed derived types must be treated
6258 specially in that they are registered without a check if the are
6259 already associated. This does not hold for ultimate coarray
6260 pointers. */
6261 non_ulimate_coarray_ptr_comp = (prev_ref->u.c.component->attr.pointer
6262 && !prev_ref->u.c.component->attr.codimension);
6263 dimension = prev_ref->u.c.component->attr.dimension;
6266 /* For allocatable/pointer arrays in derived types, one of the refs has to be
6267 a coarray. In this case it does not matter whether we are on this_image
6268 or not. */
6269 coarray = false;
6270 for (coref = expr->ref; coref; coref = coref->next)
6271 if (coref->type == REF_ARRAY && coref->u.ar.codimen > 0)
6273 coarray = true;
6274 break;
6277 if (!dimension)
6278 gcc_assert (coarray);
6280 if (ref->u.ar.type == AR_FULL && expr3 != NULL)
6282 gfc_ref *old_ref = ref;
6283 /* F08:C633: Array shape from expr3. */
6284 ref = expr3->ref;
6286 /* Find the last reference in the chain. */
6287 if (!retrieve_last_ref (&ref, &prev_ref))
6289 if (expr3->expr_type == EXPR_FUNCTION
6290 && gfc_expr_attr (expr3).dimension)
6291 ref = old_ref;
6292 else
6293 return false;
6295 alloc_w_e3_arr_spec = true;
6298 /* Figure out the size of the array. */
6299 switch (ref->u.ar.type)
6301 case AR_ELEMENT:
6302 if (!coarray)
6304 lower = NULL;
6305 upper = ref->u.ar.start;
6306 break;
6308 /* Fall through. */
6310 case AR_SECTION:
6311 lower = ref->u.ar.start;
6312 upper = ref->u.ar.end;
6313 break;
6315 case AR_FULL:
6316 gcc_assert (ref->u.ar.as->type == AS_EXPLICIT
6317 || alloc_w_e3_arr_spec);
6319 lower = ref->u.ar.as->lower;
6320 upper = ref->u.ar.as->upper;
6321 break;
6323 default:
6324 gcc_unreachable ();
6325 break;
6328 overflow = integer_zero_node;
6330 if (expr->ts.type == BT_CHARACTER
6331 && TREE_CODE (se->string_length) == COMPONENT_REF
6332 && expr->ts.u.cl->backend_decl != se->string_length
6333 && VAR_P (expr->ts.u.cl->backend_decl))
6334 gfc_add_modify (&se->pre, expr->ts.u.cl->backend_decl,
6335 fold_convert (TREE_TYPE (expr->ts.u.cl->backend_decl),
6336 se->string_length));
6338 gfc_init_block (&set_descriptor_block);
6339 /* Take the corank only from the actual ref and not from the coref. The
6340 later will mislead the generation of the array dimensions for allocatable/
6341 pointer components in derived types. */
6342 size = gfc_array_init_size (se->expr, alloc_w_e3_arr_spec ? expr->rank
6343 : ref->u.ar.as->rank,
6344 coarray ? ref->u.ar.as->corank : 0,
6345 &offset, lower, upper,
6346 &se->pre, &set_descriptor_block, &overflow,
6347 expr3_elem_size, nelems, expr3, e3_arr_desc,
6348 e3_has_nodescriptor, expr, &element_size);
6350 if (dimension)
6352 var_overflow = gfc_create_var (integer_type_node, "overflow");
6353 gfc_add_modify (&se->pre, var_overflow, overflow);
6355 if (status == NULL_TREE)
6357 /* Generate the block of code handling overflow. */
6358 msg = gfc_build_addr_expr (pchar_type_node,
6359 gfc_build_localized_cstring_const
6360 ("Integer overflow when calculating the amount of "
6361 "memory to allocate"));
6362 error = build_call_expr_loc (input_location,
6363 gfor_fndecl_runtime_error, 1, msg);
6365 else
6367 tree status_type = TREE_TYPE (status);
6368 stmtblock_t set_status_block;
6370 gfc_start_block (&set_status_block);
6371 gfc_add_modify (&set_status_block, status,
6372 build_int_cst (status_type, LIBERROR_ALLOCATION));
6373 error = gfc_finish_block (&set_status_block);
6377 /* Allocate memory to store the data. */
6378 if (POINTER_TYPE_P (TREE_TYPE (se->expr)))
6379 se->expr = build_fold_indirect_ref_loc (input_location, se->expr);
6381 if (coarray && flag_coarray == GFC_FCOARRAY_LIB)
6383 pointer = non_ulimate_coarray_ptr_comp ? se->expr
6384 : gfc_conv_descriptor_data_get (se->expr);
6385 token = gfc_conv_descriptor_token (se->expr);
6386 token = gfc_build_addr_expr (NULL_TREE, token);
6388 else
6390 pointer = gfc_conv_descriptor_data_get (se->expr);
6391 if (omp_alloc)
6392 omp_cond = boolean_true_node;
6394 STRIP_NOPS (pointer);
6396 if (allocatable)
6398 not_prev_allocated = gfc_create_var (logical_type_node,
6399 "not_prev_allocated");
6400 tmp = fold_build2_loc (input_location, EQ_EXPR,
6401 logical_type_node, pointer,
6402 build_int_cst (TREE_TYPE (pointer), 0));
6404 gfc_add_modify (&se->pre, not_prev_allocated, tmp);
6407 gfc_start_block (&elseblock);
6409 tree succ_add_expr = NULL_TREE;
6410 if (omp_cond)
6412 tree align, alloc, sz;
6413 gfc_se se2;
6414 if (omp_alloc->u2.allocator)
6416 gfc_init_se (&se2, NULL);
6417 gfc_conv_expr (&se2, omp_alloc->u2.allocator);
6418 gfc_add_block_to_block (&elseblock, &se2.pre);
6419 alloc = gfc_evaluate_now (se2.expr, &elseblock);
6420 gfc_add_block_to_block (&elseblock, &se2.post);
6422 else
6423 alloc = build_zero_cst (ptr_type_node);
6424 tmp = TREE_TYPE (TREE_TYPE (pointer));
6425 if (tmp == void_type_node)
6426 tmp = gfc_typenode_for_spec (&expr->ts, 0);
6427 if (omp_alloc->u.align)
6429 gfc_init_se (&se2, NULL);
6430 gfc_conv_expr (&se2, omp_alloc->u.align);
6431 gcc_assert (CONSTANT_CLASS_P (se2.expr)
6432 && se2.pre.head == NULL
6433 && se2.post.head == NULL);
6434 align = build_int_cst (size_type_node,
6435 MAX (tree_to_uhwi (se2.expr),
6436 TYPE_ALIGN_UNIT (tmp)));
6438 else
6439 align = build_int_cst (size_type_node, TYPE_ALIGN_UNIT (tmp));
6440 sz = fold_build2_loc (input_location, MAX_EXPR, size_type_node,
6441 fold_convert (size_type_node, size),
6442 build_int_cst (size_type_node, 1));
6443 omp_alt_alloc = builtin_decl_explicit (BUILT_IN_GOMP_ALLOC);
6444 DECL_ATTRIBUTES (omp_alt_alloc)
6445 = tree_cons (get_identifier ("omp allocator"),
6446 build_tree_list (NULL_TREE, alloc),
6447 DECL_ATTRIBUTES (omp_alt_alloc));
6448 omp_alt_alloc = build_call_expr (omp_alt_alloc, 3, align, sz, alloc);
6449 succ_add_expr = fold_build2_loc (input_location, MODIFY_EXPR,
6450 void_type_node,
6451 gfc_conv_descriptor_version (se->expr),
6452 build_int_cst (integer_type_node, 1));
6455 /* The allocatable variant takes the old pointer as first argument. */
6456 if (allocatable)
6457 gfc_allocate_allocatable (&elseblock, pointer, size, token,
6458 status, errmsg, errlen, label_finish, expr,
6459 coref != NULL ? coref->u.ar.as->corank : 0,
6460 omp_cond, omp_alt_alloc, succ_add_expr);
6461 else if (non_ulimate_coarray_ptr_comp && token)
6462 /* The token is set only for GFC_FCOARRAY_LIB mode. */
6463 gfc_allocate_using_caf_lib (&elseblock, pointer, size, token, status,
6464 errmsg, errlen,
6465 GFC_CAF_COARRAY_ALLOC_ALLOCATE_ONLY);
6466 else
6467 gfc_allocate_using_malloc (&elseblock, pointer, size, status,
6468 omp_cond, omp_alt_alloc, succ_add_expr);
6470 if (dimension)
6472 cond = gfc_unlikely (fold_build2_loc (input_location, NE_EXPR,
6473 logical_type_node, var_overflow, integer_zero_node),
6474 PRED_FORTRAN_OVERFLOW);
6475 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
6476 error, gfc_finish_block (&elseblock));
6478 else
6479 tmp = gfc_finish_block (&elseblock);
6481 gfc_add_expr_to_block (&se->pre, tmp);
6483 /* Update the array descriptor with the offset and the span. */
6484 if (dimension)
6486 gfc_conv_descriptor_offset_set (&set_descriptor_block, se->expr, offset);
6487 tmp = fold_convert (gfc_array_index_type, element_size);
6488 gfc_conv_descriptor_span_set (&set_descriptor_block, se->expr, tmp);
6491 set_descriptor = gfc_finish_block (&set_descriptor_block);
6492 if (status != NULL_TREE)
6494 cond = fold_build2_loc (input_location, EQ_EXPR,
6495 logical_type_node, status,
6496 build_int_cst (TREE_TYPE (status), 0));
6498 if (not_prev_allocated != NULL_TREE)
6499 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
6500 logical_type_node, cond, not_prev_allocated);
6502 gfc_add_expr_to_block (&se->pre,
6503 fold_build3_loc (input_location, COND_EXPR, void_type_node,
6504 cond,
6505 set_descriptor,
6506 build_empty_stmt (input_location)));
6508 else
6509 gfc_add_expr_to_block (&se->pre, set_descriptor);
6511 return true;
6515 /* Create an array constructor from an initialization expression.
6516 We assume the frontend already did any expansions and conversions. */
6518 tree
6519 gfc_conv_array_initializer (tree type, gfc_expr * expr)
6521 gfc_constructor *c;
6522 tree tmp;
6523 gfc_se se;
6524 tree index, range;
6525 vec<constructor_elt, va_gc> *v = NULL;
6527 if (expr->expr_type == EXPR_VARIABLE
6528 && expr->symtree->n.sym->attr.flavor == FL_PARAMETER
6529 && expr->symtree->n.sym->value)
6530 expr = expr->symtree->n.sym->value;
6532 switch (expr->expr_type)
6534 case EXPR_CONSTANT:
6535 case EXPR_STRUCTURE:
6536 /* A single scalar or derived type value. Create an array with all
6537 elements equal to that value. */
6538 gfc_init_se (&se, NULL);
6540 if (expr->expr_type == EXPR_CONSTANT)
6541 gfc_conv_constant (&se, expr);
6542 else
6543 gfc_conv_structure (&se, expr, 1);
6545 if (tree_int_cst_lt (TYPE_MAX_VALUE (TYPE_DOMAIN (type)),
6546 TYPE_MIN_VALUE (TYPE_DOMAIN (type))))
6547 break;
6548 else if (tree_int_cst_equal (TYPE_MIN_VALUE (TYPE_DOMAIN (type)),
6549 TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
6550 range = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
6551 else
6552 range = build2 (RANGE_EXPR, gfc_array_index_type,
6553 TYPE_MIN_VALUE (TYPE_DOMAIN (type)),
6554 TYPE_MAX_VALUE (TYPE_DOMAIN (type)));
6555 CONSTRUCTOR_APPEND_ELT (v, range, se.expr);
6556 break;
6558 case EXPR_ARRAY:
6559 /* Create a vector of all the elements. */
6560 for (c = gfc_constructor_first (expr->value.constructor);
6561 c && c->expr; c = gfc_constructor_next (c))
6563 if (c->iterator)
6565 /* Problems occur when we get something like
6566 integer :: a(lots) = (/(i, i=1, lots)/) */
6567 gfc_fatal_error ("The number of elements in the array "
6568 "constructor at %L requires an increase of "
6569 "the allowed %d upper limit. See "
6570 "%<-fmax-array-constructor%> option",
6571 &expr->where, flag_max_array_constructor);
6572 return NULL_TREE;
6574 if (mpz_cmp_si (c->offset, 0) != 0)
6575 index = gfc_conv_mpz_to_tree (c->offset, gfc_index_integer_kind);
6576 else
6577 index = NULL_TREE;
6579 if (mpz_cmp_si (c->repeat, 1) > 0)
6581 tree tmp1, tmp2;
6582 mpz_t maxval;
6584 mpz_init (maxval);
6585 mpz_add (maxval, c->offset, c->repeat);
6586 mpz_sub_ui (maxval, maxval, 1);
6587 tmp2 = gfc_conv_mpz_to_tree (maxval, gfc_index_integer_kind);
6588 if (mpz_cmp_si (c->offset, 0) != 0)
6590 mpz_add_ui (maxval, c->offset, 1);
6591 tmp1 = gfc_conv_mpz_to_tree (maxval, gfc_index_integer_kind);
6593 else
6594 tmp1 = gfc_conv_mpz_to_tree (c->offset, gfc_index_integer_kind);
6596 range = fold_build2 (RANGE_EXPR, gfc_array_index_type, tmp1, tmp2);
6597 mpz_clear (maxval);
6599 else
6600 range = NULL;
6602 gfc_init_se (&se, NULL);
6603 switch (c->expr->expr_type)
6605 case EXPR_CONSTANT:
6606 gfc_conv_constant (&se, c->expr);
6608 /* See gfortran.dg/charlen_15.f90 for instance. */
6609 if (TREE_CODE (se.expr) == STRING_CST
6610 && TREE_CODE (type) == ARRAY_TYPE)
6612 tree atype = type;
6613 while (TREE_CODE (TREE_TYPE (atype)) == ARRAY_TYPE)
6614 atype = TREE_TYPE (atype);
6615 gcc_checking_assert (TREE_CODE (TREE_TYPE (atype))
6616 == INTEGER_TYPE);
6617 gcc_checking_assert (TREE_TYPE (TREE_TYPE (se.expr))
6618 == TREE_TYPE (atype));
6619 if (tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (se.expr)))
6620 > tree_to_uhwi (TYPE_SIZE_UNIT (atype)))
6622 unsigned HOST_WIDE_INT size
6623 = tree_to_uhwi (TYPE_SIZE_UNIT (atype));
6624 const char *p = TREE_STRING_POINTER (se.expr);
6626 se.expr = build_string (size, p);
6628 TREE_TYPE (se.expr) = atype;
6630 break;
6632 case EXPR_STRUCTURE:
6633 gfc_conv_structure (&se, c->expr, 1);
6634 break;
6636 default:
6637 /* Catch those occasional beasts that do not simplify
6638 for one reason or another, assuming that if they are
6639 standard defying the frontend will catch them. */
6640 gfc_conv_expr (&se, c->expr);
6641 break;
6644 if (range == NULL_TREE)
6645 CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
6646 else
6648 if (index != NULL_TREE)
6649 CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
6650 CONSTRUCTOR_APPEND_ELT (v, range, se.expr);
6653 break;
6655 case EXPR_NULL:
6656 return gfc_build_null_descriptor (type);
6658 default:
6659 gcc_unreachable ();
6662 /* Create a constructor from the list of elements. */
6663 tmp = build_constructor (type, v);
6664 TREE_CONSTANT (tmp) = 1;
6665 return tmp;
6669 /* Generate code to evaluate non-constant coarray cobounds. */
6671 void
6672 gfc_trans_array_cobounds (tree type, stmtblock_t * pblock,
6673 const gfc_symbol *sym)
6675 int dim;
6676 tree ubound;
6677 tree lbound;
6678 gfc_se se;
6679 gfc_array_spec *as;
6681 as = IS_CLASS_ARRAY (sym) ? CLASS_DATA (sym)->as : sym->as;
6683 for (dim = as->rank; dim < as->rank + as->corank; dim++)
6685 /* Evaluate non-constant array bound expressions.
6686 F2008 4.5.6.3 para 6: If a specification expression in a scoping unit
6687 references a function, the result is finalized before execution of the
6688 executable constructs in the scoping unit.
6689 Adding the finalblocks enables this. */
6690 lbound = GFC_TYPE_ARRAY_LBOUND (type, dim);
6691 if (as->lower[dim] && !INTEGER_CST_P (lbound))
6693 gfc_init_se (&se, NULL);
6694 gfc_conv_expr_type (&se, as->lower[dim], gfc_array_index_type);
6695 gfc_add_block_to_block (pblock, &se.pre);
6696 gfc_add_block_to_block (pblock, &se.finalblock);
6697 gfc_add_modify (pblock, lbound, se.expr);
6699 ubound = GFC_TYPE_ARRAY_UBOUND (type, dim);
6700 if (as->upper[dim] && !INTEGER_CST_P (ubound))
6702 gfc_init_se (&se, NULL);
6703 gfc_conv_expr_type (&se, as->upper[dim], gfc_array_index_type);
6704 gfc_add_block_to_block (pblock, &se.pre);
6705 gfc_add_block_to_block (pblock, &se.finalblock);
6706 gfc_add_modify (pblock, ubound, se.expr);
6712 /* Generate code to evaluate non-constant array bounds. Sets *poffset and
6713 returns the size (in elements) of the array. */
6715 tree
6716 gfc_trans_array_bounds (tree type, gfc_symbol * sym, tree * poffset,
6717 stmtblock_t * pblock)
6719 gfc_array_spec *as;
6720 tree size;
6721 tree stride;
6722 tree offset;
6723 tree ubound;
6724 tree lbound;
6725 tree tmp;
6726 gfc_se se;
6728 int dim;
6730 as = IS_CLASS_ARRAY (sym) ? CLASS_DATA (sym)->as : sym->as;
6732 size = gfc_index_one_node;
6733 offset = gfc_index_zero_node;
6734 for (dim = 0; dim < as->rank; dim++)
6736 /* Evaluate non-constant array bound expressions.
6737 F2008 4.5.6.3 para 6: If a specification expression in a scoping unit
6738 references a function, the result is finalized before execution of the
6739 executable constructs in the scoping unit.
6740 Adding the finalblocks enables this. */
6741 lbound = GFC_TYPE_ARRAY_LBOUND (type, dim);
6742 if (as->lower[dim] && !INTEGER_CST_P (lbound))
6744 gfc_init_se (&se, NULL);
6745 gfc_conv_expr_type (&se, as->lower[dim], gfc_array_index_type);
6746 gfc_add_block_to_block (pblock, &se.pre);
6747 gfc_add_block_to_block (pblock, &se.finalblock);
6748 gfc_add_modify (pblock, lbound, se.expr);
6750 ubound = GFC_TYPE_ARRAY_UBOUND (type, dim);
6751 if (as->upper[dim] && !INTEGER_CST_P (ubound))
6753 gfc_init_se (&se, NULL);
6754 gfc_conv_expr_type (&se, as->upper[dim], gfc_array_index_type);
6755 gfc_add_block_to_block (pblock, &se.pre);
6756 gfc_add_block_to_block (pblock, &se.finalblock);
6757 gfc_add_modify (pblock, ubound, se.expr);
6759 /* The offset of this dimension. offset = offset - lbound * stride. */
6760 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
6761 lbound, size);
6762 offset = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
6763 offset, tmp);
6765 /* The size of this dimension, and the stride of the next. */
6766 if (dim + 1 < as->rank)
6767 stride = GFC_TYPE_ARRAY_STRIDE (type, dim + 1);
6768 else
6769 stride = GFC_TYPE_ARRAY_SIZE (type);
6771 if (ubound != NULL_TREE && !(stride && INTEGER_CST_P (stride)))
6773 /* Calculate stride = size * (ubound + 1 - lbound). */
6774 tmp = fold_build2_loc (input_location, MINUS_EXPR,
6775 gfc_array_index_type,
6776 gfc_index_one_node, lbound);
6777 tmp = fold_build2_loc (input_location, PLUS_EXPR,
6778 gfc_array_index_type, ubound, tmp);
6779 tmp = fold_build2_loc (input_location, MULT_EXPR,
6780 gfc_array_index_type, size, tmp);
6781 if (stride)
6782 gfc_add_modify (pblock, stride, tmp);
6783 else
6784 stride = gfc_evaluate_now (tmp, pblock);
6786 /* Make sure that negative size arrays are translated
6787 to being zero size. */
6788 tmp = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
6789 stride, gfc_index_zero_node);
6790 tmp = fold_build3_loc (input_location, COND_EXPR,
6791 gfc_array_index_type, tmp,
6792 stride, gfc_index_zero_node);
6793 gfc_add_modify (pblock, stride, tmp);
6796 size = stride;
6799 gfc_trans_array_cobounds (type, pblock, sym);
6800 gfc_trans_vla_type_sizes (sym, pblock);
6802 *poffset = offset;
6803 return size;
6807 /* Generate code to initialize/allocate an array variable. */
6809 void
6810 gfc_trans_auto_array_allocation (tree decl, gfc_symbol * sym,
6811 gfc_wrapped_block * block)
6813 stmtblock_t init;
6814 tree type;
6815 tree tmp = NULL_TREE;
6816 tree size;
6817 tree offset;
6818 tree space;
6819 tree inittree;
6820 bool onstack;
6822 gcc_assert (!(sym->attr.pointer || sym->attr.allocatable));
6824 /* Do nothing for USEd variables. */
6825 if (sym->attr.use_assoc)
6826 return;
6828 type = TREE_TYPE (decl);
6829 gcc_assert (GFC_ARRAY_TYPE_P (type));
6830 onstack = TREE_CODE (type) != POINTER_TYPE;
6832 gfc_init_block (&init);
6834 /* Evaluate character string length. */
6835 if (sym->ts.type == BT_CHARACTER
6836 && onstack && !INTEGER_CST_P (sym->ts.u.cl->backend_decl))
6838 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
6840 gfc_trans_vla_type_sizes (sym, &init);
6842 /* Emit a DECL_EXPR for this variable, which will cause the
6843 gimplifier to allocate storage, and all that good stuff. */
6844 tmp = fold_build1_loc (input_location, DECL_EXPR, TREE_TYPE (decl), decl);
6845 gfc_add_expr_to_block (&init, tmp);
6846 if (sym->attr.omp_allocate)
6848 /* Save location of size calculation to ensure GOMP_alloc is placed
6849 after it. */
6850 tree omp_alloc = lookup_attribute ("omp allocate",
6851 DECL_ATTRIBUTES (decl));
6852 TREE_CHAIN (TREE_CHAIN (TREE_VALUE (omp_alloc)))
6853 = build_tree_list (NULL_TREE, tsi_stmt (tsi_last (init.head)));
6857 if (onstack)
6859 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
6860 return;
6863 type = TREE_TYPE (type);
6865 gcc_assert (!sym->attr.use_assoc);
6866 gcc_assert (!sym->module);
6868 if (sym->ts.type == BT_CHARACTER
6869 && !INTEGER_CST_P (sym->ts.u.cl->backend_decl))
6870 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
6872 size = gfc_trans_array_bounds (type, sym, &offset, &init);
6874 /* Don't actually allocate space for Cray Pointees. */
6875 if (sym->attr.cray_pointee)
6877 if (VAR_P (GFC_TYPE_ARRAY_OFFSET (type)))
6878 gfc_add_modify (&init, GFC_TYPE_ARRAY_OFFSET (type), offset);
6880 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
6881 return;
6883 if (sym->attr.omp_allocate)
6885 /* The size is the number of elements in the array, so multiply by the
6886 size of an element to get the total size. */
6887 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
6888 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
6889 size, fold_convert (gfc_array_index_type, tmp));
6890 size = gfc_evaluate_now (size, &init);
6892 tree omp_alloc = lookup_attribute ("omp allocate",
6893 DECL_ATTRIBUTES (decl));
6894 TREE_CHAIN (TREE_CHAIN (TREE_VALUE (omp_alloc)))
6895 = build_tree_list (size, NULL_TREE);
6896 space = NULL_TREE;
6898 else if (flag_stack_arrays)
6900 gcc_assert (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE);
6901 space = build_decl (gfc_get_location (&sym->declared_at),
6902 VAR_DECL, create_tmp_var_name ("A"),
6903 TREE_TYPE (TREE_TYPE (decl)));
6904 gfc_trans_vla_type_sizes (sym, &init);
6906 else
6908 /* The size is the number of elements in the array, so multiply by the
6909 size of an element to get the total size. */
6910 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
6911 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
6912 size, fold_convert (gfc_array_index_type, tmp));
6914 /* Allocate memory to hold the data. */
6915 tmp = gfc_call_malloc (&init, TREE_TYPE (decl), size);
6916 gfc_add_modify (&init, decl, tmp);
6918 /* Free the temporary. */
6919 tmp = gfc_call_free (decl);
6920 space = NULL_TREE;
6923 /* Set offset of the array. */
6924 if (VAR_P (GFC_TYPE_ARRAY_OFFSET (type)))
6925 gfc_add_modify (&init, GFC_TYPE_ARRAY_OFFSET (type), offset);
6927 /* Automatic arrays should not have initializers. */
6928 gcc_assert (!sym->value);
6930 inittree = gfc_finish_block (&init);
6932 if (space)
6934 tree addr;
6935 pushdecl (space);
6937 /* Don't create new scope, emit the DECL_EXPR in exactly the scope
6938 where also space is located. */
6939 gfc_init_block (&init);
6940 tmp = fold_build1_loc (input_location, DECL_EXPR,
6941 TREE_TYPE (space), space);
6942 gfc_add_expr_to_block (&init, tmp);
6943 addr = fold_build1_loc (gfc_get_location (&sym->declared_at),
6944 ADDR_EXPR, TREE_TYPE (decl), space);
6945 gfc_add_modify (&init, decl, addr);
6946 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
6947 tmp = NULL_TREE;
6949 gfc_add_init_cleanup (block, inittree, tmp);
6953 /* Generate entry and exit code for g77 calling convention arrays. */
6955 void
6956 gfc_trans_g77_array (gfc_symbol * sym, gfc_wrapped_block * block)
6958 tree parm;
6959 tree type;
6960 locus loc;
6961 tree offset;
6962 tree tmp;
6963 tree stmt;
6964 stmtblock_t init;
6966 gfc_save_backend_locus (&loc);
6967 gfc_set_backend_locus (&sym->declared_at);
6969 /* Descriptor type. */
6970 parm = sym->backend_decl;
6971 type = TREE_TYPE (parm);
6972 gcc_assert (GFC_ARRAY_TYPE_P (type));
6974 gfc_start_block (&init);
6976 if (sym->ts.type == BT_CHARACTER
6977 && VAR_P (sym->ts.u.cl->backend_decl))
6978 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
6980 /* Evaluate the bounds of the array. */
6981 gfc_trans_array_bounds (type, sym, &offset, &init);
6983 /* Set the offset. */
6984 if (VAR_P (GFC_TYPE_ARRAY_OFFSET (type)))
6985 gfc_add_modify (&init, GFC_TYPE_ARRAY_OFFSET (type), offset);
6987 /* Set the pointer itself if we aren't using the parameter directly. */
6988 if (TREE_CODE (parm) != PARM_DECL)
6990 tmp = GFC_DECL_SAVED_DESCRIPTOR (parm);
6991 if (sym->ts.type == BT_CLASS)
6993 tmp = build_fold_indirect_ref_loc (input_location, tmp);
6994 tmp = gfc_class_data_get (tmp);
6995 tmp = gfc_conv_descriptor_data_get (tmp);
6997 tmp = convert (TREE_TYPE (parm), tmp);
6998 gfc_add_modify (&init, parm, tmp);
7000 stmt = gfc_finish_block (&init);
7002 gfc_restore_backend_locus (&loc);
7004 /* Add the initialization code to the start of the function. */
7006 if ((sym->ts.type == BT_CLASS && CLASS_DATA (sym)->attr.optional)
7007 || sym->attr.optional
7008 || sym->attr.not_always_present)
7010 tree nullify;
7011 if (TREE_CODE (parm) != PARM_DECL)
7012 nullify = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
7013 parm, null_pointer_node);
7014 else
7015 nullify = build_empty_stmt (input_location);
7016 tmp = gfc_conv_expr_present (sym, true);
7017 stmt = build3_v (COND_EXPR, tmp, stmt, nullify);
7020 gfc_add_init_cleanup (block, stmt, NULL_TREE);
7024 /* Modify the descriptor of an array parameter so that it has the
7025 correct lower bound. Also move the upper bound accordingly.
7026 If the array is not packed, it will be copied into a temporary.
7027 For each dimension we set the new lower and upper bounds. Then we copy the
7028 stride and calculate the offset for this dimension. We also work out
7029 what the stride of a packed array would be, and see it the two match.
7030 If the array need repacking, we set the stride to the values we just
7031 calculated, recalculate the offset and copy the array data.
7032 Code is also added to copy the data back at the end of the function.
7035 void
7036 gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc,
7037 gfc_wrapped_block * block)
7039 tree size;
7040 tree type;
7041 tree offset;
7042 locus loc;
7043 stmtblock_t init;
7044 tree stmtInit, stmtCleanup;
7045 tree lbound;
7046 tree ubound;
7047 tree dubound;
7048 tree dlbound;
7049 tree dumdesc;
7050 tree tmp;
7051 tree stride, stride2;
7052 tree stmt_packed;
7053 tree stmt_unpacked;
7054 tree partial;
7055 gfc_se se;
7056 int n;
7057 int checkparm;
7058 int no_repack;
7059 bool optional_arg;
7060 gfc_array_spec *as;
7061 bool is_classarray = IS_CLASS_ARRAY (sym);
7063 /* Do nothing for pointer and allocatable arrays. */
7064 if ((sym->ts.type != BT_CLASS && sym->attr.pointer)
7065 || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)->attr.class_pointer)
7066 || sym->attr.allocatable
7067 || (is_classarray && CLASS_DATA (sym)->attr.allocatable))
7068 return;
7070 if (!is_classarray && sym->attr.dummy && gfc_is_nodesc_array (sym))
7072 gfc_trans_g77_array (sym, block);
7073 return;
7076 loc.nextc = NULL;
7077 gfc_save_backend_locus (&loc);
7078 /* loc.nextc is not set by save_backend_locus but the location routines
7079 depend on it. */
7080 if (loc.nextc == NULL)
7081 loc.nextc = loc.lb->line;
7082 gfc_set_backend_locus (&sym->declared_at);
7084 /* Descriptor type. */
7085 type = TREE_TYPE (tmpdesc);
7086 gcc_assert (GFC_ARRAY_TYPE_P (type));
7087 dumdesc = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
7088 if (is_classarray)
7089 /* For a class array the dummy array descriptor is in the _class
7090 component. */
7091 dumdesc = gfc_class_data_get (dumdesc);
7092 else
7093 dumdesc = build_fold_indirect_ref_loc (input_location, dumdesc);
7094 as = IS_CLASS_ARRAY (sym) ? CLASS_DATA (sym)->as : sym->as;
7095 gfc_start_block (&init);
7097 if (sym->ts.type == BT_CHARACTER
7098 && VAR_P (sym->ts.u.cl->backend_decl))
7099 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
7101 /* TODO: Fix the exclusion of class arrays from extent checking. */
7102 checkparm = (as->type == AS_EXPLICIT && !is_classarray
7103 && (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS));
7105 no_repack = !(GFC_DECL_PACKED_ARRAY (tmpdesc)
7106 || GFC_DECL_PARTIAL_PACKED_ARRAY (tmpdesc));
7108 if (GFC_DECL_PARTIAL_PACKED_ARRAY (tmpdesc))
7110 /* For non-constant shape arrays we only check if the first dimension
7111 is contiguous. Repacking higher dimensions wouldn't gain us
7112 anything as we still don't know the array stride. */
7113 partial = gfc_create_var (logical_type_node, "partial");
7114 TREE_USED (partial) = 1;
7115 tmp = gfc_conv_descriptor_stride_get (dumdesc, gfc_rank_cst[0]);
7116 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, tmp,
7117 gfc_index_one_node);
7118 gfc_add_modify (&init, partial, tmp);
7120 else
7121 partial = NULL_TREE;
7123 /* The naming of stmt_unpacked and stmt_packed may be counter-intuitive
7124 here, however I think it does the right thing. */
7125 if (no_repack)
7127 /* Set the first stride. */
7128 stride = gfc_conv_descriptor_stride_get (dumdesc, gfc_rank_cst[0]);
7129 stride = gfc_evaluate_now (stride, &init);
7131 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
7132 stride, gfc_index_zero_node);
7133 tmp = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
7134 tmp, gfc_index_one_node, stride);
7135 stride = GFC_TYPE_ARRAY_STRIDE (type, 0);
7136 gfc_add_modify (&init, stride, tmp);
7138 /* Allow the user to disable array repacking. */
7139 stmt_unpacked = NULL_TREE;
7141 else
7143 gcc_assert (integer_onep (GFC_TYPE_ARRAY_STRIDE (type, 0)));
7144 /* A library call to repack the array if necessary. */
7145 tmp = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
7146 stmt_unpacked = build_call_expr_loc (input_location,
7147 gfor_fndecl_in_pack, 1, tmp);
7149 stride = gfc_index_one_node;
7151 if (warn_array_temporaries)
7152 gfc_warning (OPT_Warray_temporaries,
7153 "Creating array temporary at %L", &loc);
7156 /* This is for the case where the array data is used directly without
7157 calling the repack function. */
7158 if (no_repack || partial != NULL_TREE)
7159 stmt_packed = gfc_conv_descriptor_data_get (dumdesc);
7160 else
7161 stmt_packed = NULL_TREE;
7163 /* Assign the data pointer. */
7164 if (stmt_packed != NULL_TREE && stmt_unpacked != NULL_TREE)
7166 /* Don't repack unknown shape arrays when the first stride is 1. */
7167 tmp = fold_build3_loc (input_location, COND_EXPR, TREE_TYPE (stmt_packed),
7168 partial, stmt_packed, stmt_unpacked);
7170 else
7171 tmp = stmt_packed != NULL_TREE ? stmt_packed : stmt_unpacked;
7172 gfc_add_modify (&init, tmpdesc, fold_convert (type, tmp));
7174 offset = gfc_index_zero_node;
7175 size = gfc_index_one_node;
7177 /* Evaluate the bounds of the array. */
7178 for (n = 0; n < as->rank; n++)
7180 if (checkparm || !as->upper[n])
7182 /* Get the bounds of the actual parameter. */
7183 dubound = gfc_conv_descriptor_ubound_get (dumdesc, gfc_rank_cst[n]);
7184 dlbound = gfc_conv_descriptor_lbound_get (dumdesc, gfc_rank_cst[n]);
7186 else
7188 dubound = NULL_TREE;
7189 dlbound = NULL_TREE;
7192 lbound = GFC_TYPE_ARRAY_LBOUND (type, n);
7193 if (!INTEGER_CST_P (lbound))
7195 gfc_init_se (&se, NULL);
7196 gfc_conv_expr_type (&se, as->lower[n],
7197 gfc_array_index_type);
7198 gfc_add_block_to_block (&init, &se.pre);
7199 gfc_add_modify (&init, lbound, se.expr);
7202 ubound = GFC_TYPE_ARRAY_UBOUND (type, n);
7203 /* Set the desired upper bound. */
7204 if (as->upper[n])
7206 /* We know what we want the upper bound to be. */
7207 if (!INTEGER_CST_P (ubound))
7209 gfc_init_se (&se, NULL);
7210 gfc_conv_expr_type (&se, as->upper[n],
7211 gfc_array_index_type);
7212 gfc_add_block_to_block (&init, &se.pre);
7213 gfc_add_modify (&init, ubound, se.expr);
7216 /* Check the sizes match. */
7217 if (checkparm)
7219 /* Check (ubound(a) - lbound(a) == ubound(b) - lbound(b)). */
7220 char * msg;
7221 tree temp;
7223 temp = fold_build2_loc (input_location, MINUS_EXPR,
7224 gfc_array_index_type, ubound, lbound);
7225 temp = fold_build2_loc (input_location, PLUS_EXPR,
7226 gfc_array_index_type,
7227 gfc_index_one_node, temp);
7228 stride2 = fold_build2_loc (input_location, MINUS_EXPR,
7229 gfc_array_index_type, dubound,
7230 dlbound);
7231 stride2 = fold_build2_loc (input_location, PLUS_EXPR,
7232 gfc_array_index_type,
7233 gfc_index_one_node, stride2);
7234 tmp = fold_build2_loc (input_location, NE_EXPR,
7235 gfc_array_index_type, temp, stride2);
7236 msg = xasprintf ("Dimension %d of array '%s' has extent "
7237 "%%ld instead of %%ld", n+1, sym->name);
7239 gfc_trans_runtime_check (true, false, tmp, &init, &loc, msg,
7240 fold_convert (long_integer_type_node, temp),
7241 fold_convert (long_integer_type_node, stride2));
7243 free (msg);
7246 else
7248 /* For assumed shape arrays move the upper bound by the same amount
7249 as the lower bound. */
7250 tmp = fold_build2_loc (input_location, MINUS_EXPR,
7251 gfc_array_index_type, dubound, dlbound);
7252 tmp = fold_build2_loc (input_location, PLUS_EXPR,
7253 gfc_array_index_type, tmp, lbound);
7254 gfc_add_modify (&init, ubound, tmp);
7256 /* The offset of this dimension. offset = offset - lbound * stride. */
7257 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
7258 lbound, stride);
7259 offset = fold_build2_loc (input_location, MINUS_EXPR,
7260 gfc_array_index_type, offset, tmp);
7262 /* The size of this dimension, and the stride of the next. */
7263 if (n + 1 < as->rank)
7265 stride = GFC_TYPE_ARRAY_STRIDE (type, n + 1);
7267 if (no_repack || partial != NULL_TREE)
7268 stmt_unpacked =
7269 gfc_conv_descriptor_stride_get (dumdesc, gfc_rank_cst[n+1]);
7271 /* Figure out the stride if not a known constant. */
7272 if (!INTEGER_CST_P (stride))
7274 if (no_repack)
7275 stmt_packed = NULL_TREE;
7276 else
7278 /* Calculate stride = size * (ubound + 1 - lbound). */
7279 tmp = fold_build2_loc (input_location, MINUS_EXPR,
7280 gfc_array_index_type,
7281 gfc_index_one_node, lbound);
7282 tmp = fold_build2_loc (input_location, PLUS_EXPR,
7283 gfc_array_index_type, ubound, tmp);
7284 size = fold_build2_loc (input_location, MULT_EXPR,
7285 gfc_array_index_type, size, tmp);
7286 stmt_packed = size;
7289 /* Assign the stride. */
7290 if (stmt_packed != NULL_TREE && stmt_unpacked != NULL_TREE)
7291 tmp = fold_build3_loc (input_location, COND_EXPR,
7292 gfc_array_index_type, partial,
7293 stmt_unpacked, stmt_packed);
7294 else
7295 tmp = (stmt_packed != NULL_TREE) ? stmt_packed : stmt_unpacked;
7296 gfc_add_modify (&init, stride, tmp);
7299 else
7301 stride = GFC_TYPE_ARRAY_SIZE (type);
7303 if (stride && !INTEGER_CST_P (stride))
7305 /* Calculate size = stride * (ubound + 1 - lbound). */
7306 tmp = fold_build2_loc (input_location, MINUS_EXPR,
7307 gfc_array_index_type,
7308 gfc_index_one_node, lbound);
7309 tmp = fold_build2_loc (input_location, PLUS_EXPR,
7310 gfc_array_index_type,
7311 ubound, tmp);
7312 tmp = fold_build2_loc (input_location, MULT_EXPR,
7313 gfc_array_index_type,
7314 GFC_TYPE_ARRAY_STRIDE (type, n), tmp);
7315 gfc_add_modify (&init, stride, tmp);
7320 gfc_trans_array_cobounds (type, &init, sym);
7322 /* Set the offset. */
7323 if (VAR_P (GFC_TYPE_ARRAY_OFFSET (type)))
7324 gfc_add_modify (&init, GFC_TYPE_ARRAY_OFFSET (type), offset);
7326 gfc_trans_vla_type_sizes (sym, &init);
7328 stmtInit = gfc_finish_block (&init);
7330 /* Only do the entry/initialization code if the arg is present. */
7331 dumdesc = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
7332 optional_arg = (sym->attr.optional
7333 || (sym->ns->proc_name->attr.entry_master
7334 && sym->attr.dummy));
7335 if (optional_arg)
7337 tree zero_init = fold_convert (TREE_TYPE (tmpdesc), null_pointer_node);
7338 zero_init = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
7339 tmpdesc, zero_init);
7340 tmp = gfc_conv_expr_present (sym, true);
7341 stmtInit = build3_v (COND_EXPR, tmp, stmtInit, zero_init);
7344 /* Cleanup code. */
7345 if (no_repack)
7346 stmtCleanup = NULL_TREE;
7347 else
7349 stmtblock_t cleanup;
7350 gfc_start_block (&cleanup);
7352 if (sym->attr.intent != INTENT_IN)
7354 /* Copy the data back. */
7355 tmp = build_call_expr_loc (input_location,
7356 gfor_fndecl_in_unpack, 2, dumdesc, tmpdesc);
7357 gfc_add_expr_to_block (&cleanup, tmp);
7360 /* Free the temporary. */
7361 tmp = gfc_call_free (tmpdesc);
7362 gfc_add_expr_to_block (&cleanup, tmp);
7364 stmtCleanup = gfc_finish_block (&cleanup);
7366 /* Only do the cleanup if the array was repacked. */
7367 if (is_classarray)
7368 /* For a class array the dummy array descriptor is in the _class
7369 component. */
7370 tmp = gfc_class_data_get (dumdesc);
7371 else
7372 tmp = build_fold_indirect_ref_loc (input_location, dumdesc);
7373 tmp = gfc_conv_descriptor_data_get (tmp);
7374 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
7375 tmp, tmpdesc);
7376 stmtCleanup = build3_v (COND_EXPR, tmp, stmtCleanup,
7377 build_empty_stmt (input_location));
7379 if (optional_arg)
7381 tmp = gfc_conv_expr_present (sym);
7382 stmtCleanup = build3_v (COND_EXPR, tmp, stmtCleanup,
7383 build_empty_stmt (input_location));
7387 /* We don't need to free any memory allocated by internal_pack as it will
7388 be freed at the end of the function by pop_context. */
7389 gfc_add_init_cleanup (block, stmtInit, stmtCleanup);
7391 gfc_restore_backend_locus (&loc);
7395 /* Calculate the overall offset, including subreferences. */
7396 void
7397 gfc_get_dataptr_offset (stmtblock_t *block, tree parm, tree desc, tree offset,
7398 bool subref, gfc_expr *expr)
7400 tree tmp;
7401 tree field;
7402 tree stride;
7403 tree index;
7404 gfc_ref *ref;
7405 gfc_se start;
7406 int n;
7408 /* If offset is NULL and this is not a subreferenced array, there is
7409 nothing to do. */
7410 if (offset == NULL_TREE)
7412 if (subref)
7413 offset = gfc_index_zero_node;
7414 else
7415 return;
7418 tmp = build_array_ref (desc, offset, NULL, NULL);
7420 /* Offset the data pointer for pointer assignments from arrays with
7421 subreferences; e.g. my_integer => my_type(:)%integer_component. */
7422 if (subref)
7424 /* Go past the array reference. */
7425 for (ref = expr->ref; ref; ref = ref->next)
7426 if (ref->type == REF_ARRAY &&
7427 ref->u.ar.type != AR_ELEMENT)
7429 ref = ref->next;
7430 break;
7433 /* Calculate the offset for each subsequent subreference. */
7434 for (; ref; ref = ref->next)
7436 switch (ref->type)
7438 case REF_COMPONENT:
7439 field = ref->u.c.component->backend_decl;
7440 gcc_assert (field && TREE_CODE (field) == FIELD_DECL);
7441 tmp = fold_build3_loc (input_location, COMPONENT_REF,
7442 TREE_TYPE (field),
7443 tmp, field, NULL_TREE);
7444 break;
7446 case REF_SUBSTRING:
7447 gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE);
7448 gfc_init_se (&start, NULL);
7449 gfc_conv_expr_type (&start, ref->u.ss.start, gfc_charlen_type_node);
7450 gfc_add_block_to_block (block, &start.pre);
7451 tmp = gfc_build_array_ref (tmp, start.expr, NULL);
7452 break;
7454 case REF_ARRAY:
7455 gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE
7456 && ref->u.ar.type == AR_ELEMENT);
7458 /* TODO - Add bounds checking. */
7459 stride = gfc_index_one_node;
7460 index = gfc_index_zero_node;
7461 for (n = 0; n < ref->u.ar.dimen; n++)
7463 tree itmp;
7464 tree jtmp;
7466 /* Update the index. */
7467 gfc_init_se (&start, NULL);
7468 gfc_conv_expr_type (&start, ref->u.ar.start[n], gfc_array_index_type);
7469 itmp = gfc_evaluate_now (start.expr, block);
7470 gfc_init_se (&start, NULL);
7471 gfc_conv_expr_type (&start, ref->u.ar.as->lower[n], gfc_array_index_type);
7472 jtmp = gfc_evaluate_now (start.expr, block);
7473 itmp = fold_build2_loc (input_location, MINUS_EXPR,
7474 gfc_array_index_type, itmp, jtmp);
7475 itmp = fold_build2_loc (input_location, MULT_EXPR,
7476 gfc_array_index_type, itmp, stride);
7477 index = fold_build2_loc (input_location, PLUS_EXPR,
7478 gfc_array_index_type, itmp, index);
7479 index = gfc_evaluate_now (index, block);
7481 /* Update the stride. */
7482 gfc_init_se (&start, NULL);
7483 gfc_conv_expr_type (&start, ref->u.ar.as->upper[n], gfc_array_index_type);
7484 itmp = fold_build2_loc (input_location, MINUS_EXPR,
7485 gfc_array_index_type, start.expr,
7486 jtmp);
7487 itmp = fold_build2_loc (input_location, PLUS_EXPR,
7488 gfc_array_index_type,
7489 gfc_index_one_node, itmp);
7490 stride = fold_build2_loc (input_location, MULT_EXPR,
7491 gfc_array_index_type, stride, itmp);
7492 stride = gfc_evaluate_now (stride, block);
7495 /* Apply the index to obtain the array element. */
7496 tmp = gfc_build_array_ref (tmp, index, NULL);
7497 break;
7499 case REF_INQUIRY:
7500 switch (ref->u.i)
7502 case INQUIRY_RE:
7503 tmp = fold_build1_loc (input_location, REALPART_EXPR,
7504 TREE_TYPE (TREE_TYPE (tmp)), tmp);
7505 break;
7507 case INQUIRY_IM:
7508 tmp = fold_build1_loc (input_location, IMAGPART_EXPR,
7509 TREE_TYPE (TREE_TYPE (tmp)), tmp);
7510 break;
7512 default:
7513 break;
7515 break;
7517 default:
7518 gcc_unreachable ();
7519 break;
7524 /* Set the target data pointer. */
7525 offset = gfc_build_addr_expr (gfc_array_dataptr_type (desc), tmp);
7526 gfc_conv_descriptor_data_set (block, parm, offset);
7530 /* gfc_conv_expr_descriptor needs the string length an expression
7531 so that the size of the temporary can be obtained. This is done
7532 by adding up the string lengths of all the elements in the
7533 expression. Function with non-constant expressions have their
7534 string lengths mapped onto the actual arguments using the
7535 interface mapping machinery in trans-expr.cc. */
7536 static void
7537 get_array_charlen (gfc_expr *expr, gfc_se *se)
7539 gfc_interface_mapping mapping;
7540 gfc_formal_arglist *formal;
7541 gfc_actual_arglist *arg;
7542 gfc_se tse;
7543 gfc_expr *e;
7545 if (expr->ts.u.cl->length
7546 && gfc_is_constant_expr (expr->ts.u.cl->length))
7548 if (!expr->ts.u.cl->backend_decl)
7549 gfc_conv_string_length (expr->ts.u.cl, expr, &se->pre);
7550 return;
7553 switch (expr->expr_type)
7555 case EXPR_ARRAY:
7557 /* This is somewhat brutal. The expression for the first
7558 element of the array is evaluated and assigned to a
7559 new string length for the original expression. */
7560 e = gfc_constructor_first (expr->value.constructor)->expr;
7562 gfc_init_se (&tse, NULL);
7564 /* Avoid evaluating trailing array references since all we need is
7565 the string length. */
7566 if (e->rank)
7567 tse.descriptor_only = 1;
7568 if (e->rank && e->expr_type != EXPR_VARIABLE)
7569 gfc_conv_expr_descriptor (&tse, e);
7570 else
7571 gfc_conv_expr (&tse, e);
7573 gfc_add_block_to_block (&se->pre, &tse.pre);
7574 gfc_add_block_to_block (&se->post, &tse.post);
7576 if (!expr->ts.u.cl->backend_decl || !VAR_P (expr->ts.u.cl->backend_decl))
7578 expr->ts.u.cl = gfc_new_charlen (gfc_current_ns, NULL);
7579 expr->ts.u.cl->backend_decl =
7580 gfc_create_var (gfc_charlen_type_node, "sln");
7583 gfc_add_modify (&se->pre, expr->ts.u.cl->backend_decl,
7584 tse.string_length);
7586 /* Make sure that deferred length components point to the hidden
7587 string_length component. */
7588 if (TREE_CODE (tse.expr) == COMPONENT_REF
7589 && TREE_CODE (tse.string_length) == COMPONENT_REF
7590 && TREE_OPERAND (tse.expr, 0) == TREE_OPERAND (tse.string_length, 0))
7591 e->ts.u.cl->backend_decl = expr->ts.u.cl->backend_decl;
7593 return;
7595 case EXPR_OP:
7596 get_array_charlen (expr->value.op.op1, se);
7598 /* For parentheses the expression ts.u.cl should be identical. */
7599 if (expr->value.op.op == INTRINSIC_PARENTHESES)
7601 if (expr->value.op.op1->ts.u.cl != expr->ts.u.cl)
7602 expr->ts.u.cl->backend_decl
7603 = expr->value.op.op1->ts.u.cl->backend_decl;
7604 return;
7607 expr->ts.u.cl->backend_decl =
7608 gfc_create_var (gfc_charlen_type_node, "sln");
7610 if (expr->value.op.op2)
7612 get_array_charlen (expr->value.op.op2, se);
7614 gcc_assert (expr->value.op.op == INTRINSIC_CONCAT);
7616 /* Add the string lengths and assign them to the expression
7617 string length backend declaration. */
7618 gfc_add_modify (&se->pre, expr->ts.u.cl->backend_decl,
7619 fold_build2_loc (input_location, PLUS_EXPR,
7620 gfc_charlen_type_node,
7621 expr->value.op.op1->ts.u.cl->backend_decl,
7622 expr->value.op.op2->ts.u.cl->backend_decl));
7624 else
7625 gfc_add_modify (&se->pre, expr->ts.u.cl->backend_decl,
7626 expr->value.op.op1->ts.u.cl->backend_decl);
7627 break;
7629 case EXPR_FUNCTION:
7630 if (expr->value.function.esym == NULL
7631 || expr->ts.u.cl->length->expr_type == EXPR_CONSTANT)
7633 gfc_conv_string_length (expr->ts.u.cl, expr, &se->pre);
7634 break;
7637 /* Map expressions involving the dummy arguments onto the actual
7638 argument expressions. */
7639 gfc_init_interface_mapping (&mapping);
7640 formal = gfc_sym_get_dummy_args (expr->symtree->n.sym);
7641 arg = expr->value.function.actual;
7643 /* Set se = NULL in the calls to the interface mapping, to suppress any
7644 backend stuff. */
7645 for (; arg != NULL; arg = arg->next, formal = formal ? formal->next : NULL)
7647 if (!arg->expr)
7648 continue;
7649 if (formal->sym)
7650 gfc_add_interface_mapping (&mapping, formal->sym, NULL, arg->expr);
7653 gfc_init_se (&tse, NULL);
7655 /* Build the expression for the character length and convert it. */
7656 gfc_apply_interface_mapping (&mapping, &tse, expr->ts.u.cl->length);
7658 gfc_add_block_to_block (&se->pre, &tse.pre);
7659 gfc_add_block_to_block (&se->post, &tse.post);
7660 tse.expr = fold_convert (gfc_charlen_type_node, tse.expr);
7661 tse.expr = fold_build2_loc (input_location, MAX_EXPR,
7662 TREE_TYPE (tse.expr), tse.expr,
7663 build_zero_cst (TREE_TYPE (tse.expr)));
7664 expr->ts.u.cl->backend_decl = tse.expr;
7665 gfc_free_interface_mapping (&mapping);
7666 break;
7668 default:
7669 gfc_conv_string_length (expr->ts.u.cl, expr, &se->pre);
7670 break;
7675 /* Helper function to check dimensions. */
7676 static bool
7677 transposed_dims (gfc_ss *ss)
7679 int n;
7681 for (n = 0; n < ss->dimen; n++)
7682 if (ss->dim[n] != n)
7683 return true;
7684 return false;
7688 /* Convert the last ref of a scalar coarray from an AR_ELEMENT to an
7689 AR_FULL, suitable for the scalarizer. */
7691 static gfc_ss *
7692 walk_coarray (gfc_expr *e)
7694 gfc_ss *ss;
7696 gcc_assert (gfc_get_corank (e) > 0);
7698 ss = gfc_walk_expr (e);
7700 /* Fix scalar coarray. */
7701 if (ss == gfc_ss_terminator)
7703 gfc_ref *ref;
7705 ref = e->ref;
7706 while (ref)
7708 if (ref->type == REF_ARRAY
7709 && ref->u.ar.codimen > 0)
7710 break;
7712 ref = ref->next;
7715 gcc_assert (ref != NULL);
7716 if (ref->u.ar.type == AR_ELEMENT)
7717 ref->u.ar.type = AR_SECTION;
7718 ss = gfc_reverse_ss (gfc_walk_array_ref (ss, e, ref));
7721 return ss;
7725 /* Convert an array for passing as an actual argument. Expressions and
7726 vector subscripts are evaluated and stored in a temporary, which is then
7727 passed. For whole arrays the descriptor is passed. For array sections
7728 a modified copy of the descriptor is passed, but using the original data.
7730 This function is also used for array pointer assignments, and there
7731 are three cases:
7733 - se->want_pointer && !se->direct_byref
7734 EXPR is an actual argument. On exit, se->expr contains a
7735 pointer to the array descriptor.
7737 - !se->want_pointer && !se->direct_byref
7738 EXPR is an actual argument to an intrinsic function or the
7739 left-hand side of a pointer assignment. On exit, se->expr
7740 contains the descriptor for EXPR.
7742 - !se->want_pointer && se->direct_byref
7743 EXPR is the right-hand side of a pointer assignment and
7744 se->expr is the descriptor for the previously-evaluated
7745 left-hand side. The function creates an assignment from
7746 EXPR to se->expr.
7749 The se->force_tmp flag disables the non-copying descriptor optimization
7750 that is used for transpose. It may be used in cases where there is an
7751 alias between the transpose argument and another argument in the same
7752 function call. */
7754 void
7755 gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
7757 gfc_ss *ss;
7758 gfc_ss_type ss_type;
7759 gfc_ss_info *ss_info;
7760 gfc_loopinfo loop;
7761 gfc_array_info *info;
7762 int need_tmp;
7763 int n;
7764 tree tmp;
7765 tree desc;
7766 stmtblock_t block;
7767 tree start;
7768 int full;
7769 bool subref_array_target = false;
7770 bool deferred_array_component = false;
7771 bool substr = false;
7772 gfc_expr *arg, *ss_expr;
7774 if (se->want_coarray)
7775 ss = walk_coarray (expr);
7776 else
7777 ss = gfc_walk_expr (expr);
7779 gcc_assert (ss != NULL);
7780 gcc_assert (ss != gfc_ss_terminator);
7782 ss_info = ss->info;
7783 ss_type = ss_info->type;
7784 ss_expr = ss_info->expr;
7786 /* Special case: TRANSPOSE which needs no temporary. */
7787 while (expr->expr_type == EXPR_FUNCTION && expr->value.function.isym
7788 && (arg = gfc_get_noncopying_intrinsic_argument (expr)) != NULL)
7790 /* This is a call to transpose which has already been handled by the
7791 scalarizer, so that we just need to get its argument's descriptor. */
7792 gcc_assert (expr->value.function.isym->id == GFC_ISYM_TRANSPOSE);
7793 expr = expr->value.function.actual->expr;
7796 if (!se->direct_byref)
7797 se->unlimited_polymorphic = UNLIMITED_POLY (expr);
7799 /* Special case things we know we can pass easily. */
7800 switch (expr->expr_type)
7802 case EXPR_VARIABLE:
7803 /* If we have a linear array section, we can pass it directly.
7804 Otherwise we need to copy it into a temporary. */
7806 gcc_assert (ss_type == GFC_SS_SECTION);
7807 gcc_assert (ss_expr == expr);
7808 info = &ss_info->data.array;
7810 /* Get the descriptor for the array. */
7811 gfc_conv_ss_descriptor (&se->pre, ss, 0);
7812 desc = info->descriptor;
7814 /* The charlen backend decl for deferred character components cannot
7815 be used because it is fixed at zero. Instead, the hidden string
7816 length component is used. */
7817 if (expr->ts.type == BT_CHARACTER
7818 && expr->ts.deferred
7819 && TREE_CODE (desc) == COMPONENT_REF)
7820 deferred_array_component = true;
7822 substr = info->ref && info->ref->next
7823 && info->ref->next->type == REF_SUBSTRING;
7825 subref_array_target = (is_subref_array (expr)
7826 && (se->direct_byref
7827 || expr->ts.type == BT_CHARACTER));
7828 need_tmp = (gfc_ref_needs_temporary_p (expr->ref)
7829 && !subref_array_target);
7831 if (se->force_tmp)
7832 need_tmp = 1;
7833 else if (se->force_no_tmp)
7834 need_tmp = 0;
7836 if (need_tmp)
7837 full = 0;
7838 else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
7840 /* Create a new descriptor if the array doesn't have one. */
7841 full = 0;
7843 else if (info->ref->u.ar.type == AR_FULL || se->descriptor_only)
7844 full = 1;
7845 else if (se->direct_byref)
7846 full = 0;
7847 else if (info->ref->u.ar.dimen == 0 && !info->ref->next)
7848 full = 1;
7849 else if (info->ref->u.ar.type == AR_SECTION && se->want_pointer)
7850 full = 0;
7851 else
7852 full = gfc_full_array_ref_p (info->ref, NULL);
7854 if (full && !transposed_dims (ss))
7856 if (se->direct_byref && !se->byref_noassign)
7858 /* Copy the descriptor for pointer assignments. */
7859 gfc_add_modify (&se->pre, se->expr, desc);
7861 /* Add any offsets from subreferences. */
7862 gfc_get_dataptr_offset (&se->pre, se->expr, desc, NULL_TREE,
7863 subref_array_target, expr);
7865 /* ....and set the span field. */
7866 if (ss_info->expr->ts.type == BT_CHARACTER)
7867 tmp = gfc_conv_descriptor_span_get (desc);
7868 else
7869 tmp = gfc_get_array_span (desc, expr);
7870 gfc_conv_descriptor_span_set (&se->pre, se->expr, tmp);
7872 else if (se->want_pointer)
7874 /* We pass full arrays directly. This means that pointers and
7875 allocatable arrays should also work. */
7876 se->expr = gfc_build_addr_expr (NULL_TREE, desc);
7878 else
7880 se->expr = desc;
7883 if (expr->ts.type == BT_CHARACTER && !deferred_array_component)
7884 se->string_length = gfc_get_expr_charlen (expr);
7885 /* The ss_info string length is returned set to the value of the
7886 hidden string length component. */
7887 else if (deferred_array_component)
7888 se->string_length = ss_info->string_length;
7890 se->class_container = ss_info->class_container;
7892 gfc_free_ss_chain (ss);
7893 return;
7895 break;
7897 case EXPR_FUNCTION:
7898 /* A transformational function return value will be a temporary
7899 array descriptor. We still need to go through the scalarizer
7900 to create the descriptor. Elemental functions are handled as
7901 arbitrary expressions, i.e. copy to a temporary. */
7903 if (se->direct_byref)
7905 gcc_assert (ss_type == GFC_SS_FUNCTION && ss_expr == expr);
7907 /* For pointer assignments pass the descriptor directly. */
7908 if (se->ss == NULL)
7909 se->ss = ss;
7910 else
7911 gcc_assert (se->ss == ss);
7913 if (!is_pointer_array (se->expr))
7915 tmp = gfc_get_element_type (TREE_TYPE (se->expr));
7916 tmp = fold_convert (gfc_array_index_type,
7917 size_in_bytes (tmp));
7918 gfc_conv_descriptor_span_set (&se->pre, se->expr, tmp);
7921 se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
7922 gfc_conv_expr (se, expr);
7924 gfc_free_ss_chain (ss);
7925 return;
7928 if (ss_expr != expr || ss_type != GFC_SS_FUNCTION)
7930 if (ss_expr != expr)
7931 /* Elemental function. */
7932 gcc_assert ((expr->value.function.esym != NULL
7933 && expr->value.function.esym->attr.elemental)
7934 || (expr->value.function.isym != NULL
7935 && expr->value.function.isym->elemental)
7936 || (gfc_expr_attr (expr).proc_pointer
7937 && gfc_expr_attr (expr).elemental)
7938 || gfc_inline_intrinsic_function_p (expr));
7940 need_tmp = 1;
7941 if (expr->ts.type == BT_CHARACTER
7942 && expr->ts.u.cl->length
7943 && expr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
7944 get_array_charlen (expr, se);
7946 info = NULL;
7948 else
7950 /* Transformational function. */
7951 info = &ss_info->data.array;
7952 need_tmp = 0;
7954 break;
7956 case EXPR_ARRAY:
7957 /* Constant array constructors don't need a temporary. */
7958 if (ss_type == GFC_SS_CONSTRUCTOR
7959 && expr->ts.type != BT_CHARACTER
7960 && gfc_constant_array_constructor_p (expr->value.constructor))
7962 need_tmp = 0;
7963 info = &ss_info->data.array;
7965 else
7967 need_tmp = 1;
7968 info = NULL;
7970 break;
7972 default:
7973 /* Something complicated. Copy it into a temporary. */
7974 need_tmp = 1;
7975 info = NULL;
7976 break;
7979 /* If we are creating a temporary, we don't need to bother about aliases
7980 anymore. */
7981 if (need_tmp)
7982 se->force_tmp = 0;
7984 gfc_init_loopinfo (&loop);
7986 /* Associate the SS with the loop. */
7987 gfc_add_ss_to_loop (&loop, ss);
7989 /* Tell the scalarizer not to bother creating loop variables, etc. */
7990 if (!need_tmp)
7991 loop.array_parameter = 1;
7992 else
7993 /* The right-hand side of a pointer assignment mustn't use a temporary. */
7994 gcc_assert (!se->direct_byref);
7996 /* Do we need bounds checking or not? */
7997 ss->no_bounds_check = expr->no_bounds_check;
7999 /* Setup the scalarizing loops and bounds. */
8000 gfc_conv_ss_startstride (&loop);
8002 /* Add bounds-checking for elemental dimensions. */
8003 if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS) && !expr->no_bounds_check)
8004 array_bound_check_elemental (se, ss, expr);
8006 if (need_tmp)
8008 if (expr->ts.type == BT_CHARACTER
8009 && (!expr->ts.u.cl->backend_decl || expr->expr_type == EXPR_ARRAY))
8010 get_array_charlen (expr, se);
8012 /* Tell the scalarizer to make a temporary. */
8013 loop.temp_ss = gfc_get_temp_ss (gfc_typenode_for_spec (&expr->ts),
8014 ((expr->ts.type == BT_CHARACTER)
8015 ? expr->ts.u.cl->backend_decl
8016 : NULL),
8017 loop.dimen);
8019 se->string_length = loop.temp_ss->info->string_length;
8020 gcc_assert (loop.temp_ss->dimen == loop.dimen);
8021 gfc_add_ss_to_loop (&loop, loop.temp_ss);
8024 gfc_conv_loop_setup (&loop, & expr->where);
8026 if (need_tmp)
8028 /* Copy into a temporary and pass that. We don't need to copy the data
8029 back because expressions and vector subscripts must be INTENT_IN. */
8030 /* TODO: Optimize passing function return values. */
8031 gfc_se lse;
8032 gfc_se rse;
8033 bool deep_copy;
8035 /* Start the copying loops. */
8036 gfc_mark_ss_chain_used (loop.temp_ss, 1);
8037 gfc_mark_ss_chain_used (ss, 1);
8038 gfc_start_scalarized_body (&loop, &block);
8040 /* Copy each data element. */
8041 gfc_init_se (&lse, NULL);
8042 gfc_copy_loopinfo_to_se (&lse, &loop);
8043 gfc_init_se (&rse, NULL);
8044 gfc_copy_loopinfo_to_se (&rse, &loop);
8046 lse.ss = loop.temp_ss;
8047 rse.ss = ss;
8049 gfc_conv_tmp_array_ref (&lse);
8050 if (expr->ts.type == BT_CHARACTER)
8052 gfc_conv_expr (&rse, expr);
8053 if (POINTER_TYPE_P (TREE_TYPE (rse.expr)))
8054 rse.expr = build_fold_indirect_ref_loc (input_location,
8055 rse.expr);
8057 else
8058 gfc_conv_expr_val (&rse, expr);
8060 gfc_add_block_to_block (&block, &rse.pre);
8061 gfc_add_block_to_block (&block, &lse.pre);
8063 lse.string_length = rse.string_length;
8065 deep_copy = !se->data_not_needed
8066 && (expr->expr_type == EXPR_VARIABLE
8067 || expr->expr_type == EXPR_ARRAY);
8068 tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts,
8069 deep_copy, false);
8070 gfc_add_expr_to_block (&block, tmp);
8072 /* Finish the copying loops. */
8073 gfc_trans_scalarizing_loops (&loop, &block);
8075 desc = loop.temp_ss->info->data.array.descriptor;
8077 else if (expr->expr_type == EXPR_FUNCTION && !transposed_dims (ss))
8079 desc = info->descriptor;
8080 se->string_length = ss_info->string_length;
8082 else
8084 /* We pass sections without copying to a temporary. Make a new
8085 descriptor and point it at the section we want. The loop variable
8086 limits will be the limits of the section.
8087 A function may decide to repack the array to speed up access, but
8088 we're not bothered about that here. */
8089 int dim, ndim, codim;
8090 tree parm;
8091 tree parmtype;
8092 tree dtype;
8093 tree stride;
8094 tree from;
8095 tree to;
8096 tree base;
8097 tree offset;
8099 ndim = info->ref ? info->ref->u.ar.dimen : ss->dimen;
8101 if (se->want_coarray)
8103 gfc_array_ref *ar = &info->ref->u.ar;
8105 codim = gfc_get_corank (expr);
8106 for (n = 0; n < codim - 1; n++)
8108 /* Make sure we are not lost somehow. */
8109 gcc_assert (ar->dimen_type[n + ndim] == DIMEN_THIS_IMAGE);
8111 /* Make sure the call to gfc_conv_section_startstride won't
8112 generate unnecessary code to calculate stride. */
8113 gcc_assert (ar->stride[n + ndim] == NULL);
8115 gfc_conv_section_startstride (&loop.pre, ss, n + ndim);
8116 loop.from[n + loop.dimen] = info->start[n + ndim];
8117 loop.to[n + loop.dimen] = info->end[n + ndim];
8120 gcc_assert (n == codim - 1);
8121 evaluate_bound (&loop.pre, info->start, ar->start,
8122 info->descriptor, n + ndim, true,
8123 ar->as->type == AS_DEFERRED);
8124 loop.from[n + loop.dimen] = info->start[n + ndim];
8126 else
8127 codim = 0;
8129 /* Set the string_length for a character array. */
8130 if (expr->ts.type == BT_CHARACTER)
8132 if (deferred_array_component && !substr)
8133 se->string_length = ss_info->string_length;
8134 else
8135 se->string_length = gfc_get_expr_charlen (expr);
8137 if (VAR_P (se->string_length)
8138 && expr->ts.u.cl->backend_decl == se->string_length)
8139 tmp = ss_info->string_length;
8140 else
8141 tmp = se->string_length;
8143 if (expr->ts.deferred && expr->ts.u.cl->backend_decl
8144 && VAR_P (expr->ts.u.cl->backend_decl))
8145 gfc_add_modify (&se->pre, expr->ts.u.cl->backend_decl, tmp);
8146 else
8147 expr->ts.u.cl->backend_decl = tmp;
8150 /* If we have an array section, are assigning or passing an array
8151 section argument make sure that the lower bound is 1. References
8152 to the full array should otherwise keep the original bounds. */
8153 if (!info->ref || info->ref->u.ar.type != AR_FULL)
8154 for (dim = 0; dim < loop.dimen; dim++)
8155 if (!integer_onep (loop.from[dim]))
8157 tmp = fold_build2_loc (input_location, MINUS_EXPR,
8158 gfc_array_index_type, gfc_index_one_node,
8159 loop.from[dim]);
8160 loop.to[dim] = fold_build2_loc (input_location, PLUS_EXPR,
8161 gfc_array_index_type,
8162 loop.to[dim], tmp);
8163 loop.from[dim] = gfc_index_one_node;
8166 desc = info->descriptor;
8167 if (se->direct_byref && !se->byref_noassign)
8169 /* For pointer assignments we fill in the destination. */
8170 parm = se->expr;
8171 parmtype = TREE_TYPE (parm);
8173 else
8175 /* Otherwise make a new one. */
8176 if (expr->ts.type == BT_CHARACTER)
8177 parmtype = gfc_typenode_for_spec (&expr->ts);
8178 else
8179 parmtype = gfc_get_element_type (TREE_TYPE (desc));
8181 parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen, codim,
8182 loop.from, loop.to, 0,
8183 GFC_ARRAY_UNKNOWN, false);
8184 parm = gfc_create_var (parmtype, "parm");
8186 /* When expression is a class object, then add the class' handle to
8187 the parm_decl. */
8188 if (expr->ts.type == BT_CLASS && expr->expr_type == EXPR_VARIABLE)
8190 gfc_expr *class_expr = gfc_find_and_cut_at_last_class_ref (expr);
8191 gfc_se classse;
8193 /* class_expr can be NULL, when no _class ref is in expr.
8194 We must not fix this here with a gfc_fix_class_ref (). */
8195 if (class_expr)
8197 gfc_init_se (&classse, NULL);
8198 gfc_conv_expr (&classse, class_expr);
8199 gfc_free_expr (class_expr);
8201 gcc_assert (classse.pre.head == NULL_TREE
8202 && classse.post.head == NULL_TREE);
8203 gfc_allocate_lang_decl (parm);
8204 GFC_DECL_SAVED_DESCRIPTOR (parm) = classse.expr;
8209 if (expr->ts.type == BT_CHARACTER
8210 && VAR_P (TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (parm)))))
8212 tree elem_len = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (parm)));
8213 gfc_add_modify (&loop.pre, elem_len,
8214 fold_convert (TREE_TYPE (elem_len),
8215 gfc_get_array_span (desc, expr)));
8218 /* Set the span field. */
8219 tmp = NULL_TREE;
8220 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
8221 tmp = gfc_conv_descriptor_span_get (desc);
8222 else
8223 tmp = gfc_get_array_span (desc, expr);
8224 if (tmp)
8225 gfc_conv_descriptor_span_set (&loop.pre, parm, tmp);
8227 /* The following can be somewhat confusing. We have two
8228 descriptors, a new one and the original array.
8229 {parm, parmtype, dim} refer to the new one.
8230 {desc, type, n, loop} refer to the original, which maybe
8231 a descriptorless array.
8232 The bounds of the scalarization are the bounds of the section.
8233 We don't have to worry about numeric overflows when calculating
8234 the offsets because all elements are within the array data. */
8236 /* Set the dtype. */
8237 tmp = gfc_conv_descriptor_dtype (parm);
8238 if (se->unlimited_polymorphic)
8239 dtype = gfc_get_dtype (TREE_TYPE (desc), &loop.dimen);
8240 else if (expr->ts.type == BT_ASSUMED)
8242 tree tmp2 = desc;
8243 if (DECL_LANG_SPECIFIC (tmp2) && GFC_DECL_SAVED_DESCRIPTOR (tmp2))
8244 tmp2 = GFC_DECL_SAVED_DESCRIPTOR (tmp2);
8245 if (POINTER_TYPE_P (TREE_TYPE (tmp2)))
8246 tmp2 = build_fold_indirect_ref_loc (input_location, tmp2);
8247 dtype = gfc_conv_descriptor_dtype (tmp2);
8249 else
8250 dtype = gfc_get_dtype (parmtype);
8251 gfc_add_modify (&loop.pre, tmp, dtype);
8253 /* The 1st element in the section. */
8254 base = gfc_index_zero_node;
8256 /* The offset from the 1st element in the section. */
8257 offset = gfc_index_zero_node;
8259 for (n = 0; n < ndim; n++)
8261 stride = gfc_conv_array_stride (desc, n);
8263 /* Work out the 1st element in the section. */
8264 if (info->ref
8265 && info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
8267 gcc_assert (info->subscript[n]
8268 && info->subscript[n]->info->type == GFC_SS_SCALAR);
8269 start = info->subscript[n]->info->data.scalar.value;
8271 else
8273 /* Evaluate and remember the start of the section. */
8274 start = info->start[n];
8275 stride = gfc_evaluate_now (stride, &loop.pre);
8278 tmp = gfc_conv_array_lbound (desc, n);
8279 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp),
8280 start, tmp);
8281 tmp = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (tmp),
8282 tmp, stride);
8283 base = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (tmp),
8284 base, tmp);
8286 if (info->ref
8287 && info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
8289 /* For elemental dimensions, we only need the 1st
8290 element in the section. */
8291 continue;
8294 /* Vector subscripts need copying and are handled elsewhere. */
8295 if (info->ref)
8296 gcc_assert (info->ref->u.ar.dimen_type[n] == DIMEN_RANGE);
8298 /* look for the corresponding scalarizer dimension: dim. */
8299 for (dim = 0; dim < ndim; dim++)
8300 if (ss->dim[dim] == n)
8301 break;
8303 /* loop exited early: the DIM being looked for has been found. */
8304 gcc_assert (dim < ndim);
8306 /* Set the new lower bound. */
8307 from = loop.from[dim];
8308 to = loop.to[dim];
8310 gfc_conv_descriptor_lbound_set (&loop.pre, parm,
8311 gfc_rank_cst[dim], from);
8313 /* Set the new upper bound. */
8314 gfc_conv_descriptor_ubound_set (&loop.pre, parm,
8315 gfc_rank_cst[dim], to);
8317 /* Multiply the stride by the section stride to get the
8318 total stride. */
8319 stride = fold_build2_loc (input_location, MULT_EXPR,
8320 gfc_array_index_type,
8321 stride, info->stride[n]);
8323 tmp = fold_build2_loc (input_location, MULT_EXPR,
8324 TREE_TYPE (offset), stride, from);
8325 offset = fold_build2_loc (input_location, MINUS_EXPR,
8326 TREE_TYPE (offset), offset, tmp);
8328 /* Store the new stride. */
8329 gfc_conv_descriptor_stride_set (&loop.pre, parm,
8330 gfc_rank_cst[dim], stride);
8333 for (n = loop.dimen; n < loop.dimen + codim; n++)
8335 from = loop.from[n];
8336 to = loop.to[n];
8337 gfc_conv_descriptor_lbound_set (&loop.pre, parm,
8338 gfc_rank_cst[n], from);
8339 if (n < loop.dimen + codim - 1)
8340 gfc_conv_descriptor_ubound_set (&loop.pre, parm,
8341 gfc_rank_cst[n], to);
8344 if (se->data_not_needed)
8345 gfc_conv_descriptor_data_set (&loop.pre, parm,
8346 gfc_index_zero_node);
8347 else
8348 /* Point the data pointer at the 1st element in the section. */
8349 gfc_get_dataptr_offset (&loop.pre, parm, desc, base,
8350 subref_array_target, expr);
8352 gfc_conv_descriptor_offset_set (&loop.pre, parm, offset);
8354 desc = parm;
8357 /* For class arrays add the class tree into the saved descriptor to
8358 enable getting of _vptr and the like. */
8359 if (expr->expr_type == EXPR_VARIABLE && VAR_P (desc)
8360 && IS_CLASS_ARRAY (expr->symtree->n.sym))
8362 gfc_allocate_lang_decl (desc);
8363 GFC_DECL_SAVED_DESCRIPTOR (desc) =
8364 DECL_LANG_SPECIFIC (expr->symtree->n.sym->backend_decl) ?
8365 GFC_DECL_SAVED_DESCRIPTOR (expr->symtree->n.sym->backend_decl)
8366 : expr->symtree->n.sym->backend_decl;
8368 else if (expr->expr_type == EXPR_ARRAY && VAR_P (desc)
8369 && IS_CLASS_ARRAY (expr))
8371 tree vtype;
8372 gfc_allocate_lang_decl (desc);
8373 tmp = gfc_create_var (expr->ts.u.derived->backend_decl, "class");
8374 GFC_DECL_SAVED_DESCRIPTOR (desc) = tmp;
8375 vtype = gfc_class_vptr_get (tmp);
8376 gfc_add_modify (&se->pre, vtype,
8377 gfc_build_addr_expr (TREE_TYPE (vtype),
8378 gfc_find_vtab (&expr->ts)->backend_decl));
8380 if (!se->direct_byref || se->byref_noassign)
8382 /* Get a pointer to the new descriptor. */
8383 if (se->want_pointer)
8384 se->expr = gfc_build_addr_expr (NULL_TREE, desc);
8385 else
8386 se->expr = desc;
8389 gfc_add_block_to_block (&se->pre, &loop.pre);
8390 gfc_add_block_to_block (&se->post, &loop.post);
8392 /* Cleanup the scalarizer. */
8393 gfc_cleanup_loop (&loop);
8397 /* Calculate the array size (number of elements); if dim != NULL_TREE,
8398 return size for that dim (dim=0..rank-1; only for GFC_DESCRIPTOR_TYPE_P). */
8399 tree
8400 gfc_tree_array_size (stmtblock_t *block, tree desc, gfc_expr *expr, tree dim)
8402 if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
8404 gcc_assert (dim == NULL_TREE);
8405 return GFC_TYPE_ARRAY_SIZE (TREE_TYPE (desc));
8407 tree size, tmp, rank = NULL_TREE, cond = NULL_TREE;
8408 symbol_attribute attr = gfc_expr_attr (expr);
8409 gfc_array_spec *as = gfc_get_full_arrayspec_from_expr (expr);
8410 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)));
8411 if ((!attr.pointer && !attr.allocatable && as && as->type == AS_ASSUMED_RANK)
8412 || !dim)
8414 if (expr->rank < 0)
8415 rank = fold_convert (signed_char_type_node,
8416 gfc_conv_descriptor_rank (desc));
8417 else
8418 rank = build_int_cst (signed_char_type_node, expr->rank);
8421 if (dim || expr->rank == 1)
8423 if (!dim)
8424 dim = gfc_index_zero_node;
8425 tree ubound = gfc_conv_descriptor_ubound_get (desc, dim);
8426 tree lbound = gfc_conv_descriptor_lbound_get (desc, dim);
8428 size = fold_build2_loc (input_location, MINUS_EXPR,
8429 gfc_array_index_type, ubound, lbound);
8430 size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
8431 size, gfc_index_one_node);
8432 /* if (!allocatable && !pointer && assumed rank)
8433 size = (idx == rank && ubound[rank-1] == -1 ? -1 : size;
8434 else
8435 size = max (0, size); */
8436 size = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
8437 size, gfc_index_zero_node);
8438 if (!attr.pointer && !attr.allocatable
8439 && as && as->type == AS_ASSUMED_RANK)
8441 tmp = fold_build2_loc (input_location, MINUS_EXPR, signed_char_type_node,
8442 rank, build_int_cst (signed_char_type_node, 1));
8443 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
8444 fold_convert (signed_char_type_node, dim),
8445 tmp);
8446 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
8447 gfc_conv_descriptor_ubound_get (desc, dim),
8448 build_int_cst (gfc_array_index_type, -1));
8449 cond = fold_build2_loc (input_location, TRUTH_AND_EXPR, boolean_type_node,
8450 cond, tmp);
8451 tmp = build_int_cst (gfc_array_index_type, -1);
8452 size = build3_loc (input_location, COND_EXPR, gfc_array_index_type,
8453 cond, tmp, size);
8455 return size;
8458 /* size = 1. */
8459 size = gfc_create_var (gfc_array_index_type, "size");
8460 gfc_add_modify (block, size, build_int_cst (TREE_TYPE (size), 1));
8461 tree extent = gfc_create_var (gfc_array_index_type, "extent");
8463 stmtblock_t cond_block, loop_body;
8464 gfc_init_block (&cond_block);
8465 gfc_init_block (&loop_body);
8467 /* Loop: for (i = 0; i < rank; ++i). */
8468 tree idx = gfc_create_var (signed_char_type_node, "idx");
8469 /* Loop body. */
8470 /* #if (assumed-rank + !allocatable && !pointer)
8471 if (idx == rank - 1 && dim[idx].ubound == -1)
8472 extent = -1;
8473 else
8474 #endif
8475 extent = gfc->dim[i].ubound - gfc->dim[i].lbound + 1
8476 if (extent < 0)
8477 extent = 0
8478 size *= extent. */
8479 cond = NULL_TREE;
8480 if (!attr.pointer && !attr.allocatable && as && as->type == AS_ASSUMED_RANK)
8482 tmp = fold_build2_loc (input_location, MINUS_EXPR, signed_char_type_node,
8483 rank, build_int_cst (signed_char_type_node, 1));
8484 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
8485 idx, tmp);
8486 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
8487 gfc_conv_descriptor_ubound_get (desc, idx),
8488 build_int_cst (gfc_array_index_type, -1));
8489 cond = fold_build2_loc (input_location, TRUTH_AND_EXPR, boolean_type_node,
8490 cond, tmp);
8492 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
8493 gfc_conv_descriptor_ubound_get (desc, idx),
8494 gfc_conv_descriptor_lbound_get (desc, idx));
8495 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
8496 tmp, gfc_index_one_node);
8497 gfc_add_modify (&cond_block, extent, tmp);
8498 tmp = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
8499 extent, gfc_index_zero_node);
8500 tmp = build3_v (COND_EXPR, tmp,
8501 fold_build2_loc (input_location, MODIFY_EXPR,
8502 gfc_array_index_type,
8503 extent, gfc_index_zero_node),
8504 build_empty_stmt (input_location));
8505 gfc_add_expr_to_block (&cond_block, tmp);
8506 tmp = gfc_finish_block (&cond_block);
8507 if (cond)
8508 tmp = build3_v (COND_EXPR, cond,
8509 fold_build2_loc (input_location, MODIFY_EXPR,
8510 gfc_array_index_type, extent,
8511 build_int_cst (gfc_array_index_type, -1)),
8512 tmp);
8513 gfc_add_expr_to_block (&loop_body, tmp);
8514 /* size *= extent. */
8515 gfc_add_modify (&loop_body, size,
8516 fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
8517 size, extent));
8518 /* Generate loop. */
8519 gfc_simple_for_loop (block, idx, build_int_cst (TREE_TYPE (idx), 0), rank, LT_EXPR,
8520 build_int_cst (TREE_TYPE (idx), 1),
8521 gfc_finish_block (&loop_body));
8522 return size;
8525 /* Helper function for gfc_conv_array_parameter if array size needs to be
8526 computed. */
8528 static void
8529 array_parameter_size (stmtblock_t *block, tree desc, gfc_expr *expr, tree *size)
8531 tree elem;
8532 *size = gfc_tree_array_size (block, desc, expr, NULL);
8533 elem = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
8534 *size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
8535 *size, fold_convert (gfc_array_index_type, elem));
8538 /* Helper function - return true if the argument is a pointer. */
8540 static bool
8541 is_pointer (gfc_expr *e)
8543 gfc_symbol *sym;
8545 if (e->expr_type != EXPR_VARIABLE || e->symtree == NULL)
8546 return false;
8548 sym = e->symtree->n.sym;
8549 if (sym == NULL)
8550 return false;
8552 return sym->attr.pointer || sym->attr.proc_pointer;
8555 /* Convert an array for passing as an actual parameter. */
8557 void
8558 gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, bool g77,
8559 const gfc_symbol *fsym, const char *proc_name,
8560 tree *size)
8562 tree ptr;
8563 tree desc;
8564 tree tmp = NULL_TREE;
8565 tree stmt;
8566 tree parent = DECL_CONTEXT (current_function_decl);
8567 bool full_array_var;
8568 bool this_array_result;
8569 bool contiguous;
8570 bool no_pack;
8571 bool array_constructor;
8572 bool good_allocatable;
8573 bool ultimate_ptr_comp;
8574 bool ultimate_alloc_comp;
8575 gfc_symbol *sym;
8576 stmtblock_t block;
8577 gfc_ref *ref;
8579 ultimate_ptr_comp = false;
8580 ultimate_alloc_comp = false;
8582 for (ref = expr->ref; ref; ref = ref->next)
8584 if (ref->next == NULL)
8585 break;
8587 if (ref->type == REF_COMPONENT)
8589 ultimate_ptr_comp = ref->u.c.component->attr.pointer;
8590 ultimate_alloc_comp = ref->u.c.component->attr.allocatable;
8594 full_array_var = false;
8595 contiguous = false;
8597 if (expr->expr_type == EXPR_VARIABLE && ref && !ultimate_ptr_comp)
8598 full_array_var = gfc_full_array_ref_p (ref, &contiguous);
8600 sym = full_array_var ? expr->symtree->n.sym : NULL;
8602 /* The symbol should have an array specification. */
8603 gcc_assert (!sym || sym->as || ref->u.ar.as);
8605 if (expr->expr_type == EXPR_ARRAY && expr->ts.type == BT_CHARACTER)
8607 get_array_ctor_strlen (&se->pre, expr->value.constructor, &tmp);
8608 expr->ts.u.cl->backend_decl = tmp;
8609 se->string_length = tmp;
8612 /* Is this the result of the enclosing procedure? */
8613 this_array_result = (full_array_var && sym->attr.flavor == FL_PROCEDURE);
8614 if (this_array_result
8615 && (sym->backend_decl != current_function_decl)
8616 && (sym->backend_decl != parent))
8617 this_array_result = false;
8619 /* Passing address of the array if it is not pointer or assumed-shape. */
8620 if (full_array_var && g77 && !this_array_result
8621 && sym->ts.type != BT_DERIVED && sym->ts.type != BT_CLASS)
8623 tmp = gfc_get_symbol_decl (sym);
8625 if (sym->ts.type == BT_CHARACTER)
8626 se->string_length = sym->ts.u.cl->backend_decl;
8628 if (!sym->attr.pointer
8629 && sym->as
8630 && sym->as->type != AS_ASSUMED_SHAPE
8631 && sym->as->type != AS_DEFERRED
8632 && sym->as->type != AS_ASSUMED_RANK
8633 && !sym->attr.allocatable)
8635 /* Some variables are declared directly, others are declared as
8636 pointers and allocated on the heap. */
8637 if (sym->attr.dummy || POINTER_TYPE_P (TREE_TYPE (tmp)))
8638 se->expr = tmp;
8639 else
8640 se->expr = gfc_build_addr_expr (NULL_TREE, tmp);
8641 if (size)
8642 array_parameter_size (&se->pre, tmp, expr, size);
8643 return;
8646 if (sym->attr.allocatable)
8648 if (sym->attr.dummy || sym->attr.result)
8650 gfc_conv_expr_descriptor (se, expr);
8651 tmp = se->expr;
8653 if (size)
8654 array_parameter_size (&se->pre, tmp, expr, size);
8655 se->expr = gfc_conv_array_data (tmp);
8656 return;
8660 /* A convenient reduction in scope. */
8661 contiguous = g77 && !this_array_result && contiguous;
8663 /* There is no need to pack and unpack the array, if it is contiguous
8664 and not a deferred- or assumed-shape array, or if it is simply
8665 contiguous. */
8666 no_pack = ((sym && sym->as
8667 && !sym->attr.pointer
8668 && sym->as->type != AS_DEFERRED
8669 && sym->as->type != AS_ASSUMED_RANK
8670 && sym->as->type != AS_ASSUMED_SHAPE)
8672 (ref && ref->u.ar.as
8673 && ref->u.ar.as->type != AS_DEFERRED
8674 && ref->u.ar.as->type != AS_ASSUMED_RANK
8675 && ref->u.ar.as->type != AS_ASSUMED_SHAPE)
8677 gfc_is_simply_contiguous (expr, false, true));
8679 no_pack = contiguous && no_pack;
8681 /* If we have an EXPR_OP or a function returning an explicit-shaped
8682 or allocatable array, an array temporary will be generated which
8683 does not need to be packed / unpacked if passed to an
8684 explicit-shape dummy array. */
8686 if (g77)
8688 if (expr->expr_type == EXPR_OP)
8689 no_pack = 1;
8690 else if (expr->expr_type == EXPR_FUNCTION && expr->value.function.esym)
8692 gfc_symbol *result = expr->value.function.esym->result;
8693 if (result->attr.dimension
8694 && (result->as->type == AS_EXPLICIT
8695 || result->attr.allocatable
8696 || result->attr.contiguous))
8697 no_pack = 1;
8701 /* Array constructors are always contiguous and do not need packing. */
8702 array_constructor = g77 && !this_array_result && expr->expr_type == EXPR_ARRAY;
8704 /* Same is true of contiguous sections from allocatable variables. */
8705 good_allocatable = contiguous
8706 && expr->symtree
8707 && expr->symtree->n.sym->attr.allocatable;
8709 /* Or ultimate allocatable components. */
8710 ultimate_alloc_comp = contiguous && ultimate_alloc_comp;
8712 if (no_pack || array_constructor || good_allocatable || ultimate_alloc_comp)
8714 gfc_conv_expr_descriptor (se, expr);
8715 /* Deallocate the allocatable components of structures that are
8716 not variable. */
8717 if ((expr->ts.type == BT_DERIVED || expr->ts.type == BT_CLASS)
8718 && expr->ts.u.derived->attr.alloc_comp
8719 && expr->expr_type != EXPR_VARIABLE)
8721 tmp = gfc_deallocate_alloc_comp (expr->ts.u.derived, se->expr, expr->rank);
8723 /* The components shall be deallocated before their containing entity. */
8724 gfc_prepend_expr_to_block (&se->post, tmp);
8726 if (expr->ts.type == BT_CHARACTER && expr->expr_type != EXPR_FUNCTION)
8727 se->string_length = expr->ts.u.cl->backend_decl;
8728 if (size)
8729 array_parameter_size (&se->pre, se->expr, expr, size);
8730 se->expr = gfc_conv_array_data (se->expr);
8731 return;
8734 if (this_array_result)
8736 /* Result of the enclosing function. */
8737 gfc_conv_expr_descriptor (se, expr);
8738 if (size)
8739 array_parameter_size (&se->pre, se->expr, expr, size);
8740 se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
8742 if (g77 && TREE_TYPE (TREE_TYPE (se->expr)) != NULL_TREE
8743 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (se->expr))))
8744 se->expr = gfc_conv_array_data (build_fold_indirect_ref_loc (input_location,
8745 se->expr));
8747 return;
8749 else
8751 /* Every other type of array. */
8752 se->want_pointer = 1;
8753 gfc_conv_expr_descriptor (se, expr);
8755 if (size)
8756 array_parameter_size (&se->pre,
8757 build_fold_indirect_ref_loc (input_location,
8758 se->expr),
8759 expr, size);
8762 /* Deallocate the allocatable components of structures that are
8763 not variable, for descriptorless arguments.
8764 Arguments with a descriptor are handled in gfc_conv_procedure_call. */
8765 if (g77 && (expr->ts.type == BT_DERIVED || expr->ts.type == BT_CLASS)
8766 && expr->ts.u.derived->attr.alloc_comp
8767 && expr->expr_type != EXPR_VARIABLE)
8769 tmp = build_fold_indirect_ref_loc (input_location, se->expr);
8770 tmp = gfc_deallocate_alloc_comp (expr->ts.u.derived, tmp, expr->rank);
8772 /* The components shall be deallocated before their containing entity. */
8773 gfc_prepend_expr_to_block (&se->post, tmp);
8776 if (g77 || (fsym && fsym->attr.contiguous
8777 && !gfc_is_simply_contiguous (expr, false, true)))
8779 tree origptr = NULL_TREE;
8781 desc = se->expr;
8783 /* For contiguous arrays, save the original value of the descriptor. */
8784 if (!g77)
8786 origptr = gfc_create_var (pvoid_type_node, "origptr");
8787 tmp = build_fold_indirect_ref_loc (input_location, desc);
8788 tmp = gfc_conv_array_data (tmp);
8789 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
8790 TREE_TYPE (origptr), origptr,
8791 fold_convert (TREE_TYPE (origptr), tmp));
8792 gfc_add_expr_to_block (&se->pre, tmp);
8795 /* Repack the array. */
8796 if (warn_array_temporaries)
8798 if (fsym)
8799 gfc_warning (OPT_Warray_temporaries,
8800 "Creating array temporary at %L for argument %qs",
8801 &expr->where, fsym->name);
8802 else
8803 gfc_warning (OPT_Warray_temporaries,
8804 "Creating array temporary at %L", &expr->where);
8807 /* When optimizing, we can use gfc_conv_subref_array_arg for
8808 making the packing and unpacking operation visible to the
8809 optimizers. */
8811 if (g77 && flag_inline_arg_packing && expr->expr_type == EXPR_VARIABLE
8812 && !is_pointer (expr) && ! gfc_has_dimen_vector_ref (expr)
8813 && !(expr->symtree->n.sym->as
8814 && expr->symtree->n.sym->as->type == AS_ASSUMED_RANK)
8815 && (fsym == NULL || fsym->ts.type != BT_ASSUMED))
8817 gfc_conv_subref_array_arg (se, expr, g77,
8818 fsym ? fsym->attr.intent : INTENT_INOUT,
8819 false, fsym, proc_name, sym, true);
8820 return;
8823 ptr = build_call_expr_loc (input_location,
8824 gfor_fndecl_in_pack, 1, desc);
8826 if (fsym && fsym->attr.optional && sym && sym->attr.optional)
8828 tmp = gfc_conv_expr_present (sym);
8829 ptr = build3_loc (input_location, COND_EXPR, TREE_TYPE (se->expr),
8830 tmp, fold_convert (TREE_TYPE (se->expr), ptr),
8831 fold_convert (TREE_TYPE (se->expr), null_pointer_node));
8834 ptr = gfc_evaluate_now (ptr, &se->pre);
8836 /* Use the packed data for the actual argument, except for contiguous arrays,
8837 where the descriptor's data component is set. */
8838 if (g77)
8839 se->expr = ptr;
8840 else
8842 tmp = build_fold_indirect_ref_loc (input_location, desc);
8844 gfc_ss * ss = gfc_walk_expr (expr);
8845 if (!transposed_dims (ss))
8846 gfc_conv_descriptor_data_set (&se->pre, tmp, ptr);
8847 else
8849 tree old_field, new_field;
8851 /* The original descriptor has transposed dims so we can't reuse
8852 it directly; we have to create a new one. */
8853 tree old_desc = tmp;
8854 tree new_desc = gfc_create_var (TREE_TYPE (old_desc), "arg_desc");
8856 old_field = gfc_conv_descriptor_dtype (old_desc);
8857 new_field = gfc_conv_descriptor_dtype (new_desc);
8858 gfc_add_modify (&se->pre, new_field, old_field);
8860 old_field = gfc_conv_descriptor_offset (old_desc);
8861 new_field = gfc_conv_descriptor_offset (new_desc);
8862 gfc_add_modify (&se->pre, new_field, old_field);
8864 for (int i = 0; i < expr->rank; i++)
8866 old_field = gfc_conv_descriptor_dimension (old_desc,
8867 gfc_rank_cst[get_array_ref_dim_for_loop_dim (ss, i)]);
8868 new_field = gfc_conv_descriptor_dimension (new_desc,
8869 gfc_rank_cst[i]);
8870 gfc_add_modify (&se->pre, new_field, old_field);
8873 if (flag_coarray == GFC_FCOARRAY_LIB
8874 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (old_desc))
8875 && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (old_desc))
8876 == GFC_ARRAY_ALLOCATABLE)
8878 old_field = gfc_conv_descriptor_token (old_desc);
8879 new_field = gfc_conv_descriptor_token (new_desc);
8880 gfc_add_modify (&se->pre, new_field, old_field);
8883 gfc_conv_descriptor_data_set (&se->pre, new_desc, ptr);
8884 se->expr = gfc_build_addr_expr (NULL_TREE, new_desc);
8886 gfc_free_ss (ss);
8889 if (gfc_option.rtcheck & GFC_RTCHECK_ARRAY_TEMPS)
8891 char * msg;
8893 if (fsym && proc_name)
8894 msg = xasprintf ("An array temporary was created for argument "
8895 "'%s' of procedure '%s'", fsym->name, proc_name);
8896 else
8897 msg = xasprintf ("An array temporary was created");
8899 tmp = build_fold_indirect_ref_loc (input_location,
8900 desc);
8901 tmp = gfc_conv_array_data (tmp);
8902 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
8903 fold_convert (TREE_TYPE (tmp), ptr), tmp);
8905 if (fsym && fsym->attr.optional && sym && sym->attr.optional)
8906 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
8907 logical_type_node,
8908 gfc_conv_expr_present (sym), tmp);
8910 gfc_trans_runtime_check (false, true, tmp, &se->pre,
8911 &expr->where, msg);
8912 free (msg);
8915 gfc_start_block (&block);
8917 /* Copy the data back. */
8918 if (fsym == NULL || fsym->attr.intent != INTENT_IN)
8920 tmp = build_call_expr_loc (input_location,
8921 gfor_fndecl_in_unpack, 2, desc, ptr);
8922 gfc_add_expr_to_block (&block, tmp);
8925 /* Free the temporary. */
8926 tmp = gfc_call_free (ptr);
8927 gfc_add_expr_to_block (&block, tmp);
8929 stmt = gfc_finish_block (&block);
8931 gfc_init_block (&block);
8932 /* Only if it was repacked. This code needs to be executed before the
8933 loop cleanup code. */
8934 tmp = build_fold_indirect_ref_loc (input_location,
8935 desc);
8936 tmp = gfc_conv_array_data (tmp);
8937 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
8938 fold_convert (TREE_TYPE (tmp), ptr), tmp);
8940 if (fsym && fsym->attr.optional && sym && sym->attr.optional)
8941 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
8942 logical_type_node,
8943 gfc_conv_expr_present (sym), tmp);
8945 tmp = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt (input_location));
8947 gfc_add_expr_to_block (&block, tmp);
8948 gfc_add_block_to_block (&block, &se->post);
8950 gfc_init_block (&se->post);
8952 /* Reset the descriptor pointer. */
8953 if (!g77)
8955 tmp = build_fold_indirect_ref_loc (input_location, desc);
8956 gfc_conv_descriptor_data_set (&se->post, tmp, origptr);
8959 gfc_add_block_to_block (&se->post, &block);
8964 /* This helper function calculates the size in words of a full array. */
8966 tree
8967 gfc_full_array_size (stmtblock_t *block, tree decl, int rank)
8969 tree idx;
8970 tree nelems;
8971 tree tmp;
8972 idx = gfc_rank_cst[rank - 1];
8973 nelems = gfc_conv_descriptor_ubound_get (decl, idx);
8974 tmp = gfc_conv_descriptor_lbound_get (decl, idx);
8975 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
8976 nelems, tmp);
8977 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
8978 tmp, gfc_index_one_node);
8979 tmp = gfc_evaluate_now (tmp, block);
8981 nelems = gfc_conv_descriptor_stride_get (decl, idx);
8982 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
8983 nelems, tmp);
8984 return gfc_evaluate_now (tmp, block);
8988 /* Allocate dest to the same size as src, and copy src -> dest.
8989 If no_malloc is set, only the copy is done. */
8991 static tree
8992 duplicate_allocatable (tree dest, tree src, tree type, int rank,
8993 bool no_malloc, bool no_memcpy, tree str_sz,
8994 tree add_when_allocated)
8996 tree tmp;
8997 tree eltype;
8998 tree size;
8999 tree nelems;
9000 tree null_cond;
9001 tree null_data;
9002 stmtblock_t block;
9004 /* If the source is null, set the destination to null. Then,
9005 allocate memory to the destination. */
9006 gfc_init_block (&block);
9008 if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (dest)))
9010 gfc_add_modify (&block, dest, fold_convert (type, null_pointer_node));
9011 null_data = gfc_finish_block (&block);
9013 gfc_init_block (&block);
9014 eltype = TREE_TYPE (type);
9015 if (str_sz != NULL_TREE)
9016 size = str_sz;
9017 else
9018 size = TYPE_SIZE_UNIT (eltype);
9020 if (!no_malloc)
9022 tmp = gfc_call_malloc (&block, type, size);
9023 gfc_add_modify (&block, dest, fold_convert (type, tmp));
9026 if (!no_memcpy)
9028 tmp = builtin_decl_explicit (BUILT_IN_MEMCPY);
9029 tmp = build_call_expr_loc (input_location, tmp, 3, dest, src,
9030 fold_convert (size_type_node, size));
9031 gfc_add_expr_to_block (&block, tmp);
9034 else
9036 gfc_conv_descriptor_data_set (&block, dest, null_pointer_node);
9037 null_data = gfc_finish_block (&block);
9039 gfc_init_block (&block);
9040 if (rank)
9041 nelems = gfc_full_array_size (&block, src, rank);
9042 else
9043 nelems = gfc_index_one_node;
9045 /* If type is not the array type, then it is the element type. */
9046 if (GFC_ARRAY_TYPE_P (type) || GFC_DESCRIPTOR_TYPE_P (type))
9047 eltype = gfc_get_element_type (type);
9048 else
9049 eltype = type;
9051 if (str_sz != NULL_TREE)
9052 tmp = fold_convert (gfc_array_index_type, str_sz);
9053 else
9054 tmp = fold_convert (gfc_array_index_type,
9055 TYPE_SIZE_UNIT (eltype));
9057 tmp = gfc_evaluate_now (tmp, &block);
9058 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
9059 nelems, tmp);
9060 if (!no_malloc)
9062 tmp = TREE_TYPE (gfc_conv_descriptor_data_get (src));
9063 tmp = gfc_call_malloc (&block, tmp, size);
9064 gfc_conv_descriptor_data_set (&block, dest, tmp);
9067 /* We know the temporary and the value will be the same length,
9068 so can use memcpy. */
9069 if (!no_memcpy)
9071 tmp = builtin_decl_explicit (BUILT_IN_MEMCPY);
9072 tmp = build_call_expr_loc (input_location, tmp, 3,
9073 gfc_conv_descriptor_data_get (dest),
9074 gfc_conv_descriptor_data_get (src),
9075 fold_convert (size_type_node, size));
9076 gfc_add_expr_to_block (&block, tmp);
9080 gfc_add_expr_to_block (&block, add_when_allocated);
9081 tmp = gfc_finish_block (&block);
9083 /* Null the destination if the source is null; otherwise do
9084 the allocate and copy. */
9085 if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (src)))
9086 null_cond = src;
9087 else
9088 null_cond = gfc_conv_descriptor_data_get (src);
9090 null_cond = convert (pvoid_type_node, null_cond);
9091 null_cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
9092 null_cond, null_pointer_node);
9093 return build3_v (COND_EXPR, null_cond, tmp, null_data);
9097 /* Allocate dest to the same size as src, and copy data src -> dest. */
9099 tree
9100 gfc_duplicate_allocatable (tree dest, tree src, tree type, int rank,
9101 tree add_when_allocated)
9103 return duplicate_allocatable (dest, src, type, rank, false, false,
9104 NULL_TREE, add_when_allocated);
9108 /* Copy data src -> dest. */
9110 tree
9111 gfc_copy_allocatable_data (tree dest, tree src, tree type, int rank)
9113 return duplicate_allocatable (dest, src, type, rank, true, false,
9114 NULL_TREE, NULL_TREE);
9117 /* Allocate dest to the same size as src, but don't copy anything. */
9119 tree
9120 gfc_duplicate_allocatable_nocopy (tree dest, tree src, tree type, int rank)
9122 return duplicate_allocatable (dest, src, type, rank, false, true,
9123 NULL_TREE, NULL_TREE);
9127 static tree
9128 duplicate_allocatable_coarray (tree dest, tree dest_tok, tree src,
9129 tree type, int rank)
9131 tree tmp;
9132 tree size;
9133 tree nelems;
9134 tree null_cond;
9135 tree null_data;
9136 stmtblock_t block, globalblock;
9138 /* If the source is null, set the destination to null. Then,
9139 allocate memory to the destination. */
9140 gfc_init_block (&block);
9141 gfc_init_block (&globalblock);
9143 if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (dest)))
9145 gfc_se se;
9146 symbol_attribute attr;
9147 tree dummy_desc;
9149 gfc_init_se (&se, NULL);
9150 gfc_clear_attr (&attr);
9151 attr.allocatable = 1;
9152 dummy_desc = gfc_conv_scalar_to_descriptor (&se, dest, attr);
9153 gfc_add_block_to_block (&globalblock, &se.pre);
9154 size = TYPE_SIZE_UNIT (TREE_TYPE (type));
9156 gfc_add_modify (&block, dest, fold_convert (type, null_pointer_node));
9157 gfc_allocate_using_caf_lib (&block, dummy_desc, size,
9158 gfc_build_addr_expr (NULL_TREE, dest_tok),
9159 NULL_TREE, NULL_TREE, NULL_TREE,
9160 GFC_CAF_COARRAY_ALLOC_REGISTER_ONLY);
9161 null_data = gfc_finish_block (&block);
9163 gfc_init_block (&block);
9165 gfc_allocate_using_caf_lib (&block, dummy_desc,
9166 fold_convert (size_type_node, size),
9167 gfc_build_addr_expr (NULL_TREE, dest_tok),
9168 NULL_TREE, NULL_TREE, NULL_TREE,
9169 GFC_CAF_COARRAY_ALLOC);
9171 tmp = builtin_decl_explicit (BUILT_IN_MEMCPY);
9172 tmp = build_call_expr_loc (input_location, tmp, 3, dest, src,
9173 fold_convert (size_type_node, size));
9174 gfc_add_expr_to_block (&block, tmp);
9176 else
9178 /* Set the rank or unitialized memory access may be reported. */
9179 tmp = gfc_conv_descriptor_rank (dest);
9180 gfc_add_modify (&globalblock, tmp, build_int_cst (TREE_TYPE (tmp), rank));
9182 if (rank)
9183 nelems = gfc_full_array_size (&block, src, rank);
9184 else
9185 nelems = integer_one_node;
9187 tmp = fold_convert (size_type_node,
9188 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
9189 size = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
9190 fold_convert (size_type_node, nelems), tmp);
9192 gfc_conv_descriptor_data_set (&block, dest, null_pointer_node);
9193 gfc_allocate_using_caf_lib (&block, dest, fold_convert (size_type_node,
9194 size),
9195 gfc_build_addr_expr (NULL_TREE, dest_tok),
9196 NULL_TREE, NULL_TREE, NULL_TREE,
9197 GFC_CAF_COARRAY_ALLOC_REGISTER_ONLY);
9198 null_data = gfc_finish_block (&block);
9200 gfc_init_block (&block);
9201 gfc_allocate_using_caf_lib (&block, dest,
9202 fold_convert (size_type_node, size),
9203 gfc_build_addr_expr (NULL_TREE, dest_tok),
9204 NULL_TREE, NULL_TREE, NULL_TREE,
9205 GFC_CAF_COARRAY_ALLOC);
9207 tmp = builtin_decl_explicit (BUILT_IN_MEMCPY);
9208 tmp = build_call_expr_loc (input_location, tmp, 3,
9209 gfc_conv_descriptor_data_get (dest),
9210 gfc_conv_descriptor_data_get (src),
9211 fold_convert (size_type_node, size));
9212 gfc_add_expr_to_block (&block, tmp);
9215 tmp = gfc_finish_block (&block);
9217 /* Null the destination if the source is null; otherwise do
9218 the register and copy. */
9219 if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (src)))
9220 null_cond = src;
9221 else
9222 null_cond = gfc_conv_descriptor_data_get (src);
9224 null_cond = convert (pvoid_type_node, null_cond);
9225 null_cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
9226 null_cond, null_pointer_node);
9227 gfc_add_expr_to_block (&globalblock, build3_v (COND_EXPR, null_cond, tmp,
9228 null_data));
9229 return gfc_finish_block (&globalblock);
9233 /* Helper function to abstract whether coarray processing is enabled. */
9235 static bool
9236 caf_enabled (int caf_mode)
9238 return (caf_mode & GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY)
9239 == GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY;
9243 /* Helper function to abstract whether coarray processing is enabled
9244 and we are in a derived type coarray. */
9246 static bool
9247 caf_in_coarray (int caf_mode)
9249 static const int pat = GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY
9250 | GFC_STRUCTURE_CAF_MODE_IN_COARRAY;
9251 return (caf_mode & pat) == pat;
9255 /* Helper function to abstract whether coarray is to deallocate only. */
9257 bool
9258 gfc_caf_is_dealloc_only (int caf_mode)
9260 return (caf_mode & GFC_STRUCTURE_CAF_MODE_DEALLOC_ONLY)
9261 == GFC_STRUCTURE_CAF_MODE_DEALLOC_ONLY;
9265 /* Recursively traverse an object of derived type, generating code to
9266 deallocate, nullify or copy allocatable components. This is the work horse
9267 function for the functions named in this enum. */
9269 enum {DEALLOCATE_ALLOC_COMP = 1, NULLIFY_ALLOC_COMP,
9270 COPY_ALLOC_COMP, COPY_ONLY_ALLOC_COMP, REASSIGN_CAF_COMP,
9271 ALLOCATE_PDT_COMP, DEALLOCATE_PDT_COMP, CHECK_PDT_DUMMY,
9272 BCAST_ALLOC_COMP};
9274 static gfc_actual_arglist *pdt_param_list;
9276 static tree
9277 structure_alloc_comps (gfc_symbol * der_type, tree decl, tree dest,
9278 int rank, int purpose, int caf_mode,
9279 gfc_co_subroutines_args *args,
9280 bool no_finalization = false)
9282 gfc_component *c;
9283 gfc_loopinfo loop;
9284 stmtblock_t fnblock;
9285 stmtblock_t loopbody;
9286 stmtblock_t tmpblock;
9287 tree decl_type;
9288 tree tmp;
9289 tree comp;
9290 tree dcmp;
9291 tree nelems;
9292 tree index;
9293 tree var;
9294 tree cdecl;
9295 tree ctype;
9296 tree vref, dref;
9297 tree null_cond = NULL_TREE;
9298 tree add_when_allocated;
9299 tree dealloc_fndecl;
9300 tree caf_token;
9301 gfc_symbol *vtab;
9302 int caf_dereg_mode;
9303 symbol_attribute *attr;
9304 bool deallocate_called;
9306 gfc_init_block (&fnblock);
9308 decl_type = TREE_TYPE (decl);
9310 if ((POINTER_TYPE_P (decl_type))
9311 || (TREE_CODE (decl_type) == REFERENCE_TYPE && rank == 0))
9313 decl = build_fold_indirect_ref_loc (input_location, decl);
9314 /* Deref dest in sync with decl, but only when it is not NULL. */
9315 if (dest)
9316 dest = build_fold_indirect_ref_loc (input_location, dest);
9318 /* Update the decl_type because it got dereferenced. */
9319 decl_type = TREE_TYPE (decl);
9322 /* If this is an array of derived types with allocatable components
9323 build a loop and recursively call this function. */
9324 if (TREE_CODE (decl_type) == ARRAY_TYPE
9325 || (GFC_DESCRIPTOR_TYPE_P (decl_type) && rank != 0))
9327 tmp = gfc_conv_array_data (decl);
9328 var = build_fold_indirect_ref_loc (input_location, tmp);
9330 /* Get the number of elements - 1 and set the counter. */
9331 if (GFC_DESCRIPTOR_TYPE_P (decl_type))
9333 /* Use the descriptor for an allocatable array. Since this
9334 is a full array reference, we only need the descriptor
9335 information from dimension = rank. */
9336 tmp = gfc_full_array_size (&fnblock, decl, rank);
9337 tmp = fold_build2_loc (input_location, MINUS_EXPR,
9338 gfc_array_index_type, tmp,
9339 gfc_index_one_node);
9341 null_cond = gfc_conv_descriptor_data_get (decl);
9342 null_cond = fold_build2_loc (input_location, NE_EXPR,
9343 logical_type_node, null_cond,
9344 build_int_cst (TREE_TYPE (null_cond), 0));
9346 else
9348 /* Otherwise use the TYPE_DOMAIN information. */
9349 tmp = array_type_nelts (decl_type);
9350 tmp = fold_convert (gfc_array_index_type, tmp);
9353 /* Remember that this is, in fact, the no. of elements - 1. */
9354 nelems = gfc_evaluate_now (tmp, &fnblock);
9355 index = gfc_create_var (gfc_array_index_type, "S");
9357 /* Build the body of the loop. */
9358 gfc_init_block (&loopbody);
9360 vref = gfc_build_array_ref (var, index, NULL);
9362 if (purpose == COPY_ALLOC_COMP || purpose == COPY_ONLY_ALLOC_COMP)
9364 tmp = build_fold_indirect_ref_loc (input_location,
9365 gfc_conv_array_data (dest));
9366 dref = gfc_build_array_ref (tmp, index, NULL);
9367 tmp = structure_alloc_comps (der_type, vref, dref, rank,
9368 COPY_ALLOC_COMP, caf_mode, args,
9369 no_finalization);
9371 else
9372 tmp = structure_alloc_comps (der_type, vref, NULL_TREE, rank, purpose,
9373 caf_mode, args, no_finalization);
9375 gfc_add_expr_to_block (&loopbody, tmp);
9377 /* Build the loop and return. */
9378 gfc_init_loopinfo (&loop);
9379 loop.dimen = 1;
9380 loop.from[0] = gfc_index_zero_node;
9381 loop.loopvar[0] = index;
9382 loop.to[0] = nelems;
9383 gfc_trans_scalarizing_loops (&loop, &loopbody);
9384 gfc_add_block_to_block (&fnblock, &loop.pre);
9386 tmp = gfc_finish_block (&fnblock);
9387 /* When copying allocateable components, the above implements the
9388 deep copy. Nevertheless is a deep copy only allowed, when the current
9389 component is allocated, for which code will be generated in
9390 gfc_duplicate_allocatable (), where the deep copy code is just added
9391 into the if's body, by adding tmp (the deep copy code) as last
9392 argument to gfc_duplicate_allocatable (). */
9393 if (purpose == COPY_ALLOC_COMP
9394 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (dest)))
9395 tmp = gfc_duplicate_allocatable (dest, decl, decl_type, rank,
9396 tmp);
9397 else if (null_cond != NULL_TREE)
9398 tmp = build3_v (COND_EXPR, null_cond, tmp,
9399 build_empty_stmt (input_location));
9401 return tmp;
9404 if (purpose == DEALLOCATE_ALLOC_COMP && der_type->attr.pdt_type)
9406 tmp = structure_alloc_comps (der_type, decl, NULL_TREE, rank,
9407 DEALLOCATE_PDT_COMP, 0, args,
9408 no_finalization);
9409 gfc_add_expr_to_block (&fnblock, tmp);
9411 else if (purpose == ALLOCATE_PDT_COMP && der_type->attr.alloc_comp)
9413 tmp = structure_alloc_comps (der_type, decl, NULL_TREE, rank,
9414 NULLIFY_ALLOC_COMP, 0, args,
9415 no_finalization);
9416 gfc_add_expr_to_block (&fnblock, tmp);
9419 /* Still having a descriptor array of rank == 0 here, indicates an
9420 allocatable coarrays. Dereference it correctly. */
9421 if (GFC_DESCRIPTOR_TYPE_P (decl_type))
9423 decl = build_fold_indirect_ref (gfc_conv_array_data (decl));
9425 /* Otherwise, act on the components or recursively call self to
9426 act on a chain of components. */
9427 for (c = der_type->components; c; c = c->next)
9429 bool cmp_has_alloc_comps = (c->ts.type == BT_DERIVED
9430 || c->ts.type == BT_CLASS)
9431 && c->ts.u.derived->attr.alloc_comp;
9432 bool same_type = (c->ts.type == BT_DERIVED && der_type == c->ts.u.derived)
9433 || (c->ts.type == BT_CLASS && der_type == CLASS_DATA (c)->ts.u.derived);
9435 bool is_pdt_type = c->ts.type == BT_DERIVED
9436 && c->ts.u.derived->attr.pdt_type;
9438 cdecl = c->backend_decl;
9439 ctype = TREE_TYPE (cdecl);
9441 switch (purpose)
9444 case BCAST_ALLOC_COMP:
9446 tree ubound;
9447 tree cdesc;
9448 stmtblock_t derived_type_block;
9450 gfc_init_block (&tmpblock);
9452 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
9453 decl, cdecl, NULL_TREE);
9455 /* Shortcut to get the attributes of the component. */
9456 if (c->ts.type == BT_CLASS)
9458 attr = &CLASS_DATA (c)->attr;
9459 if (attr->class_pointer)
9460 continue;
9462 else
9464 attr = &c->attr;
9465 if (attr->pointer)
9466 continue;
9469 /* Do not broadcast a caf_token. These are local to the image. */
9470 if (attr->caf_token)
9471 continue;
9473 add_when_allocated = NULL_TREE;
9474 if (cmp_has_alloc_comps
9475 && !c->attr.pointer && !c->attr.proc_pointer)
9477 if (c->ts.type == BT_CLASS)
9479 rank = CLASS_DATA (c)->as ? CLASS_DATA (c)->as->rank : 0;
9480 add_when_allocated
9481 = structure_alloc_comps (CLASS_DATA (c)->ts.u.derived,
9482 comp, NULL_TREE, rank, purpose,
9483 caf_mode, args, no_finalization);
9485 else
9487 rank = c->as ? c->as->rank : 0;
9488 add_when_allocated = structure_alloc_comps (c->ts.u.derived,
9489 comp, NULL_TREE,
9490 rank, purpose,
9491 caf_mode, args,
9492 no_finalization);
9496 gfc_init_block (&derived_type_block);
9497 if (add_when_allocated)
9498 gfc_add_expr_to_block (&derived_type_block, add_when_allocated);
9499 tmp = gfc_finish_block (&derived_type_block);
9500 gfc_add_expr_to_block (&tmpblock, tmp);
9502 /* Convert the component into a rank 1 descriptor type. */
9503 if (attr->dimension)
9505 tmp = gfc_get_element_type (TREE_TYPE (comp));
9506 if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (comp)))
9507 ubound = GFC_TYPE_ARRAY_SIZE (TREE_TYPE (comp));
9508 else
9509 ubound = gfc_full_array_size (&tmpblock, comp,
9510 c->ts.type == BT_CLASS
9511 ? CLASS_DATA (c)->as->rank
9512 : c->as->rank);
9514 else
9516 tmp = TREE_TYPE (comp);
9517 ubound = build_int_cst (gfc_array_index_type, 1);
9520 /* Treat strings like arrays. Or the other way around, do not
9521 * generate an additional array layer for scalar components. */
9522 if (attr->dimension || c->ts.type == BT_CHARACTER)
9524 cdesc = gfc_get_array_type_bounds (tmp, 1, 0, &gfc_index_one_node,
9525 &ubound, 1,
9526 GFC_ARRAY_ALLOCATABLE, false);
9528 cdesc = gfc_create_var (cdesc, "cdesc");
9529 DECL_ARTIFICIAL (cdesc) = 1;
9531 gfc_add_modify (&tmpblock, gfc_conv_descriptor_dtype (cdesc),
9532 gfc_get_dtype_rank_type (1, tmp));
9533 gfc_conv_descriptor_lbound_set (&tmpblock, cdesc,
9534 gfc_index_zero_node,
9535 gfc_index_one_node);
9536 gfc_conv_descriptor_stride_set (&tmpblock, cdesc,
9537 gfc_index_zero_node,
9538 gfc_index_one_node);
9539 gfc_conv_descriptor_ubound_set (&tmpblock, cdesc,
9540 gfc_index_zero_node, ubound);
9542 else
9543 /* Prevent warning. */
9544 cdesc = NULL_TREE;
9546 if (attr->dimension)
9548 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (comp)))
9549 comp = gfc_conv_descriptor_data_get (comp);
9550 else
9551 comp = gfc_build_addr_expr (NULL_TREE, comp);
9553 else
9555 gfc_se se;
9557 gfc_init_se (&se, NULL);
9559 comp = gfc_conv_scalar_to_descriptor (&se, comp,
9560 c->ts.type == BT_CLASS
9561 ? CLASS_DATA (c)->attr
9562 : c->attr);
9563 if (c->ts.type == BT_CHARACTER)
9564 comp = gfc_build_addr_expr (NULL_TREE, comp);
9565 gfc_add_block_to_block (&tmpblock, &se.pre);
9568 if (attr->dimension || c->ts.type == BT_CHARACTER)
9569 gfc_conv_descriptor_data_set (&tmpblock, cdesc, comp);
9570 else
9571 cdesc = comp;
9573 tree fndecl;
9575 fndecl = build_call_expr_loc (input_location,
9576 gfor_fndecl_co_broadcast, 5,
9577 gfc_build_addr_expr (pvoid_type_node,cdesc),
9578 args->image_index,
9579 null_pointer_node, null_pointer_node,
9580 null_pointer_node);
9582 gfc_add_expr_to_block (&tmpblock, fndecl);
9583 gfc_add_block_to_block (&fnblock, &tmpblock);
9585 break;
9587 case DEALLOCATE_ALLOC_COMP:
9589 gfc_init_block (&tmpblock);
9591 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
9592 decl, cdecl, NULL_TREE);
9594 /* Shortcut to get the attributes of the component. */
9595 if (c->ts.type == BT_CLASS)
9597 attr = &CLASS_DATA (c)->attr;
9598 if (attr->class_pointer)
9599 continue;
9601 else
9603 attr = &c->attr;
9604 if (attr->pointer)
9605 continue;
9608 if (!no_finalization && ((c->ts.type == BT_DERIVED && !c->attr.pointer)
9609 || (c->ts.type == BT_CLASS && !CLASS_DATA (c)->attr.class_pointer)))
9610 /* Call the finalizer, which will free the memory and nullify the
9611 pointer of an array. */
9612 deallocate_called = gfc_add_comp_finalizer_call (&tmpblock, comp, c,
9613 caf_enabled (caf_mode))
9614 && attr->dimension;
9615 else
9616 deallocate_called = false;
9618 /* Add the _class ref for classes. */
9619 if (c->ts.type == BT_CLASS && attr->allocatable)
9620 comp = gfc_class_data_get (comp);
9622 add_when_allocated = NULL_TREE;
9623 if (cmp_has_alloc_comps
9624 && !c->attr.pointer && !c->attr.proc_pointer
9625 && !same_type
9626 && !deallocate_called)
9628 /* Add checked deallocation of the components. This code is
9629 obviously added because the finalizer is not trusted to free
9630 all memory. */
9631 if (c->ts.type == BT_CLASS)
9633 rank = CLASS_DATA (c)->as ? CLASS_DATA (c)->as->rank : 0;
9634 add_when_allocated
9635 = structure_alloc_comps (CLASS_DATA (c)->ts.u.derived,
9636 comp, NULL_TREE, rank, purpose,
9637 caf_mode, args, no_finalization);
9639 else
9641 rank = c->as ? c->as->rank : 0;
9642 add_when_allocated = structure_alloc_comps (c->ts.u.derived,
9643 comp, NULL_TREE,
9644 rank, purpose,
9645 caf_mode, args,
9646 no_finalization);
9650 if (attr->allocatable && !same_type
9651 && (!attr->codimension || caf_enabled (caf_mode)))
9653 /* Handle all types of components besides components of the
9654 same_type as the current one, because those would create an
9655 endless loop. */
9656 caf_dereg_mode
9657 = (caf_in_coarray (caf_mode) || attr->codimension)
9658 ? (gfc_caf_is_dealloc_only (caf_mode)
9659 ? GFC_CAF_COARRAY_DEALLOCATE_ONLY
9660 : GFC_CAF_COARRAY_DEREGISTER)
9661 : GFC_CAF_COARRAY_NOCOARRAY;
9663 caf_token = NULL_TREE;
9664 /* Coarray components are handled directly by
9665 deallocate_with_status. */
9666 if (!attr->codimension
9667 && caf_dereg_mode != GFC_CAF_COARRAY_NOCOARRAY)
9669 if (c->caf_token)
9670 caf_token = fold_build3_loc (input_location, COMPONENT_REF,
9671 TREE_TYPE (c->caf_token),
9672 decl, c->caf_token, NULL_TREE);
9673 else if (attr->dimension && !attr->proc_pointer)
9674 caf_token = gfc_conv_descriptor_token (comp);
9677 tmp = gfc_deallocate_with_status (comp, NULL_TREE, NULL_TREE,
9678 NULL_TREE, NULL_TREE, true,
9679 NULL, caf_dereg_mode, NULL_TREE,
9680 add_when_allocated, caf_token);
9682 gfc_add_expr_to_block (&tmpblock, tmp);
9684 else if (attr->allocatable && !attr->codimension
9685 && !deallocate_called)
9687 /* Case of recursive allocatable derived types. */
9688 tree is_allocated;
9689 tree ubound;
9690 tree cdesc;
9691 stmtblock_t dealloc_block;
9693 gfc_init_block (&dealloc_block);
9694 if (add_when_allocated)
9695 gfc_add_expr_to_block (&dealloc_block, add_when_allocated);
9697 /* Convert the component into a rank 1 descriptor type. */
9698 if (attr->dimension)
9700 tmp = gfc_get_element_type (TREE_TYPE (comp));
9701 ubound = gfc_full_array_size (&dealloc_block, comp,
9702 c->ts.type == BT_CLASS
9703 ? CLASS_DATA (c)->as->rank
9704 : c->as->rank);
9706 else
9708 tmp = TREE_TYPE (comp);
9709 ubound = build_int_cst (gfc_array_index_type, 1);
9712 cdesc = gfc_get_array_type_bounds (tmp, 1, 0, &gfc_index_one_node,
9713 &ubound, 1,
9714 GFC_ARRAY_ALLOCATABLE, false);
9716 cdesc = gfc_create_var (cdesc, "cdesc");
9717 DECL_ARTIFICIAL (cdesc) = 1;
9719 gfc_add_modify (&dealloc_block, gfc_conv_descriptor_dtype (cdesc),
9720 gfc_get_dtype_rank_type (1, tmp));
9721 gfc_conv_descriptor_lbound_set (&dealloc_block, cdesc,
9722 gfc_index_zero_node,
9723 gfc_index_one_node);
9724 gfc_conv_descriptor_stride_set (&dealloc_block, cdesc,
9725 gfc_index_zero_node,
9726 gfc_index_one_node);
9727 gfc_conv_descriptor_ubound_set (&dealloc_block, cdesc,
9728 gfc_index_zero_node, ubound);
9730 if (attr->dimension)
9731 comp = gfc_conv_descriptor_data_get (comp);
9733 gfc_conv_descriptor_data_set (&dealloc_block, cdesc, comp);
9735 /* Now call the deallocator. */
9736 vtab = gfc_find_vtab (&c->ts);
9737 if (vtab->backend_decl == NULL)
9738 gfc_get_symbol_decl (vtab);
9739 tmp = gfc_build_addr_expr (NULL_TREE, vtab->backend_decl);
9740 dealloc_fndecl = gfc_vptr_deallocate_get (tmp);
9741 dealloc_fndecl = build_fold_indirect_ref_loc (input_location,
9742 dealloc_fndecl);
9743 tmp = build_int_cst (TREE_TYPE (comp), 0);
9744 is_allocated = fold_build2_loc (input_location, NE_EXPR,
9745 logical_type_node, tmp,
9746 comp);
9747 cdesc = gfc_build_addr_expr (NULL_TREE, cdesc);
9749 tmp = build_call_expr_loc (input_location,
9750 dealloc_fndecl, 1,
9751 cdesc);
9752 gfc_add_expr_to_block (&dealloc_block, tmp);
9754 tmp = gfc_finish_block (&dealloc_block);
9756 tmp = fold_build3_loc (input_location, COND_EXPR,
9757 void_type_node, is_allocated, tmp,
9758 build_empty_stmt (input_location));
9760 gfc_add_expr_to_block (&tmpblock, tmp);
9762 else if (add_when_allocated)
9763 gfc_add_expr_to_block (&tmpblock, add_when_allocated);
9765 if (c->ts.type == BT_CLASS && attr->allocatable
9766 && (!attr->codimension || !caf_enabled (caf_mode)))
9768 /* Finally, reset the vptr to the declared type vtable and, if
9769 necessary reset the _len field.
9771 First recover the reference to the component and obtain
9772 the vptr. */
9773 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
9774 decl, cdecl, NULL_TREE);
9775 tmp = gfc_class_vptr_get (comp);
9777 if (UNLIMITED_POLY (c))
9779 /* Both vptr and _len field should be nulled. */
9780 gfc_add_modify (&tmpblock, tmp,
9781 build_int_cst (TREE_TYPE (tmp), 0));
9782 tmp = gfc_class_len_get (comp);
9783 gfc_add_modify (&tmpblock, tmp,
9784 build_int_cst (TREE_TYPE (tmp), 0));
9786 else
9788 /* Build the vtable address and set the vptr with it. */
9789 tree vtab;
9790 gfc_symbol *vtable;
9791 vtable = gfc_find_derived_vtab (c->ts.u.derived);
9792 vtab = vtable->backend_decl;
9793 if (vtab == NULL_TREE)
9794 vtab = gfc_get_symbol_decl (vtable);
9795 vtab = gfc_build_addr_expr (NULL, vtab);
9796 vtab = fold_convert (TREE_TYPE (tmp), vtab);
9797 gfc_add_modify (&tmpblock, tmp, vtab);
9801 /* Now add the deallocation of this component. */
9802 gfc_add_block_to_block (&fnblock, &tmpblock);
9803 break;
9805 case NULLIFY_ALLOC_COMP:
9806 /* Nullify
9807 - allocatable components (regular or in class)
9808 - components that have allocatable components
9809 - pointer components when in a coarray.
9810 Skip everything else especially proc_pointers, which may come
9811 coupled with the regular pointer attribute. */
9812 if (c->attr.proc_pointer
9813 || !(c->attr.allocatable || (c->ts.type == BT_CLASS
9814 && CLASS_DATA (c)->attr.allocatable)
9815 || (cmp_has_alloc_comps
9816 && ((c->ts.type == BT_DERIVED && !c->attr.pointer)
9817 || (c->ts.type == BT_CLASS
9818 && !CLASS_DATA (c)->attr.class_pointer)))
9819 || (caf_in_coarray (caf_mode) && c->attr.pointer)))
9820 continue;
9822 /* Process class components first, because they always have the
9823 pointer-attribute set which would be caught wrong else. */
9824 if (c->ts.type == BT_CLASS
9825 && (CLASS_DATA (c)->attr.allocatable
9826 || CLASS_DATA (c)->attr.class_pointer))
9828 tree vptr_decl;
9830 /* Allocatable CLASS components. */
9831 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
9832 decl, cdecl, NULL_TREE);
9834 vptr_decl = gfc_class_vptr_get (comp);
9836 comp = gfc_class_data_get (comp);
9837 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (comp)))
9838 gfc_conv_descriptor_data_set (&fnblock, comp,
9839 null_pointer_node);
9840 else
9842 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
9843 void_type_node, comp,
9844 build_int_cst (TREE_TYPE (comp), 0));
9845 gfc_add_expr_to_block (&fnblock, tmp);
9848 /* The dynamic type of a disassociated pointer or unallocated
9849 allocatable variable is its declared type. An unlimited
9850 polymorphic entity has no declared type. */
9851 if (!UNLIMITED_POLY (c))
9853 vtab = gfc_find_derived_vtab (c->ts.u.derived);
9854 if (!vtab->backend_decl)
9855 gfc_get_symbol_decl (vtab);
9856 tmp = gfc_build_addr_expr (NULL_TREE, vtab->backend_decl);
9858 else
9859 tmp = build_int_cst (TREE_TYPE (vptr_decl), 0);
9861 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
9862 void_type_node, vptr_decl, tmp);
9863 gfc_add_expr_to_block (&fnblock, tmp);
9865 cmp_has_alloc_comps = false;
9867 /* Coarrays need the component to be nulled before the api-call
9868 is made. */
9869 else if (c->attr.pointer || c->attr.allocatable)
9871 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
9872 decl, cdecl, NULL_TREE);
9873 if (c->attr.dimension || c->attr.codimension)
9874 gfc_conv_descriptor_data_set (&fnblock, comp,
9875 null_pointer_node);
9876 else
9877 gfc_add_modify (&fnblock, comp,
9878 build_int_cst (TREE_TYPE (comp), 0));
9879 if (gfc_deferred_strlen (c, &comp))
9881 comp = fold_build3_loc (input_location, COMPONENT_REF,
9882 TREE_TYPE (comp),
9883 decl, comp, NULL_TREE);
9884 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
9885 TREE_TYPE (comp), comp,
9886 build_int_cst (TREE_TYPE (comp), 0));
9887 gfc_add_expr_to_block (&fnblock, tmp);
9889 cmp_has_alloc_comps = false;
9892 if (flag_coarray == GFC_FCOARRAY_LIB && caf_in_coarray (caf_mode))
9894 /* Register a component of a derived type coarray with the
9895 coarray library. Do not register ultimate component
9896 coarrays here. They are treated like regular coarrays and
9897 are either allocated on all images or on none. */
9898 tree token;
9900 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
9901 decl, cdecl, NULL_TREE);
9902 if (c->attr.dimension)
9904 /* Set the dtype, because caf_register needs it. */
9905 gfc_add_modify (&fnblock, gfc_conv_descriptor_dtype (comp),
9906 gfc_get_dtype (TREE_TYPE (comp)));
9907 tmp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
9908 decl, cdecl, NULL_TREE);
9909 token = gfc_conv_descriptor_token (tmp);
9911 else
9913 gfc_se se;
9915 gfc_init_se (&se, NULL);
9916 token = fold_build3_loc (input_location, COMPONENT_REF,
9917 pvoid_type_node, decl, c->caf_token,
9918 NULL_TREE);
9919 comp = gfc_conv_scalar_to_descriptor (&se, comp,
9920 c->ts.type == BT_CLASS
9921 ? CLASS_DATA (c)->attr
9922 : c->attr);
9923 gfc_add_block_to_block (&fnblock, &se.pre);
9926 gfc_allocate_using_caf_lib (&fnblock, comp, size_zero_node,
9927 gfc_build_addr_expr (NULL_TREE,
9928 token),
9929 NULL_TREE, NULL_TREE, NULL_TREE,
9930 GFC_CAF_COARRAY_ALLOC_REGISTER_ONLY);
9933 if (cmp_has_alloc_comps)
9935 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
9936 decl, cdecl, NULL_TREE);
9937 rank = c->as ? c->as->rank : 0;
9938 tmp = structure_alloc_comps (c->ts.u.derived, comp, NULL_TREE,
9939 rank, purpose, caf_mode, args,
9940 no_finalization);
9941 gfc_add_expr_to_block (&fnblock, tmp);
9943 break;
9945 case REASSIGN_CAF_COMP:
9946 if (caf_enabled (caf_mode)
9947 && (c->attr.codimension
9948 || (c->ts.type == BT_CLASS
9949 && (CLASS_DATA (c)->attr.coarray_comp
9950 || caf_in_coarray (caf_mode)))
9951 || (c->ts.type == BT_DERIVED
9952 && (c->ts.u.derived->attr.coarray_comp
9953 || caf_in_coarray (caf_mode))))
9954 && !same_type)
9956 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
9957 decl, cdecl, NULL_TREE);
9958 dcmp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
9959 dest, cdecl, NULL_TREE);
9961 if (c->attr.codimension)
9963 if (c->ts.type == BT_CLASS)
9965 comp = gfc_class_data_get (comp);
9966 dcmp = gfc_class_data_get (dcmp);
9968 gfc_conv_descriptor_data_set (&fnblock, dcmp,
9969 gfc_conv_descriptor_data_get (comp));
9971 else
9973 tmp = structure_alloc_comps (c->ts.u.derived, comp, dcmp,
9974 rank, purpose, caf_mode
9975 | GFC_STRUCTURE_CAF_MODE_IN_COARRAY,
9976 args, no_finalization);
9977 gfc_add_expr_to_block (&fnblock, tmp);
9980 break;
9982 case COPY_ALLOC_COMP:
9983 if (c->attr.pointer || c->attr.proc_pointer)
9984 continue;
9986 /* We need source and destination components. */
9987 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype, decl,
9988 cdecl, NULL_TREE);
9989 dcmp = fold_build3_loc (input_location, COMPONENT_REF, ctype, dest,
9990 cdecl, NULL_TREE);
9991 dcmp = fold_convert (TREE_TYPE (comp), dcmp);
9993 if (c->ts.type == BT_CLASS && CLASS_DATA (c)->attr.allocatable)
9995 tree ftn_tree;
9996 tree size;
9997 tree dst_data;
9998 tree src_data;
9999 tree null_data;
10001 dst_data = gfc_class_data_get (dcmp);
10002 src_data = gfc_class_data_get (comp);
10003 size = fold_convert (size_type_node,
10004 gfc_class_vtab_size_get (comp));
10006 if (CLASS_DATA (c)->attr.dimension)
10008 nelems = gfc_conv_descriptor_size (src_data,
10009 CLASS_DATA (c)->as->rank);
10010 size = fold_build2_loc (input_location, MULT_EXPR,
10011 size_type_node, size,
10012 fold_convert (size_type_node,
10013 nelems));
10015 else
10016 nelems = build_int_cst (size_type_node, 1);
10018 if (CLASS_DATA (c)->attr.dimension
10019 || CLASS_DATA (c)->attr.codimension)
10021 src_data = gfc_conv_descriptor_data_get (src_data);
10022 dst_data = gfc_conv_descriptor_data_get (dst_data);
10025 gfc_init_block (&tmpblock);
10027 gfc_add_modify (&tmpblock, gfc_class_vptr_get (dcmp),
10028 gfc_class_vptr_get (comp));
10030 /* Copy the unlimited '_len' field. If it is greater than zero
10031 (ie. a character(_len)), multiply it by size and use this
10032 for the malloc call. */
10033 if (UNLIMITED_POLY (c))
10035 gfc_add_modify (&tmpblock, gfc_class_len_get (dcmp),
10036 gfc_class_len_get (comp));
10037 size = gfc_resize_class_size_with_len (&tmpblock, comp, size);
10040 /* Coarray component have to have the same allocation status and
10041 shape/type-parameter/effective-type on the LHS and RHS of an
10042 intrinsic assignment. Hence, we did not deallocated them - and
10043 do not allocate them here. */
10044 if (!CLASS_DATA (c)->attr.codimension)
10046 ftn_tree = builtin_decl_explicit (BUILT_IN_MALLOC);
10047 tmp = build_call_expr_loc (input_location, ftn_tree, 1, size);
10048 gfc_add_modify (&tmpblock, dst_data,
10049 fold_convert (TREE_TYPE (dst_data), tmp));
10052 tmp = gfc_copy_class_to_class (comp, dcmp, nelems,
10053 UNLIMITED_POLY (c));
10054 gfc_add_expr_to_block (&tmpblock, tmp);
10055 tmp = gfc_finish_block (&tmpblock);
10057 gfc_init_block (&tmpblock);
10058 gfc_add_modify (&tmpblock, dst_data,
10059 fold_convert (TREE_TYPE (dst_data),
10060 null_pointer_node));
10061 null_data = gfc_finish_block (&tmpblock);
10063 null_cond = fold_build2_loc (input_location, NE_EXPR,
10064 logical_type_node, src_data,
10065 null_pointer_node);
10067 gfc_add_expr_to_block (&fnblock, build3_v (COND_EXPR, null_cond,
10068 tmp, null_data));
10069 continue;
10072 /* To implement guarded deep copy, i.e., deep copy only allocatable
10073 components that are really allocated, the deep copy code has to
10074 be generated first and then added to the if-block in
10075 gfc_duplicate_allocatable (). */
10076 if (cmp_has_alloc_comps && !c->attr.proc_pointer && !same_type)
10078 rank = c->as ? c->as->rank : 0;
10079 tmp = fold_convert (TREE_TYPE (dcmp), comp);
10080 gfc_add_modify (&fnblock, dcmp, tmp);
10081 add_when_allocated = structure_alloc_comps (c->ts.u.derived,
10082 comp, dcmp,
10083 rank, purpose,
10084 caf_mode, args,
10085 no_finalization);
10087 else
10088 add_when_allocated = NULL_TREE;
10090 if (gfc_deferred_strlen (c, &tmp))
10092 tree len, size;
10093 len = tmp;
10094 tmp = fold_build3_loc (input_location, COMPONENT_REF,
10095 TREE_TYPE (len),
10096 decl, len, NULL_TREE);
10097 len = fold_build3_loc (input_location, COMPONENT_REF,
10098 TREE_TYPE (len),
10099 dest, len, NULL_TREE);
10100 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
10101 TREE_TYPE (len), len, tmp);
10102 gfc_add_expr_to_block (&fnblock, tmp);
10103 size = size_of_string_in_bytes (c->ts.kind, len);
10104 /* This component cannot have allocatable components,
10105 therefore add_when_allocated of duplicate_allocatable ()
10106 is always NULL. */
10107 rank = c->as ? c->as->rank : 0;
10108 tmp = duplicate_allocatable (dcmp, comp, ctype, rank,
10109 false, false, size, NULL_TREE);
10110 gfc_add_expr_to_block (&fnblock, tmp);
10112 else if (c->attr.pdt_array)
10114 tmp = duplicate_allocatable (dcmp, comp, ctype,
10115 c->as ? c->as->rank : 0,
10116 false, false, NULL_TREE, NULL_TREE);
10117 gfc_add_expr_to_block (&fnblock, tmp);
10119 else if ((c->attr.allocatable)
10120 && !c->attr.proc_pointer && !same_type
10121 && (!(cmp_has_alloc_comps && c->as) || c->attr.codimension
10122 || caf_in_coarray (caf_mode)))
10124 rank = c->as ? c->as->rank : 0;
10125 if (c->attr.codimension)
10126 tmp = gfc_copy_allocatable_data (dcmp, comp, ctype, rank);
10127 else if (flag_coarray == GFC_FCOARRAY_LIB
10128 && caf_in_coarray (caf_mode))
10130 tree dst_tok;
10131 if (c->as)
10132 dst_tok = gfc_conv_descriptor_token (dcmp);
10133 else
10135 /* For a scalar allocatable component the caf_token is
10136 the next component. */
10137 if (!c->caf_token)
10138 c->caf_token = c->next->backend_decl;
10139 dst_tok = fold_build3_loc (input_location,
10140 COMPONENT_REF,
10141 pvoid_type_node, dest,
10142 c->caf_token,
10143 NULL_TREE);
10145 tmp = duplicate_allocatable_coarray (dcmp, dst_tok, comp,
10146 ctype, rank);
10148 else
10149 tmp = gfc_duplicate_allocatable (dcmp, comp, ctype, rank,
10150 add_when_allocated);
10151 gfc_add_expr_to_block (&fnblock, tmp);
10153 else
10154 if (cmp_has_alloc_comps || is_pdt_type)
10155 gfc_add_expr_to_block (&fnblock, add_when_allocated);
10157 break;
10159 case ALLOCATE_PDT_COMP:
10161 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
10162 decl, cdecl, NULL_TREE);
10164 /* Set the PDT KIND and LEN fields. */
10165 if (c->attr.pdt_kind || c->attr.pdt_len)
10167 gfc_se tse;
10168 gfc_expr *c_expr = NULL;
10169 gfc_actual_arglist *param = pdt_param_list;
10170 gfc_init_se (&tse, NULL);
10171 for (; param; param = param->next)
10172 if (param->name && !strcmp (c->name, param->name))
10173 c_expr = param->expr;
10175 if (!c_expr)
10176 c_expr = c->initializer;
10178 if (c_expr)
10180 gfc_conv_expr_type (&tse, c_expr, TREE_TYPE (comp));
10181 gfc_add_modify (&fnblock, comp, tse.expr);
10185 if (c->attr.pdt_string)
10187 gfc_se tse;
10188 gfc_init_se (&tse, NULL);
10189 tree strlen = NULL_TREE;
10190 gfc_expr *e = gfc_copy_expr (c->ts.u.cl->length);
10191 /* Convert the parameterized string length to its value. The
10192 string length is stored in a hidden field in the same way as
10193 deferred string lengths. */
10194 gfc_insert_parameter_exprs (e, pdt_param_list);
10195 if (gfc_deferred_strlen (c, &strlen) && strlen != NULL_TREE)
10197 gfc_conv_expr_type (&tse, e,
10198 TREE_TYPE (strlen));
10199 strlen = fold_build3_loc (input_location, COMPONENT_REF,
10200 TREE_TYPE (strlen),
10201 decl, strlen, NULL_TREE);
10202 gfc_add_modify (&fnblock, strlen, tse.expr);
10203 c->ts.u.cl->backend_decl = strlen;
10205 gfc_free_expr (e);
10207 /* Scalar parameterized strings can be allocated now. */
10208 if (!c->as)
10210 tmp = fold_convert (gfc_array_index_type, strlen);
10211 tmp = size_of_string_in_bytes (c->ts.kind, tmp);
10212 tmp = gfc_evaluate_now (tmp, &fnblock);
10213 tmp = gfc_call_malloc (&fnblock, TREE_TYPE (comp), tmp);
10214 gfc_add_modify (&fnblock, comp, tmp);
10218 /* Allocate parameterized arrays of parameterized derived types. */
10219 if (!(c->attr.pdt_array && c->as && c->as->type == AS_EXPLICIT)
10220 && !((c->ts.type == BT_DERIVED || c->ts.type == BT_CLASS)
10221 && (c->ts.u.derived && c->ts.u.derived->attr.pdt_type)))
10222 continue;
10224 if (c->ts.type == BT_CLASS)
10225 comp = gfc_class_data_get (comp);
10227 if (c->attr.pdt_array)
10229 gfc_se tse;
10230 int i;
10231 tree size = gfc_index_one_node;
10232 tree offset = gfc_index_zero_node;
10233 tree lower, upper;
10234 gfc_expr *e;
10236 /* This chunk takes the expressions for 'lower' and 'upper'
10237 in the arrayspec and substitutes in the expressions for
10238 the parameters from 'pdt_param_list'. The descriptor
10239 fields can then be filled from the values so obtained. */
10240 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (comp)));
10241 for (i = 0; i < c->as->rank; i++)
10243 gfc_init_se (&tse, NULL);
10244 e = gfc_copy_expr (c->as->lower[i]);
10245 gfc_insert_parameter_exprs (e, pdt_param_list);
10246 gfc_conv_expr_type (&tse, e, gfc_array_index_type);
10247 gfc_free_expr (e);
10248 lower = tse.expr;
10249 gfc_conv_descriptor_lbound_set (&fnblock, comp,
10250 gfc_rank_cst[i],
10251 lower);
10252 e = gfc_copy_expr (c->as->upper[i]);
10253 gfc_insert_parameter_exprs (e, pdt_param_list);
10254 gfc_conv_expr_type (&tse, e, gfc_array_index_type);
10255 gfc_free_expr (e);
10256 upper = tse.expr;
10257 gfc_conv_descriptor_ubound_set (&fnblock, comp,
10258 gfc_rank_cst[i],
10259 upper);
10260 gfc_conv_descriptor_stride_set (&fnblock, comp,
10261 gfc_rank_cst[i],
10262 size);
10263 size = gfc_evaluate_now (size, &fnblock);
10264 offset = fold_build2_loc (input_location,
10265 MINUS_EXPR,
10266 gfc_array_index_type,
10267 offset, size);
10268 offset = gfc_evaluate_now (offset, &fnblock);
10269 tmp = fold_build2_loc (input_location, MINUS_EXPR,
10270 gfc_array_index_type,
10271 upper, lower);
10272 tmp = fold_build2_loc (input_location, PLUS_EXPR,
10273 gfc_array_index_type,
10274 tmp, gfc_index_one_node);
10275 size = fold_build2_loc (input_location, MULT_EXPR,
10276 gfc_array_index_type, size, tmp);
10278 gfc_conv_descriptor_offset_set (&fnblock, comp, offset);
10279 if (c->ts.type == BT_CLASS)
10281 tmp = gfc_get_vptr_from_expr (comp);
10282 if (POINTER_TYPE_P (TREE_TYPE (tmp)))
10283 tmp = build_fold_indirect_ref_loc (input_location, tmp);
10284 tmp = gfc_vptr_size_get (tmp);
10286 else
10287 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (ctype));
10288 tmp = fold_convert (gfc_array_index_type, tmp);
10289 size = fold_build2_loc (input_location, MULT_EXPR,
10290 gfc_array_index_type, size, tmp);
10291 size = gfc_evaluate_now (size, &fnblock);
10292 tmp = gfc_call_malloc (&fnblock, NULL, size);
10293 gfc_conv_descriptor_data_set (&fnblock, comp, tmp);
10294 tmp = gfc_conv_descriptor_dtype (comp);
10295 gfc_add_modify (&fnblock, tmp, gfc_get_dtype (ctype));
10297 if (c->initializer && c->initializer->rank)
10299 gfc_init_se (&tse, NULL);
10300 e = gfc_copy_expr (c->initializer);
10301 gfc_insert_parameter_exprs (e, pdt_param_list);
10302 gfc_conv_expr_descriptor (&tse, e);
10303 gfc_add_block_to_block (&fnblock, &tse.pre);
10304 gfc_free_expr (e);
10305 tmp = builtin_decl_explicit (BUILT_IN_MEMCPY);
10306 tmp = build_call_expr_loc (input_location, tmp, 3,
10307 gfc_conv_descriptor_data_get (comp),
10308 gfc_conv_descriptor_data_get (tse.expr),
10309 fold_convert (size_type_node, size));
10310 gfc_add_expr_to_block (&fnblock, tmp);
10311 gfc_add_block_to_block (&fnblock, &tse.post);
10315 /* Recurse in to PDT components. */
10316 if ((c->ts.type == BT_DERIVED || c->ts.type == BT_CLASS)
10317 && c->ts.u.derived && c->ts.u.derived->attr.pdt_type
10318 && !(c->attr.pointer || c->attr.allocatable))
10320 bool is_deferred = false;
10321 gfc_actual_arglist *tail = c->param_list;
10323 for (; tail; tail = tail->next)
10324 if (!tail->expr)
10325 is_deferred = true;
10327 tail = is_deferred ? pdt_param_list : c->param_list;
10328 tmp = gfc_allocate_pdt_comp (c->ts.u.derived, comp,
10329 c->as ? c->as->rank : 0,
10330 tail);
10331 gfc_add_expr_to_block (&fnblock, tmp);
10334 break;
10336 case DEALLOCATE_PDT_COMP:
10337 /* Deallocate array or parameterized string length components
10338 of parameterized derived types. */
10339 if (!(c->attr.pdt_array && c->as && c->as->type == AS_EXPLICIT)
10340 && !c->attr.pdt_string
10341 && !((c->ts.type == BT_DERIVED || c->ts.type == BT_CLASS)
10342 && (c->ts.u.derived && c->ts.u.derived->attr.pdt_type)))
10343 continue;
10345 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
10346 decl, cdecl, NULL_TREE);
10347 if (c->ts.type == BT_CLASS)
10348 comp = gfc_class_data_get (comp);
10350 /* Recurse in to PDT components. */
10351 if ((c->ts.type == BT_DERIVED || c->ts.type == BT_CLASS)
10352 && c->ts.u.derived && c->ts.u.derived->attr.pdt_type
10353 && (!c->attr.pointer && !c->attr.allocatable))
10355 tmp = gfc_deallocate_pdt_comp (c->ts.u.derived, comp,
10356 c->as ? c->as->rank : 0);
10357 gfc_add_expr_to_block (&fnblock, tmp);
10360 if (c->attr.pdt_array || c->attr.pdt_string)
10362 tmp = comp;
10363 if (c->attr.pdt_array)
10364 tmp = gfc_conv_descriptor_data_get (comp);
10365 null_cond = fold_build2_loc (input_location, NE_EXPR,
10366 logical_type_node, tmp,
10367 build_int_cst (TREE_TYPE (tmp), 0));
10368 if (flag_openmp_allocators)
10370 tree cd, t;
10371 if (c->attr.pdt_array)
10372 cd = fold_build2_loc (input_location, EQ_EXPR,
10373 boolean_type_node,
10374 gfc_conv_descriptor_version (comp),
10375 build_int_cst (integer_type_node, 1));
10376 else
10377 cd = gfc_omp_call_is_alloc (tmp);
10378 t = builtin_decl_explicit (BUILT_IN_GOMP_FREE);
10379 t = build_call_expr_loc (input_location, t, 1, tmp);
10381 stmtblock_t tblock;
10382 gfc_init_block (&tblock);
10383 gfc_add_expr_to_block (&tblock, t);
10384 if (c->attr.pdt_array)
10385 gfc_add_modify (&tblock, gfc_conv_descriptor_version (comp),
10386 build_zero_cst (integer_type_node));
10387 tmp = build3_loc (input_location, COND_EXPR, void_type_node,
10388 cd, gfc_finish_block (&tblock),
10389 gfc_call_free (tmp));
10391 else
10392 tmp = gfc_call_free (tmp);
10393 tmp = build3_v (COND_EXPR, null_cond, tmp,
10394 build_empty_stmt (input_location));
10395 gfc_add_expr_to_block (&fnblock, tmp);
10397 if (c->attr.pdt_array)
10398 gfc_conv_descriptor_data_set (&fnblock, comp, null_pointer_node);
10399 else
10401 tmp = fold_convert (TREE_TYPE (comp), null_pointer_node);
10402 gfc_add_modify (&fnblock, comp, tmp);
10406 break;
10408 case CHECK_PDT_DUMMY:
10410 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
10411 decl, cdecl, NULL_TREE);
10412 if (c->ts.type == BT_CLASS)
10413 comp = gfc_class_data_get (comp);
10415 /* Recurse in to PDT components. */
10416 if ((c->ts.type == BT_DERIVED || c->ts.type == BT_CLASS)
10417 && c->ts.u.derived && c->ts.u.derived->attr.pdt_type)
10419 tmp = gfc_check_pdt_dummy (c->ts.u.derived, comp,
10420 c->as ? c->as->rank : 0,
10421 pdt_param_list);
10422 gfc_add_expr_to_block (&fnblock, tmp);
10425 if (!c->attr.pdt_len)
10426 continue;
10427 else
10429 gfc_se tse;
10430 gfc_expr *c_expr = NULL;
10431 gfc_actual_arglist *param = pdt_param_list;
10433 gfc_init_se (&tse, NULL);
10434 for (; param; param = param->next)
10435 if (!strcmp (c->name, param->name)
10436 && param->spec_type == SPEC_EXPLICIT)
10437 c_expr = param->expr;
10439 if (c_expr)
10441 tree error, cond, cname;
10442 gfc_conv_expr_type (&tse, c_expr, TREE_TYPE (comp));
10443 cond = fold_build2_loc (input_location, NE_EXPR,
10444 logical_type_node,
10445 comp, tse.expr);
10446 cname = gfc_build_cstring_const (c->name);
10447 cname = gfc_build_addr_expr (pchar_type_node, cname);
10448 error = gfc_trans_runtime_error (true, NULL,
10449 "The value of the PDT LEN "
10450 "parameter '%s' does not "
10451 "agree with that in the "
10452 "dummy declaration",
10453 cname);
10454 tmp = fold_build3_loc (input_location, COND_EXPR,
10455 void_type_node, cond, error,
10456 build_empty_stmt (input_location));
10457 gfc_add_expr_to_block (&fnblock, tmp);
10460 break;
10462 default:
10463 gcc_unreachable ();
10464 break;
10468 return gfc_finish_block (&fnblock);
10471 /* Recursively traverse an object of derived type, generating code to
10472 nullify allocatable components. */
10474 tree
10475 gfc_nullify_alloc_comp (gfc_symbol * der_type, tree decl, int rank,
10476 int caf_mode)
10478 return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
10479 NULLIFY_ALLOC_COMP,
10480 GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY | caf_mode,
10481 NULL);
10485 /* Recursively traverse an object of derived type, generating code to
10486 deallocate allocatable components. */
10488 tree
10489 gfc_deallocate_alloc_comp (gfc_symbol * der_type, tree decl, int rank,
10490 int caf_mode)
10492 return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
10493 DEALLOCATE_ALLOC_COMP,
10494 GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY | caf_mode,
10495 NULL);
10498 tree
10499 gfc_bcast_alloc_comp (gfc_symbol *derived, gfc_expr *expr, int rank,
10500 tree image_index, tree stat, tree errmsg,
10501 tree errmsg_len)
10503 tree tmp, array;
10504 gfc_se argse;
10505 stmtblock_t block, post_block;
10506 gfc_co_subroutines_args args;
10508 args.image_index = image_index;
10509 args.stat = stat;
10510 args.errmsg = errmsg;
10511 args.errmsg_len = errmsg_len;
10513 if (rank == 0)
10515 gfc_start_block (&block);
10516 gfc_init_block (&post_block);
10517 gfc_init_se (&argse, NULL);
10518 gfc_conv_expr (&argse, expr);
10519 gfc_add_block_to_block (&block, &argse.pre);
10520 gfc_add_block_to_block (&post_block, &argse.post);
10521 array = argse.expr;
10523 else
10525 gfc_init_se (&argse, NULL);
10526 argse.want_pointer = 1;
10527 gfc_conv_expr_descriptor (&argse, expr);
10528 array = argse.expr;
10531 tmp = structure_alloc_comps (derived, array, NULL_TREE, rank,
10532 BCAST_ALLOC_COMP,
10533 GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY,
10534 &args);
10535 return tmp;
10538 /* Recursively traverse an object of derived type, generating code to
10539 deallocate allocatable components. But do not deallocate coarrays.
10540 To be used for intrinsic assignment, which may not change the allocation
10541 status of coarrays. */
10543 tree
10544 gfc_deallocate_alloc_comp_no_caf (gfc_symbol * der_type, tree decl, int rank,
10545 bool no_finalization)
10547 return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
10548 DEALLOCATE_ALLOC_COMP, 0, NULL,
10549 no_finalization);
10553 tree
10554 gfc_reassign_alloc_comp_caf (gfc_symbol *der_type, tree decl, tree dest)
10556 return structure_alloc_comps (der_type, decl, dest, 0, REASSIGN_CAF_COMP,
10557 GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY,
10558 NULL);
10562 /* Recursively traverse an object of derived type, generating code to
10563 copy it and its allocatable components. */
10565 tree
10566 gfc_copy_alloc_comp (gfc_symbol * der_type, tree decl, tree dest, int rank,
10567 int caf_mode)
10569 return structure_alloc_comps (der_type, decl, dest, rank, COPY_ALLOC_COMP,
10570 caf_mode, NULL);
10574 /* Recursively traverse an object of derived type, generating code to
10575 copy it and its allocatable components, while suppressing any
10576 finalization that might occur. This is used in the finalization of
10577 function results. */
10579 tree
10580 gfc_copy_alloc_comp_no_fini (gfc_symbol * der_type, tree decl, tree dest,
10581 int rank, int caf_mode)
10583 return structure_alloc_comps (der_type, decl, dest, rank, COPY_ALLOC_COMP,
10584 caf_mode, NULL, true);
10588 /* Recursively traverse an object of derived type, generating code to
10589 copy only its allocatable components. */
10591 tree
10592 gfc_copy_only_alloc_comp (gfc_symbol * der_type, tree decl, tree dest, int rank)
10594 return structure_alloc_comps (der_type, decl, dest, rank,
10595 COPY_ONLY_ALLOC_COMP, 0, NULL);
10599 /* Recursively traverse an object of parameterized derived type, generating
10600 code to allocate parameterized components. */
10602 tree
10603 gfc_allocate_pdt_comp (gfc_symbol * der_type, tree decl, int rank,
10604 gfc_actual_arglist *param_list)
10606 tree res;
10607 gfc_actual_arglist *old_param_list = pdt_param_list;
10608 pdt_param_list = param_list;
10609 res = structure_alloc_comps (der_type, decl, NULL_TREE, rank,
10610 ALLOCATE_PDT_COMP, 0, NULL);
10611 pdt_param_list = old_param_list;
10612 return res;
10615 /* Recursively traverse an object of parameterized derived type, generating
10616 code to deallocate parameterized components. */
10618 tree
10619 gfc_deallocate_pdt_comp (gfc_symbol * der_type, tree decl, int rank)
10621 return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
10622 DEALLOCATE_PDT_COMP, 0, NULL);
10626 /* Recursively traverse a dummy of parameterized derived type to check the
10627 values of LEN parameters. */
10629 tree
10630 gfc_check_pdt_dummy (gfc_symbol * der_type, tree decl, int rank,
10631 gfc_actual_arglist *param_list)
10633 tree res;
10634 gfc_actual_arglist *old_param_list = pdt_param_list;
10635 pdt_param_list = param_list;
10636 res = structure_alloc_comps (der_type, decl, NULL_TREE, rank,
10637 CHECK_PDT_DUMMY, 0, NULL);
10638 pdt_param_list = old_param_list;
10639 return res;
10643 /* Returns the value of LBOUND for an expression. This could be broken out
10644 from gfc_conv_intrinsic_bound but this seemed to be simpler. This is
10645 called by gfc_alloc_allocatable_for_assignment. */
10646 static tree
10647 get_std_lbound (gfc_expr *expr, tree desc, int dim, bool assumed_size)
10649 tree lbound;
10650 tree ubound;
10651 tree stride;
10652 tree cond, cond1, cond3, cond4;
10653 tree tmp;
10654 gfc_ref *ref;
10656 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
10658 tmp = gfc_rank_cst[dim];
10659 lbound = gfc_conv_descriptor_lbound_get (desc, tmp);
10660 ubound = gfc_conv_descriptor_ubound_get (desc, tmp);
10661 stride = gfc_conv_descriptor_stride_get (desc, tmp);
10662 cond1 = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
10663 ubound, lbound);
10664 cond3 = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
10665 stride, gfc_index_zero_node);
10666 cond3 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
10667 logical_type_node, cond3, cond1);
10668 cond4 = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
10669 stride, gfc_index_zero_node);
10670 if (assumed_size)
10671 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
10672 tmp, build_int_cst (gfc_array_index_type,
10673 expr->rank - 1));
10674 else
10675 cond = logical_false_node;
10677 cond1 = fold_build2_loc (input_location, TRUTH_OR_EXPR,
10678 logical_type_node, cond3, cond4);
10679 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
10680 logical_type_node, cond, cond1);
10682 return fold_build3_loc (input_location, COND_EXPR,
10683 gfc_array_index_type, cond,
10684 lbound, gfc_index_one_node);
10687 if (expr->expr_type == EXPR_FUNCTION)
10689 /* A conversion function, so use the argument. */
10690 gcc_assert (expr->value.function.isym
10691 && expr->value.function.isym->conversion);
10692 expr = expr->value.function.actual->expr;
10695 if (expr->expr_type == EXPR_VARIABLE)
10697 tmp = TREE_TYPE (expr->symtree->n.sym->backend_decl);
10698 for (ref = expr->ref; ref; ref = ref->next)
10700 if (ref->type == REF_COMPONENT
10701 && ref->u.c.component->as
10702 && ref->next
10703 && ref->next->u.ar.type == AR_FULL)
10704 tmp = TREE_TYPE (ref->u.c.component->backend_decl);
10706 return GFC_TYPE_ARRAY_LBOUND(tmp, dim);
10709 return gfc_index_one_node;
10713 /* Returns true if an expression represents an lhs that can be reallocated
10714 on assignment. */
10716 bool
10717 gfc_is_reallocatable_lhs (gfc_expr *expr)
10719 gfc_ref * ref;
10720 gfc_symbol *sym;
10722 if (!expr->ref)
10723 return false;
10725 sym = expr->symtree->n.sym;
10727 if (sym->attr.associate_var && !expr->ref)
10728 return false;
10730 /* An allocatable class variable with no reference. */
10731 if (sym->ts.type == BT_CLASS
10732 && (!sym->attr.associate_var || sym->attr.select_rank_temporary)
10733 && CLASS_DATA (sym)->attr.allocatable
10734 && expr->ref
10735 && ((expr->ref->type == REF_ARRAY && expr->ref->u.ar.type == AR_FULL
10736 && expr->ref->next == NULL)
10737 || (expr->ref->type == REF_COMPONENT
10738 && strcmp (expr->ref->u.c.component->name, "_data") == 0
10739 && (expr->ref->next == NULL
10740 || (expr->ref->next->type == REF_ARRAY
10741 && expr->ref->next->u.ar.type == AR_FULL
10742 && expr->ref->next->next == NULL)))))
10743 return true;
10745 /* An allocatable variable. */
10746 if (sym->attr.allocatable
10747 && (!sym->attr.associate_var || sym->attr.select_rank_temporary)
10748 && expr->ref
10749 && expr->ref->type == REF_ARRAY
10750 && expr->ref->u.ar.type == AR_FULL)
10751 return true;
10753 /* All that can be left are allocatable components. */
10754 if ((sym->ts.type != BT_DERIVED
10755 && sym->ts.type != BT_CLASS)
10756 || !sym->ts.u.derived->attr.alloc_comp)
10757 return false;
10759 /* Find a component ref followed by an array reference. */
10760 for (ref = expr->ref; ref; ref = ref->next)
10761 if (ref->next
10762 && ref->type == REF_COMPONENT
10763 && ref->next->type == REF_ARRAY
10764 && !ref->next->next)
10765 break;
10767 if (!ref)
10768 return false;
10770 /* Return true if valid reallocatable lhs. */
10771 if (ref->u.c.component->attr.allocatable
10772 && ref->next->u.ar.type == AR_FULL)
10773 return true;
10775 return false;
10779 static tree
10780 concat_str_length (gfc_expr* expr)
10782 tree type;
10783 tree len1;
10784 tree len2;
10785 gfc_se se;
10787 type = gfc_typenode_for_spec (&expr->value.op.op1->ts);
10788 len1 = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
10789 if (len1 == NULL_TREE)
10791 if (expr->value.op.op1->expr_type == EXPR_OP)
10792 len1 = concat_str_length (expr->value.op.op1);
10793 else if (expr->value.op.op1->expr_type == EXPR_CONSTANT)
10794 len1 = build_int_cst (gfc_charlen_type_node,
10795 expr->value.op.op1->value.character.length);
10796 else if (expr->value.op.op1->ts.u.cl->length)
10798 gfc_init_se (&se, NULL);
10799 gfc_conv_expr (&se, expr->value.op.op1->ts.u.cl->length);
10800 len1 = se.expr;
10802 else
10804 /* Last resort! */
10805 gfc_init_se (&se, NULL);
10806 se.want_pointer = 1;
10807 se.descriptor_only = 1;
10808 gfc_conv_expr (&se, expr->value.op.op1);
10809 len1 = se.string_length;
10813 type = gfc_typenode_for_spec (&expr->value.op.op2->ts);
10814 len2 = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
10815 if (len2 == NULL_TREE)
10817 if (expr->value.op.op2->expr_type == EXPR_OP)
10818 len2 = concat_str_length (expr->value.op.op2);
10819 else if (expr->value.op.op2->expr_type == EXPR_CONSTANT)
10820 len2 = build_int_cst (gfc_charlen_type_node,
10821 expr->value.op.op2->value.character.length);
10822 else if (expr->value.op.op2->ts.u.cl->length)
10824 gfc_init_se (&se, NULL);
10825 gfc_conv_expr (&se, expr->value.op.op2->ts.u.cl->length);
10826 len2 = se.expr;
10828 else
10830 /* Last resort! */
10831 gfc_init_se (&se, NULL);
10832 se.want_pointer = 1;
10833 se.descriptor_only = 1;
10834 gfc_conv_expr (&se, expr->value.op.op2);
10835 len2 = se.string_length;
10839 gcc_assert(len1 && len2);
10840 len1 = fold_convert (gfc_charlen_type_node, len1);
10841 len2 = fold_convert (gfc_charlen_type_node, len2);
10843 return fold_build2_loc (input_location, PLUS_EXPR,
10844 gfc_charlen_type_node, len1, len2);
10848 /* Allocate the lhs of an assignment to an allocatable array, otherwise
10849 reallocate it. */
10851 tree
10852 gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
10853 gfc_expr *expr1,
10854 gfc_expr *expr2)
10856 stmtblock_t realloc_block;
10857 stmtblock_t alloc_block;
10858 stmtblock_t fblock;
10859 gfc_ss *rss;
10860 gfc_ss *lss;
10861 gfc_array_info *linfo;
10862 tree realloc_expr;
10863 tree alloc_expr;
10864 tree size1;
10865 tree size2;
10866 tree elemsize1;
10867 tree elemsize2;
10868 tree array1;
10869 tree cond_null;
10870 tree cond;
10871 tree tmp;
10872 tree tmp2;
10873 tree lbound;
10874 tree ubound;
10875 tree desc;
10876 tree old_desc;
10877 tree desc2;
10878 tree offset;
10879 tree jump_label1;
10880 tree jump_label2;
10881 tree lbd;
10882 tree class_expr2 = NULL_TREE;
10883 int n;
10884 int dim;
10885 gfc_array_spec * as;
10886 bool coarray = (flag_coarray == GFC_FCOARRAY_LIB
10887 && gfc_caf_attr (expr1, true).codimension);
10888 tree token;
10889 gfc_se caf_se;
10891 /* x = f(...) with x allocatable. In this case, expr1 is the rhs.
10892 Find the lhs expression in the loop chain and set expr1 and
10893 expr2 accordingly. */
10894 if (expr1->expr_type == EXPR_FUNCTION && expr2 == NULL)
10896 expr2 = expr1;
10897 /* Find the ss for the lhs. */
10898 lss = loop->ss;
10899 for (; lss && lss != gfc_ss_terminator; lss = lss->loop_chain)
10900 if (lss->info->expr && lss->info->expr->expr_type == EXPR_VARIABLE)
10901 break;
10902 if (lss == gfc_ss_terminator)
10903 return NULL_TREE;
10904 expr1 = lss->info->expr;
10907 /* Bail out if this is not a valid allocate on assignment. */
10908 if (!gfc_is_reallocatable_lhs (expr1)
10909 || (expr2 && !expr2->rank))
10910 return NULL_TREE;
10912 /* Find the ss for the lhs. */
10913 lss = loop->ss;
10914 for (; lss && lss != gfc_ss_terminator; lss = lss->loop_chain)
10915 if (lss->info->expr == expr1)
10916 break;
10918 if (lss == gfc_ss_terminator)
10919 return NULL_TREE;
10921 linfo = &lss->info->data.array;
10923 /* Find an ss for the rhs. For operator expressions, we see the
10924 ss's for the operands. Any one of these will do. */
10925 rss = loop->ss;
10926 for (; rss && rss != gfc_ss_terminator; rss = rss->loop_chain)
10927 if (rss->info->expr != expr1 && rss != loop->temp_ss)
10928 break;
10930 if (expr2 && rss == gfc_ss_terminator)
10931 return NULL_TREE;
10933 /* Ensure that the string length from the current scope is used. */
10934 if (expr2->ts.type == BT_CHARACTER
10935 && expr2->expr_type == EXPR_FUNCTION
10936 && !expr2->value.function.isym)
10937 expr2->ts.u.cl->backend_decl = rss->info->string_length;
10939 gfc_start_block (&fblock);
10941 /* Since the lhs is allocatable, this must be a descriptor type.
10942 Get the data and array size. */
10943 desc = linfo->descriptor;
10944 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)));
10945 array1 = gfc_conv_descriptor_data_get (desc);
10947 if (expr2)
10948 desc2 = rss->info->data.array.descriptor;
10949 else
10950 desc2 = NULL_TREE;
10952 /* Get the old lhs element size for deferred character and class expr1. */
10953 if (expr1->ts.type == BT_CHARACTER && expr1->ts.deferred)
10955 if (expr1->ts.u.cl->backend_decl
10956 && VAR_P (expr1->ts.u.cl->backend_decl))
10957 elemsize1 = expr1->ts.u.cl->backend_decl;
10958 else
10959 elemsize1 = lss->info->string_length;
10960 tree unit_size = TYPE_SIZE_UNIT (gfc_get_char_type (expr1->ts.kind));
10961 elemsize1 = fold_build2_loc (input_location, MULT_EXPR,
10962 TREE_TYPE (elemsize1), elemsize1,
10963 fold_convert (TREE_TYPE (elemsize1), unit_size));
10966 else if (expr1->ts.type == BT_CLASS)
10968 /* Unfortunately, the lhs vptr is set too early in many cases.
10969 Play it safe by using the descriptor element length. */
10970 tmp = gfc_conv_descriptor_elem_len (desc);
10971 elemsize1 = fold_convert (gfc_array_index_type, tmp);
10973 else
10974 elemsize1 = NULL_TREE;
10975 if (elemsize1 != NULL_TREE)
10976 elemsize1 = gfc_evaluate_now (elemsize1, &fblock);
10978 /* Get the new lhs size in bytes. */
10979 if (expr1->ts.type == BT_CHARACTER && expr1->ts.deferred)
10981 if (expr2->ts.deferred)
10983 if (expr2->ts.u.cl->backend_decl
10984 && VAR_P (expr2->ts.u.cl->backend_decl))
10985 tmp = expr2->ts.u.cl->backend_decl;
10986 else
10987 tmp = rss->info->string_length;
10989 else
10991 tmp = expr2->ts.u.cl->backend_decl;
10992 if (!tmp && expr2->expr_type == EXPR_OP
10993 && expr2->value.op.op == INTRINSIC_CONCAT)
10995 tmp = concat_str_length (expr2);
10996 expr2->ts.u.cl->backend_decl = gfc_evaluate_now (tmp, &fblock);
10998 else if (!tmp && expr2->ts.u.cl->length)
11000 gfc_se tmpse;
11001 gfc_init_se (&tmpse, NULL);
11002 gfc_conv_expr_type (&tmpse, expr2->ts.u.cl->length,
11003 gfc_charlen_type_node);
11004 tmp = tmpse.expr;
11005 expr2->ts.u.cl->backend_decl = gfc_evaluate_now (tmp, &fblock);
11007 tmp = fold_convert (TREE_TYPE (expr1->ts.u.cl->backend_decl), tmp);
11010 if (expr1->ts.u.cl->backend_decl
11011 && VAR_P (expr1->ts.u.cl->backend_decl))
11012 gfc_add_modify (&fblock, expr1->ts.u.cl->backend_decl, tmp);
11013 else
11014 gfc_add_modify (&fblock, lss->info->string_length, tmp);
11016 if (expr1->ts.kind > 1)
11017 tmp = fold_build2_loc (input_location, MULT_EXPR,
11018 TREE_TYPE (tmp),
11019 tmp, build_int_cst (TREE_TYPE (tmp),
11020 expr1->ts.kind));
11022 else if (expr1->ts.type == BT_CHARACTER && expr1->ts.u.cl->backend_decl)
11024 tmp = TYPE_SIZE_UNIT (TREE_TYPE (gfc_typenode_for_spec (&expr1->ts)));
11025 tmp = fold_build2_loc (input_location, MULT_EXPR,
11026 gfc_array_index_type, tmp,
11027 expr1->ts.u.cl->backend_decl);
11029 else if (UNLIMITED_POLY (expr1) && expr2->ts.type != BT_CLASS)
11030 tmp = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&expr2->ts));
11031 else if (expr1->ts.type == BT_CLASS && expr2->ts.type == BT_CLASS)
11033 tmp = expr2->rank ? gfc_get_class_from_expr (desc2) : NULL_TREE;
11034 if (tmp == NULL_TREE && expr2->expr_type == EXPR_VARIABLE)
11035 tmp = class_expr2 = gfc_get_class_from_gfc_expr (expr2);
11037 if (tmp != NULL_TREE)
11038 tmp = gfc_class_vtab_size_get (tmp);
11039 else
11040 tmp = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&CLASS_DATA (expr2)->ts));
11042 else
11043 tmp = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&expr2->ts));
11044 elemsize2 = fold_convert (gfc_array_index_type, tmp);
11045 elemsize2 = gfc_evaluate_now (elemsize2, &fblock);
11047 /* 7.4.1.3 "If variable is an allocated allocatable variable, it is
11048 deallocated if expr is an array of different shape or any of the
11049 corresponding length type parameter values of variable and expr
11050 differ." This assures F95 compatibility. */
11051 jump_label1 = gfc_build_label_decl (NULL_TREE);
11052 jump_label2 = gfc_build_label_decl (NULL_TREE);
11054 /* Allocate if data is NULL. */
11055 cond_null = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
11056 array1, build_int_cst (TREE_TYPE (array1), 0));
11057 cond_null= gfc_evaluate_now (cond_null, &fblock);
11059 tmp = build3_v (COND_EXPR, cond_null,
11060 build1_v (GOTO_EXPR, jump_label1),
11061 build_empty_stmt (input_location));
11062 gfc_add_expr_to_block (&fblock, tmp);
11064 /* Get arrayspec if expr is a full array. */
11065 if (expr2 && expr2->expr_type == EXPR_FUNCTION
11066 && expr2->value.function.isym
11067 && expr2->value.function.isym->conversion)
11069 /* For conversion functions, take the arg. */
11070 gfc_expr *arg = expr2->value.function.actual->expr;
11071 as = gfc_get_full_arrayspec_from_expr (arg);
11073 else if (expr2)
11074 as = gfc_get_full_arrayspec_from_expr (expr2);
11075 else
11076 as = NULL;
11078 /* If the lhs shape is not the same as the rhs jump to setting the
11079 bounds and doing the reallocation....... */
11080 for (n = 0; n < expr1->rank; n++)
11082 /* Check the shape. */
11083 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[n]);
11084 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[n]);
11085 tmp = fold_build2_loc (input_location, MINUS_EXPR,
11086 gfc_array_index_type,
11087 loop->to[n], loop->from[n]);
11088 tmp = fold_build2_loc (input_location, PLUS_EXPR,
11089 gfc_array_index_type,
11090 tmp, lbound);
11091 tmp = fold_build2_loc (input_location, MINUS_EXPR,
11092 gfc_array_index_type,
11093 tmp, ubound);
11094 cond = fold_build2_loc (input_location, NE_EXPR,
11095 logical_type_node,
11096 tmp, gfc_index_zero_node);
11097 tmp = build3_v (COND_EXPR, cond,
11098 build1_v (GOTO_EXPR, jump_label1),
11099 build_empty_stmt (input_location));
11100 gfc_add_expr_to_block (&fblock, tmp);
11103 /* ...else if the element lengths are not the same also go to
11104 setting the bounds and doing the reallocation.... */
11105 if (elemsize1 != NULL_TREE)
11107 cond = fold_build2_loc (input_location, NE_EXPR,
11108 logical_type_node,
11109 elemsize1, elemsize2);
11110 tmp = build3_v (COND_EXPR, cond,
11111 build1_v (GOTO_EXPR, jump_label1),
11112 build_empty_stmt (input_location));
11113 gfc_add_expr_to_block (&fblock, tmp);
11116 /* ....else jump past the (re)alloc code. */
11117 tmp = build1_v (GOTO_EXPR, jump_label2);
11118 gfc_add_expr_to_block (&fblock, tmp);
11120 /* Add the label to start automatic (re)allocation. */
11121 tmp = build1_v (LABEL_EXPR, jump_label1);
11122 gfc_add_expr_to_block (&fblock, tmp);
11124 /* Get the rhs size and fix it. */
11125 size2 = gfc_index_one_node;
11126 for (n = 0; n < expr2->rank; n++)
11128 tmp = fold_build2_loc (input_location, MINUS_EXPR,
11129 gfc_array_index_type,
11130 loop->to[n], loop->from[n]);
11131 tmp = fold_build2_loc (input_location, PLUS_EXPR,
11132 gfc_array_index_type,
11133 tmp, gfc_index_one_node);
11134 size2 = fold_build2_loc (input_location, MULT_EXPR,
11135 gfc_array_index_type,
11136 tmp, size2);
11138 size2 = gfc_evaluate_now (size2, &fblock);
11140 /* Deallocation of allocatable components will have to occur on
11141 reallocation. Fix the old descriptor now. */
11142 if ((expr1->ts.type == BT_DERIVED)
11143 && expr1->ts.u.derived->attr.alloc_comp)
11144 old_desc = gfc_evaluate_now (desc, &fblock);
11145 else
11146 old_desc = NULL_TREE;
11148 /* Now modify the lhs descriptor and the associated scalarizer
11149 variables. F2003 7.4.1.3: "If variable is or becomes an
11150 unallocated allocatable variable, then it is allocated with each
11151 deferred type parameter equal to the corresponding type parameters
11152 of expr , with the shape of expr , and with each lower bound equal
11153 to the corresponding element of LBOUND(expr)."
11154 Reuse size1 to keep a dimension-by-dimension track of the
11155 stride of the new array. */
11156 size1 = gfc_index_one_node;
11157 offset = gfc_index_zero_node;
11159 for (n = 0; n < expr2->rank; n++)
11161 tmp = fold_build2_loc (input_location, MINUS_EXPR,
11162 gfc_array_index_type,
11163 loop->to[n], loop->from[n]);
11164 tmp = fold_build2_loc (input_location, PLUS_EXPR,
11165 gfc_array_index_type,
11166 tmp, gfc_index_one_node);
11168 lbound = gfc_index_one_node;
11169 ubound = tmp;
11171 if (as)
11173 lbd = get_std_lbound (expr2, desc2, n,
11174 as->type == AS_ASSUMED_SIZE);
11175 ubound = fold_build2_loc (input_location,
11176 MINUS_EXPR,
11177 gfc_array_index_type,
11178 ubound, lbound);
11179 ubound = fold_build2_loc (input_location,
11180 PLUS_EXPR,
11181 gfc_array_index_type,
11182 ubound, lbd);
11183 lbound = lbd;
11186 gfc_conv_descriptor_lbound_set (&fblock, desc,
11187 gfc_rank_cst[n],
11188 lbound);
11189 gfc_conv_descriptor_ubound_set (&fblock, desc,
11190 gfc_rank_cst[n],
11191 ubound);
11192 gfc_conv_descriptor_stride_set (&fblock, desc,
11193 gfc_rank_cst[n],
11194 size1);
11195 lbound = gfc_conv_descriptor_lbound_get (desc,
11196 gfc_rank_cst[n]);
11197 tmp2 = fold_build2_loc (input_location, MULT_EXPR,
11198 gfc_array_index_type,
11199 lbound, size1);
11200 offset = fold_build2_loc (input_location, MINUS_EXPR,
11201 gfc_array_index_type,
11202 offset, tmp2);
11203 size1 = fold_build2_loc (input_location, MULT_EXPR,
11204 gfc_array_index_type,
11205 tmp, size1);
11208 /* Set the lhs descriptor and scalarizer offsets. For rank > 1,
11209 the array offset is saved and the info.offset is used for a
11210 running offset. Use the saved_offset instead. */
11211 tmp = gfc_conv_descriptor_offset (desc);
11212 gfc_add_modify (&fblock, tmp, offset);
11213 if (linfo->saved_offset
11214 && VAR_P (linfo->saved_offset))
11215 gfc_add_modify (&fblock, linfo->saved_offset, tmp);
11217 /* Now set the deltas for the lhs. */
11218 for (n = 0; n < expr1->rank; n++)
11220 tmp = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[n]);
11221 dim = lss->dim[n];
11222 tmp = fold_build2_loc (input_location, MINUS_EXPR,
11223 gfc_array_index_type, tmp,
11224 loop->from[dim]);
11225 if (linfo->delta[dim] && VAR_P (linfo->delta[dim]))
11226 gfc_add_modify (&fblock, linfo->delta[dim], tmp);
11229 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
11230 gfc_conv_descriptor_span_set (&fblock, desc, elemsize2);
11232 size2 = fold_build2_loc (input_location, MULT_EXPR,
11233 gfc_array_index_type,
11234 elemsize2, size2);
11235 size2 = fold_convert (size_type_node, size2);
11236 size2 = fold_build2_loc (input_location, MAX_EXPR, size_type_node,
11237 size2, size_one_node);
11238 size2 = gfc_evaluate_now (size2, &fblock);
11240 /* For deferred character length, the 'size' field of the dtype might
11241 have changed so set the dtype. */
11242 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc))
11243 && expr1->ts.type == BT_CHARACTER && expr1->ts.deferred)
11245 tree type;
11246 tmp = gfc_conv_descriptor_dtype (desc);
11247 if (expr2->ts.u.cl->backend_decl)
11248 type = gfc_typenode_for_spec (&expr2->ts);
11249 else
11250 type = gfc_typenode_for_spec (&expr1->ts);
11252 gfc_add_modify (&fblock, tmp,
11253 gfc_get_dtype_rank_type (expr1->rank,type));
11255 else if (expr1->ts.type == BT_CLASS)
11257 tree type;
11258 tmp = gfc_conv_descriptor_dtype (desc);
11260 if (expr2->ts.type != BT_CLASS)
11261 type = gfc_typenode_for_spec (&expr2->ts);
11262 else
11263 type = gfc_get_character_type_len (1, elemsize2);
11265 gfc_add_modify (&fblock, tmp,
11266 gfc_get_dtype_rank_type (expr2->rank,type));
11267 /* Set the _len field as well... */
11268 if (UNLIMITED_POLY (expr1))
11270 tmp = gfc_class_len_get (TREE_OPERAND (desc, 0));
11271 if (expr2->ts.type == BT_CHARACTER)
11272 gfc_add_modify (&fblock, tmp,
11273 fold_convert (TREE_TYPE (tmp),
11274 TYPE_SIZE_UNIT (type)));
11275 else
11276 gfc_add_modify (&fblock, tmp,
11277 build_int_cst (TREE_TYPE (tmp), 0));
11279 /* ...and the vptr. */
11280 tmp = gfc_class_vptr_get (TREE_OPERAND (desc, 0));
11281 if (expr2->ts.type == BT_CLASS && !VAR_P (desc2)
11282 && TREE_CODE (desc2) == COMPONENT_REF)
11284 tmp2 = gfc_get_class_from_expr (desc2);
11285 tmp2 = gfc_class_vptr_get (tmp2);
11287 else if (expr2->ts.type == BT_CLASS && class_expr2 != NULL_TREE)
11288 tmp2 = gfc_class_vptr_get (class_expr2);
11289 else
11291 tmp2 = gfc_get_symbol_decl (gfc_find_vtab (&expr2->ts));
11292 tmp2 = gfc_build_addr_expr (TREE_TYPE (tmp), tmp2);
11295 gfc_add_modify (&fblock, tmp, fold_convert (TREE_TYPE (tmp), tmp2));
11297 else if (coarray && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
11299 gfc_add_modify (&fblock, gfc_conv_descriptor_dtype (desc),
11300 gfc_get_dtype (TREE_TYPE (desc)));
11303 /* Realloc expression. Note that the scalarizer uses desc.data
11304 in the array reference - (*desc.data)[<element>]. */
11305 gfc_init_block (&realloc_block);
11306 gfc_init_se (&caf_se, NULL);
11308 if (coarray)
11310 token = gfc_get_ultimate_alloc_ptr_comps_caf_token (&caf_se, expr1);
11311 if (token == NULL_TREE)
11313 tmp = gfc_get_tree_for_caf_expr (expr1);
11314 if (POINTER_TYPE_P (TREE_TYPE (tmp)))
11315 tmp = build_fold_indirect_ref (tmp);
11316 gfc_get_caf_token_offset (&caf_se, &token, NULL, tmp, NULL_TREE,
11317 expr1);
11318 token = gfc_build_addr_expr (NULL_TREE, token);
11321 gfc_add_block_to_block (&realloc_block, &caf_se.pre);
11323 if ((expr1->ts.type == BT_DERIVED)
11324 && expr1->ts.u.derived->attr.alloc_comp)
11326 tmp = gfc_deallocate_alloc_comp_no_caf (expr1->ts.u.derived, old_desc,
11327 expr1->rank, true);
11328 gfc_add_expr_to_block (&realloc_block, tmp);
11331 if (!coarray)
11333 tmp = build_call_expr_loc (input_location,
11334 builtin_decl_explicit (BUILT_IN_REALLOC), 2,
11335 fold_convert (pvoid_type_node, array1),
11336 size2);
11337 if (flag_openmp_allocators)
11339 tree cond, omp_tmp;
11340 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
11341 gfc_conv_descriptor_version (desc),
11342 build_int_cst (integer_type_node, 1));
11343 omp_tmp = builtin_decl_explicit (BUILT_IN_GOMP_REALLOC);
11344 omp_tmp = build_call_expr_loc (input_location, omp_tmp, 4,
11345 fold_convert (pvoid_type_node, array1), size2,
11346 build_zero_cst (ptr_type_node),
11347 build_zero_cst (ptr_type_node));
11348 tmp = build3_loc (input_location, COND_EXPR, TREE_TYPE (tmp), cond,
11349 omp_tmp, tmp);
11352 gfc_conv_descriptor_data_set (&realloc_block, desc, tmp);
11354 else
11356 tmp = build_call_expr_loc (input_location,
11357 gfor_fndecl_caf_deregister, 5, token,
11358 build_int_cst (integer_type_node,
11359 GFC_CAF_COARRAY_DEALLOCATE_ONLY),
11360 null_pointer_node, null_pointer_node,
11361 integer_zero_node);
11362 gfc_add_expr_to_block (&realloc_block, tmp);
11363 tmp = build_call_expr_loc (input_location,
11364 gfor_fndecl_caf_register,
11365 7, size2,
11366 build_int_cst (integer_type_node,
11367 GFC_CAF_COARRAY_ALLOC_ALLOCATE_ONLY),
11368 token, gfc_build_addr_expr (NULL_TREE, desc),
11369 null_pointer_node, null_pointer_node,
11370 integer_zero_node);
11371 gfc_add_expr_to_block (&realloc_block, tmp);
11374 if ((expr1->ts.type == BT_DERIVED)
11375 && expr1->ts.u.derived->attr.alloc_comp)
11377 tmp = gfc_nullify_alloc_comp (expr1->ts.u.derived, desc,
11378 expr1->rank);
11379 gfc_add_expr_to_block (&realloc_block, tmp);
11382 gfc_add_block_to_block (&realloc_block, &caf_se.post);
11383 realloc_expr = gfc_finish_block (&realloc_block);
11385 /* Malloc expression. */
11386 gfc_init_block (&alloc_block);
11387 if (!coarray)
11389 tmp = build_call_expr_loc (input_location,
11390 builtin_decl_explicit (BUILT_IN_MALLOC),
11391 1, size2);
11392 gfc_conv_descriptor_data_set (&alloc_block,
11393 desc, tmp);
11395 else
11397 tmp = build_call_expr_loc (input_location,
11398 gfor_fndecl_caf_register,
11399 7, size2,
11400 build_int_cst (integer_type_node,
11401 GFC_CAF_COARRAY_ALLOC),
11402 token, gfc_build_addr_expr (NULL_TREE, desc),
11403 null_pointer_node, null_pointer_node,
11404 integer_zero_node);
11405 gfc_add_expr_to_block (&alloc_block, tmp);
11409 /* We already set the dtype in the case of deferred character
11410 length arrays and class lvalues. */
11411 if (!(GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc))
11412 && ((expr1->ts.type == BT_CHARACTER && expr1->ts.deferred)
11413 || coarray))
11414 && expr1->ts.type != BT_CLASS)
11416 tmp = gfc_conv_descriptor_dtype (desc);
11417 gfc_add_modify (&alloc_block, tmp, gfc_get_dtype (TREE_TYPE (desc)));
11420 if ((expr1->ts.type == BT_DERIVED)
11421 && expr1->ts.u.derived->attr.alloc_comp)
11423 tmp = gfc_nullify_alloc_comp (expr1->ts.u.derived, desc,
11424 expr1->rank);
11425 gfc_add_expr_to_block (&alloc_block, tmp);
11427 alloc_expr = gfc_finish_block (&alloc_block);
11429 /* Malloc if not allocated; realloc otherwise. */
11430 tmp = build3_v (COND_EXPR, cond_null, alloc_expr, realloc_expr);
11431 gfc_add_expr_to_block (&fblock, tmp);
11433 /* Make sure that the scalarizer data pointer is updated. */
11434 if (linfo->data && VAR_P (linfo->data))
11436 tmp = gfc_conv_descriptor_data_get (desc);
11437 gfc_add_modify (&fblock, linfo->data, tmp);
11440 /* Add the label for same shape lhs and rhs. */
11441 tmp = build1_v (LABEL_EXPR, jump_label2);
11442 gfc_add_expr_to_block (&fblock, tmp);
11444 return gfc_finish_block (&fblock);
11448 /* Initialize class descriptor's TKR information. */
11450 void
11451 gfc_trans_class_array (gfc_symbol * sym, gfc_wrapped_block * block)
11453 tree type, etype;
11454 tree tmp;
11455 tree descriptor;
11456 stmtblock_t init;
11457 locus loc;
11458 int rank;
11460 /* Make sure the frontend gets these right. */
11461 gcc_assert (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
11462 && (CLASS_DATA (sym)->attr.class_pointer
11463 || CLASS_DATA (sym)->attr.allocatable));
11465 gcc_assert (VAR_P (sym->backend_decl)
11466 || TREE_CODE (sym->backend_decl) == PARM_DECL);
11468 if (sym->attr.dummy)
11469 return;
11471 descriptor = gfc_class_data_get (sym->backend_decl);
11472 type = TREE_TYPE (descriptor);
11474 if (type == NULL || !GFC_DESCRIPTOR_TYPE_P (type))
11475 return;
11477 gfc_save_backend_locus (&loc);
11478 gfc_set_backend_locus (&sym->declared_at);
11479 gfc_init_block (&init);
11481 rank = CLASS_DATA (sym)->as ? (CLASS_DATA (sym)->as->rank) : (0);
11482 gcc_assert (rank>=0);
11483 tmp = gfc_conv_descriptor_dtype (descriptor);
11484 etype = gfc_get_element_type (type);
11485 tmp = fold_build2_loc (input_location, MODIFY_EXPR, TREE_TYPE (tmp), tmp,
11486 gfc_get_dtype_rank_type (rank, etype));
11487 gfc_add_expr_to_block (&init, tmp);
11489 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
11490 gfc_restore_backend_locus (&loc);
11494 /* NULLIFY an allocatable/pointer array on function entry, free it on exit.
11495 Do likewise, recursively if necessary, with the allocatable components of
11496 derived types. This function is also called for assumed-rank arrays, which
11497 are always dummy arguments. */
11499 void
11500 gfc_trans_deferred_array (gfc_symbol * sym, gfc_wrapped_block * block)
11502 tree type;
11503 tree tmp;
11504 tree descriptor;
11505 stmtblock_t init;
11506 stmtblock_t cleanup;
11507 locus loc;
11508 int rank;
11509 bool sym_has_alloc_comp, has_finalizer;
11511 sym_has_alloc_comp = (sym->ts.type == BT_DERIVED
11512 || sym->ts.type == BT_CLASS)
11513 && sym->ts.u.derived->attr.alloc_comp;
11514 has_finalizer = gfc_may_be_finalized (sym->ts);
11516 /* Make sure the frontend gets these right. */
11517 gcc_assert (sym->attr.pointer || sym->attr.allocatable || sym_has_alloc_comp
11518 || has_finalizer
11519 || (sym->as->type == AS_ASSUMED_RANK && sym->attr.dummy));
11521 gfc_save_backend_locus (&loc);
11522 gfc_set_backend_locus (&sym->declared_at);
11523 gfc_init_block (&init);
11525 gcc_assert (VAR_P (sym->backend_decl)
11526 || TREE_CODE (sym->backend_decl) == PARM_DECL);
11528 if (sym->ts.type == BT_CHARACTER
11529 && !INTEGER_CST_P (sym->ts.u.cl->backend_decl))
11531 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
11532 gfc_trans_vla_type_sizes (sym, &init);
11534 /* Presence check of optional deferred-length character dummy. */
11535 if (sym->ts.deferred && sym->attr.dummy && sym->attr.optional)
11537 tmp = gfc_finish_block (&init);
11538 tmp = build3_v (COND_EXPR, gfc_conv_expr_present (sym),
11539 tmp, build_empty_stmt (input_location));
11540 gfc_add_expr_to_block (&init, tmp);
11544 /* Dummy, use associated and result variables don't need anything special. */
11545 if (sym->attr.dummy || sym->attr.use_assoc || sym->attr.result)
11547 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
11548 gfc_restore_backend_locus (&loc);
11549 return;
11552 descriptor = sym->backend_decl;
11554 /* Although static, derived types with default initializers and
11555 allocatable components must not be nulled wholesale; instead they
11556 are treated component by component. */
11557 if (TREE_STATIC (descriptor) && !sym_has_alloc_comp && !has_finalizer)
11559 /* SAVEd variables are not freed on exit. */
11560 gfc_trans_static_array_pointer (sym);
11562 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
11563 gfc_restore_backend_locus (&loc);
11564 return;
11567 /* Get the descriptor type. */
11568 type = TREE_TYPE (sym->backend_decl);
11570 if ((sym_has_alloc_comp || (has_finalizer && sym->ts.type != BT_CLASS))
11571 && !(sym->attr.pointer || sym->attr.allocatable))
11573 if (!sym->attr.save
11574 && !(TREE_STATIC (sym->backend_decl) && sym->attr.is_main_program))
11576 if (sym->value == NULL
11577 || !gfc_has_default_initializer (sym->ts.u.derived))
11579 rank = sym->as ? sym->as->rank : 0;
11580 tmp = gfc_nullify_alloc_comp (sym->ts.u.derived,
11581 descriptor, rank);
11582 gfc_add_expr_to_block (&init, tmp);
11584 else
11585 gfc_init_default_dt (sym, &init, false);
11588 else if (!GFC_DESCRIPTOR_TYPE_P (type))
11590 /* If the backend_decl is not a descriptor, we must have a pointer
11591 to one. */
11592 descriptor = build_fold_indirect_ref_loc (input_location,
11593 sym->backend_decl);
11594 type = TREE_TYPE (descriptor);
11597 /* NULLIFY the data pointer, for non-saved allocatables. */
11598 if (GFC_DESCRIPTOR_TYPE_P (type) && !sym->attr.save && sym->attr.allocatable)
11600 gfc_conv_descriptor_data_set (&init, descriptor, null_pointer_node);
11601 if (flag_coarray == GFC_FCOARRAY_LIB && sym->attr.codimension)
11603 /* Declare the variable static so its array descriptor stays present
11604 after leaving the scope. It may still be accessed through another
11605 image. This may happen, for example, with the caf_mpi
11606 implementation. */
11607 TREE_STATIC (descriptor) = 1;
11608 tmp = gfc_conv_descriptor_token (descriptor);
11609 gfc_add_modify (&init, tmp, fold_convert (TREE_TYPE (tmp),
11610 null_pointer_node));
11614 /* Set initial TKR for pointers and allocatables */
11615 if (GFC_DESCRIPTOR_TYPE_P (type)
11616 && (sym->attr.pointer || sym->attr.allocatable))
11618 tree etype;
11620 gcc_assert (sym->as && sym->as->rank>=0);
11621 tmp = gfc_conv_descriptor_dtype (descriptor);
11622 etype = gfc_get_element_type (type);
11623 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
11624 TREE_TYPE (tmp), tmp,
11625 gfc_get_dtype_rank_type (sym->as->rank, etype));
11626 gfc_add_expr_to_block (&init, tmp);
11628 gfc_restore_backend_locus (&loc);
11629 gfc_init_block (&cleanup);
11631 /* Allocatable arrays need to be freed when they go out of scope.
11632 The allocatable components of pointers must not be touched. */
11633 if (!sym->attr.allocatable && has_finalizer && sym->ts.type != BT_CLASS
11634 && !sym->attr.pointer && !sym->attr.artificial && !sym->attr.save
11635 && !sym->ns->proc_name->attr.is_main_program)
11637 gfc_expr *e;
11638 sym->attr.referenced = 1;
11639 e = gfc_lval_expr_from_sym (sym);
11640 gfc_add_finalizer_call (&cleanup, e);
11641 gfc_free_expr (e);
11643 else if ((!sym->attr.allocatable || !has_finalizer)
11644 && sym_has_alloc_comp && !(sym->attr.function || sym->attr.result)
11645 && !sym->attr.pointer && !sym->attr.save
11646 && !(sym->attr.artificial && sym->name[0] == '_')
11647 && !sym->ns->proc_name->attr.is_main_program)
11649 int rank;
11650 rank = sym->as ? sym->as->rank : 0;
11651 tmp = gfc_deallocate_alloc_comp (sym->ts.u.derived, descriptor, rank,
11652 (sym->attr.codimension
11653 && flag_coarray == GFC_FCOARRAY_LIB)
11654 ? GFC_STRUCTURE_CAF_MODE_IN_COARRAY
11655 : 0);
11656 gfc_add_expr_to_block (&cleanup, tmp);
11659 if (sym->attr.allocatable && (sym->attr.dimension || sym->attr.codimension)
11660 && !sym->attr.save && !sym->attr.result
11661 && !sym->ns->proc_name->attr.is_main_program)
11663 gfc_expr *e;
11664 e = has_finalizer ? gfc_lval_expr_from_sym (sym) : NULL;
11665 tmp = gfc_deallocate_with_status (sym->backend_decl, NULL_TREE, NULL_TREE,
11666 NULL_TREE, NULL_TREE, true, e,
11667 sym->attr.codimension
11668 ? GFC_CAF_COARRAY_DEREGISTER
11669 : GFC_CAF_COARRAY_NOCOARRAY,
11670 NULL_TREE, gfc_finish_block (&cleanup));
11671 if (e)
11672 gfc_free_expr (e);
11673 gfc_init_block (&cleanup);
11674 gfc_add_expr_to_block (&cleanup, tmp);
11677 gfc_add_init_cleanup (block, gfc_finish_block (&init),
11678 gfc_finish_block (&cleanup));
11681 /************ Expression Walking Functions ******************/
11683 /* Walk a variable reference.
11685 Possible extension - multiple component subscripts.
11686 x(:,:) = foo%a(:)%b(:)
11687 Transforms to
11688 forall (i=..., j=...)
11689 x(i,j) = foo%a(j)%b(i)
11690 end forall
11691 This adds a fair amount of complexity because you need to deal with more
11692 than one ref. Maybe handle in a similar manner to vector subscripts.
11693 Maybe not worth the effort. */
11696 static gfc_ss *
11697 gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
11699 gfc_ref *ref;
11701 gfc_fix_class_refs (expr);
11703 for (ref = expr->ref; ref; ref = ref->next)
11704 if (ref->type == REF_ARRAY && ref->u.ar.type != AR_ELEMENT)
11705 break;
11707 return gfc_walk_array_ref (ss, expr, ref);
11711 gfc_ss *
11712 gfc_walk_array_ref (gfc_ss * ss, gfc_expr * expr, gfc_ref * ref)
11714 gfc_array_ref *ar;
11715 gfc_ss *newss;
11716 int n;
11718 for (; ref; ref = ref->next)
11720 if (ref->type == REF_SUBSTRING)
11722 ss = gfc_get_scalar_ss (ss, ref->u.ss.start);
11723 if (ref->u.ss.end)
11724 ss = gfc_get_scalar_ss (ss, ref->u.ss.end);
11727 /* We're only interested in array sections from now on. */
11728 if (ref->type != REF_ARRAY)
11729 continue;
11731 ar = &ref->u.ar;
11733 switch (ar->type)
11735 case AR_ELEMENT:
11736 for (n = ar->dimen - 1; n >= 0; n--)
11737 ss = gfc_get_scalar_ss (ss, ar->start[n]);
11738 break;
11740 case AR_FULL:
11741 /* Assumed shape arrays from interface mapping need this fix. */
11742 if (!ar->as && expr->symtree->n.sym->as)
11744 ar->as = gfc_get_array_spec();
11745 *ar->as = *expr->symtree->n.sym->as;
11747 newss = gfc_get_array_ss (ss, expr, ar->as->rank, GFC_SS_SECTION);
11748 newss->info->data.array.ref = ref;
11750 /* Make sure array is the same as array(:,:), this way
11751 we don't need to special case all the time. */
11752 ar->dimen = ar->as->rank;
11753 for (n = 0; n < ar->dimen; n++)
11755 ar->dimen_type[n] = DIMEN_RANGE;
11757 gcc_assert (ar->start[n] == NULL);
11758 gcc_assert (ar->end[n] == NULL);
11759 gcc_assert (ar->stride[n] == NULL);
11761 ss = newss;
11762 break;
11764 case AR_SECTION:
11765 newss = gfc_get_array_ss (ss, expr, 0, GFC_SS_SECTION);
11766 newss->info->data.array.ref = ref;
11768 /* We add SS chains for all the subscripts in the section. */
11769 for (n = 0; n < ar->dimen; n++)
11771 gfc_ss *indexss;
11773 switch (ar->dimen_type[n])
11775 case DIMEN_ELEMENT:
11776 /* Add SS for elemental (scalar) subscripts. */
11777 gcc_assert (ar->start[n]);
11778 indexss = gfc_get_scalar_ss (gfc_ss_terminator, ar->start[n]);
11779 indexss->loop_chain = gfc_ss_terminator;
11780 newss->info->data.array.subscript[n] = indexss;
11781 break;
11783 case DIMEN_RANGE:
11784 /* We don't add anything for sections, just remember this
11785 dimension for later. */
11786 newss->dim[newss->dimen] = n;
11787 newss->dimen++;
11788 break;
11790 case DIMEN_VECTOR:
11791 /* Create a GFC_SS_VECTOR index in which we can store
11792 the vector's descriptor. */
11793 indexss = gfc_get_array_ss (gfc_ss_terminator, ar->start[n],
11794 1, GFC_SS_VECTOR);
11795 indexss->loop_chain = gfc_ss_terminator;
11796 newss->info->data.array.subscript[n] = indexss;
11797 newss->dim[newss->dimen] = n;
11798 newss->dimen++;
11799 break;
11801 default:
11802 /* We should know what sort of section it is by now. */
11803 gcc_unreachable ();
11806 /* We should have at least one non-elemental dimension,
11807 unless we are creating a descriptor for a (scalar) coarray. */
11808 gcc_assert (newss->dimen > 0
11809 || newss->info->data.array.ref->u.ar.as->corank > 0);
11810 ss = newss;
11811 break;
11813 default:
11814 /* We should know what sort of section it is by now. */
11815 gcc_unreachable ();
11819 return ss;
11823 /* Walk an expression operator. If only one operand of a binary expression is
11824 scalar, we must also add the scalar term to the SS chain. */
11826 static gfc_ss *
11827 gfc_walk_op_expr (gfc_ss * ss, gfc_expr * expr)
11829 gfc_ss *head;
11830 gfc_ss *head2;
11832 head = gfc_walk_subexpr (ss, expr->value.op.op1);
11833 if (expr->value.op.op2 == NULL)
11834 head2 = head;
11835 else
11836 head2 = gfc_walk_subexpr (head, expr->value.op.op2);
11838 /* All operands are scalar. Pass back and let the caller deal with it. */
11839 if (head2 == ss)
11840 return head2;
11842 /* All operands require scalarization. */
11843 if (head != ss && (expr->value.op.op2 == NULL || head2 != head))
11844 return head2;
11846 /* One of the operands needs scalarization, the other is scalar.
11847 Create a gfc_ss for the scalar expression. */
11848 if (head == ss)
11850 /* First operand is scalar. We build the chain in reverse order, so
11851 add the scalar SS after the second operand. */
11852 head = head2;
11853 while (head && head->next != ss)
11854 head = head->next;
11855 /* Check we haven't somehow broken the chain. */
11856 gcc_assert (head);
11857 head->next = gfc_get_scalar_ss (ss, expr->value.op.op1);
11859 else /* head2 == head */
11861 gcc_assert (head2 == head);
11862 /* Second operand is scalar. */
11863 head2 = gfc_get_scalar_ss (head2, expr->value.op.op2);
11866 return head2;
11870 /* Reverse a SS chain. */
11872 gfc_ss *
11873 gfc_reverse_ss (gfc_ss * ss)
11875 gfc_ss *next;
11876 gfc_ss *head;
11878 gcc_assert (ss != NULL);
11880 head = gfc_ss_terminator;
11881 while (ss != gfc_ss_terminator)
11883 next = ss->next;
11884 /* Check we didn't somehow break the chain. */
11885 gcc_assert (next != NULL);
11886 ss->next = head;
11887 head = ss;
11888 ss = next;
11891 return (head);
11895 /* Given an expression referring to a procedure, return the symbol of its
11896 interface. We can't get the procedure symbol directly as we have to handle
11897 the case of (deferred) type-bound procedures. */
11899 gfc_symbol *
11900 gfc_get_proc_ifc_for_expr (gfc_expr *procedure_ref)
11902 gfc_symbol *sym;
11903 gfc_ref *ref;
11905 if (procedure_ref == NULL)
11906 return NULL;
11908 /* Normal procedure case. */
11909 if (procedure_ref->expr_type == EXPR_FUNCTION
11910 && procedure_ref->value.function.esym)
11911 sym = procedure_ref->value.function.esym;
11912 else
11913 sym = procedure_ref->symtree->n.sym;
11915 /* Typebound procedure case. */
11916 for (ref = procedure_ref->ref; ref; ref = ref->next)
11918 if (ref->type == REF_COMPONENT
11919 && ref->u.c.component->attr.proc_pointer)
11920 sym = ref->u.c.component->ts.interface;
11921 else
11922 sym = NULL;
11925 return sym;
11929 /* Given an expression referring to an intrinsic function call,
11930 return the intrinsic symbol. */
11932 gfc_intrinsic_sym *
11933 gfc_get_intrinsic_for_expr (gfc_expr *call)
11935 if (call == NULL)
11936 return NULL;
11938 /* Normal procedure case. */
11939 if (call->expr_type == EXPR_FUNCTION)
11940 return call->value.function.isym;
11941 else
11942 return NULL;
11946 /* Indicates whether an argument to an intrinsic function should be used in
11947 scalarization. It is usually the case, except for some intrinsics
11948 requiring the value to be constant, and using the value at compile time only.
11949 As the value is not used at runtime in those cases, we don’t produce code
11950 for it, and it should not be visible to the scalarizer.
11951 FUNCTION is the intrinsic function being called, ACTUAL_ARG is the actual
11952 argument being examined in that call, and ARG_NUM the index number
11953 of ACTUAL_ARG in the list of arguments.
11954 The intrinsic procedure’s dummy argument associated with ACTUAL_ARG is
11955 identified using the name in ACTUAL_ARG if it is present (that is: if it’s
11956 a keyword argument), otherwise using ARG_NUM. */
11958 static bool
11959 arg_evaluated_for_scalarization (gfc_intrinsic_sym *function,
11960 gfc_dummy_arg *dummy_arg)
11962 if (function != NULL && dummy_arg != NULL)
11964 switch (function->id)
11966 case GFC_ISYM_INDEX:
11967 case GFC_ISYM_LEN_TRIM:
11968 case GFC_ISYM_MASKL:
11969 case GFC_ISYM_MASKR:
11970 case GFC_ISYM_SCAN:
11971 case GFC_ISYM_VERIFY:
11972 if (strcmp ("kind", gfc_dummy_arg_get_name (*dummy_arg)) == 0)
11973 return false;
11974 /* Fallthrough. */
11976 default:
11977 break;
11981 return true;
11985 /* Walk the arguments of an elemental function.
11986 PROC_EXPR is used to check whether an argument is permitted to be absent. If
11987 it is NULL, we don't do the check and the argument is assumed to be present.
11990 gfc_ss *
11991 gfc_walk_elemental_function_args (gfc_ss * ss, gfc_actual_arglist *arg,
11992 gfc_intrinsic_sym *intrinsic_sym,
11993 gfc_ss_type type)
11995 int scalar;
11996 gfc_ss *head;
11997 gfc_ss *tail;
11998 gfc_ss *newss;
12000 head = gfc_ss_terminator;
12001 tail = NULL;
12003 scalar = 1;
12004 for (; arg; arg = arg->next)
12006 gfc_dummy_arg * const dummy_arg = arg->associated_dummy;
12007 if (!arg->expr
12008 || arg->expr->expr_type == EXPR_NULL
12009 || !arg_evaluated_for_scalarization (intrinsic_sym, dummy_arg))
12010 continue;
12012 newss = gfc_walk_subexpr (head, arg->expr);
12013 if (newss == head)
12015 /* Scalar argument. */
12016 gcc_assert (type == GFC_SS_SCALAR || type == GFC_SS_REFERENCE);
12017 newss = gfc_get_scalar_ss (head, arg->expr);
12018 newss->info->type = type;
12019 if (dummy_arg)
12020 newss->info->data.scalar.dummy_arg = dummy_arg;
12022 else
12023 scalar = 0;
12025 if (dummy_arg != NULL
12026 && gfc_dummy_arg_is_optional (*dummy_arg)
12027 && arg->expr->expr_type == EXPR_VARIABLE
12028 && (gfc_expr_attr (arg->expr).optional
12029 || gfc_expr_attr (arg->expr).allocatable
12030 || gfc_expr_attr (arg->expr).pointer))
12031 newss->info->can_be_null_ref = true;
12033 head = newss;
12034 if (!tail)
12036 tail = head;
12037 while (tail->next != gfc_ss_terminator)
12038 tail = tail->next;
12042 if (scalar)
12044 /* If all the arguments are scalar we don't need the argument SS. */
12045 gfc_free_ss_chain (head);
12046 /* Pass it back. */
12047 return ss;
12050 /* Add it onto the existing chain. */
12051 tail->next = ss;
12052 return head;
12056 /* Walk a function call. Scalar functions are passed back, and taken out of
12057 scalarization loops. For elemental functions we walk their arguments.
12058 The result of functions returning arrays is stored in a temporary outside
12059 the loop, so that the function is only called once. Hence we do not need
12060 to walk their arguments. */
12062 static gfc_ss *
12063 gfc_walk_function_expr (gfc_ss * ss, gfc_expr * expr)
12065 gfc_intrinsic_sym *isym;
12066 gfc_symbol *sym;
12067 gfc_component *comp = NULL;
12069 isym = expr->value.function.isym;
12071 /* Handle intrinsic functions separately. */
12072 if (isym)
12073 return gfc_walk_intrinsic_function (ss, expr, isym);
12075 sym = expr->value.function.esym;
12076 if (!sym)
12077 sym = expr->symtree->n.sym;
12079 if (gfc_is_class_array_function (expr))
12080 return gfc_get_array_ss (ss, expr,
12081 CLASS_DATA (expr->value.function.esym->result)->as->rank,
12082 GFC_SS_FUNCTION);
12084 /* A function that returns arrays. */
12085 comp = gfc_get_proc_ptr_comp (expr);
12086 if ((!comp && gfc_return_by_reference (sym) && sym->result->attr.dimension)
12087 || (comp && comp->attr.dimension))
12088 return gfc_get_array_ss (ss, expr, expr->rank, GFC_SS_FUNCTION);
12090 /* Walk the parameters of an elemental function. For now we always pass
12091 by reference. */
12092 if (sym->attr.elemental || (comp && comp->attr.elemental))
12094 gfc_ss *old_ss = ss;
12096 ss = gfc_walk_elemental_function_args (old_ss,
12097 expr->value.function.actual,
12098 gfc_get_intrinsic_for_expr (expr),
12099 GFC_SS_REFERENCE);
12100 if (ss != old_ss
12101 && (comp
12102 || sym->attr.proc_pointer
12103 || sym->attr.if_source != IFSRC_DECL
12104 || sym->attr.array_outer_dependency))
12105 ss->info->array_outer_dependency = 1;
12108 /* Scalar functions are OK as these are evaluated outside the scalarization
12109 loop. Pass back and let the caller deal with it. */
12110 return ss;
12114 /* An array temporary is constructed for array constructors. */
12116 static gfc_ss *
12117 gfc_walk_array_constructor (gfc_ss * ss, gfc_expr * expr)
12119 return gfc_get_array_ss (ss, expr, expr->rank, GFC_SS_CONSTRUCTOR);
12123 /* Walk an expression. Add walked expressions to the head of the SS chain.
12124 A wholly scalar expression will not be added. */
12126 gfc_ss *
12127 gfc_walk_subexpr (gfc_ss * ss, gfc_expr * expr)
12129 gfc_ss *head;
12131 switch (expr->expr_type)
12133 case EXPR_VARIABLE:
12134 head = gfc_walk_variable_expr (ss, expr);
12135 return head;
12137 case EXPR_OP:
12138 head = gfc_walk_op_expr (ss, expr);
12139 return head;
12141 case EXPR_FUNCTION:
12142 head = gfc_walk_function_expr (ss, expr);
12143 return head;
12145 case EXPR_CONSTANT:
12146 case EXPR_NULL:
12147 case EXPR_STRUCTURE:
12148 /* Pass back and let the caller deal with it. */
12149 break;
12151 case EXPR_ARRAY:
12152 head = gfc_walk_array_constructor (ss, expr);
12153 return head;
12155 case EXPR_SUBSTRING:
12156 /* Pass back and let the caller deal with it. */
12157 break;
12159 default:
12160 gfc_internal_error ("bad expression type during walk (%d)",
12161 expr->expr_type);
12163 return ss;
12167 /* Entry point for expression walking.
12168 A return value equal to the passed chain means this is
12169 a scalar expression. It is up to the caller to take whatever action is
12170 necessary to translate these. */
12172 gfc_ss *
12173 gfc_walk_expr (gfc_expr * expr)
12175 gfc_ss *res;
12177 res = gfc_walk_subexpr (gfc_ss_terminator, expr);
12178 return gfc_reverse_ss (res);