Line data Source code
1 : /* Expression translation
2 : Copyright (C) 2002-2026 Free Software Foundation, Inc.
3 : Contributed by Paul Brook <paul@nowt.org>
4 : and Steven Bosscher <s.bosscher@student.tudelft.nl>
5 :
6 : This file is part of GCC.
7 :
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.
12 :
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.
17 :
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/>. */
21 :
22 : /* trans-expr.cc-- generate GENERIC trees for gfc_expr. */
23 :
24 : #define INCLUDE_MEMORY
25 : #include "config.h"
26 : #include "system.h"
27 : #include "coretypes.h"
28 : #include "options.h"
29 : #include "tree.h"
30 : #include "gfortran.h"
31 : #include "trans.h"
32 : #include "stringpool.h"
33 : #include "diagnostic-core.h" /* For fatal_error. */
34 : #include "fold-const.h"
35 : #include "langhooks.h"
36 : #include "arith.h"
37 : #include "constructor.h"
38 : #include "trans-const.h"
39 : #include "trans-types.h"
40 : #include "trans-array.h"
41 : #include "trans-descriptor.h"
42 : /* Only for gfc_trans_assign and gfc_trans_pointer_assign. */
43 : #include "trans-stmt.h"
44 : #include "dependency.h"
45 : #include "gimplify.h"
46 : #include "tm.h" /* For CHAR_TYPE_SIZE. */
47 :
48 :
49 : /* Calculate the number of characters in a string. */
50 :
51 : static tree
52 36202 : gfc_get_character_len (tree type)
53 : {
54 36202 : tree len;
55 :
56 36202 : gcc_assert (type && TREE_CODE (type) == ARRAY_TYPE
57 : && TYPE_STRING_FLAG (type));
58 :
59 36202 : len = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
60 36202 : len = (len) ? (len) : (integer_zero_node);
61 36202 : return fold_convert (gfc_charlen_type_node, len);
62 : }
63 :
64 :
65 :
66 : /* Calculate the number of bytes in a string. */
67 :
68 : tree
69 36202 : gfc_get_character_len_in_bytes (tree type)
70 : {
71 36202 : tree tmp, len;
72 :
73 36202 : gcc_assert (type && TREE_CODE (type) == ARRAY_TYPE
74 : && TYPE_STRING_FLAG (type));
75 :
76 36202 : tmp = TYPE_SIZE_UNIT (TREE_TYPE (type));
77 72404 : tmp = (tmp && !integer_zerop (tmp))
78 72404 : ? (fold_convert (gfc_charlen_type_node, tmp)) : (NULL_TREE);
79 36202 : len = gfc_get_character_len (type);
80 36202 : if (tmp && len && !integer_zerop (len))
81 35430 : len = fold_build2_loc (input_location, MULT_EXPR,
82 : gfc_charlen_type_node, len, tmp);
83 36202 : return len;
84 : }
85 :
86 :
87 : /* Convert a scalar to an array descriptor. To be used for assumed-rank
88 : arrays. */
89 :
90 : static tree
91 6342 : get_scalar_to_descriptor_type (tree scalar, symbol_attribute attr)
92 : {
93 6342 : enum gfc_array_kind akind;
94 6342 : tree *lbound = NULL, *ubound = NULL;
95 6342 : int codim = 0;
96 :
97 6342 : if (attr.pointer)
98 : akind = GFC_ARRAY_POINTER_CONT;
99 5990 : else if (attr.allocatable)
100 : akind = GFC_ARRAY_ALLOCATABLE;
101 : else
102 5221 : akind = GFC_ARRAY_ASSUMED_SHAPE_CONT;
103 :
104 6342 : if (POINTER_TYPE_P (TREE_TYPE (scalar)))
105 5377 : scalar = TREE_TYPE (scalar);
106 6342 : if (TYPE_LANG_SPECIFIC (TREE_TYPE (scalar)))
107 : {
108 4800 : struct lang_type *lang_specific = TYPE_LANG_SPECIFIC (TREE_TYPE (scalar));
109 4800 : codim = lang_specific->corank;
110 4800 : lbound = lang_specific->lbound;
111 4800 : ubound = lang_specific->ubound;
112 : }
113 6342 : return gfc_get_array_type_bounds (TREE_TYPE (scalar), 0, codim, lbound,
114 : ubound, 1, akind,
115 6342 : !(attr.pointer || attr.target));
116 : }
117 :
118 : tree
119 5664 : gfc_conv_scalar_to_descriptor (gfc_se *se, tree scalar, symbol_attribute attr)
120 : {
121 5664 : tree desc, type, etype;
122 :
123 5664 : type = get_scalar_to_descriptor_type (scalar, attr);
124 5664 : etype = TREE_TYPE (scalar);
125 5664 : desc = gfc_create_var (type, "desc");
126 5664 : DECL_ARTIFICIAL (desc) = 1;
127 :
128 5664 : if (CONSTANT_CLASS_P (scalar))
129 : {
130 54 : tree tmp;
131 54 : tmp = gfc_create_var (TREE_TYPE (scalar), "scalar");
132 54 : gfc_add_modify (&se->pre, tmp, scalar);
133 54 : scalar = tmp;
134 : }
135 5664 : if (!POINTER_TYPE_P (TREE_TYPE (scalar)))
136 965 : scalar = gfc_build_addr_expr (NULL_TREE, scalar);
137 4699 : else if (TREE_TYPE (etype) && TREE_CODE (TREE_TYPE (etype)) == ARRAY_TYPE)
138 158 : etype = TREE_TYPE (etype);
139 5664 : gfc_add_modify (&se->pre, gfc_conv_descriptor_dtype (desc),
140 : gfc_get_dtype_rank_type (0, etype));
141 5664 : gfc_conv_descriptor_data_set (&se->pre, desc, scalar);
142 5664 : gfc_conv_descriptor_span_set (&se->pre, desc,
143 : gfc_conv_descriptor_elem_len (desc));
144 :
145 : /* Copy pointer address back - but only if it could have changed and
146 : if the actual argument is a pointer and not, e.g., NULL(). */
147 5664 : if ((attr.pointer || attr.allocatable) && attr.intent != INTENT_IN)
148 846 : gfc_add_modify (&se->post, scalar,
149 423 : fold_convert (TREE_TYPE (scalar),
150 : gfc_conv_descriptor_data_get (desc)));
151 5664 : return desc;
152 : }
153 :
154 :
155 : /* Get the coarray token from the ultimate array or component ref.
156 : Returns a NULL_TREE, when the ref object is not allocatable or pointer. */
157 :
158 : tree
159 512 : gfc_get_ultimate_alloc_ptr_comps_caf_token (gfc_se *outerse, gfc_expr *expr)
160 : {
161 512 : gfc_symbol *sym = expr->symtree->n.sym;
162 1024 : bool is_coarray = sym->ts.type == BT_CLASS
163 512 : ? CLASS_DATA (sym)->attr.codimension
164 467 : : sym->attr.codimension;
165 512 : gfc_expr *caf_expr = gfc_copy_expr (expr);
166 512 : gfc_ref *ref = caf_expr->ref, *last_caf_ref = NULL;
167 :
168 1622 : while (ref)
169 : {
170 1110 : if (ref->type == REF_COMPONENT
171 417 : && (ref->u.c.component->attr.allocatable
172 104 : || ref->u.c.component->attr.pointer)
173 415 : && (is_coarray || ref->u.c.component->attr.codimension))
174 1110 : last_caf_ref = ref;
175 1110 : ref = ref->next;
176 : }
177 :
178 512 : if (last_caf_ref == NULL)
179 : {
180 180 : gfc_free_expr (caf_expr);
181 180 : return NULL_TREE;
182 : }
183 :
184 143 : tree comp = last_caf_ref->u.c.component->caf_token
185 332 : ? gfc_comp_caf_token (last_caf_ref->u.c.component)
186 : : NULL_TREE,
187 : caf;
188 332 : gfc_se se;
189 332 : bool comp_ref = !last_caf_ref->u.c.component->attr.dimension;
190 332 : if (comp == NULL_TREE && comp_ref)
191 : {
192 46 : gfc_free_expr (caf_expr);
193 46 : return NULL_TREE;
194 : }
195 286 : gfc_init_se (&se, outerse);
196 286 : gfc_free_ref_list (last_caf_ref->next);
197 286 : last_caf_ref->next = NULL;
198 286 : caf_expr->rank = comp_ref ? 0 : last_caf_ref->u.c.component->as->rank;
199 572 : caf_expr->corank = last_caf_ref->u.c.component->as
200 286 : ? last_caf_ref->u.c.component->as->corank
201 : : expr->corank;
202 286 : se.want_pointer = comp_ref;
203 286 : gfc_conv_expr (&se, caf_expr);
204 286 : gfc_add_block_to_block (&outerse->pre, &se.pre);
205 :
206 286 : if (TREE_CODE (se.expr) == COMPONENT_REF && comp_ref)
207 143 : se.expr = TREE_OPERAND (se.expr, 0);
208 286 : gfc_free_expr (caf_expr);
209 :
210 286 : if (comp_ref)
211 143 : caf = fold_build3_loc (input_location, COMPONENT_REF,
212 143 : TREE_TYPE (comp), se.expr, comp, NULL_TREE);
213 : else
214 143 : caf = gfc_conv_descriptor_token (se.expr);
215 286 : return gfc_build_addr_expr (NULL_TREE, caf);
216 : }
217 :
218 :
219 : /* This is the seed for an eventual trans-class.c
220 :
221 : The following parameters should not be used directly since they might
222 : in future implementations. Use the corresponding APIs. */
223 : #define CLASS_DATA_FIELD 0
224 : #define CLASS_VPTR_FIELD 1
225 : #define CLASS_LEN_FIELD 2
226 : #define VTABLE_HASH_FIELD 0
227 : #define VTABLE_SIZE_FIELD 1
228 : #define VTABLE_EXTENDS_FIELD 2
229 : #define VTABLE_DEF_INIT_FIELD 3
230 : #define VTABLE_COPY_FIELD 4
231 : #define VTABLE_FINAL_FIELD 5
232 : #define VTABLE_DEALLOCATE_FIELD 6
233 :
234 :
235 : tree
236 40 : gfc_class_set_static_fields (tree decl, tree vptr, tree data)
237 : {
238 40 : tree tmp;
239 40 : tree field;
240 40 : vec<constructor_elt, va_gc> *init = NULL;
241 :
242 40 : field = TYPE_FIELDS (TREE_TYPE (decl));
243 40 : tmp = gfc_advance_chain (field, CLASS_DATA_FIELD);
244 40 : CONSTRUCTOR_APPEND_ELT (init, tmp, data);
245 :
246 40 : tmp = gfc_advance_chain (field, CLASS_VPTR_FIELD);
247 40 : CONSTRUCTOR_APPEND_ELT (init, tmp, vptr);
248 :
249 40 : return build_constructor (TREE_TYPE (decl), init);
250 : }
251 :
252 :
253 : tree
254 32510 : gfc_class_data_get (tree decl)
255 : {
256 32510 : tree data;
257 32510 : if (POINTER_TYPE_P (TREE_TYPE (decl)))
258 5441 : decl = build_fold_indirect_ref_loc (input_location, decl);
259 32510 : data = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (decl)),
260 : CLASS_DATA_FIELD);
261 32510 : return fold_build3_loc (input_location, COMPONENT_REF,
262 32510 : TREE_TYPE (data), decl, data,
263 32510 : NULL_TREE);
264 : }
265 :
266 :
267 : tree
268 46061 : gfc_class_vptr_get (tree decl)
269 : {
270 46061 : tree vptr;
271 : /* For class arrays decl may be a temporary descriptor handle, the vptr is
272 : then available through the saved descriptor. */
273 28442 : if (VAR_P (decl) && DECL_LANG_SPECIFIC (decl)
274 47867 : && GFC_DECL_SAVED_DESCRIPTOR (decl))
275 1303 : decl = GFC_DECL_SAVED_DESCRIPTOR (decl);
276 46061 : if (POINTER_TYPE_P (TREE_TYPE (decl)))
277 2369 : decl = build_fold_indirect_ref_loc (input_location, decl);
278 46061 : vptr = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (decl)),
279 : CLASS_VPTR_FIELD);
280 46061 : return fold_build3_loc (input_location, COMPONENT_REF,
281 46061 : TREE_TYPE (vptr), decl, vptr,
282 46061 : NULL_TREE);
283 : }
284 :
285 :
286 : tree
287 6805 : gfc_class_len_get (tree decl)
288 : {
289 6805 : tree len;
290 : /* For class arrays decl may be a temporary descriptor handle, the len is
291 : then available through the saved descriptor. */
292 4859 : if (VAR_P (decl) && DECL_LANG_SPECIFIC (decl)
293 7060 : && GFC_DECL_SAVED_DESCRIPTOR (decl))
294 91 : decl = GFC_DECL_SAVED_DESCRIPTOR (decl);
295 6805 : if (POINTER_TYPE_P (TREE_TYPE (decl)))
296 668 : decl = build_fold_indirect_ref_loc (input_location, decl);
297 6805 : len = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (decl)),
298 : CLASS_LEN_FIELD);
299 6805 : return fold_build3_loc (input_location, COMPONENT_REF,
300 6805 : TREE_TYPE (len), decl, len,
301 6805 : NULL_TREE);
302 : }
303 :
304 :
305 : /* Try to get the _len component of a class. When the class is not unlimited
306 : poly, i.e. no _len field exists, then return a zero node. */
307 :
308 : static tree
309 8374 : gfc_class_len_or_zero_get (tree decl)
310 : {
311 8374 : tree len;
312 : /* For class arrays decl may be a temporary descriptor handle, the vptr is
313 : then available through the saved descriptor. */
314 4138 : if (VAR_P (decl) && DECL_LANG_SPECIFIC (decl)
315 8440 : && GFC_DECL_SAVED_DESCRIPTOR (decl))
316 0 : decl = GFC_DECL_SAVED_DESCRIPTOR (decl);
317 8374 : if (POINTER_TYPE_P (TREE_TYPE (decl)))
318 12 : decl = build_fold_indirect_ref_loc (input_location, decl);
319 8374 : len = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (decl)),
320 : CLASS_LEN_FIELD);
321 10698 : return len != NULL_TREE ? fold_build3_loc (input_location, COMPONENT_REF,
322 2324 : TREE_TYPE (len), decl, len,
323 : NULL_TREE)
324 6050 : : build_zero_cst (gfc_charlen_type_node);
325 : }
326 :
327 :
328 : tree
329 8204 : gfc_resize_class_size_with_len (stmtblock_t * block, tree class_expr, tree size)
330 : {
331 8204 : tree tmp;
332 8204 : tree tmp2;
333 8204 : tree type;
334 :
335 8204 : tmp = gfc_class_len_or_zero_get (class_expr);
336 :
337 : /* Include the len value in the element size if present. */
338 8204 : if (!integer_zerop (tmp))
339 : {
340 2154 : type = TREE_TYPE (size);
341 2154 : if (block)
342 : {
343 996 : size = gfc_evaluate_now (size, block);
344 996 : tmp = gfc_evaluate_now (fold_convert (type , tmp), block);
345 : }
346 : else
347 1158 : tmp = fold_convert (type , tmp);
348 2154 : tmp2 = fold_build2_loc (input_location, MULT_EXPR,
349 : type, size, tmp);
350 2154 : tmp = fold_build2_loc (input_location, GT_EXPR,
351 : logical_type_node, tmp,
352 : build_zero_cst (type));
353 2154 : size = fold_build3_loc (input_location, COND_EXPR,
354 : type, tmp, tmp2, size);
355 : }
356 : else
357 : return size;
358 :
359 2154 : if (block)
360 996 : size = gfc_evaluate_now (size, block);
361 :
362 : return size;
363 : }
364 :
365 :
366 : /* Get the specified FIELD from the VPTR. */
367 :
368 : static tree
369 21406 : vptr_field_get (tree vptr, int fieldno)
370 : {
371 21406 : tree field;
372 21406 : vptr = build_fold_indirect_ref_loc (input_location, vptr);
373 21406 : field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (vptr)),
374 : fieldno);
375 21406 : field = fold_build3_loc (input_location, COMPONENT_REF,
376 21406 : TREE_TYPE (field), vptr, field,
377 : NULL_TREE);
378 21406 : gcc_assert (field);
379 21406 : return field;
380 : }
381 :
382 :
383 : /* Get the field from the class' vptr. */
384 :
385 : static tree
386 9984 : class_vtab_field_get (tree decl, int fieldno)
387 : {
388 9984 : tree vptr;
389 9984 : vptr = gfc_class_vptr_get (decl);
390 9984 : return vptr_field_get (vptr, fieldno);
391 : }
392 :
393 :
394 : /* Define a macro for creating the class_vtab_* and vptr_* accessors in
395 : unison. */
396 : #define VTAB_GET_FIELD_GEN(name, field) tree \
397 : gfc_class_vtab_## name ##_get (tree cl) \
398 : { \
399 : return class_vtab_field_get (cl, field); \
400 : } \
401 : \
402 : tree \
403 : gfc_vptr_## name ##_get (tree vptr) \
404 : { \
405 : return vptr_field_get (vptr, field); \
406 : }
407 :
408 183 : VTAB_GET_FIELD_GEN (hash, VTABLE_HASH_FIELD)
409 0 : VTAB_GET_FIELD_GEN (extends, VTABLE_EXTENDS_FIELD)
410 0 : VTAB_GET_FIELD_GEN (def_init, VTABLE_DEF_INIT_FIELD)
411 4377 : VTAB_GET_FIELD_GEN (copy, VTABLE_COPY_FIELD)
412 1836 : VTAB_GET_FIELD_GEN (final, VTABLE_FINAL_FIELD)
413 1023 : VTAB_GET_FIELD_GEN (deallocate, VTABLE_DEALLOCATE_FIELD)
414 : #undef VTAB_GET_FIELD_GEN
415 :
416 : /* The size field is returned as an array index type. Therefore treat
417 : it and only it specially. */
418 :
419 : tree
420 7970 : gfc_class_vtab_size_get (tree cl)
421 : {
422 7970 : tree size;
423 7970 : size = class_vtab_field_get (cl, VTABLE_SIZE_FIELD);
424 : /* Always return size as an array index type. */
425 7970 : size = fold_convert (gfc_array_index_type, size);
426 7970 : gcc_assert (size);
427 7970 : return size;
428 : }
429 :
430 : tree
431 6017 : gfc_vptr_size_get (tree vptr)
432 : {
433 6017 : tree size;
434 6017 : size = vptr_field_get (vptr, VTABLE_SIZE_FIELD);
435 : /* Always return size as an array index type. */
436 6017 : size = fold_convert (gfc_array_index_type, size);
437 6017 : gcc_assert (size);
438 6017 : return size;
439 : }
440 :
441 :
442 : #undef CLASS_DATA_FIELD
443 : #undef CLASS_VPTR_FIELD
444 : #undef CLASS_LEN_FIELD
445 : #undef VTABLE_HASH_FIELD
446 : #undef VTABLE_SIZE_FIELD
447 : #undef VTABLE_EXTENDS_FIELD
448 : #undef VTABLE_DEF_INIT_FIELD
449 : #undef VTABLE_COPY_FIELD
450 : #undef VTABLE_FINAL_FIELD
451 :
452 :
453 : /* IF ts is null (default), search for the last _class ref in the chain
454 : of references of the expression and cut the chain there. Although
455 : this routine is similar to class.cc:gfc_add_component_ref (), there
456 : is a significant difference: gfc_add_component_ref () concentrates
457 : on an array ref that is the last ref in the chain and is oblivious
458 : to the kind of refs following.
459 : ELSE IF ts is non-null the cut is at the class entity or component
460 : that is followed by an array reference, which is not an element.
461 : These calls come from trans-array.cc:build_class_array_ref, which
462 : handles scalarized class array references.*/
463 :
464 : gfc_expr *
465 9493 : gfc_find_and_cut_at_last_class_ref (gfc_expr *e, bool is_mold,
466 : gfc_typespec **ts)
467 : {
468 9493 : gfc_expr *base_expr;
469 9493 : gfc_ref *ref, *class_ref, *tail = NULL, *array_ref;
470 :
471 : /* Find the last class reference. */
472 9493 : class_ref = NULL;
473 9493 : array_ref = NULL;
474 :
475 9493 : if (ts)
476 : {
477 435 : if (e->symtree
478 410 : && e->symtree->n.sym->ts.type == BT_CLASS)
479 410 : *ts = &e->symtree->n.sym->ts;
480 : else
481 25 : *ts = NULL;
482 : }
483 :
484 23893 : for (ref = e->ref; ref; ref = ref->next)
485 : {
486 14820 : if (ts)
487 : {
488 1038 : if (ref->type == REF_COMPONENT
489 490 : && ref->u.c.component->ts.type == BT_CLASS
490 0 : && ref->next && ref->next->type == REF_COMPONENT
491 0 : && !strcmp (ref->next->u.c.component->name, "_data")
492 0 : && ref->next->next
493 0 : && ref->next->next->type == REF_ARRAY
494 0 : && ref->next->next->u.ar.type != AR_ELEMENT)
495 : {
496 0 : *ts = &ref->u.c.component->ts;
497 0 : class_ref = ref;
498 0 : break;
499 : }
500 :
501 1038 : if (ref->next == NULL)
502 : break;
503 : }
504 : else
505 : {
506 13782 : if (ref->type == REF_ARRAY && ref->u.ar.type != AR_ELEMENT)
507 13782 : array_ref = ref;
508 :
509 13782 : if (ref->type == REF_COMPONENT
510 8289 : && ref->u.c.component->ts.type == BT_CLASS)
511 : {
512 : /* Component to the right of a part reference with nonzero
513 : rank must not have the ALLOCATABLE attribute. If attempts
514 : are made to reference such a component reference, an error
515 : results followed by an ICE. */
516 1618 : if (array_ref
517 10 : && CLASS_DATA (ref->u.c.component)->attr.allocatable)
518 : return NULL;
519 : class_ref = ref;
520 : }
521 : }
522 : }
523 :
524 9483 : if (ts && *ts == NULL)
525 : return NULL;
526 :
527 : /* Remove and store all subsequent references after the
528 : CLASS reference. */
529 9458 : if (class_ref)
530 : {
531 1416 : tail = class_ref->next;
532 1416 : class_ref->next = NULL;
533 : }
534 8042 : else if (e->symtree && e->symtree->n.sym->ts.type == BT_CLASS)
535 : {
536 8042 : tail = e->ref;
537 8042 : e->ref = NULL;
538 : }
539 :
540 9458 : if (is_mold)
541 61 : base_expr = gfc_expr_to_initialize (e);
542 : else
543 9397 : base_expr = gfc_copy_expr (e);
544 :
545 : /* Restore the original tail expression. */
546 9458 : if (class_ref)
547 : {
548 1416 : gfc_free_ref_list (class_ref->next);
549 1416 : class_ref->next = tail;
550 : }
551 8042 : else if (e->symtree && e->symtree->n.sym->ts.type == BT_CLASS)
552 : {
553 8042 : gfc_free_ref_list (e->ref);
554 8042 : e->ref = tail;
555 : }
556 : return base_expr;
557 : }
558 :
559 : /* Reset the vptr to the declared type, e.g. after deallocation.
560 : Use the variable in CLASS_CONTAINER if available. Otherwise, recreate
561 : one with e or class_type. At least one of the two has to be set. The
562 : generated assignment code is added at the end of BLOCK. */
563 :
564 : void
565 11290 : gfc_reset_vptr (stmtblock_t *block, gfc_expr *e, tree class_container,
566 : gfc_symbol *class_type)
567 : {
568 11290 : tree vptr = NULL_TREE;
569 :
570 11290 : if (class_container != NULL_TREE)
571 6764 : vptr = gfc_get_vptr_from_expr (class_container);
572 :
573 6764 : if (vptr == NULL_TREE)
574 : {
575 4533 : gfc_se se;
576 4533 : gcc_assert (e);
577 :
578 : /* Evaluate the expression and obtain the vptr from it. */
579 4533 : gfc_init_se (&se, NULL);
580 4533 : if (e->rank)
581 2261 : gfc_conv_expr_descriptor (&se, e);
582 : else
583 2272 : gfc_conv_expr (&se, e);
584 4533 : gfc_add_block_to_block (block, &se.pre);
585 :
586 4533 : vptr = gfc_get_vptr_from_expr (se.expr);
587 : }
588 :
589 : /* If a vptr is not found, we can do nothing more. */
590 4533 : if (vptr == NULL_TREE)
591 : return;
592 :
593 11280 : if (UNLIMITED_POLY (e)
594 10244 : || UNLIMITED_POLY (class_type)
595 : /* When the class_type's source is not a symbol (e.g. a component's ts),
596 : then look at the _data-components type. */
597 1529 : || (class_type != NULL && class_type->ts.type == BT_UNKNOWN
598 1529 : && class_type->components && class_type->components->ts.u.derived
599 1523 : && class_type->components->ts.u.derived->attr.unlimited_polymorphic))
600 1204 : gfc_add_modify (block, vptr, build_int_cst (TREE_TYPE (vptr), 0));
601 : else
602 : {
603 10076 : gfc_symbol *vtab, *type = nullptr;
604 10076 : tree vtable;
605 :
606 10076 : if (e)
607 8715 : type = e->ts.u.derived;
608 1361 : else if (class_type)
609 : {
610 1361 : if (class_type->ts.type == BT_CLASS)
611 0 : type = CLASS_DATA (class_type)->ts.u.derived;
612 : else
613 : type = class_type;
614 : }
615 8715 : gcc_assert (type);
616 : /* Return the vptr to the address of the declared type. */
617 10076 : vtab = gfc_find_derived_vtab (type);
618 10076 : vtable = vtab->backend_decl;
619 10076 : if (vtable == NULL_TREE)
620 100 : vtable = gfc_get_symbol_decl (vtab);
621 10076 : vtable = gfc_build_addr_expr (NULL, vtable);
622 10076 : vtable = fold_convert (TREE_TYPE (vptr), vtable);
623 10076 : gfc_add_modify (block, vptr, vtable);
624 : }
625 : }
626 :
627 : /* Set the vptr of a class in to from the type given in from. If from is NULL,
628 : then reset the vptr to the default or to. */
629 :
630 : void
631 228 : gfc_class_set_vptr (stmtblock_t *block, tree to, tree from)
632 : {
633 228 : tree tmp, vptr_ref;
634 228 : gfc_symbol *type;
635 :
636 228 : vptr_ref = gfc_get_vptr_from_expr (to);
637 264 : if (POINTER_TYPE_P (TREE_TYPE (from))
638 228 : && GFC_CLASS_TYPE_P (TREE_TYPE (TREE_TYPE (from))))
639 : {
640 44 : gfc_add_modify (block, vptr_ref,
641 22 : fold_convert (TREE_TYPE (vptr_ref),
642 : gfc_get_vptr_from_expr (from)));
643 250 : return;
644 : }
645 206 : tmp = gfc_get_vptr_from_expr (from);
646 206 : if (tmp)
647 : {
648 170 : gfc_add_modify (block, vptr_ref,
649 170 : fold_convert (TREE_TYPE (vptr_ref), tmp));
650 170 : return;
651 : }
652 36 : if (VAR_P (from)
653 36 : && strncmp (IDENTIFIER_POINTER (DECL_NAME (from)), "__vtab", 6) == 0)
654 : {
655 36 : gfc_add_modify (block, vptr_ref,
656 36 : gfc_build_addr_expr (TREE_TYPE (vptr_ref), from));
657 36 : return;
658 : }
659 0 : if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (from)))
660 0 : && GFC_CLASS_TYPE_P (
661 : TREE_TYPE (TREE_OPERAND (TREE_OPERAND (from, 0), 0))))
662 : {
663 0 : gfc_add_modify (block, vptr_ref,
664 0 : fold_convert (TREE_TYPE (vptr_ref),
665 : gfc_get_vptr_from_expr (TREE_OPERAND (
666 : TREE_OPERAND (from, 0), 0))));
667 0 : return;
668 : }
669 :
670 : /* If nothing of the above matches, set the vtype according to the type. */
671 0 : tmp = TREE_TYPE (from);
672 0 : if (POINTER_TYPE_P (tmp))
673 0 : tmp = TREE_TYPE (tmp);
674 0 : gfc_find_symbol (IDENTIFIER_POINTER (TYPE_NAME (tmp)), gfc_current_ns, 1,
675 : &type);
676 0 : tmp = gfc_find_derived_vtab (type)->backend_decl;
677 0 : gcc_assert (tmp);
678 0 : gfc_add_modify (block, vptr_ref,
679 0 : gfc_build_addr_expr (TREE_TYPE (vptr_ref), tmp));
680 : }
681 :
682 : /* Reset the len for unlimited polymorphic objects. */
683 :
684 : void
685 639 : gfc_reset_len (stmtblock_t *block, gfc_expr *expr)
686 : {
687 639 : gfc_expr *e;
688 639 : gfc_se se_len;
689 639 : e = gfc_find_and_cut_at_last_class_ref (expr);
690 639 : if (e == NULL)
691 0 : return;
692 639 : gfc_add_len_component (e);
693 639 : gfc_init_se (&se_len, NULL);
694 639 : gfc_conv_expr (&se_len, e);
695 639 : gfc_add_modify (block, se_len.expr,
696 639 : fold_convert (TREE_TYPE (se_len.expr), integer_zero_node));
697 639 : gfc_free_expr (e);
698 : }
699 :
700 :
701 : /* Obtain the last class reference in a gfc_expr. Return NULL_TREE if no class
702 : reference is found. Note that it is up to the caller to avoid using this
703 : for expressions other than variables. */
704 :
705 : tree
706 1451 : gfc_get_class_from_gfc_expr (gfc_expr *e)
707 : {
708 1451 : gfc_expr *class_expr;
709 1451 : gfc_se cse;
710 1451 : class_expr = gfc_find_and_cut_at_last_class_ref (e);
711 1451 : if (class_expr == NULL)
712 : return NULL_TREE;
713 1451 : gfc_init_se (&cse, NULL);
714 1451 : gfc_conv_expr (&cse, class_expr);
715 1451 : gfc_free_expr (class_expr);
716 1451 : return cse.expr;
717 : }
718 :
719 :
720 : /* Obtain the last class reference in an expression.
721 : Return NULL_TREE if no class reference is found. */
722 :
723 : tree
724 108473 : gfc_get_class_from_expr (tree expr)
725 : {
726 108473 : tree tmp;
727 108473 : tree type;
728 108473 : bool array_descr_found = false;
729 108473 : bool comp_after_descr_found = false;
730 :
731 279519 : for (tmp = expr; tmp; tmp = TREE_OPERAND (tmp, 0))
732 : {
733 279519 : if (CONSTANT_CLASS_P (tmp))
734 : return NULL_TREE;
735 :
736 279482 : type = TREE_TYPE (tmp);
737 324061 : while (type)
738 : {
739 316183 : if (GFC_CLASS_TYPE_P (type))
740 : return tmp;
741 296121 : if (GFC_DESCRIPTOR_TYPE_P (type))
742 35404 : array_descr_found = true;
743 296121 : if (type != TYPE_CANONICAL (type))
744 44579 : type = TYPE_CANONICAL (type);
745 : else
746 : type = NULL_TREE;
747 : }
748 259420 : if (VAR_P (tmp) || TREE_CODE (tmp) == PARM_DECL)
749 : break;
750 :
751 : /* Avoid walking up the reference chain too far. For class arrays, the
752 : array descriptor is a direct component (through a pointer) of the class
753 : container. So there is exactly one COMPONENT_REF between a class
754 : container and its child array descriptor. After seeing an array
755 : descriptor, we can give up on the second COMPONENT_REF we see, if no
756 : class container was found until that point. */
757 171046 : if (array_descr_found)
758 : {
759 7467 : if (comp_after_descr_found)
760 : {
761 12 : if (TREE_CODE (tmp) == COMPONENT_REF)
762 : return NULL_TREE;
763 : }
764 7455 : else if (TREE_CODE (tmp) == COMPONENT_REF)
765 7467 : comp_after_descr_found = true;
766 : }
767 : }
768 :
769 88374 : if (POINTER_TYPE_P (TREE_TYPE (tmp)))
770 59282 : tmp = build_fold_indirect_ref_loc (input_location, tmp);
771 :
772 88374 : if (GFC_CLASS_TYPE_P (TREE_TYPE (tmp)))
773 : return tmp;
774 :
775 : return NULL_TREE;
776 : }
777 :
778 :
779 : /* Obtain the vptr of the last class reference in an expression.
780 : Return NULL_TREE if no class reference is found. */
781 :
782 : tree
783 11945 : gfc_get_vptr_from_expr (tree expr)
784 : {
785 11945 : tree tmp;
786 :
787 11945 : tmp = gfc_get_class_from_expr (expr);
788 :
789 11945 : if (tmp != NULL_TREE)
790 11880 : return gfc_class_vptr_get (tmp);
791 :
792 : return NULL_TREE;
793 : }
794 :
795 : static void
796 2287 : copy_coarray_desc_part (stmtblock_t *block, tree dest, tree src)
797 : {
798 2287 : tree src_type = TREE_TYPE (src);
799 2287 : if (TYPE_LANG_SPECIFIC (src_type) && TYPE_LANG_SPECIFIC (src_type)->corank)
800 : {
801 135 : struct lang_type *lang_specific = TYPE_LANG_SPECIFIC (src_type);
802 270 : for (int c = 0; c < lang_specific->corank; ++c)
803 : {
804 135 : int dim = lang_specific->rank + c;
805 135 : tree codim = gfc_rank_cst[dim];
806 :
807 135 : if (lang_specific->lbound[dim])
808 54 : gfc_conv_descriptor_lbound_set (block, dest, codim,
809 : lang_specific->lbound[dim]);
810 : else
811 81 : gfc_conv_descriptor_lbound_set (
812 : block, dest, codim, gfc_conv_descriptor_lbound_get (src, codim));
813 135 : if (dim + 1 < lang_specific->corank)
814 : {
815 0 : if (lang_specific->ubound[dim])
816 0 : gfc_conv_descriptor_ubound_set (block, dest, codim,
817 : lang_specific->ubound[dim]);
818 : else
819 0 : gfc_conv_descriptor_ubound_set (
820 : block, dest, codim,
821 : gfc_conv_descriptor_ubound_get (src, codim));
822 : }
823 : }
824 : }
825 2287 : }
826 :
827 : void
828 1965 : gfc_class_array_data_assign (stmtblock_t *block, tree lhs_desc, tree rhs_desc,
829 : bool lhs_type)
830 : {
831 1965 : tree lhs_dim, rhs_dim, type;
832 :
833 1965 : gfc_conv_descriptor_data_set (block, lhs_desc,
834 : gfc_conv_descriptor_data_get (rhs_desc));
835 1965 : gfc_conv_descriptor_offset_set (block, lhs_desc,
836 : gfc_conv_descriptor_offset_get (rhs_desc));
837 :
838 1965 : gfc_add_modify (block, gfc_conv_descriptor_dtype (lhs_desc),
839 : gfc_conv_descriptor_dtype (rhs_desc));
840 :
841 : /* Assign the dimension as range-ref. */
842 1965 : lhs_dim = gfc_get_descriptor_dimension (lhs_desc);
843 1965 : rhs_dim = gfc_get_descriptor_dimension (rhs_desc);
844 :
845 1965 : type = lhs_type ? TREE_TYPE (lhs_dim) : TREE_TYPE (rhs_dim);
846 1965 : lhs_dim = build4_loc (input_location, ARRAY_RANGE_REF, type, lhs_dim,
847 : gfc_index_zero_node, NULL_TREE, NULL_TREE);
848 1965 : rhs_dim = build4_loc (input_location, ARRAY_RANGE_REF, type, rhs_dim,
849 : gfc_index_zero_node, NULL_TREE, NULL_TREE);
850 1965 : gfc_add_modify (block, lhs_dim, rhs_dim);
851 :
852 : /* The corank dimensions are not copied by the ARRAY_RANGE_REF. */
853 1965 : copy_coarray_desc_part (block, lhs_desc, rhs_desc);
854 1965 : }
855 :
856 : /* Takes a derived type expression and returns the address of a temporary
857 : class object of the 'declared' type. If opt_vptr_src is not NULL, this is
858 : used for the temporary class object.
859 : optional_alloc_ptr is false when the dummy is neither allocatable
860 : nor a pointer; that's only relevant for the optional handling.
861 : The optional argument 'derived_array' is used to preserve the parmse
862 : expression for deallocation of allocatable components. Assumed rank
863 : formal arguments made this necessary. */
864 : void
865 5253 : gfc_conv_derived_to_class (gfc_se *parmse, gfc_expr *e, gfc_symbol *fsym,
866 : tree opt_vptr_src, bool optional,
867 : bool optional_alloc_ptr, const char *proc_name,
868 : tree *derived_array)
869 : {
870 5253 : tree cond_optional = NULL_TREE;
871 5253 : gfc_ss *ss;
872 5253 : tree ctree;
873 5253 : tree var;
874 5253 : tree tmp;
875 5253 : tree packed = NULL_TREE;
876 :
877 : /* The derived type needs to be converted to a temporary CLASS object. */
878 5253 : tmp = gfc_typenode_for_spec (&fsym->ts);
879 5253 : var = gfc_create_var (tmp, "class");
880 :
881 : /* Set the vptr. */
882 5253 : if (opt_vptr_src)
883 128 : gfc_class_set_vptr (&parmse->pre, var, opt_vptr_src);
884 : else
885 5125 : gfc_reset_vptr (&parmse->pre, e, var);
886 :
887 : /* Now set the data field. */
888 5253 : ctree = gfc_class_data_get (var);
889 :
890 5253 : if (flag_coarray == GFC_FCOARRAY_LIB && CLASS_DATA (fsym)->attr.codimension)
891 : {
892 4 : tree token;
893 4 : tmp = gfc_get_tree_for_caf_expr (e);
894 4 : if (POINTER_TYPE_P (TREE_TYPE (tmp)))
895 2 : tmp = build_fold_indirect_ref (tmp);
896 4 : gfc_get_caf_token_offset (parmse, &token, nullptr, tmp, NULL_TREE, e);
897 4 : gfc_add_modify (&parmse->pre, gfc_conv_descriptor_token (ctree), token);
898 : }
899 :
900 5253 : if (optional)
901 576 : cond_optional = gfc_conv_expr_present (e->symtree->n.sym);
902 :
903 : /* Set the _len as early as possible. */
904 5253 : if (fsym->ts.u.derived->components->ts.type == BT_DERIVED
905 5253 : && fsym->ts.u.derived->components->ts.u.derived->attr
906 5253 : .unlimited_polymorphic)
907 : {
908 : /* Take care about initializing the _len component correctly. */
909 386 : tree len_tree = gfc_class_len_get (var);
910 386 : if (UNLIMITED_POLY (e))
911 : {
912 12 : gfc_expr *len;
913 12 : gfc_se se;
914 :
915 12 : len = gfc_find_and_cut_at_last_class_ref (e);
916 12 : gfc_add_len_component (len);
917 12 : gfc_init_se (&se, NULL);
918 12 : gfc_conv_expr (&se, len);
919 12 : if (optional)
920 0 : tmp = build3_loc (input_location, COND_EXPR, TREE_TYPE (se.expr),
921 : cond_optional, se.expr,
922 0 : fold_convert (TREE_TYPE (se.expr),
923 : integer_zero_node));
924 : else
925 12 : tmp = se.expr;
926 12 : gfc_free_expr (len);
927 12 : }
928 : else
929 374 : tmp = integer_zero_node;
930 386 : gfc_add_modify (&parmse->pre, len_tree,
931 386 : fold_convert (TREE_TYPE (len_tree), tmp));
932 : }
933 :
934 5253 : if (parmse->expr && POINTER_TYPE_P (TREE_TYPE (parmse->expr)))
935 : {
936 : /* If there is a ready made pointer to a derived type, use it
937 : rather than evaluating the expression again. */
938 535 : tmp = fold_convert (TREE_TYPE (ctree), parmse->expr);
939 535 : gfc_add_modify (&parmse->pre, ctree, tmp);
940 : }
941 4718 : else if (parmse->ss && parmse->ss->info && parmse->ss->info->useflags)
942 : {
943 : /* For an array reference in an elemental procedure call we need
944 : to retain the ss to provide the scalarized array reference. */
945 445 : gfc_conv_expr_reference (parmse, e);
946 445 : tmp = fold_convert (TREE_TYPE (ctree), parmse->expr);
947 445 : if (optional)
948 0 : tmp = build3_loc (input_location, COND_EXPR, TREE_TYPE (tmp),
949 : cond_optional, tmp,
950 0 : fold_convert (TREE_TYPE (tmp), null_pointer_node));
951 445 : gfc_add_modify (&parmse->pre, ctree, tmp);
952 : }
953 : else
954 : {
955 4273 : ss = gfc_walk_expr (e);
956 4273 : if (ss == gfc_ss_terminator)
957 : {
958 3019 : parmse->ss = NULL;
959 3019 : gfc_conv_expr_reference (parmse, e);
960 :
961 : /* Scalar to an assumed-rank array. */
962 3019 : if (fsym->ts.u.derived->components->as)
963 : {
964 322 : tree type;
965 322 : type = get_scalar_to_descriptor_type (parmse->expr,
966 : gfc_expr_attr (e));
967 322 : gfc_add_modify (&parmse->pre, gfc_conv_descriptor_dtype (ctree),
968 : gfc_get_dtype (type));
969 322 : copy_coarray_desc_part (&parmse->pre, ctree, parmse->expr);
970 322 : if (optional)
971 192 : parmse->expr = build3_loc (input_location, COND_EXPR,
972 96 : TREE_TYPE (parmse->expr),
973 : cond_optional, parmse->expr,
974 96 : fold_convert (TREE_TYPE (parmse->expr),
975 : null_pointer_node));
976 322 : gfc_conv_descriptor_data_set (&parmse->pre, ctree, parmse->expr);
977 : }
978 : else
979 : {
980 2697 : tmp = fold_convert (TREE_TYPE (ctree), parmse->expr);
981 2697 : if (optional)
982 132 : tmp = build3_loc (input_location, COND_EXPR, TREE_TYPE (tmp),
983 : cond_optional, tmp,
984 132 : fold_convert (TREE_TYPE (tmp),
985 : null_pointer_node));
986 2697 : gfc_add_modify (&parmse->pre, ctree, tmp);
987 : }
988 : }
989 : else
990 : {
991 1254 : stmtblock_t block;
992 1254 : gfc_init_block (&block);
993 1254 : gfc_ref *ref;
994 1254 : int dim;
995 1254 : tree lbshift = NULL_TREE;
996 :
997 : /* Array refs with sections indicate, that a for a formal argument
998 : expecting contiguous repacking needs to be done. */
999 2357 : for (ref = e->ref; ref; ref = ref->next)
1000 1253 : if (ref->type == REF_ARRAY && ref->u.ar.type == AR_SECTION)
1001 : break;
1002 1254 : if (IS_CLASS_ARRAY (fsym)
1003 1146 : && (CLASS_DATA (fsym)->as->type == AS_EXPLICIT
1004 888 : || CLASS_DATA (fsym)->as->type == AS_ASSUMED_SIZE)
1005 354 : && (ref || e->rank != fsym->ts.u.derived->components->as->rank))
1006 144 : fsym->attr.contiguous = 1;
1007 :
1008 : /* Detect any array references with vector subscripts. */
1009 2501 : for (ref = e->ref; ref; ref = ref->next)
1010 1253 : if (ref->type == REF_ARRAY && ref->u.ar.type != AR_ELEMENT
1011 1211 : && ref->u.ar.type != AR_FULL)
1012 : {
1013 336 : for (dim = 0; dim < ref->u.ar.dimen; dim++)
1014 192 : if (ref->u.ar.dimen_type[dim] == DIMEN_VECTOR)
1015 : break;
1016 150 : if (dim < ref->u.ar.dimen)
1017 : break;
1018 : }
1019 : /* Array references with vector subscripts and non-variable
1020 : expressions need be converted to a one-based descriptor. */
1021 1254 : if (ref || e->expr_type != EXPR_VARIABLE)
1022 49 : lbshift = gfc_index_one_node;
1023 :
1024 1254 : parmse->expr = var;
1025 1254 : gfc_conv_array_parameter (parmse, e, false, fsym, proc_name, nullptr,
1026 : &lbshift, &packed);
1027 :
1028 1254 : if (derived_array && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (parmse->expr)))
1029 : {
1030 1158 : *derived_array
1031 1158 : = gfc_create_var (TREE_TYPE (parmse->expr), "array");
1032 1158 : if (e->rank == -1)
1033 : {
1034 : /* Assumed-rank actual: parmse->expr physically holds only
1035 : dtype.rank dims; a full struct assign reads past the end.
1036 : Copy field-by-field with a runtime-sized dim[] memcpy.
1037 : PR fortran/60576. */
1038 78 : tree rank, dim_field, dim_size, copy_size, dst_ptr, src_ptr;
1039 :
1040 78 : gfc_conv_descriptor_data_set
1041 78 : (&block, *derived_array,
1042 : gfc_conv_descriptor_data_get (parmse->expr));
1043 78 : gfc_conv_descriptor_offset_set
1044 78 : (&block, *derived_array,
1045 : gfc_conv_descriptor_offset_get (parmse->expr));
1046 78 : gfc_add_modify (&block,
1047 : gfc_conv_descriptor_dtype (*derived_array),
1048 : gfc_conv_descriptor_dtype (parmse->expr));
1049 78 : rank = fold_convert (size_type_node,
1050 : gfc_conv_descriptor_rank (parmse->expr));
1051 78 : dim_field = gfc_get_descriptor_dimension (parmse->expr);
1052 78 : dim_size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (dim_field)));
1053 78 : copy_size = fold_build2_loc (input_location, MULT_EXPR,
1054 : size_type_node, rank, dim_size);
1055 78 : dst_ptr = gfc_build_addr_expr
1056 78 : (pvoid_type_node, gfc_get_descriptor_dimension (*derived_array));
1057 78 : src_ptr = gfc_build_addr_expr (pvoid_type_node, dim_field);
1058 78 : gfc_add_expr_to_block (&block,
1059 : build_call_expr_loc (input_location,
1060 : builtin_decl_explicit (BUILT_IN_MEMCPY),
1061 : 3, dst_ptr, src_ptr, copy_size));
1062 : }
1063 : else
1064 1080 : gfc_add_modify (&block, *derived_array, parmse->expr);
1065 : }
1066 :
1067 1254 : if (optional)
1068 : {
1069 348 : tmp = gfc_finish_block (&block);
1070 :
1071 348 : gfc_init_block (&block);
1072 348 : gfc_conv_descriptor_data_set (&block, ctree, null_pointer_node);
1073 348 : if (derived_array && *derived_array != NULL_TREE)
1074 348 : gfc_conv_descriptor_data_set (&block, *derived_array,
1075 : null_pointer_node);
1076 :
1077 348 : tmp = build3_v (COND_EXPR, cond_optional, tmp,
1078 : gfc_finish_block (&block));
1079 348 : gfc_add_expr_to_block (&parmse->pre, tmp);
1080 : }
1081 : else
1082 906 : gfc_add_block_to_block (&parmse->pre, &block);
1083 : }
1084 : }
1085 :
1086 : /* Pass the address of the class object. */
1087 5253 : if (packed)
1088 96 : parmse->expr = packed;
1089 : else
1090 5157 : parmse->expr = gfc_build_addr_expr (NULL_TREE, var);
1091 :
1092 5253 : if (optional && optional_alloc_ptr)
1093 84 : parmse->expr
1094 84 : = build3_loc (input_location, COND_EXPR, TREE_TYPE (parmse->expr),
1095 : cond_optional, parmse->expr,
1096 84 : fold_convert (TREE_TYPE (parmse->expr), null_pointer_node));
1097 5253 : }
1098 :
1099 : /* Create a new class container, which is required as scalar coarrays
1100 : have an array descriptor while normal scalars haven't. Optionally,
1101 : NULL pointer checks are added if the argument is OPTIONAL. */
1102 :
1103 : static void
1104 48 : class_scalar_coarray_to_class (gfc_se *parmse, gfc_expr *e,
1105 : gfc_typespec class_ts, bool optional)
1106 : {
1107 48 : tree var, ctree, tmp;
1108 48 : stmtblock_t block;
1109 48 : gfc_ref *ref;
1110 48 : gfc_ref *class_ref;
1111 :
1112 48 : gfc_init_block (&block);
1113 :
1114 48 : class_ref = NULL;
1115 144 : for (ref = e->ref; ref; ref = ref->next)
1116 : {
1117 96 : if (ref->type == REF_COMPONENT
1118 48 : && ref->u.c.component->ts.type == BT_CLASS)
1119 96 : class_ref = ref;
1120 : }
1121 :
1122 48 : if (class_ref == NULL
1123 48 : && e->symtree && e->symtree->n.sym->ts.type == BT_CLASS)
1124 48 : tmp = e->symtree->n.sym->backend_decl;
1125 : else
1126 : {
1127 : /* Remove everything after the last class reference, convert the
1128 : expression and then recover its tailend once more. */
1129 0 : gfc_se tmpse;
1130 0 : ref = class_ref->next;
1131 0 : class_ref->next = NULL;
1132 0 : gfc_init_se (&tmpse, NULL);
1133 0 : gfc_conv_expr (&tmpse, e);
1134 0 : class_ref->next = ref;
1135 0 : tmp = tmpse.expr;
1136 : }
1137 :
1138 48 : var = gfc_typenode_for_spec (&class_ts);
1139 48 : var = gfc_create_var (var, "class");
1140 :
1141 48 : ctree = gfc_class_vptr_get (var);
1142 96 : gfc_add_modify (&block, ctree,
1143 48 : fold_convert (TREE_TYPE (ctree), gfc_class_vptr_get (tmp)));
1144 :
1145 48 : ctree = gfc_class_data_get (var);
1146 48 : tmp = gfc_conv_descriptor_data_get (
1147 48 : gfc_class_data_get (GFC_CLASS_TYPE_P (TREE_TYPE (TREE_TYPE (tmp)))
1148 : ? tmp
1149 24 : : GFC_DECL_SAVED_DESCRIPTOR (tmp)));
1150 48 : gfc_add_modify (&block, ctree, fold_convert (TREE_TYPE (ctree), tmp));
1151 :
1152 : /* Pass the address of the class object. */
1153 48 : parmse->expr = gfc_build_addr_expr (NULL_TREE, var);
1154 :
1155 48 : if (optional)
1156 : {
1157 48 : tree cond = gfc_conv_expr_present (e->symtree->n.sym);
1158 48 : tree tmp2;
1159 :
1160 48 : tmp = gfc_finish_block (&block);
1161 :
1162 48 : gfc_init_block (&block);
1163 48 : tmp2 = gfc_class_data_get (var);
1164 48 : gfc_add_modify (&block, tmp2, fold_convert (TREE_TYPE (tmp2),
1165 : null_pointer_node));
1166 48 : tmp2 = gfc_finish_block (&block);
1167 :
1168 48 : tmp = build3_loc (input_location, COND_EXPR, void_type_node,
1169 : cond, tmp, tmp2);
1170 48 : gfc_add_expr_to_block (&parmse->pre, tmp);
1171 : }
1172 : else
1173 0 : gfc_add_block_to_block (&parmse->pre, &block);
1174 48 : }
1175 :
1176 :
1177 : /* Takes an intrinsic type expression and returns the address of a temporary
1178 : class object of the 'declared' type. */
1179 : void
1180 882 : gfc_conv_intrinsic_to_class (gfc_se *parmse, gfc_expr *e,
1181 : gfc_typespec class_ts)
1182 : {
1183 882 : gfc_symbol *vtab;
1184 882 : gfc_ss *ss;
1185 882 : tree ctree;
1186 882 : tree var;
1187 882 : tree tmp;
1188 882 : int dim;
1189 882 : bool unlimited_poly;
1190 :
1191 1764 : unlimited_poly = class_ts.type == BT_CLASS
1192 882 : && class_ts.u.derived->components->ts.type == BT_DERIVED
1193 882 : && class_ts.u.derived->components->ts.u.derived
1194 882 : ->attr.unlimited_polymorphic;
1195 :
1196 : /* The intrinsic type needs to be converted to a temporary
1197 : CLASS object. */
1198 882 : tmp = gfc_typenode_for_spec (&class_ts);
1199 882 : var = gfc_create_var (tmp, "class");
1200 :
1201 : /* Force a temporary for component or substring references. */
1202 882 : if (unlimited_poly
1203 882 : && class_ts.u.derived->components->attr.dimension
1204 623 : && !class_ts.u.derived->components->attr.allocatable
1205 623 : && !class_ts.u.derived->components->attr.class_pointer
1206 1505 : && is_subref_array (e))
1207 17 : parmse->force_tmp = 1;
1208 :
1209 : /* Set the vptr. */
1210 882 : ctree = gfc_class_vptr_get (var);
1211 :
1212 882 : vtab = gfc_find_vtab (&e->ts);
1213 882 : gcc_assert (vtab);
1214 882 : tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
1215 882 : gfc_add_modify (&parmse->pre, ctree,
1216 882 : fold_convert (TREE_TYPE (ctree), tmp));
1217 :
1218 : /* Now set the data field. */
1219 882 : ctree = gfc_class_data_get (var);
1220 882 : if (parmse->ss && parmse->ss->info->useflags)
1221 : {
1222 : /* For an array reference in an elemental procedure call we need
1223 : to retain the ss to provide the scalarized array reference. */
1224 36 : gfc_conv_expr_reference (parmse, e);
1225 36 : tmp = fold_convert (TREE_TYPE (ctree), parmse->expr);
1226 36 : gfc_add_modify (&parmse->pre, ctree, tmp);
1227 : }
1228 : else
1229 : {
1230 846 : ss = gfc_walk_expr (e);
1231 846 : if (ss == gfc_ss_terminator)
1232 : {
1233 247 : parmse->ss = NULL;
1234 247 : gfc_conv_expr_reference (parmse, e);
1235 247 : if (class_ts.u.derived->components->as
1236 24 : && class_ts.u.derived->components->as->type == AS_ASSUMED_RANK)
1237 : {
1238 24 : tmp = gfc_conv_scalar_to_descriptor (parmse, parmse->expr,
1239 : gfc_expr_attr (e));
1240 24 : tmp = fold_build1_loc (input_location, VIEW_CONVERT_EXPR,
1241 24 : TREE_TYPE (ctree), tmp);
1242 : }
1243 : else
1244 223 : tmp = fold_convert (TREE_TYPE (ctree), parmse->expr);
1245 247 : gfc_add_modify (&parmse->pre, ctree, tmp);
1246 : }
1247 : else
1248 : {
1249 599 : parmse->ss = ss;
1250 599 : gfc_conv_expr_descriptor (parmse, e);
1251 :
1252 : /* Array references with vector subscripts and non-variable expressions
1253 : need be converted to a one-based descriptor. */
1254 599 : if (e->expr_type != EXPR_VARIABLE)
1255 : {
1256 368 : for (dim = 0; dim < e->rank; ++dim)
1257 193 : gfc_conv_shift_descriptor_lbound (&parmse->pre, parmse->expr,
1258 : dim, gfc_index_one_node);
1259 : }
1260 :
1261 599 : if (class_ts.u.derived->components->as->rank != e->rank)
1262 : {
1263 49 : tmp = fold_build1_loc (input_location, VIEW_CONVERT_EXPR,
1264 49 : TREE_TYPE (ctree), parmse->expr);
1265 49 : gfc_add_modify (&parmse->pre, ctree, tmp);
1266 : }
1267 : else
1268 550 : gfc_add_modify (&parmse->pre, ctree, parmse->expr);
1269 : }
1270 : }
1271 :
1272 882 : gcc_assert (class_ts.type == BT_CLASS);
1273 882 : if (unlimited_poly)
1274 : {
1275 882 : ctree = gfc_class_len_get (var);
1276 : /* When the actual arg is a char array, then set the _len component of the
1277 : unlimited polymorphic entity to the length of the string. */
1278 882 : if (e->ts.type == BT_CHARACTER)
1279 : {
1280 : /* Start with parmse->string_length because this seems to be set to a
1281 : correct value more often. */
1282 175 : if (parmse->string_length)
1283 : tmp = parmse->string_length;
1284 : /* When the string_length is not yet set, then try the backend_decl of
1285 : the cl. */
1286 0 : else if (e->ts.u.cl->backend_decl)
1287 : tmp = e->ts.u.cl->backend_decl;
1288 : /* If both of the above approaches fail, then try to generate an
1289 : expression from the input, which is only feasible currently, when the
1290 : expression can be evaluated to a constant one. */
1291 : else
1292 : {
1293 : /* Try to simplify the expression. */
1294 0 : gfc_simplify_expr (e, 0);
1295 0 : if (e->expr_type == EXPR_CONSTANT && !e->ts.u.cl->resolved)
1296 : {
1297 : /* Amazingly all data is present to compute the length of a
1298 : constant string, but the expression is not yet there. */
1299 0 : e->ts.u.cl->length = gfc_get_constant_expr (BT_INTEGER,
1300 : gfc_charlen_int_kind,
1301 : &e->where);
1302 0 : mpz_set_ui (e->ts.u.cl->length->value.integer,
1303 0 : e->value.character.length);
1304 0 : gfc_conv_const_charlen (e->ts.u.cl);
1305 0 : e->ts.u.cl->resolved = 1;
1306 0 : tmp = e->ts.u.cl->backend_decl;
1307 : }
1308 : else
1309 : {
1310 0 : gfc_error ("Cannot compute the length of the char array "
1311 : "at %L.", &e->where);
1312 : }
1313 : }
1314 : }
1315 : else
1316 707 : tmp = integer_zero_node;
1317 :
1318 882 : gfc_add_modify (&parmse->pre, ctree, fold_convert (TREE_TYPE (ctree), tmp));
1319 : }
1320 :
1321 : /* Pass the address of the class object. */
1322 882 : parmse->expr = gfc_build_addr_expr (NULL_TREE, var);
1323 882 : }
1324 :
1325 :
1326 : /* Takes a scalarized class array expression and returns the
1327 : address of a temporary scalar class object of the 'declared'
1328 : type.
1329 : OOP-TODO: This could be improved by adding code that branched on
1330 : the dynamic type being the same as the declared type. In this case
1331 : the original class expression can be passed directly.
1332 : optional_alloc_ptr is false when the dummy is neither allocatable
1333 : nor a pointer; that's relevant for the optional handling.
1334 : Set copyback to true if class container's _data and _vtab pointers
1335 : might get modified. */
1336 :
1337 : void
1338 3654 : gfc_conv_class_to_class (gfc_se *parmse, gfc_expr *e, gfc_typespec class_ts,
1339 : bool elemental, bool copyback, bool optional,
1340 : bool optional_alloc_ptr)
1341 : {
1342 3654 : tree ctree;
1343 3654 : tree var;
1344 3654 : tree tmp;
1345 3654 : tree vptr;
1346 3654 : tree cond = NULL_TREE;
1347 3654 : tree slen = NULL_TREE;
1348 3654 : gfc_ref *ref;
1349 3654 : gfc_ref *class_ref;
1350 3654 : stmtblock_t block;
1351 3654 : bool full_array = false;
1352 :
1353 : /* If this is the data field of a class temporary, the class expression
1354 : can be obtained and returned directly. */
1355 3654 : if (e->expr_type != EXPR_VARIABLE
1356 180 : && TREE_CODE (parmse->expr) == COMPONENT_REF
1357 36 : && !GFC_CLASS_TYPE_P (TREE_TYPE (parmse->expr))
1358 3690 : && GFC_CLASS_TYPE_P (TREE_TYPE (TREE_OPERAND (parmse->expr, 0))))
1359 : {
1360 36 : parmse->expr = TREE_OPERAND (parmse->expr, 0);
1361 36 : if (!VAR_P (parmse->expr))
1362 0 : parmse->expr = gfc_evaluate_now (parmse->expr, &parmse->pre);
1363 36 : parmse->expr = gfc_build_addr_expr (NULL_TREE, parmse->expr);
1364 174 : return;
1365 : }
1366 :
1367 3618 : gfc_init_block (&block);
1368 :
1369 3618 : class_ref = NULL;
1370 7273 : for (ref = e->ref; ref; ref = ref->next)
1371 : {
1372 6897 : if (ref->type == REF_COMPONENT
1373 3688 : && ref->u.c.component->ts.type == BT_CLASS)
1374 6897 : class_ref = ref;
1375 :
1376 6897 : if (ref->next == NULL)
1377 : break;
1378 : }
1379 :
1380 3618 : if ((ref == NULL || class_ref == ref)
1381 488 : && !(gfc_is_class_array_function (e) && parmse->class_vptr != NULL_TREE)
1382 4088 : && (!class_ts.u.derived->components->as
1383 379 : || class_ts.u.derived->components->as->rank != -1))
1384 : return;
1385 :
1386 : /* Test for FULL_ARRAY. */
1387 3480 : if (e->rank == 0
1388 3480 : && ((gfc_expr_attr (e).codimension && gfc_expr_attr (e).dimension)
1389 494 : || (class_ts.u.derived->components->as
1390 366 : && class_ts.u.derived->components->as->type == AS_ASSUMED_RANK)))
1391 411 : full_array = true;
1392 : else
1393 3069 : gfc_is_class_array_ref (e, &full_array);
1394 :
1395 : /* The derived type needs to be converted to a temporary
1396 : CLASS object. */
1397 3480 : tmp = gfc_typenode_for_spec (&class_ts);
1398 3480 : var = gfc_create_var (tmp, "class");
1399 :
1400 : /* Set the data. */
1401 3480 : ctree = gfc_class_data_get (var);
1402 3480 : if (class_ts.u.derived->components->as
1403 3196 : && e->rank != class_ts.u.derived->components->as->rank)
1404 : {
1405 977 : if (e->rank == 0)
1406 : {
1407 356 : tree type = get_scalar_to_descriptor_type (parmse->expr,
1408 : gfc_expr_attr (e));
1409 356 : gfc_add_modify (&block, gfc_conv_descriptor_dtype (ctree),
1410 : gfc_get_dtype (type));
1411 :
1412 356 : tmp = gfc_class_data_get (parmse->expr);
1413 356 : if (!POINTER_TYPE_P (TREE_TYPE (tmp)))
1414 12 : tmp = gfc_build_addr_expr (NULL_TREE, tmp);
1415 :
1416 356 : gfc_conv_descriptor_data_set (&block, ctree, tmp);
1417 : }
1418 : else
1419 621 : gfc_class_array_data_assign (&block, ctree, parmse->expr, false);
1420 : }
1421 : else
1422 : {
1423 2503 : if (TREE_TYPE (parmse->expr) != TREE_TYPE (ctree))
1424 1451 : parmse->expr = fold_build1_loc (input_location, VIEW_CONVERT_EXPR,
1425 1451 : TREE_TYPE (ctree), parmse->expr);
1426 2503 : gfc_add_modify (&block, ctree, parmse->expr);
1427 : }
1428 :
1429 : /* Return the data component, except in the case of scalarized array
1430 : references, where nullification of the cannot occur and so there
1431 : is no need. */
1432 3480 : if (!elemental && full_array && copyback)
1433 : {
1434 1164 : if (class_ts.u.derived->components->as
1435 1164 : && e->rank != class_ts.u.derived->components->as->rank)
1436 : {
1437 270 : if (e->rank == 0)
1438 : {
1439 102 : tmp = gfc_class_data_get (parmse->expr);
1440 204 : gfc_add_modify (&parmse->post, tmp,
1441 102 : fold_convert (TREE_TYPE (tmp),
1442 : gfc_conv_descriptor_data_get (ctree)));
1443 : }
1444 : else
1445 168 : gfc_class_array_data_assign (&parmse->post, parmse->expr, ctree,
1446 : true);
1447 : }
1448 : else
1449 894 : gfc_add_modify (&parmse->post, parmse->expr, ctree);
1450 : }
1451 :
1452 : /* Set the vptr. */
1453 3480 : ctree = gfc_class_vptr_get (var);
1454 :
1455 : /* The vptr is the second field of the actual argument.
1456 : First we have to find the corresponding class reference. */
1457 :
1458 3480 : tmp = NULL_TREE;
1459 3480 : if (gfc_is_class_array_function (e)
1460 3480 : && parmse->class_vptr != NULL_TREE)
1461 : tmp = parmse->class_vptr;
1462 3462 : else if (class_ref == NULL
1463 2999 : && e->symtree && e->symtree->n.sym->ts.type == BT_CLASS)
1464 : {
1465 2999 : tmp = e->symtree->n.sym->backend_decl;
1466 :
1467 2999 : if (TREE_CODE (tmp) == FUNCTION_DECL)
1468 6 : tmp = gfc_get_fake_result_decl (e->symtree->n.sym, 0);
1469 :
1470 2999 : if (DECL_LANG_SPECIFIC (tmp) && GFC_DECL_SAVED_DESCRIPTOR (tmp))
1471 397 : tmp = GFC_DECL_SAVED_DESCRIPTOR (tmp);
1472 :
1473 2999 : slen = build_zero_cst (size_type_node);
1474 : }
1475 463 : else if (parmse->class_container != NULL_TREE)
1476 : /* Don't redundantly evaluate the expression if the required information
1477 : is already available. */
1478 : tmp = parmse->class_container;
1479 : else
1480 : {
1481 : /* Remove everything after the last class reference, convert the
1482 : expression and then recover its tailend once more. */
1483 18 : gfc_se tmpse;
1484 18 : ref = class_ref->next;
1485 18 : class_ref->next = NULL;
1486 18 : gfc_init_se (&tmpse, NULL);
1487 18 : gfc_conv_expr (&tmpse, e);
1488 18 : class_ref->next = ref;
1489 18 : tmp = tmpse.expr;
1490 18 : slen = tmpse.string_length;
1491 : }
1492 :
1493 3480 : gcc_assert (tmp != NULL_TREE);
1494 :
1495 : /* Dereference if needs be. */
1496 3480 : if (TREE_CODE (TREE_TYPE (tmp)) == REFERENCE_TYPE)
1497 345 : tmp = build_fold_indirect_ref_loc (input_location, tmp);
1498 :
1499 3480 : if (!(gfc_is_class_array_function (e) && parmse->class_vptr))
1500 3462 : vptr = gfc_class_vptr_get (tmp);
1501 : else
1502 : vptr = tmp;
1503 :
1504 3480 : gfc_add_modify (&block, ctree,
1505 3480 : fold_convert (TREE_TYPE (ctree), vptr));
1506 :
1507 : /* Return the vptr component, except in the case of scalarized array
1508 : references, where the dynamic type cannot change. */
1509 3480 : if (!elemental && full_array && copyback)
1510 1164 : gfc_add_modify (&parmse->post, vptr,
1511 1164 : fold_convert (TREE_TYPE (vptr), ctree));
1512 :
1513 : /* For unlimited polymorphic objects also set the _len component. */
1514 3480 : if (class_ts.type == BT_CLASS
1515 3480 : && class_ts.u.derived->components
1516 3480 : && class_ts.u.derived->components->ts.u
1517 3480 : .derived->attr.unlimited_polymorphic)
1518 : {
1519 1146 : ctree = gfc_class_len_get (var);
1520 1146 : if (UNLIMITED_POLY (e))
1521 943 : tmp = gfc_class_len_get (tmp);
1522 203 : else if (e->ts.type == BT_CHARACTER)
1523 : {
1524 0 : gcc_assert (slen != NULL_TREE);
1525 : tmp = slen;
1526 : }
1527 : else
1528 203 : tmp = build_zero_cst (size_type_node);
1529 1146 : gfc_add_modify (&parmse->pre, ctree,
1530 1146 : fold_convert (TREE_TYPE (ctree), tmp));
1531 :
1532 : /* Return the len component, except in the case of scalarized array
1533 : references, where the dynamic type cannot change. */
1534 1146 : if (!elemental && full_array && copyback
1535 447 : && (UNLIMITED_POLY (e) || VAR_P (tmp)))
1536 434 : gfc_add_modify (&parmse->post, tmp,
1537 434 : fold_convert (TREE_TYPE (tmp), ctree));
1538 : }
1539 :
1540 3480 : if (optional)
1541 : {
1542 510 : tree tmp2;
1543 :
1544 510 : cond = gfc_conv_expr_present (e->symtree->n.sym);
1545 : /* parmse->pre may contain some preparatory instructions for the
1546 : temporary array descriptor. Those may only be executed when the
1547 : optional argument is set, therefore add parmse->pre's instructions
1548 : to block, which is later guarded by an if (optional_arg_given). */
1549 510 : gfc_add_block_to_block (&parmse->pre, &block);
1550 510 : block.head = parmse->pre.head;
1551 510 : parmse->pre.head = NULL_TREE;
1552 510 : tmp = gfc_finish_block (&block);
1553 :
1554 510 : if (optional_alloc_ptr)
1555 102 : tmp2 = build_empty_stmt (input_location);
1556 : else
1557 : {
1558 408 : gfc_init_block (&block);
1559 :
1560 408 : tmp2 = gfc_conv_descriptor_data_get (gfc_class_data_get (var));
1561 408 : gfc_add_modify (&block, tmp2, fold_convert (TREE_TYPE (tmp2),
1562 : null_pointer_node));
1563 408 : tmp2 = gfc_finish_block (&block);
1564 : }
1565 :
1566 510 : tmp = build3_loc (input_location, COND_EXPR, void_type_node,
1567 : cond, tmp, tmp2);
1568 510 : gfc_add_expr_to_block (&parmse->pre, tmp);
1569 :
1570 510 : if (!elemental && full_array && copyback)
1571 : {
1572 30 : tmp2 = build_empty_stmt (input_location);
1573 30 : tmp = gfc_finish_block (&parmse->post);
1574 30 : tmp = build3_loc (input_location, COND_EXPR, void_type_node,
1575 : cond, tmp, tmp2);
1576 30 : gfc_add_expr_to_block (&parmse->post, tmp);
1577 : }
1578 : }
1579 : else
1580 2970 : gfc_add_block_to_block (&parmse->pre, &block);
1581 :
1582 : /* Pass the address of the class object. */
1583 3480 : parmse->expr = gfc_build_addr_expr (NULL_TREE, var);
1584 :
1585 3480 : if (optional && optional_alloc_ptr)
1586 204 : parmse->expr = build3_loc (input_location, COND_EXPR,
1587 102 : TREE_TYPE (parmse->expr),
1588 : cond, parmse->expr,
1589 102 : fold_convert (TREE_TYPE (parmse->expr),
1590 : null_pointer_node));
1591 : }
1592 :
1593 :
1594 : /* Given a class array declaration and an index, returns the address
1595 : of the referenced element. */
1596 :
1597 : static tree
1598 744 : gfc_get_class_array_ref (tree index, tree class_decl, tree data_comp,
1599 : bool unlimited)
1600 : {
1601 744 : tree data, size, tmp, ctmp, offset, ptr;
1602 :
1603 744 : data = data_comp != NULL_TREE ? data_comp :
1604 0 : gfc_class_data_get (class_decl);
1605 744 : size = gfc_class_vtab_size_get (class_decl);
1606 :
1607 744 : if (unlimited)
1608 : {
1609 220 : tmp = fold_convert (gfc_array_index_type,
1610 : gfc_class_len_get (class_decl));
1611 220 : ctmp = fold_build2_loc (input_location, MULT_EXPR,
1612 : gfc_array_index_type, size, tmp);
1613 220 : tmp = fold_build2_loc (input_location, GT_EXPR,
1614 : logical_type_node, tmp,
1615 220 : build_zero_cst (TREE_TYPE (tmp)));
1616 220 : size = fold_build3_loc (input_location, COND_EXPR,
1617 : gfc_array_index_type, tmp, ctmp, size);
1618 : }
1619 :
1620 744 : offset = fold_build2_loc (input_location, MULT_EXPR,
1621 : gfc_array_index_type,
1622 : index, size);
1623 :
1624 744 : data = gfc_conv_descriptor_data_get (data);
1625 744 : ptr = fold_convert (pvoid_type_node, data);
1626 744 : ptr = fold_build_pointer_plus_loc (input_location, ptr, offset);
1627 744 : return fold_convert (TREE_TYPE (data), ptr);
1628 : }
1629 :
1630 :
1631 : /* Copies one class expression to another, assuming that if either
1632 : 'to' or 'from' are arrays they are packed. Should 'from' be
1633 : NULL_TREE, the initialization expression for 'to' is used, assuming
1634 : that the _vptr is set. */
1635 :
1636 : tree
1637 780 : gfc_copy_class_to_class (tree from, tree to, tree nelems, bool unlimited)
1638 : {
1639 780 : tree fcn;
1640 780 : tree fcn_type;
1641 780 : tree from_data;
1642 780 : tree from_len;
1643 780 : tree to_data;
1644 780 : tree to_len;
1645 780 : tree to_ref;
1646 780 : tree from_ref;
1647 780 : vec<tree, va_gc> *args;
1648 780 : tree tmp;
1649 780 : tree stdcopy;
1650 780 : tree extcopy;
1651 780 : tree index;
1652 780 : bool is_from_desc = false, is_to_class = false;
1653 :
1654 780 : args = NULL;
1655 : /* To prevent warnings on uninitialized variables. */
1656 780 : from_len = to_len = NULL_TREE;
1657 :
1658 780 : if (from != NULL_TREE)
1659 780 : fcn = gfc_class_vtab_copy_get (from);
1660 : else
1661 0 : fcn = gfc_class_vtab_copy_get (to);
1662 :
1663 780 : fcn_type = TREE_TYPE (TREE_TYPE (fcn));
1664 :
1665 780 : if (from != NULL_TREE)
1666 : {
1667 780 : is_from_desc = GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (from));
1668 780 : if (is_from_desc)
1669 : {
1670 0 : from_data = from;
1671 0 : from = GFC_DECL_SAVED_DESCRIPTOR (from);
1672 : }
1673 : else
1674 : {
1675 : /* Check that from is a class. When the class is part of a coarray,
1676 : then from is a common pointer and is to be used as is. */
1677 1560 : tmp = POINTER_TYPE_P (TREE_TYPE (from))
1678 780 : ? build_fold_indirect_ref (from) : from;
1679 1560 : from_data =
1680 780 : (GFC_CLASS_TYPE_P (TREE_TYPE (tmp))
1681 0 : || (DECL_P (tmp) && GFC_DECL_CLASS (tmp)))
1682 780 : ? gfc_class_data_get (from) : from;
1683 780 : is_from_desc = GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (from_data));
1684 : }
1685 : }
1686 : else
1687 0 : from_data = gfc_class_vtab_def_init_get (to);
1688 :
1689 780 : if (unlimited)
1690 : {
1691 170 : if (from != NULL_TREE && unlimited)
1692 170 : from_len = gfc_class_len_or_zero_get (from);
1693 : else
1694 0 : from_len = build_zero_cst (size_type_node);
1695 : }
1696 :
1697 780 : if (GFC_CLASS_TYPE_P (TREE_TYPE (to)))
1698 : {
1699 780 : is_to_class = true;
1700 780 : to_data = gfc_class_data_get (to);
1701 780 : if (unlimited)
1702 170 : to_len = gfc_class_len_get (to);
1703 : }
1704 : else
1705 : /* When to is a BT_DERIVED and not a BT_CLASS, then to_data == to. */
1706 0 : to_data = to;
1707 :
1708 780 : if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (to_data)))
1709 : {
1710 372 : stmtblock_t loopbody;
1711 372 : stmtblock_t body;
1712 372 : stmtblock_t ifbody;
1713 372 : gfc_loopinfo loop;
1714 :
1715 372 : gfc_init_block (&body);
1716 372 : tmp = fold_build2_loc (input_location, MINUS_EXPR,
1717 : gfc_array_index_type, nelems,
1718 : gfc_index_one_node);
1719 372 : nelems = gfc_evaluate_now (tmp, &body);
1720 372 : index = gfc_create_var (gfc_array_index_type, "S");
1721 :
1722 372 : if (is_from_desc)
1723 : {
1724 372 : from_ref = gfc_get_class_array_ref (index, from, from_data,
1725 : unlimited);
1726 372 : vec_safe_push (args, from_ref);
1727 : }
1728 : else
1729 0 : vec_safe_push (args, from_data);
1730 :
1731 372 : if (is_to_class)
1732 372 : to_ref = gfc_get_class_array_ref (index, to, to_data, unlimited);
1733 : else
1734 : {
1735 0 : tmp = gfc_conv_array_data (to);
1736 0 : tmp = build_fold_indirect_ref_loc (input_location, tmp);
1737 0 : to_ref = gfc_build_addr_expr (NULL_TREE,
1738 : gfc_build_array_ref (tmp, index, to));
1739 : }
1740 372 : vec_safe_push (args, to_ref);
1741 :
1742 : /* Add bounds check. */
1743 372 : if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS) > 0 && is_from_desc)
1744 : {
1745 25 : const char *name = "<<unknown>>";
1746 25 : int dim, rank;
1747 :
1748 25 : if (DECL_P (to))
1749 0 : name = IDENTIFIER_POINTER (DECL_NAME (to));
1750 :
1751 25 : rank = GFC_TYPE_ARRAY_RANK (TREE_TYPE (from_data));
1752 55 : for (dim = 1; dim <= rank; dim++)
1753 : {
1754 30 : tree from_len, to_len, cond;
1755 30 : char *msg;
1756 :
1757 30 : from_len = gfc_conv_descriptor_size (from_data, dim);
1758 30 : from_len = fold_convert (long_integer_type_node, from_len);
1759 30 : to_len = gfc_conv_descriptor_size (to_data, dim);
1760 30 : to_len = fold_convert (long_integer_type_node, to_len);
1761 30 : msg = xasprintf ("Array bound mismatch for dimension %d "
1762 : "of array '%s' (%%ld/%%ld)",
1763 : dim, name);
1764 30 : cond = fold_build2_loc (input_location, NE_EXPR,
1765 : logical_type_node, from_len, to_len);
1766 30 : gfc_trans_runtime_check (true, false, cond, &body,
1767 : NULL, msg, to_len, from_len);
1768 30 : free (msg);
1769 : }
1770 : }
1771 :
1772 372 : tmp = build_call_vec (fcn_type, fcn, args);
1773 :
1774 : /* Build the body of the loop. */
1775 372 : gfc_init_block (&loopbody);
1776 372 : gfc_add_expr_to_block (&loopbody, tmp);
1777 :
1778 : /* Build the loop and return. */
1779 372 : gfc_init_loopinfo (&loop);
1780 372 : loop.dimen = 1;
1781 372 : loop.from[0] = gfc_index_zero_node;
1782 372 : loop.loopvar[0] = index;
1783 372 : loop.to[0] = nelems;
1784 372 : gfc_trans_scalarizing_loops (&loop, &loopbody);
1785 372 : gfc_init_block (&ifbody);
1786 372 : gfc_add_block_to_block (&ifbody, &loop.pre);
1787 372 : stdcopy = gfc_finish_block (&ifbody);
1788 : /* In initialization mode from_len is a constant zero. */
1789 372 : if (unlimited && !integer_zerop (from_len))
1790 : {
1791 110 : vec_safe_push (args, from_len);
1792 110 : vec_safe_push (args, to_len);
1793 110 : tmp = build_call_vec (fcn_type, fcn, args);
1794 : /* Build the body of the loop. */
1795 110 : gfc_init_block (&loopbody);
1796 110 : gfc_add_expr_to_block (&loopbody, tmp);
1797 :
1798 : /* Build the loop and return. */
1799 110 : gfc_init_loopinfo (&loop);
1800 110 : loop.dimen = 1;
1801 110 : loop.from[0] = gfc_index_zero_node;
1802 110 : loop.loopvar[0] = index;
1803 110 : loop.to[0] = nelems;
1804 110 : gfc_trans_scalarizing_loops (&loop, &loopbody);
1805 110 : gfc_init_block (&ifbody);
1806 110 : gfc_add_block_to_block (&ifbody, &loop.pre);
1807 110 : extcopy = gfc_finish_block (&ifbody);
1808 :
1809 110 : tmp = fold_build2_loc (input_location, GT_EXPR,
1810 : logical_type_node, from_len,
1811 110 : build_zero_cst (TREE_TYPE (from_len)));
1812 110 : tmp = fold_build3_loc (input_location, COND_EXPR,
1813 : void_type_node, tmp, extcopy, stdcopy);
1814 110 : gfc_add_expr_to_block (&body, tmp);
1815 110 : tmp = gfc_finish_block (&body);
1816 : }
1817 : else
1818 : {
1819 262 : gfc_add_expr_to_block (&body, stdcopy);
1820 262 : tmp = gfc_finish_block (&body);
1821 : }
1822 372 : gfc_cleanup_loop (&loop);
1823 : }
1824 : else
1825 : {
1826 408 : gcc_assert (!is_from_desc);
1827 408 : vec_safe_push (args, from_data);
1828 408 : vec_safe_push (args, to_data);
1829 408 : stdcopy = build_call_vec (fcn_type, fcn, args);
1830 :
1831 : /* In initialization mode from_len is a constant zero. */
1832 408 : if (unlimited && !integer_zerop (from_len))
1833 : {
1834 60 : vec_safe_push (args, from_len);
1835 60 : vec_safe_push (args, to_len);
1836 60 : extcopy = build_call_vec (fcn_type, unshare_expr (fcn), args);
1837 60 : tmp = fold_build2_loc (input_location, GT_EXPR,
1838 : logical_type_node, from_len,
1839 60 : build_zero_cst (TREE_TYPE (from_len)));
1840 60 : tmp = fold_build3_loc (input_location, COND_EXPR,
1841 : void_type_node, tmp, extcopy, stdcopy);
1842 : }
1843 : else
1844 : tmp = stdcopy;
1845 : }
1846 :
1847 : /* Only copy _def_init to to_data, when it is not a NULL-pointer. */
1848 780 : if (from == NULL_TREE)
1849 : {
1850 0 : tree cond;
1851 0 : cond = fold_build2_loc (input_location, NE_EXPR,
1852 : logical_type_node,
1853 : from_data, null_pointer_node);
1854 0 : tmp = fold_build3_loc (input_location, COND_EXPR,
1855 : void_type_node, cond,
1856 : tmp, build_empty_stmt (input_location));
1857 : }
1858 :
1859 780 : return tmp;
1860 : }
1861 :
1862 :
1863 : static tree
1864 106 : gfc_trans_class_array_init_assign (gfc_expr *rhs, gfc_expr *lhs, gfc_expr *obj)
1865 : {
1866 106 : gfc_actual_arglist *actual;
1867 106 : gfc_expr *ppc;
1868 106 : gfc_code *ppc_code;
1869 106 : tree res;
1870 :
1871 106 : actual = gfc_get_actual_arglist ();
1872 106 : actual->expr = gfc_copy_expr (rhs);
1873 106 : actual->next = gfc_get_actual_arglist ();
1874 106 : actual->next->expr = gfc_copy_expr (lhs);
1875 106 : ppc = gfc_copy_expr (obj);
1876 106 : gfc_add_vptr_component (ppc);
1877 106 : gfc_add_component_ref (ppc, "_copy");
1878 106 : ppc_code = gfc_get_code (EXEC_CALL);
1879 106 : ppc_code->resolved_sym = ppc->symtree->n.sym;
1880 : /* Although '_copy' is set to be elemental in class.cc, it is
1881 : not staying that way. Find out why, sometime.... */
1882 106 : ppc_code->resolved_sym->attr.elemental = 1;
1883 106 : ppc_code->ext.actual = actual;
1884 106 : ppc_code->expr1 = ppc;
1885 : /* Since '_copy' is elemental, the scalarizer will take care
1886 : of arrays in gfc_trans_call. */
1887 106 : res = gfc_trans_call (ppc_code, false, NULL, NULL, false);
1888 106 : gfc_free_statements (ppc_code);
1889 :
1890 106 : if (UNLIMITED_POLY(obj))
1891 : {
1892 : /* Check if rhs is non-NULL. */
1893 24 : gfc_se src;
1894 24 : gfc_init_se (&src, NULL);
1895 24 : gfc_conv_expr (&src, rhs);
1896 24 : src.expr = gfc_build_addr_expr (NULL_TREE, src.expr);
1897 24 : tree cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
1898 24 : src.expr, fold_convert (TREE_TYPE (src.expr),
1899 : null_pointer_node));
1900 24 : res = build3_loc (input_location, COND_EXPR, TREE_TYPE (res), cond, res,
1901 : build_empty_stmt (input_location));
1902 : }
1903 :
1904 106 : return res;
1905 : }
1906 :
1907 : /* Special case for initializing a polymorphic dummy with INTENT(OUT).
1908 : A MEMCPY is needed to copy the full data from the default initializer
1909 : of the dynamic type. */
1910 :
1911 : tree
1912 461 : gfc_trans_class_init_assign (gfc_code *code)
1913 : {
1914 461 : stmtblock_t block;
1915 461 : tree tmp;
1916 461 : bool cmp_flag = true;
1917 461 : gfc_se dst,src,memsz;
1918 461 : gfc_expr *lhs, *rhs, *sz;
1919 461 : gfc_component *cmp;
1920 461 : gfc_symbol *sym;
1921 461 : gfc_ref *ref;
1922 :
1923 461 : gfc_start_block (&block);
1924 :
1925 461 : lhs = gfc_copy_expr (code->expr1);
1926 :
1927 461 : rhs = gfc_copy_expr (code->expr1);
1928 461 : gfc_add_vptr_component (rhs);
1929 :
1930 : /* Make sure that the component backend_decls have been built, which
1931 : will not have happened if the derived types concerned have not
1932 : been referenced. */
1933 461 : gfc_get_derived_type (rhs->ts.u.derived);
1934 461 : gfc_add_def_init_component (rhs);
1935 : /* The _def_init is always scalar. */
1936 461 : rhs->rank = 0;
1937 :
1938 : /* Check def_init for initializers. If this is an INTENT(OUT) dummy with all
1939 : default initializer components NULL, use the passed value even though
1940 : F2018(8.5.10) asserts that it should considered to be undefined. This is
1941 : needed for consistency with other brands. */
1942 461 : sym = code->expr1->expr_type == EXPR_VARIABLE ? code->expr1->symtree->n.sym
1943 : : NULL;
1944 461 : if (code->op != EXEC_ALLOCATE
1945 400 : && sym && sym->attr.dummy
1946 400 : && sym->attr.intent == INTENT_OUT)
1947 : {
1948 400 : ref = rhs->ref;
1949 800 : while (ref && ref->next)
1950 : ref = ref->next;
1951 400 : cmp = ref->u.c.component->ts.u.derived->components;
1952 611 : for (; cmp; cmp = cmp->next)
1953 : {
1954 428 : if (cmp->initializer)
1955 : break;
1956 211 : else if (!cmp->next)
1957 146 : cmp_flag = false;
1958 : }
1959 : }
1960 :
1961 461 : if (code->expr1->ts.type == BT_CLASS
1962 438 : && CLASS_DATA (code->expr1)->attr.dimension)
1963 : {
1964 106 : gfc_array_spec *tmparr = gfc_get_array_spec ();
1965 106 : *tmparr = *CLASS_DATA (code->expr1)->as;
1966 : /* Adding the array ref to the class expression results in correct
1967 : indexing to the dynamic type. */
1968 106 : gfc_add_full_array_ref (lhs, tmparr);
1969 106 : tmp = gfc_trans_class_array_init_assign (rhs, lhs, code->expr1);
1970 106 : }
1971 355 : else if (cmp_flag)
1972 : {
1973 : /* Scalar initialization needs the _data component. */
1974 222 : gfc_add_data_component (lhs);
1975 222 : sz = gfc_copy_expr (code->expr1);
1976 222 : gfc_add_vptr_component (sz);
1977 222 : gfc_add_size_component (sz);
1978 :
1979 222 : gfc_init_se (&dst, NULL);
1980 222 : gfc_init_se (&src, NULL);
1981 222 : gfc_init_se (&memsz, NULL);
1982 222 : gfc_conv_expr (&dst, lhs);
1983 222 : gfc_conv_expr (&src, rhs);
1984 222 : gfc_conv_expr (&memsz, sz);
1985 222 : gfc_add_block_to_block (&block, &src.pre);
1986 222 : src.expr = gfc_build_addr_expr (NULL_TREE, src.expr);
1987 :
1988 222 : tmp = gfc_build_memcpy_call (dst.expr, src.expr, memsz.expr);
1989 :
1990 222 : if (UNLIMITED_POLY(code->expr1))
1991 : {
1992 : /* Check if _def_init is non-NULL. */
1993 7 : tree cond = fold_build2_loc (input_location, NE_EXPR,
1994 : logical_type_node, src.expr,
1995 7 : fold_convert (TREE_TYPE (src.expr),
1996 : null_pointer_node));
1997 7 : tmp = build3_loc (input_location, COND_EXPR, TREE_TYPE (tmp), cond,
1998 : tmp, build_empty_stmt (input_location));
1999 : }
2000 : }
2001 : else
2002 133 : tmp = build_empty_stmt (input_location);
2003 :
2004 461 : if (code->expr1->symtree->n.sym->attr.dummy
2005 410 : && (code->expr1->symtree->n.sym->attr.optional
2006 404 : || code->expr1->symtree->n.sym->ns->proc_name->attr.entry_master))
2007 : {
2008 6 : tree present = gfc_conv_expr_present (code->expr1->symtree->n.sym);
2009 6 : tmp = build3_loc (input_location, COND_EXPR, TREE_TYPE (tmp),
2010 : present, tmp,
2011 : build_empty_stmt (input_location));
2012 : }
2013 :
2014 461 : gfc_add_expr_to_block (&block, tmp);
2015 461 : gfc_free_expr (lhs);
2016 461 : gfc_free_expr (rhs);
2017 :
2018 461 : return gfc_finish_block (&block);
2019 : }
2020 :
2021 :
2022 : /* Class valued elemental function calls or class array elements arriving
2023 : in gfc_trans_scalar_assign come here. Wherever possible the vptr copy
2024 : is used to ensure that the rhs dynamic type is assigned to the lhs. */
2025 :
2026 : static bool
2027 788 : trans_scalar_class_assign (stmtblock_t *block, gfc_se *lse, gfc_se *rse)
2028 : {
2029 788 : tree fcn;
2030 788 : tree rse_expr;
2031 788 : tree class_data;
2032 788 : tree tmp;
2033 788 : tree zero;
2034 788 : tree cond;
2035 788 : tree final_cond;
2036 788 : stmtblock_t inner_block;
2037 788 : bool is_descriptor;
2038 788 : bool not_call_expr = TREE_CODE (rse->expr) != CALL_EXPR;
2039 788 : bool not_lhs_array_type;
2040 :
2041 : /* Temporaries arising from dependencies in assignment get cast as a
2042 : character type of the dynamic size of the rhs. Use the vptr copy
2043 : for this case. */
2044 788 : tmp = TREE_TYPE (lse->expr);
2045 788 : not_lhs_array_type = !(tmp && TREE_CODE (tmp) == ARRAY_TYPE
2046 0 : && TYPE_MAX_VALUE (TYPE_DOMAIN (tmp)) != NULL_TREE);
2047 :
2048 : /* Use ordinary assignment if the rhs is not a call expression or
2049 : the lhs is not a class entity or an array(ie. character) type. */
2050 740 : if ((not_call_expr && gfc_get_class_from_expr (lse->expr) == NULL_TREE)
2051 1061 : && not_lhs_array_type)
2052 : return false;
2053 :
2054 : /* Ordinary assignment can be used if both sides are class expressions
2055 : since the dynamic type is preserved by copying the vptr. This
2056 : should only occur, where temporaries are involved. */
2057 515 : if (GFC_CLASS_TYPE_P (TREE_TYPE (lse->expr))
2058 515 : && GFC_CLASS_TYPE_P (TREE_TYPE (rse->expr)))
2059 : return false;
2060 :
2061 : /* Fix the class expression and the class data of the rhs. */
2062 454 : if (!GFC_CLASS_TYPE_P (TREE_TYPE (rse->expr))
2063 454 : || not_call_expr)
2064 : {
2065 454 : tmp = gfc_get_class_from_expr (rse->expr);
2066 454 : if (tmp == NULL_TREE)
2067 : return false;
2068 146 : rse_expr = gfc_evaluate_now (tmp, block);
2069 : }
2070 : else
2071 0 : rse_expr = gfc_evaluate_now (rse->expr, block);
2072 :
2073 146 : class_data = gfc_class_data_get (rse_expr);
2074 :
2075 : /* Check that the rhs data is not null. */
2076 146 : is_descriptor = GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (class_data));
2077 146 : if (is_descriptor)
2078 146 : class_data = gfc_conv_descriptor_data_get (class_data);
2079 146 : class_data = gfc_evaluate_now (class_data, block);
2080 :
2081 146 : zero = build_int_cst (TREE_TYPE (class_data), 0);
2082 146 : cond = fold_build2_loc (input_location, NE_EXPR,
2083 : logical_type_node,
2084 : class_data, zero);
2085 :
2086 : /* Copy the rhs to the lhs. */
2087 146 : fcn = gfc_vptr_copy_get (gfc_class_vptr_get (rse_expr));
2088 146 : fcn = build_fold_indirect_ref_loc (input_location, fcn);
2089 146 : tmp = gfc_evaluate_now (gfc_build_addr_expr (NULL, rse->expr), block);
2090 146 : tmp = is_descriptor ? tmp : class_data;
2091 146 : tmp = build_call_expr_loc (input_location, fcn, 2, tmp,
2092 : gfc_build_addr_expr (NULL, lse->expr));
2093 146 : gfc_add_expr_to_block (block, tmp);
2094 :
2095 : /* Only elemental function results need to be finalised and freed. */
2096 146 : if (not_call_expr)
2097 : return true;
2098 :
2099 : /* Finalize the class data if needed. */
2100 0 : gfc_init_block (&inner_block);
2101 0 : fcn = gfc_vptr_final_get (gfc_class_vptr_get (rse_expr));
2102 0 : zero = build_int_cst (TREE_TYPE (fcn), 0);
2103 0 : final_cond = fold_build2_loc (input_location, NE_EXPR,
2104 : logical_type_node, fcn, zero);
2105 0 : fcn = build_fold_indirect_ref_loc (input_location, fcn);
2106 0 : tmp = build_call_expr_loc (input_location, fcn, 1, class_data);
2107 0 : tmp = build3_v (COND_EXPR, final_cond,
2108 : tmp, build_empty_stmt (input_location));
2109 0 : gfc_add_expr_to_block (&inner_block, tmp);
2110 :
2111 : /* Free the class data. */
2112 0 : tmp = gfc_call_free (class_data);
2113 0 : tmp = build3_v (COND_EXPR, cond, tmp,
2114 : build_empty_stmt (input_location));
2115 0 : gfc_add_expr_to_block (&inner_block, tmp);
2116 :
2117 : /* Finish the inner block and subject it to the condition on the
2118 : class data being non-zero. */
2119 0 : tmp = gfc_finish_block (&inner_block);
2120 0 : tmp = build3_v (COND_EXPR, cond, tmp,
2121 : build_empty_stmt (input_location));
2122 0 : gfc_add_expr_to_block (block, tmp);
2123 :
2124 0 : return true;
2125 : }
2126 :
2127 : /* End of prototype trans-class.c */
2128 :
2129 :
2130 : static void
2131 12864 : realloc_lhs_warning (bt type, bool array, locus *where)
2132 : {
2133 12864 : if (array && type != BT_CLASS && type != BT_DERIVED && warn_realloc_lhs)
2134 25 : gfc_warning (OPT_Wrealloc_lhs,
2135 : "Code for reallocating the allocatable array at %L will "
2136 : "be added", where);
2137 12839 : else if (warn_realloc_lhs_all)
2138 4 : gfc_warning (OPT_Wrealloc_lhs_all,
2139 : "Code for reallocating the allocatable variable at %L "
2140 : "will be added", where);
2141 12864 : }
2142 :
2143 :
2144 : static void gfc_apply_interface_mapping_to_expr (gfc_interface_mapping *,
2145 : gfc_expr *);
2146 :
2147 : /* Copy the scalarization loop variables. */
2148 :
2149 : static void
2150 1282713 : gfc_copy_se_loopvars (gfc_se * dest, gfc_se * src)
2151 : {
2152 1282713 : dest->ss = src->ss;
2153 1282713 : dest->loop = src->loop;
2154 1282713 : }
2155 :
2156 :
2157 : /* Initialize a simple expression holder.
2158 :
2159 : Care must be taken when multiple se are created with the same parent.
2160 : The child se must be kept in sync. The easiest way is to delay creation
2161 : of a child se until after the previous se has been translated. */
2162 :
2163 : void
2164 4658308 : gfc_init_se (gfc_se * se, gfc_se * parent)
2165 : {
2166 4658308 : memset (se, 0, sizeof (gfc_se));
2167 4658308 : gfc_init_block (&se->pre);
2168 4658308 : gfc_init_block (&se->finalblock);
2169 4658308 : gfc_init_block (&se->post);
2170 :
2171 4658308 : se->parent = parent;
2172 :
2173 4658308 : if (parent)
2174 1282713 : gfc_copy_se_loopvars (se, parent);
2175 4658308 : }
2176 :
2177 :
2178 : /* Advances to the next SS in the chain. Use this rather than setting
2179 : se->ss = se->ss->next because all the parents needs to be kept in sync.
2180 : See gfc_init_se. */
2181 :
2182 : void
2183 243620 : gfc_advance_se_ss_chain (gfc_se * se)
2184 : {
2185 243620 : gfc_se *p;
2186 :
2187 243620 : gcc_assert (se != NULL && se->ss != NULL && se->ss != gfc_ss_terminator);
2188 :
2189 : p = se;
2190 : /* Walk down the parent chain. */
2191 639734 : while (p != NULL)
2192 : {
2193 : /* Simple consistency check. */
2194 396114 : gcc_assert (p->parent == NULL || p->parent->ss == p->ss
2195 : || p->parent->ss->nested_ss == p->ss);
2196 :
2197 396114 : p->ss = p->ss->next;
2198 :
2199 396114 : p = p->parent;
2200 : }
2201 243620 : }
2202 :
2203 :
2204 : /* Ensures the result of the expression as either a temporary variable
2205 : or a constant so that it can be used repeatedly. */
2206 :
2207 : void
2208 8136 : gfc_make_safe_expr (gfc_se * se)
2209 : {
2210 8136 : tree var;
2211 :
2212 8136 : if (CONSTANT_CLASS_P (se->expr))
2213 : return;
2214 :
2215 : /* We need a temporary for this result. */
2216 274 : var = gfc_create_var (TREE_TYPE (se->expr), NULL);
2217 274 : gfc_add_modify (&se->pre, var, se->expr);
2218 274 : se->expr = var;
2219 : }
2220 :
2221 :
2222 : /* Return an expression which determines if a dummy parameter is present.
2223 : Also used for arguments to procedures with multiple entry points. */
2224 :
2225 : tree
2226 11604 : gfc_conv_expr_present (gfc_symbol * sym, bool use_saved_desc)
2227 : {
2228 11604 : tree decl, orig_decl, cond;
2229 :
2230 11604 : gcc_assert (sym->attr.dummy);
2231 11604 : orig_decl = decl = gfc_get_symbol_decl (sym);
2232 :
2233 : /* Intrinsic scalars and derived types with VALUE attribute which are passed
2234 : by value use a hidden argument to denote the presence status. */
2235 11604 : if (sym->attr.value && !sym->attr.dimension && sym->ts.type != BT_CLASS)
2236 : {
2237 1052 : char name[GFC_MAX_SYMBOL_LEN + 2];
2238 1052 : tree tree_name;
2239 :
2240 1052 : gcc_assert (TREE_CODE (decl) == PARM_DECL);
2241 1052 : name[0] = '.';
2242 1052 : strcpy (&name[1], sym->name);
2243 1052 : tree_name = get_identifier (name);
2244 :
2245 : /* Walk function argument list to find hidden arg. */
2246 1052 : cond = DECL_ARGUMENTS (DECL_CONTEXT (decl));
2247 5320 : for ( ; cond != NULL_TREE; cond = TREE_CHAIN (cond))
2248 5320 : if (DECL_NAME (cond) == tree_name
2249 5320 : && DECL_ARTIFICIAL (cond))
2250 : break;
2251 :
2252 1052 : gcc_assert (cond);
2253 1052 : return cond;
2254 : }
2255 :
2256 : /* Assumed-shape arrays use a local variable for the array data;
2257 : the actual PARAM_DECL is in a saved decl. As the local variable
2258 : is NULL, it can be checked instead, unless use_saved_desc is
2259 : requested. */
2260 :
2261 10552 : if (use_saved_desc && TREE_CODE (decl) != PARM_DECL)
2262 : {
2263 822 : gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl))
2264 : || GFC_ARRAY_TYPE_P (TREE_TYPE (decl)));
2265 822 : decl = GFC_DECL_SAVED_DESCRIPTOR (decl);
2266 : }
2267 :
2268 10552 : cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, decl,
2269 10552 : fold_convert (TREE_TYPE (decl), null_pointer_node));
2270 :
2271 : /* Fortran 2008 allows to pass null pointers and non-associated pointers
2272 : as actual argument to denote absent dummies. For array descriptors,
2273 : we thus also need to check the array descriptor. For BT_CLASS, it
2274 : can also occur for scalars and F2003 due to type->class wrapping and
2275 : class->class wrapping. Note further that BT_CLASS always uses an
2276 : array descriptor for arrays, also for explicit-shape/assumed-size.
2277 : For assumed-rank arrays, no local variable is generated, hence,
2278 : the following also applies with !use_saved_desc. */
2279 :
2280 10552 : if ((use_saved_desc || TREE_CODE (orig_decl) == PARM_DECL)
2281 7511 : && !sym->attr.allocatable
2282 6299 : && ((sym->ts.type != BT_CLASS && !sym->attr.pointer)
2283 2296 : || (sym->ts.type == BT_CLASS
2284 1041 : && !CLASS_DATA (sym)->attr.allocatable
2285 567 : && !CLASS_DATA (sym)->attr.class_pointer))
2286 4210 : && ((gfc_option.allow_std & GFC_STD_F2008) != 0
2287 6 : || sym->ts.type == BT_CLASS))
2288 : {
2289 4204 : tree tmp;
2290 :
2291 4204 : if ((sym->as && (sym->as->type == AS_ASSUMED_SHAPE
2292 1495 : || sym->as->type == AS_ASSUMED_RANK
2293 1407 : || sym->attr.codimension))
2294 3336 : || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)->as))
2295 : {
2296 1039 : tmp = build_fold_indirect_ref_loc (input_location, decl);
2297 1039 : if (sym->ts.type == BT_CLASS)
2298 171 : tmp = gfc_class_data_get (tmp);
2299 1039 : tmp = gfc_conv_array_data (tmp);
2300 : }
2301 3165 : else if (sym->ts.type == BT_CLASS)
2302 36 : tmp = gfc_class_data_get (decl);
2303 : else
2304 : tmp = NULL_TREE;
2305 :
2306 1075 : if (tmp != NULL_TREE)
2307 : {
2308 1075 : tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp,
2309 1075 : fold_convert (TREE_TYPE (tmp), null_pointer_node));
2310 1075 : cond = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
2311 : logical_type_node, cond, tmp);
2312 : }
2313 : }
2314 :
2315 : return cond;
2316 : }
2317 :
2318 :
2319 : /* Converts a missing, dummy argument into a null or zero. */
2320 :
2321 : void
2322 844 : gfc_conv_missing_dummy (gfc_se * se, gfc_expr * arg, gfc_typespec ts, int kind)
2323 : {
2324 844 : tree present;
2325 844 : tree tmp;
2326 :
2327 844 : present = gfc_conv_expr_present (arg->symtree->n.sym);
2328 :
2329 844 : if (kind > 0)
2330 : {
2331 : /* Create a temporary and convert it to the correct type. */
2332 54 : tmp = gfc_get_int_type (kind);
2333 54 : tmp = fold_convert (tmp, build_fold_indirect_ref_loc (input_location,
2334 : se->expr));
2335 :
2336 : /* Test for a NULL value. */
2337 54 : tmp = build3_loc (input_location, COND_EXPR, TREE_TYPE (tmp), present,
2338 54 : tmp, fold_convert (TREE_TYPE (tmp), integer_one_node));
2339 54 : tmp = gfc_evaluate_now (tmp, &se->pre);
2340 54 : se->expr = gfc_build_addr_expr (NULL_TREE, tmp);
2341 : }
2342 : else
2343 : {
2344 790 : tmp = build3_loc (input_location, COND_EXPR, TREE_TYPE (se->expr),
2345 : present, se->expr,
2346 790 : build_zero_cst (TREE_TYPE (se->expr)));
2347 790 : tmp = gfc_evaluate_now (tmp, &se->pre);
2348 790 : se->expr = tmp;
2349 : }
2350 :
2351 844 : if (ts.type == BT_CHARACTER)
2352 : {
2353 : /* Handle deferred-length dummies that pass the character length by
2354 : reference so that the value can be returned. */
2355 244 : if (ts.deferred && INDIRECT_REF_P (se->string_length))
2356 : {
2357 18 : tmp = gfc_build_addr_expr (NULL_TREE, se->string_length);
2358 18 : tmp = fold_build3_loc (input_location, COND_EXPR, TREE_TYPE (tmp),
2359 : present, tmp, null_pointer_node);
2360 18 : tmp = gfc_evaluate_now (tmp, &se->pre);
2361 18 : tmp = build_fold_indirect_ref_loc (input_location, tmp);
2362 : }
2363 : else
2364 : {
2365 226 : tmp = build_int_cst (gfc_charlen_type_node, 0);
2366 226 : tmp = fold_build3_loc (input_location, COND_EXPR,
2367 : gfc_charlen_type_node,
2368 : present, se->string_length, tmp);
2369 226 : tmp = gfc_evaluate_now (tmp, &se->pre);
2370 : }
2371 244 : se->string_length = tmp;
2372 : }
2373 844 : return;
2374 : }
2375 :
2376 :
2377 : /* Get the character length of an expression, looking through gfc_refs
2378 : if necessary. */
2379 :
2380 : tree
2381 20183 : gfc_get_expr_charlen (gfc_expr *e)
2382 : {
2383 20183 : gfc_ref *r;
2384 20183 : tree length;
2385 20183 : tree previous = NULL_TREE;
2386 20183 : gfc_se se;
2387 :
2388 20183 : gcc_assert (e->expr_type == EXPR_VARIABLE
2389 : && e->ts.type == BT_CHARACTER);
2390 :
2391 20183 : length = NULL; /* To silence compiler warning. */
2392 :
2393 20183 : if (is_subref_array (e) && e->ts.u.cl->length)
2394 : {
2395 767 : gfc_se tmpse;
2396 767 : gfc_init_se (&tmpse, NULL);
2397 767 : gfc_conv_expr_type (&tmpse, e->ts.u.cl->length, gfc_charlen_type_node);
2398 767 : e->ts.u.cl->backend_decl = tmpse.expr;
2399 767 : return tmpse.expr;
2400 : }
2401 :
2402 : /* First candidate: if the variable is of type CHARACTER, the
2403 : expression's length could be the length of the character
2404 : variable. */
2405 19416 : if (e->symtree->n.sym->ts.type == BT_CHARACTER)
2406 19116 : length = e->symtree->n.sym->ts.u.cl->backend_decl;
2407 :
2408 : /* Look through the reference chain for component references. */
2409 38975 : for (r = e->ref; r; r = r->next)
2410 : {
2411 19559 : previous = length;
2412 19559 : switch (r->type)
2413 : {
2414 300 : case REF_COMPONENT:
2415 300 : if (r->u.c.component->ts.type == BT_CHARACTER)
2416 300 : length = r->u.c.component->ts.u.cl->backend_decl;
2417 : break;
2418 :
2419 : case REF_ARRAY:
2420 : /* Do nothing. */
2421 : break;
2422 :
2423 20 : case REF_SUBSTRING:
2424 20 : gfc_init_se (&se, NULL);
2425 20 : gfc_conv_expr_type (&se, r->u.ss.start, gfc_charlen_type_node);
2426 20 : length = se.expr;
2427 20 : if (r->u.ss.end)
2428 0 : gfc_conv_expr_type (&se, r->u.ss.end, gfc_charlen_type_node);
2429 : else
2430 20 : se.expr = previous;
2431 20 : length = fold_build2_loc (input_location, MINUS_EXPR,
2432 : gfc_charlen_type_node,
2433 : se.expr, length);
2434 20 : length = fold_build2_loc (input_location, PLUS_EXPR,
2435 : gfc_charlen_type_node, length,
2436 : gfc_index_one_node);
2437 20 : break;
2438 :
2439 0 : default:
2440 0 : gcc_unreachable ();
2441 19559 : break;
2442 : }
2443 : }
2444 :
2445 19416 : gcc_assert (length != NULL);
2446 : return length;
2447 : }
2448 :
2449 :
2450 : /* Return for an expression the backend decl of the coarray. */
2451 :
2452 : tree
2453 2052 : gfc_get_tree_for_caf_expr (gfc_expr *expr)
2454 : {
2455 2052 : tree caf_decl;
2456 2052 : bool found = false;
2457 2052 : gfc_ref *ref;
2458 :
2459 2052 : gcc_assert (expr && expr->expr_type == EXPR_VARIABLE);
2460 :
2461 : /* Not-implemented diagnostic. */
2462 2052 : if (expr->symtree->n.sym->ts.type == BT_CLASS
2463 39 : && UNLIMITED_POLY (expr->symtree->n.sym)
2464 0 : && CLASS_DATA (expr->symtree->n.sym)->attr.codimension)
2465 0 : gfc_error ("Sorry, coindexed access to an unlimited polymorphic object at "
2466 : "%L is not supported", &expr->where);
2467 :
2468 4335 : for (ref = expr->ref; ref; ref = ref->next)
2469 2283 : if (ref->type == REF_COMPONENT)
2470 : {
2471 195 : if (ref->u.c.component->ts.type == BT_CLASS
2472 0 : && UNLIMITED_POLY (ref->u.c.component)
2473 0 : && CLASS_DATA (ref->u.c.component)->attr.codimension)
2474 0 : gfc_error ("Sorry, coindexed access to an unlimited polymorphic "
2475 : "component at %L is not supported", &expr->where);
2476 : }
2477 :
2478 : /* Make sure the backend_decl is present before accessing it. */
2479 2052 : caf_decl = expr->symtree->n.sym->backend_decl == NULL_TREE
2480 2052 : ? gfc_get_symbol_decl (expr->symtree->n.sym)
2481 : : expr->symtree->n.sym->backend_decl;
2482 :
2483 2052 : if (expr->symtree->n.sym->ts.type == BT_CLASS)
2484 : {
2485 39 : if (DECL_P (caf_decl) && DECL_LANG_SPECIFIC (caf_decl)
2486 45 : && GFC_DECL_SAVED_DESCRIPTOR (caf_decl))
2487 6 : caf_decl = GFC_DECL_SAVED_DESCRIPTOR (caf_decl);
2488 :
2489 39 : if (expr->ref && expr->ref->type == REF_ARRAY)
2490 : {
2491 28 : caf_decl = gfc_class_data_get (caf_decl);
2492 28 : if (CLASS_DATA (expr->symtree->n.sym)->attr.codimension)
2493 : return caf_decl;
2494 : }
2495 11 : else if (DECL_P (caf_decl) && DECL_LANG_SPECIFIC (caf_decl)
2496 2 : && GFC_DECL_TOKEN (caf_decl)
2497 13 : && CLASS_DATA (expr->symtree->n.sym)->attr.codimension)
2498 : return caf_decl;
2499 :
2500 23 : for (ref = expr->ref; ref; ref = ref->next)
2501 : {
2502 18 : if (ref->type == REF_COMPONENT
2503 9 : && strcmp (ref->u.c.component->name, "_data") != 0)
2504 : {
2505 0 : caf_decl = gfc_class_data_get (caf_decl);
2506 0 : if (CLASS_DATA (expr->symtree->n.sym)->attr.codimension)
2507 : return caf_decl;
2508 : break;
2509 : }
2510 18 : else if (ref->type == REF_ARRAY && ref->u.ar.dimen)
2511 : break;
2512 : }
2513 : }
2514 2022 : if (expr->symtree->n.sym->attr.codimension)
2515 : return caf_decl;
2516 :
2517 : /* The following code assumes that the coarray is a component reachable via
2518 : only scalar components/variables; the Fortran standard guarantees this. */
2519 :
2520 46 : for (ref = expr->ref; ref; ref = ref->next)
2521 46 : if (ref->type == REF_COMPONENT)
2522 : {
2523 46 : gfc_component *comp = ref->u.c.component;
2524 :
2525 46 : if (POINTER_TYPE_P (TREE_TYPE (caf_decl)))
2526 0 : caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
2527 46 : caf_decl = fold_build3_loc (input_location, COMPONENT_REF,
2528 46 : TREE_TYPE (comp->backend_decl), caf_decl,
2529 : comp->backend_decl, NULL_TREE);
2530 46 : if (comp->ts.type == BT_CLASS)
2531 : {
2532 0 : caf_decl = gfc_class_data_get (caf_decl);
2533 0 : if (CLASS_DATA (comp)->attr.codimension)
2534 : {
2535 : found = true;
2536 : break;
2537 : }
2538 : }
2539 46 : if (comp->attr.codimension)
2540 : {
2541 : found = true;
2542 : break;
2543 : }
2544 : }
2545 46 : gcc_assert (found && caf_decl);
2546 : return caf_decl;
2547 : }
2548 :
2549 :
2550 : /* Obtain the Coarray token - and optionally also the offset. */
2551 :
2552 : void
2553 1923 : gfc_get_caf_token_offset (gfc_se *se, tree *token, tree *offset, tree caf_decl,
2554 : tree se_expr, gfc_expr *expr)
2555 : {
2556 1923 : tree tmp;
2557 :
2558 1923 : gcc_assert (flag_coarray == GFC_FCOARRAY_LIB);
2559 :
2560 : /* Coarray token. */
2561 1923 : if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (caf_decl)))
2562 548 : *token = gfc_conv_descriptor_token (caf_decl);
2563 1373 : else if (DECL_P (caf_decl) && DECL_LANG_SPECIFIC (caf_decl)
2564 1574 : && GFC_DECL_TOKEN (caf_decl) != NULL_TREE)
2565 6 : *token = GFC_DECL_TOKEN (caf_decl);
2566 : else
2567 : {
2568 1369 : gcc_assert (GFC_ARRAY_TYPE_P (TREE_TYPE (caf_decl))
2569 : && GFC_TYPE_ARRAY_CAF_TOKEN (TREE_TYPE (caf_decl)) != NULL_TREE);
2570 1369 : *token = GFC_TYPE_ARRAY_CAF_TOKEN (TREE_TYPE (caf_decl));
2571 : }
2572 :
2573 1923 : if (offset == NULL)
2574 : return;
2575 :
2576 : /* Offset between the coarray base address and the address wanted. */
2577 179 : if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (caf_decl))
2578 179 : && (GFC_TYPE_ARRAY_AKIND (TREE_TYPE (caf_decl)) == GFC_ARRAY_ALLOCATABLE
2579 0 : || GFC_TYPE_ARRAY_AKIND (TREE_TYPE (caf_decl)) == GFC_ARRAY_POINTER))
2580 0 : *offset = build_int_cst (gfc_array_index_type, 0);
2581 179 : else if (DECL_P (caf_decl) && DECL_LANG_SPECIFIC (caf_decl)
2582 179 : && GFC_DECL_CAF_OFFSET (caf_decl) != NULL_TREE)
2583 0 : *offset = GFC_DECL_CAF_OFFSET (caf_decl);
2584 179 : else if (GFC_TYPE_ARRAY_CAF_OFFSET (TREE_TYPE (caf_decl)) != NULL_TREE)
2585 0 : *offset = GFC_TYPE_ARRAY_CAF_OFFSET (TREE_TYPE (caf_decl));
2586 : else
2587 179 : *offset = build_int_cst (gfc_array_index_type, 0);
2588 :
2589 179 : if (POINTER_TYPE_P (TREE_TYPE (se_expr))
2590 179 : && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (se_expr))))
2591 : {
2592 0 : tmp = build_fold_indirect_ref_loc (input_location, se_expr);
2593 0 : tmp = gfc_conv_descriptor_data_get (tmp);
2594 : }
2595 179 : else if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se_expr)))
2596 0 : tmp = gfc_conv_descriptor_data_get (se_expr);
2597 : else
2598 : {
2599 179 : gcc_assert (POINTER_TYPE_P (TREE_TYPE (se_expr)));
2600 : tmp = se_expr;
2601 : }
2602 :
2603 179 : *offset = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
2604 : *offset, fold_convert (gfc_array_index_type, tmp));
2605 :
2606 179 : if (expr->symtree->n.sym->ts.type == BT_DERIVED
2607 0 : && expr->symtree->n.sym->attr.codimension
2608 0 : && expr->symtree->n.sym->ts.u.derived->attr.alloc_comp)
2609 : {
2610 0 : gfc_expr *base_expr = gfc_copy_expr (expr);
2611 0 : gfc_ref *ref = base_expr->ref;
2612 0 : gfc_se base_se;
2613 :
2614 : // Iterate through the refs until the last one.
2615 0 : while (ref->next)
2616 : ref = ref->next;
2617 :
2618 0 : if (ref->type == REF_ARRAY
2619 0 : && ref->u.ar.type != AR_FULL)
2620 : {
2621 0 : const int ranksum = ref->u.ar.dimen + ref->u.ar.codimen;
2622 0 : int i;
2623 0 : for (i = 0; i < ranksum; ++i)
2624 : {
2625 0 : ref->u.ar.start[i] = NULL;
2626 0 : ref->u.ar.end[i] = NULL;
2627 : }
2628 0 : ref->u.ar.type = AR_FULL;
2629 : }
2630 0 : gfc_init_se (&base_se, NULL);
2631 0 : if (gfc_caf_attr (base_expr).dimension)
2632 : {
2633 0 : gfc_conv_expr_descriptor (&base_se, base_expr);
2634 0 : tmp = gfc_conv_descriptor_data_get (base_se.expr);
2635 : }
2636 : else
2637 : {
2638 0 : gfc_conv_expr (&base_se, base_expr);
2639 0 : tmp = base_se.expr;
2640 : }
2641 :
2642 0 : gfc_free_expr (base_expr);
2643 0 : gfc_add_block_to_block (&se->pre, &base_se.pre);
2644 0 : gfc_add_block_to_block (&se->post, &base_se.post);
2645 0 : }
2646 179 : else if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (caf_decl)))
2647 0 : tmp = gfc_conv_descriptor_data_get (caf_decl);
2648 179 : else if (INDIRECT_REF_P (caf_decl))
2649 0 : tmp = TREE_OPERAND (caf_decl, 0);
2650 : else
2651 : {
2652 179 : gcc_assert (POINTER_TYPE_P (TREE_TYPE (caf_decl)));
2653 : tmp = caf_decl;
2654 : }
2655 :
2656 179 : *offset = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
2657 : fold_convert (gfc_array_index_type, *offset),
2658 : fold_convert (gfc_array_index_type, tmp));
2659 : }
2660 :
2661 :
2662 : /* Convert the coindex of a coarray into an image index; the result is
2663 : image_num = (idx(1)-lcobound(1)+1) + (idx(2)-lcobound(2))*extent(1)
2664 : + (idx(3)-lcobound(3))*extend(1)*extent(2) + ... */
2665 :
2666 : tree
2667 1634 : gfc_caf_get_image_index (stmtblock_t *block, gfc_expr *e, tree desc)
2668 : {
2669 1634 : gfc_ref *ref;
2670 1634 : tree lbound, ubound, extent, tmp, img_idx;
2671 1634 : gfc_se se;
2672 1634 : int i;
2673 :
2674 1665 : for (ref = e->ref; ref; ref = ref->next)
2675 1665 : if (ref->type == REF_ARRAY && ref->u.ar.codimen > 0)
2676 : break;
2677 1634 : gcc_assert (ref != NULL);
2678 :
2679 1634 : if (ref->u.ar.dimen_type[ref->u.ar.dimen] == DIMEN_THIS_IMAGE)
2680 95 : return build_call_expr_loc (input_location, gfor_fndecl_caf_this_image, 1,
2681 95 : null_pointer_node);
2682 :
2683 1539 : img_idx = build_zero_cst (gfc_array_index_type);
2684 1539 : extent = build_one_cst (gfc_array_index_type);
2685 1539 : if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
2686 630 : for (i = ref->u.ar.dimen; i < ref->u.ar.dimen + ref->u.ar.codimen; i++)
2687 : {
2688 321 : gfc_init_se (&se, NULL);
2689 321 : gfc_conv_expr_type (&se, ref->u.ar.start[i], gfc_array_index_type);
2690 321 : gfc_add_block_to_block (block, &se.pre);
2691 321 : lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
2692 321 : tmp = fold_build2_loc (input_location, MINUS_EXPR,
2693 321 : TREE_TYPE (lbound), se.expr, lbound);
2694 321 : tmp = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (tmp),
2695 : extent, tmp);
2696 321 : img_idx = fold_build2_loc (input_location, PLUS_EXPR,
2697 321 : TREE_TYPE (tmp), img_idx, tmp);
2698 321 : if (i < ref->u.ar.dimen + ref->u.ar.codimen - 1)
2699 : {
2700 12 : ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
2701 12 : tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL);
2702 12 : extent = fold_build2_loc (input_location, MULT_EXPR,
2703 12 : TREE_TYPE (tmp), extent, tmp);
2704 : }
2705 : }
2706 : else
2707 2476 : for (i = ref->u.ar.dimen; i < ref->u.ar.dimen + ref->u.ar.codimen; i++)
2708 : {
2709 1246 : gfc_init_se (&se, NULL);
2710 1246 : gfc_conv_expr_type (&se, ref->u.ar.start[i], gfc_array_index_type);
2711 1246 : gfc_add_block_to_block (block, &se.pre);
2712 1246 : lbound = GFC_TYPE_ARRAY_LBOUND (TREE_TYPE (desc), i);
2713 1246 : tmp = fold_build2_loc (input_location, MINUS_EXPR,
2714 1246 : TREE_TYPE (lbound), se.expr, lbound);
2715 1246 : tmp = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (tmp),
2716 : extent, tmp);
2717 1246 : img_idx = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (tmp),
2718 : img_idx, tmp);
2719 1246 : if (i < ref->u.ar.dimen + ref->u.ar.codimen - 1)
2720 : {
2721 16 : ubound = GFC_TYPE_ARRAY_UBOUND (TREE_TYPE (desc), i);
2722 16 : tmp = fold_build2_loc (input_location, MINUS_EXPR,
2723 16 : TREE_TYPE (ubound), ubound, lbound);
2724 16 : tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (tmp),
2725 16 : tmp, build_one_cst (TREE_TYPE (tmp)));
2726 16 : extent = fold_build2_loc (input_location, MULT_EXPR,
2727 16 : TREE_TYPE (tmp), extent, tmp);
2728 : }
2729 : }
2730 1539 : img_idx = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (img_idx),
2731 1539 : img_idx, build_one_cst (TREE_TYPE (img_idx)));
2732 1539 : return fold_convert (integer_type_node, img_idx);
2733 : }
2734 :
2735 :
2736 : /* For each character array constructor subexpression without a ts.u.cl->length,
2737 : replace it by its first element (if there aren't any elements, the length
2738 : should already be set to zero). */
2739 :
2740 : static void
2741 110 : flatten_array_ctors_without_strlen (gfc_expr* e)
2742 : {
2743 110 : gfc_actual_arglist* arg;
2744 110 : gfc_constructor* c;
2745 :
2746 110 : if (!e)
2747 : return;
2748 :
2749 110 : switch (e->expr_type)
2750 : {
2751 :
2752 0 : case EXPR_OP:
2753 0 : flatten_array_ctors_without_strlen (e->value.op.op1);
2754 0 : flatten_array_ctors_without_strlen (e->value.op.op2);
2755 0 : break;
2756 :
2757 0 : case EXPR_COMPCALL:
2758 : /* TODO: Implement as with EXPR_FUNCTION when needed. */
2759 0 : gcc_unreachable ();
2760 :
2761 13 : case EXPR_FUNCTION:
2762 40 : for (arg = e->value.function.actual; arg; arg = arg->next)
2763 27 : flatten_array_ctors_without_strlen (arg->expr);
2764 : break;
2765 :
2766 0 : case EXPR_ARRAY:
2767 :
2768 : /* We've found what we're looking for. */
2769 0 : if (e->ts.type == BT_CHARACTER && !e->ts.u.cl->length)
2770 : {
2771 0 : gfc_constructor *c;
2772 0 : gfc_expr* new_expr;
2773 :
2774 0 : gcc_assert (e->value.constructor);
2775 :
2776 0 : c = gfc_constructor_first (e->value.constructor);
2777 0 : new_expr = c->expr;
2778 0 : c->expr = NULL;
2779 :
2780 0 : flatten_array_ctors_without_strlen (new_expr);
2781 0 : gfc_replace_expr (e, new_expr);
2782 0 : break;
2783 : }
2784 :
2785 : /* Otherwise, fall through to handle constructor elements. */
2786 0 : gcc_fallthrough ();
2787 0 : case EXPR_STRUCTURE:
2788 0 : for (c = gfc_constructor_first (e->value.constructor);
2789 0 : c; c = gfc_constructor_next (c))
2790 0 : flatten_array_ctors_without_strlen (c->expr);
2791 : break;
2792 :
2793 : default:
2794 : break;
2795 :
2796 : }
2797 : }
2798 :
2799 :
2800 : /* Generate code to initialize a string length variable. Returns the
2801 : value. For array constructors, cl->length might be NULL and in this case,
2802 : the first element of the constructor is needed. expr is the original
2803 : expression so we can access it but can be NULL if this is not needed. */
2804 :
2805 : void
2806 3843 : gfc_conv_string_length (gfc_charlen * cl, gfc_expr * expr, stmtblock_t * pblock)
2807 : {
2808 3843 : gfc_se se;
2809 :
2810 3843 : gfc_init_se (&se, NULL);
2811 :
2812 3843 : if (!cl->length && cl->backend_decl && VAR_P (cl->backend_decl))
2813 1361 : return;
2814 :
2815 : /* If cl->length is NULL, use gfc_conv_expr to obtain the string length but
2816 : "flatten" array constructors by taking their first element; all elements
2817 : should be the same length or a cl->length should be present. */
2818 2575 : if (!cl->length)
2819 : {
2820 176 : gfc_expr* expr_flat;
2821 176 : if (!expr)
2822 : return;
2823 83 : expr_flat = gfc_copy_expr (expr);
2824 83 : flatten_array_ctors_without_strlen (expr_flat);
2825 83 : gfc_resolve_expr (expr_flat);
2826 83 : if (expr_flat->rank)
2827 13 : gfc_conv_expr_descriptor (&se, expr_flat);
2828 : else
2829 70 : gfc_conv_expr (&se, expr_flat);
2830 83 : if (expr_flat->expr_type != EXPR_VARIABLE)
2831 77 : gfc_add_block_to_block (pblock, &se.pre);
2832 83 : se.expr = convert (gfc_charlen_type_node, se.string_length);
2833 83 : gfc_add_block_to_block (pblock, &se.post);
2834 83 : gfc_free_expr (expr_flat);
2835 : }
2836 : else
2837 : {
2838 : /* Convert cl->length. */
2839 2399 : gfc_conv_expr_type (&se, cl->length, gfc_charlen_type_node);
2840 2399 : se.expr = fold_build2_loc (input_location, MAX_EXPR,
2841 : gfc_charlen_type_node, se.expr,
2842 2399 : build_zero_cst (TREE_TYPE (se.expr)));
2843 2399 : gfc_add_block_to_block (pblock, &se.pre);
2844 : }
2845 :
2846 2482 : if (cl->backend_decl && VAR_P (cl->backend_decl))
2847 1564 : gfc_add_modify (pblock, cl->backend_decl, se.expr);
2848 : else
2849 918 : cl->backend_decl = gfc_evaluate_now (se.expr, pblock);
2850 : }
2851 :
2852 :
2853 : static void
2854 7300 : gfc_conv_substring (gfc_se * se, gfc_ref * ref, int kind,
2855 : const char *name, locus *where)
2856 : {
2857 7300 : tree tmp;
2858 7300 : tree type;
2859 7300 : tree fault;
2860 7300 : gfc_se start;
2861 7300 : gfc_se end;
2862 7300 : char *msg;
2863 7300 : mpz_t length;
2864 :
2865 7300 : type = gfc_get_character_type (kind, ref->u.ss.length);
2866 7300 : type = build_pointer_type (type);
2867 :
2868 7300 : gfc_init_se (&start, se);
2869 7300 : gfc_conv_expr_type (&start, ref->u.ss.start, gfc_charlen_type_node);
2870 7300 : gfc_add_block_to_block (&se->pre, &start.pre);
2871 :
2872 7300 : if (integer_onep (start.expr))
2873 2768 : gfc_conv_string_parameter (se);
2874 : else
2875 : {
2876 4532 : tmp = start.expr;
2877 4532 : STRIP_NOPS (tmp);
2878 : /* Avoid multiple evaluation of substring start. */
2879 4532 : if (!CONSTANT_CLASS_P (tmp) && !DECL_P (tmp))
2880 1697 : start.expr = gfc_evaluate_now (start.expr, &se->pre);
2881 :
2882 : /* Change the start of the string. */
2883 4532 : if (((TREE_CODE (TREE_TYPE (se->expr)) == ARRAY_TYPE
2884 1194 : || TREE_CODE (TREE_TYPE (se->expr)) == INTEGER_TYPE)
2885 3458 : && TYPE_STRING_FLAG (TREE_TYPE (se->expr)))
2886 5606 : || (POINTER_TYPE_P (TREE_TYPE (se->expr))
2887 1074 : && TREE_CODE (TREE_TYPE (TREE_TYPE (se->expr))) != ARRAY_TYPE))
2888 : tmp = se->expr;
2889 : else
2890 1066 : tmp = build_fold_indirect_ref_loc (input_location,
2891 : se->expr);
2892 : /* For BIND(C), a BT_CHARACTER is not an ARRAY_TYPE. */
2893 4532 : if (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE)
2894 : {
2895 4404 : tmp = gfc_build_array_ref (tmp, start.expr, NULL_TREE, true);
2896 4404 : se->expr = gfc_build_addr_expr (type, tmp);
2897 : }
2898 128 : else if (POINTER_TYPE_P (TREE_TYPE (tmp)))
2899 : {
2900 8 : tree diff;
2901 8 : diff = fold_build2 (MINUS_EXPR, gfc_charlen_type_node, start.expr,
2902 : build_one_cst (gfc_charlen_type_node));
2903 8 : diff = fold_convert (size_type_node, diff);
2904 8 : se->expr
2905 8 : = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (tmp), tmp, diff);
2906 : }
2907 : }
2908 :
2909 : /* Length = end + 1 - start. */
2910 7300 : gfc_init_se (&end, se);
2911 7300 : if (ref->u.ss.end == NULL)
2912 202 : end.expr = se->string_length;
2913 : else
2914 : {
2915 7098 : gfc_conv_expr_type (&end, ref->u.ss.end, gfc_charlen_type_node);
2916 7098 : gfc_add_block_to_block (&se->pre, &end.pre);
2917 : }
2918 7300 : tmp = end.expr;
2919 7300 : STRIP_NOPS (tmp);
2920 7300 : if (!CONSTANT_CLASS_P (tmp) && !DECL_P (tmp))
2921 2301 : end.expr = gfc_evaluate_now (end.expr, &se->pre);
2922 :
2923 7300 : if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2924 474 : && !gfc_contains_implied_index_p (ref->u.ss.start)
2925 7755 : && !gfc_contains_implied_index_p (ref->u.ss.end))
2926 : {
2927 455 : tree nonempty = fold_build2_loc (input_location, LE_EXPR,
2928 : logical_type_node, start.expr,
2929 : end.expr);
2930 :
2931 : /* Check lower bound. */
2932 455 : fault = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
2933 : start.expr,
2934 455 : build_one_cst (TREE_TYPE (start.expr)));
2935 455 : fault = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
2936 : logical_type_node, nonempty, fault);
2937 455 : if (name)
2938 454 : msg = xasprintf ("Substring out of bounds: lower bound (%%ld) of '%s' "
2939 : "is less than one", name);
2940 : else
2941 1 : msg = xasprintf ("Substring out of bounds: lower bound (%%ld) "
2942 : "is less than one");
2943 455 : gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
2944 : fold_convert (long_integer_type_node,
2945 : start.expr));
2946 455 : free (msg);
2947 :
2948 : /* Check upper bound. */
2949 455 : fault = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
2950 : end.expr, se->string_length);
2951 455 : fault = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
2952 : logical_type_node, nonempty, fault);
2953 455 : if (name)
2954 454 : msg = xasprintf ("Substring out of bounds: upper bound (%%ld) of '%s' "
2955 : "exceeds string length (%%ld)", name);
2956 : else
2957 1 : msg = xasprintf ("Substring out of bounds: upper bound (%%ld) "
2958 : "exceeds string length (%%ld)");
2959 455 : gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
2960 : fold_convert (long_integer_type_node, end.expr),
2961 : fold_convert (long_integer_type_node,
2962 : se->string_length));
2963 455 : free (msg);
2964 : }
2965 :
2966 : /* Try to calculate the length from the start and end expressions. */
2967 7300 : if (ref->u.ss.end
2968 7300 : && gfc_dep_difference (ref->u.ss.end, ref->u.ss.start, &length))
2969 : {
2970 6081 : HOST_WIDE_INT i_len;
2971 :
2972 6081 : i_len = gfc_mpz_get_hwi (length) + 1;
2973 6081 : if (i_len < 0)
2974 : i_len = 0;
2975 :
2976 6081 : tmp = build_int_cst (gfc_charlen_type_node, i_len);
2977 6081 : mpz_clear (length); /* Was initialized by gfc_dep_difference. */
2978 : }
2979 : else
2980 : {
2981 1219 : tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_charlen_type_node,
2982 : fold_convert (gfc_charlen_type_node, end.expr),
2983 : fold_convert (gfc_charlen_type_node, start.expr));
2984 1219 : tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_charlen_type_node,
2985 : build_int_cst (gfc_charlen_type_node, 1), tmp);
2986 1219 : tmp = fold_build2_loc (input_location, MAX_EXPR, gfc_charlen_type_node,
2987 : tmp, build_int_cst (gfc_charlen_type_node, 0));
2988 : }
2989 :
2990 7300 : se->string_length = tmp;
2991 7300 : }
2992 :
2993 :
2994 : /* Convert a derived type component reference. */
2995 :
2996 : void
2997 177643 : gfc_conv_component_ref (gfc_se * se, gfc_ref * ref)
2998 : {
2999 177643 : gfc_component *c;
3000 177643 : tree tmp;
3001 177643 : tree decl;
3002 177643 : tree field;
3003 177643 : tree context;
3004 :
3005 177643 : c = ref->u.c.component;
3006 :
3007 177643 : if (c->backend_decl == NULL_TREE
3008 6 : && ref->u.c.sym != NULL)
3009 6 : gfc_get_derived_type (ref->u.c.sym);
3010 :
3011 177643 : field = c->backend_decl;
3012 177643 : gcc_assert (field && TREE_CODE (field) == FIELD_DECL);
3013 177643 : decl = se->expr;
3014 177643 : context = DECL_FIELD_CONTEXT (field);
3015 :
3016 : /* Components can correspond to fields of different containing
3017 : types, as components are created without context, whereas
3018 : a concrete use of a component has the type of decl as context.
3019 : So, if the type doesn't match, we search the corresponding
3020 : FIELD_DECL in the parent type. To not waste too much time
3021 : we cache this result in norestrict_decl.
3022 : On the other hand, if the context is a UNION or a MAP (a
3023 : RECORD_TYPE within a UNION_TYPE) always use the given FIELD_DECL. */
3024 :
3025 177643 : if (context != TREE_TYPE (decl)
3026 177643 : && !( TREE_CODE (TREE_TYPE (field)) == UNION_TYPE /* Field is union */
3027 12778 : || TREE_CODE (context) == UNION_TYPE)) /* Field is map */
3028 : {
3029 12778 : tree f2 = c->norestrict_decl;
3030 21600 : if (!f2 || DECL_FIELD_CONTEXT (f2) != TREE_TYPE (decl))
3031 7855 : for (f2 = TYPE_FIELDS (TREE_TYPE (decl)); f2; f2 = DECL_CHAIN (f2))
3032 7855 : if (TREE_CODE (f2) == FIELD_DECL
3033 7855 : && DECL_NAME (f2) == DECL_NAME (field))
3034 : break;
3035 12778 : gcc_assert (f2);
3036 12778 : c->norestrict_decl = f2;
3037 12778 : field = f2;
3038 : }
3039 :
3040 177643 : if (ref->u.c.sym && ref->u.c.sym->ts.type == BT_CLASS
3041 0 : && strcmp ("_data", c->name) == 0)
3042 : {
3043 : /* Found a ref to the _data component. Store the associated ref to
3044 : the vptr in se->class_vptr. */
3045 0 : se->class_vptr = gfc_class_vptr_get (decl);
3046 : }
3047 : else
3048 177643 : se->class_vptr = NULL_TREE;
3049 :
3050 177643 : tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
3051 : decl, field, NULL_TREE);
3052 :
3053 177643 : se->expr = tmp;
3054 :
3055 : /* Allocatable deferred char arrays are to be handled by the gfc_deferred_
3056 : strlen () conditional below. */
3057 177643 : if (c->ts.type == BT_CHARACTER && !c->attr.proc_pointer
3058 8802 : && !c->ts.deferred
3059 5644 : && !c->attr.pdt_string)
3060 : {
3061 5470 : tmp = c->ts.u.cl->backend_decl;
3062 : /* Components must always be constant length. */
3063 5470 : gcc_assert (tmp && INTEGER_CST_P (tmp));
3064 5470 : se->string_length = tmp;
3065 : }
3066 :
3067 177643 : if (gfc_deferred_strlen (c, &field))
3068 : {
3069 3332 : tmp = fold_build3_loc (input_location, COMPONENT_REF,
3070 3332 : TREE_TYPE (field),
3071 : decl, field, NULL_TREE);
3072 3332 : se->string_length = tmp;
3073 : }
3074 :
3075 177643 : if (((c->attr.pointer || c->attr.allocatable)
3076 104058 : && (!c->attr.dimension && !c->attr.codimension)
3077 55870 : && c->ts.type != BT_CHARACTER)
3078 123996 : || c->attr.proc_pointer)
3079 59989 : se->expr = build_fold_indirect_ref_loc (input_location,
3080 : se->expr);
3081 177643 : }
3082 :
3083 :
3084 : /* This function deals with component references to components of the
3085 : parent type for derived type extensions. */
3086 : void
3087 64383 : conv_parent_component_references (gfc_se * se, gfc_ref * ref)
3088 : {
3089 64383 : gfc_component *c;
3090 64383 : gfc_component *cmp;
3091 64383 : gfc_symbol *dt;
3092 64383 : gfc_ref parent;
3093 :
3094 64383 : dt = ref->u.c.sym;
3095 64383 : c = ref->u.c.component;
3096 :
3097 : /* Return if the component is in this type, i.e. not in the parent type. */
3098 110838 : for (cmp = dt->components; cmp; cmp = cmp->next)
3099 100308 : if (c == cmp)
3100 53853 : return;
3101 :
3102 : /* Build a gfc_ref to recursively call gfc_conv_component_ref. */
3103 10530 : parent.type = REF_COMPONENT;
3104 10530 : parent.next = NULL;
3105 10530 : parent.u.c.sym = dt;
3106 10530 : parent.u.c.component = dt->components;
3107 :
3108 10530 : if (dt->backend_decl == NULL)
3109 0 : gfc_get_derived_type (dt);
3110 :
3111 : /* Build the reference and call self. */
3112 10530 : gfc_conv_component_ref (se, &parent);
3113 10530 : parent.u.c.sym = dt->components->ts.u.derived;
3114 10530 : parent.u.c.component = c;
3115 10530 : conv_parent_component_references (se, &parent);
3116 : }
3117 :
3118 :
3119 : static void
3120 549 : conv_inquiry (gfc_se * se, gfc_ref * ref, gfc_expr *expr, gfc_typespec *ts)
3121 : {
3122 549 : tree res = se->expr;
3123 :
3124 549 : switch (ref->u.i)
3125 : {
3126 265 : case INQUIRY_RE:
3127 530 : res = fold_build1_loc (input_location, REALPART_EXPR,
3128 265 : TREE_TYPE (TREE_TYPE (res)), res);
3129 265 : break;
3130 :
3131 239 : case INQUIRY_IM:
3132 478 : res = fold_build1_loc (input_location, IMAGPART_EXPR,
3133 239 : TREE_TYPE (TREE_TYPE (res)), res);
3134 239 : break;
3135 :
3136 7 : case INQUIRY_KIND:
3137 7 : res = build_int_cst (gfc_typenode_for_spec (&expr->ts),
3138 7 : ts->kind);
3139 7 : se->string_length = NULL_TREE;
3140 7 : break;
3141 :
3142 38 : case INQUIRY_LEN:
3143 38 : res = fold_convert (gfc_typenode_for_spec (&expr->ts),
3144 : se->string_length);
3145 38 : se->string_length = NULL_TREE;
3146 38 : break;
3147 :
3148 0 : default:
3149 0 : gcc_unreachable ();
3150 : }
3151 549 : se->expr = res;
3152 549 : }
3153 :
3154 : /* Dereference VAR where needed if it is a pointer, reference, etc.
3155 : according to Fortran semantics. */
3156 :
3157 : tree
3158 1454692 : gfc_maybe_dereference_var (gfc_symbol *sym, tree var, bool descriptor_only_p,
3159 : bool is_classarray)
3160 : {
3161 1454692 : if (!POINTER_TYPE_P (TREE_TYPE (var)))
3162 : return var;
3163 293647 : if (is_CFI_desc (sym, NULL))
3164 11892 : return build_fold_indirect_ref_loc (input_location, var);
3165 :
3166 : /* Characters are entirely different from other types, they are treated
3167 : separately. */
3168 281755 : if (sym->ts.type == BT_CHARACTER)
3169 : {
3170 : /* Dereference character pointer dummy arguments
3171 : or results. */
3172 32886 : if ((sym->attr.pointer || sym->attr.allocatable
3173 18996 : || (sym->as && sym->as->type == AS_ASSUMED_RANK))
3174 14226 : && (sym->attr.dummy
3175 10910 : || sym->attr.function
3176 10536 : || sym->attr.result))
3177 4375 : var = build_fold_indirect_ref_loc (input_location, var);
3178 : }
3179 248869 : else if (!sym->attr.value)
3180 : {
3181 : /* Dereference temporaries for class array dummy arguments. */
3182 171978 : if (sym->attr.dummy && is_classarray
3183 255764 : && GFC_ARRAY_TYPE_P (TREE_TYPE (var)))
3184 : {
3185 5343 : if (!descriptor_only_p)
3186 2722 : var = GFC_DECL_SAVED_DESCRIPTOR (var);
3187 :
3188 5343 : var = build_fold_indirect_ref_loc (input_location, var);
3189 : }
3190 :
3191 : /* Dereference non-character scalar dummy arguments. */
3192 248065 : if (sym->attr.dummy && !sym->attr.dimension
3193 104318 : && !(sym->attr.codimension && sym->attr.allocatable)
3194 104252 : && (sym->ts.type != BT_CLASS
3195 19595 : || (!CLASS_DATA (sym)->attr.dimension
3196 11426 : && !(CLASS_DATA (sym)->attr.codimension
3197 283 : && CLASS_DATA (sym)->attr.allocatable))))
3198 95942 : var = build_fold_indirect_ref_loc (input_location, var);
3199 :
3200 : /* Dereference scalar hidden result. */
3201 248065 : if (flag_f2c && sym->ts.type == BT_COMPLEX
3202 286 : && (sym->attr.function || sym->attr.result)
3203 108 : && !sym->attr.dimension && !sym->attr.pointer
3204 60 : && !sym->attr.always_explicit)
3205 36 : var = build_fold_indirect_ref_loc (input_location, var);
3206 :
3207 : /* Dereference non-character, non-class pointer variables.
3208 : These must be dummies, results, or scalars. */
3209 248065 : if (!is_classarray
3210 239920 : && (sym->attr.pointer || sym->attr.allocatable
3211 190591 : || gfc_is_associate_pointer (sym)
3212 185850 : || (sym->as && sym->as->type == AS_ASSUMED_RANK))
3213 325079 : && (sym->attr.dummy
3214 36225 : || sym->attr.function
3215 35295 : || sym->attr.result
3216 34189 : || (!sym->attr.dimension
3217 34184 : && (!sym->attr.codimension || !sym->attr.allocatable))))
3218 77009 : var = build_fold_indirect_ref_loc (input_location, var);
3219 : /* Now treat the class array pointer variables accordingly. */
3220 171056 : else if (sym->ts.type == BT_CLASS
3221 20041 : && sym->attr.dummy
3222 19595 : && (CLASS_DATA (sym)->attr.dimension
3223 11426 : || CLASS_DATA (sym)->attr.codimension)
3224 8452 : && ((CLASS_DATA (sym)->as
3225 8452 : && CLASS_DATA (sym)->as->type == AS_ASSUMED_RANK)
3226 7401 : || CLASS_DATA (sym)->attr.allocatable
3227 6076 : || CLASS_DATA (sym)->attr.class_pointer))
3228 2967 : var = build_fold_indirect_ref_loc (input_location, var);
3229 : /* And the case where a non-dummy, non-result, non-function,
3230 : non-allocable and non-pointer classarray is present. This case was
3231 : previously covered by the first if, but with introducing the
3232 : condition !is_classarray there, that case has to be covered
3233 : explicitly. */
3234 168089 : else if (sym->ts.type == BT_CLASS
3235 17074 : && !sym->attr.dummy
3236 446 : && !sym->attr.function
3237 446 : && !sym->attr.result
3238 446 : && (CLASS_DATA (sym)->attr.dimension
3239 4 : || CLASS_DATA (sym)->attr.codimension)
3240 446 : && (sym->assoc
3241 0 : || !CLASS_DATA (sym)->attr.allocatable)
3242 446 : && !CLASS_DATA (sym)->attr.class_pointer)
3243 446 : var = build_fold_indirect_ref_loc (input_location, var);
3244 : }
3245 :
3246 : return var;
3247 : }
3248 :
3249 : /* Return the contents of a variable. Also handles reference/pointer
3250 : variables (all Fortran pointer references are implicit). */
3251 :
3252 : static void
3253 1607638 : gfc_conv_variable (gfc_se * se, gfc_expr * expr)
3254 : {
3255 1607638 : gfc_ss *ss;
3256 1607638 : gfc_ref *ref;
3257 1607638 : gfc_symbol *sym;
3258 1607638 : tree parent_decl = NULL_TREE;
3259 1607638 : int parent_flag;
3260 1607638 : bool return_value;
3261 1607638 : bool alternate_entry;
3262 1607638 : bool entry_master;
3263 1607638 : bool is_classarray;
3264 1607638 : bool first_time = true;
3265 :
3266 1607638 : sym = expr->symtree->n.sym;
3267 1607638 : is_classarray = IS_CLASS_COARRAY_OR_ARRAY (sym);
3268 1607638 : ss = se->ss;
3269 1607638 : if (ss != NULL)
3270 : {
3271 133343 : gfc_ss_info *ss_info = ss->info;
3272 :
3273 : /* Check that something hasn't gone horribly wrong. */
3274 133343 : gcc_assert (ss != gfc_ss_terminator);
3275 133343 : gcc_assert (ss_info->expr == expr);
3276 :
3277 : /* A scalarized term. We already know the descriptor. */
3278 133343 : se->expr = ss_info->data.array.descriptor;
3279 133343 : se->string_length = ss_info->string_length;
3280 133343 : ref = ss_info->data.array.ref;
3281 133343 : if (ref)
3282 132989 : gcc_assert (ref->type == REF_ARRAY
3283 : && ref->u.ar.type != AR_ELEMENT);
3284 : else
3285 354 : gfc_conv_tmp_array_ref (se);
3286 : }
3287 : else
3288 : {
3289 1474295 : tree se_expr = NULL_TREE;
3290 :
3291 1474295 : se->expr = gfc_get_symbol_decl (sym);
3292 :
3293 : /* Deal with references to a parent results or entries by storing
3294 : the current_function_decl and moving to the parent_decl. */
3295 1474295 : return_value = sym->attr.function && sym->result == sym;
3296 19287 : alternate_entry = sym->attr.function && sym->attr.entry
3297 1475434 : && sym->result == sym;
3298 2948590 : entry_master = sym->attr.result
3299 14555 : && sym->ns->proc_name->attr.entry_master
3300 1474676 : && !gfc_return_by_reference (sym->ns->proc_name);
3301 1474295 : if (current_function_decl)
3302 1456122 : parent_decl = DECL_CONTEXT (current_function_decl);
3303 :
3304 1474295 : if ((se->expr == parent_decl && return_value)
3305 1474184 : || (sym->ns && sym->ns->proc_name
3306 1469256 : && parent_decl
3307 1451083 : && sym->ns->proc_name->backend_decl == parent_decl
3308 38284 : && (alternate_entry || entry_master)))
3309 : parent_flag = 1;
3310 : else
3311 1474151 : parent_flag = 0;
3312 :
3313 : /* Special case for assigning the return value of a function.
3314 : Self recursive functions must have an explicit return value. */
3315 1474295 : if (return_value && (se->expr == current_function_decl || parent_flag))
3316 10408 : se_expr = gfc_get_fake_result_decl (sym, parent_flag);
3317 :
3318 : /* Similarly for alternate entry points. */
3319 1463887 : else if (alternate_entry
3320 1106 : && (sym->ns->proc_name->backend_decl == current_function_decl
3321 0 : || parent_flag))
3322 : {
3323 1106 : gfc_entry_list *el = NULL;
3324 :
3325 1705 : for (el = sym->ns->entries; el; el = el->next)
3326 1705 : if (sym == el->sym)
3327 : {
3328 1106 : se_expr = gfc_get_fake_result_decl (sym, parent_flag);
3329 1106 : break;
3330 : }
3331 : }
3332 :
3333 1462781 : else if (entry_master
3334 295 : && (sym->ns->proc_name->backend_decl == current_function_decl
3335 0 : || parent_flag))
3336 295 : se_expr = gfc_get_fake_result_decl (sym, parent_flag);
3337 :
3338 11809 : if (se_expr)
3339 11809 : se->expr = se_expr;
3340 :
3341 : /* Procedure actual arguments. Look out for temporary variables
3342 : with the same attributes as function values. */
3343 1462486 : else if (!sym->attr.temporary
3344 1462418 : && sym->attr.flavor == FL_PROCEDURE
3345 21748 : && se->expr != current_function_decl)
3346 : {
3347 21681 : if (!sym->attr.dummy && !sym->attr.proc_pointer)
3348 : {
3349 19969 : gcc_assert (TREE_CODE (se->expr) == FUNCTION_DECL);
3350 19969 : se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
3351 : }
3352 21681 : return;
3353 : }
3354 :
3355 1452614 : if (sym->ts.type == BT_CLASS
3356 72588 : && sym->attr.class_ok
3357 72346 : && sym->ts.u.derived->attr.is_class)
3358 : {
3359 28075 : if (is_classarray && DECL_LANG_SPECIFIC (se->expr)
3360 79844 : && GFC_DECL_SAVED_DESCRIPTOR (se->expr))
3361 5485 : se->class_container = GFC_DECL_SAVED_DESCRIPTOR (se->expr);
3362 : else
3363 66861 : se->class_container = se->expr;
3364 : }
3365 :
3366 : /* Dereference the expression, where needed. */
3367 1452614 : if (se->class_container && CLASS_DATA (sym)->attr.codimension
3368 2042 : && !CLASS_DATA (sym)->attr.dimension)
3369 877 : se->expr
3370 877 : = gfc_maybe_dereference_var (sym, se->class_container,
3371 877 : se->descriptor_only, is_classarray);
3372 : else
3373 1451737 : se->expr
3374 1451737 : = gfc_maybe_dereference_var (sym, se->expr, se->descriptor_only,
3375 : is_classarray);
3376 :
3377 1452614 : ref = expr->ref;
3378 : }
3379 :
3380 : /* For character variables, also get the length. */
3381 1585957 : if (sym->ts.type == BT_CHARACTER)
3382 : {
3383 : /* If the character length of an entry isn't set, get the length from
3384 : the master function instead. */
3385 166501 : if (sym->attr.entry && !sym->ts.u.cl->backend_decl)
3386 0 : se->string_length = sym->ns->proc_name->ts.u.cl->backend_decl;
3387 : else
3388 166501 : se->string_length = sym->ts.u.cl->backend_decl;
3389 166501 : gcc_assert (se->string_length);
3390 :
3391 : /* For coarray strings return the pointer to the data and not the
3392 : descriptor. */
3393 5143 : if (sym->attr.codimension && sym->attr.associate_var
3394 6 : && !se->descriptor_only
3395 166507 : && TREE_CODE (TREE_TYPE (se->expr)) != ARRAY_TYPE)
3396 6 : se->expr = gfc_conv_descriptor_data_get (se->expr);
3397 : }
3398 :
3399 : /* F202Y: Runtime warning that an assumed rank object is associated
3400 : with an assumed size object. */
3401 1585957 : if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
3402 90708 : && (gfc_option.allow_std & GFC_STD_F202Y)
3403 1586191 : && expr->rank == -1 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se->expr)))
3404 : {
3405 60 : tree dim, lower, upper, cond;
3406 60 : char *msg;
3407 :
3408 60 : dim = fold_convert (gfc_array_dim_rank_type,
3409 : gfc_conv_descriptor_rank (se->expr));
3410 60 : dim = fold_build2_loc (input_location, MINUS_EXPR,
3411 : gfc_array_dim_rank_type, dim, gfc_rank_cst[1]);
3412 60 : lower = gfc_conv_descriptor_lbound_get (se->expr, dim);
3413 60 : upper = gfc_conv_descriptor_ubound_get (se->expr, dim);
3414 :
3415 60 : msg = xasprintf ("Assumed rank object %s is associated with an "
3416 : "assumed size object", sym->name);
3417 60 : cond = fold_build2_loc (input_location, LT_EXPR,
3418 : logical_type_node, upper, lower);
3419 60 : gfc_trans_runtime_check (false, true, cond, &se->pre,
3420 : &gfc_current_locus, msg);
3421 60 : free (msg);
3422 : }
3423 :
3424 : /* Some expressions leak through that haven't been fixed up. */
3425 1585957 : if (IS_INFERRED_TYPE (expr) && expr->ref)
3426 418 : gfc_fixup_inferred_type_refs (expr);
3427 :
3428 1585957 : gfc_typespec *ts = &sym->ts;
3429 2022096 : while (ref)
3430 : {
3431 786869 : switch (ref->type)
3432 : {
3433 612363 : case REF_ARRAY:
3434 : /* Return the descriptor if that's what we want and this is an array
3435 : section reference. */
3436 612363 : if (se->descriptor_only && ref->u.ar.type != AR_ELEMENT)
3437 : return;
3438 : /* TODO: Pointers to single elements of array sections, eg elemental subs. */
3439 : /* Return the descriptor for array pointers and allocations. */
3440 271018 : if (se->want_pointer
3441 24082 : && ref->next == NULL && (se->descriptor_only))
3442 : return;
3443 :
3444 261633 : gfc_conv_array_ref (se, &ref->u.ar, expr, &expr->where);
3445 : /* Return a pointer to an element. */
3446 261633 : break;
3447 :
3448 166915 : case REF_COMPONENT:
3449 166915 : ts = &ref->u.c.component->ts;
3450 166915 : if (first_time && IS_CLASS_ARRAY (sym) && sym->attr.dummy
3451 5835 : && se->descriptor_only && !CLASS_DATA (sym)->attr.allocatable
3452 3142 : && !CLASS_DATA (sym)->attr.class_pointer && CLASS_DATA (sym)->as
3453 3142 : && CLASS_DATA (sym)->as->type != AS_ASSUMED_RANK
3454 2621 : && strcmp ("_data", ref->u.c.component->name) == 0)
3455 : /* Skip the first ref of a _data component, because for class
3456 : arrays that one is already done by introducing a temporary
3457 : array descriptor. */
3458 : break;
3459 :
3460 164294 : if (ref->u.c.sym->attr.extension)
3461 53762 : conv_parent_component_references (se, ref);
3462 :
3463 164294 : gfc_conv_component_ref (se, ref);
3464 :
3465 164294 : if (ref->u.c.component->ts.type == BT_CLASS
3466 12023 : && ref->u.c.component->attr.class_ok
3467 12023 : && ref->u.c.component->ts.u.derived->attr.is_class)
3468 12023 : se->class_container = se->expr;
3469 152271 : else if (!(ref->u.c.sym->attr.flavor == FL_DERIVED
3470 149777 : && ref->u.c.sym->attr.is_class))
3471 84140 : se->class_container = NULL_TREE;
3472 :
3473 164294 : if (!ref->next && ref->u.c.sym->attr.codimension
3474 0 : && se->want_pointer && se->descriptor_only)
3475 : return;
3476 :
3477 : break;
3478 :
3479 7042 : case REF_SUBSTRING:
3480 7042 : gfc_conv_substring (se, ref, expr->ts.kind,
3481 7042 : expr->symtree->name, &expr->where);
3482 7042 : break;
3483 :
3484 549 : case REF_INQUIRY:
3485 549 : conv_inquiry (se, ref, expr, ts);
3486 549 : break;
3487 :
3488 0 : default:
3489 0 : gcc_unreachable ();
3490 436139 : break;
3491 : }
3492 436139 : first_time = false;
3493 436139 : ref = ref->next;
3494 : }
3495 : /* Pointer assignment, allocation or pass by reference. Arrays are handled
3496 : separately. */
3497 1235227 : if (se->want_pointer)
3498 : {
3499 133402 : if (expr->ts.type == BT_CHARACTER && !gfc_is_proc_ptr_comp (expr))
3500 8044 : gfc_conv_string_parameter (se);
3501 : else
3502 125358 : se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
3503 : }
3504 : }
3505 :
3506 :
3507 : /* Unary ops are easy... Or they would be if ! was a valid op. */
3508 :
3509 : static void
3510 28853 : gfc_conv_unary_op (enum tree_code code, gfc_se * se, gfc_expr * expr)
3511 : {
3512 28853 : gfc_se operand;
3513 28853 : tree type;
3514 :
3515 28853 : gcc_assert (expr->ts.type != BT_CHARACTER);
3516 : /* Initialize the operand. */
3517 28853 : gfc_init_se (&operand, se);
3518 28853 : gfc_conv_expr_val (&operand, expr->value.op.op1);
3519 28853 : gfc_add_block_to_block (&se->pre, &operand.pre);
3520 :
3521 28853 : type = gfc_typenode_for_spec (&expr->ts);
3522 :
3523 : /* TRUTH_NOT_EXPR is not a "true" unary operator in GCC.
3524 : We must convert it to a compare to 0 (e.g. EQ_EXPR (op1, 0)).
3525 : All other unary operators have an equivalent GIMPLE unary operator. */
3526 28853 : if (code == TRUTH_NOT_EXPR)
3527 20250 : se->expr = fold_build2_loc (input_location, EQ_EXPR, type, operand.expr,
3528 : build_int_cst (type, 0));
3529 : else
3530 8603 : se->expr = fold_build1_loc (input_location, code, type, operand.expr);
3531 :
3532 28853 : }
3533 :
3534 : /* Expand power operator to optimal multiplications when a value is raised
3535 : to a constant integer n. See section 4.6.3, "Evaluation of Powers" of
3536 : Donald E. Knuth, "Seminumerical Algorithms", Vol. 2, "The Art of Computer
3537 : Programming", 3rd Edition, 1998. */
3538 :
3539 : /* This code is mostly duplicated from expand_powi in the backend.
3540 : We establish the "optimal power tree" lookup table with the defined size.
3541 : The items in the table are the exponents used to calculate the index
3542 : exponents. Any integer n less than the value can get an "addition chain",
3543 : with the first node being one. */
3544 : #define POWI_TABLE_SIZE 256
3545 :
3546 : /* The table is from builtins.cc. */
3547 : static const unsigned char powi_table[POWI_TABLE_SIZE] =
3548 : {
3549 : 0, 1, 1, 2, 2, 3, 3, 4, /* 0 - 7 */
3550 : 4, 6, 5, 6, 6, 10, 7, 9, /* 8 - 15 */
3551 : 8, 16, 9, 16, 10, 12, 11, 13, /* 16 - 23 */
3552 : 12, 17, 13, 18, 14, 24, 15, 26, /* 24 - 31 */
3553 : 16, 17, 17, 19, 18, 33, 19, 26, /* 32 - 39 */
3554 : 20, 25, 21, 40, 22, 27, 23, 44, /* 40 - 47 */
3555 : 24, 32, 25, 34, 26, 29, 27, 44, /* 48 - 55 */
3556 : 28, 31, 29, 34, 30, 60, 31, 36, /* 56 - 63 */
3557 : 32, 64, 33, 34, 34, 46, 35, 37, /* 64 - 71 */
3558 : 36, 65, 37, 50, 38, 48, 39, 69, /* 72 - 79 */
3559 : 40, 49, 41, 43, 42, 51, 43, 58, /* 80 - 87 */
3560 : 44, 64, 45, 47, 46, 59, 47, 76, /* 88 - 95 */
3561 : 48, 65, 49, 66, 50, 67, 51, 66, /* 96 - 103 */
3562 : 52, 70, 53, 74, 54, 104, 55, 74, /* 104 - 111 */
3563 : 56, 64, 57, 69, 58, 78, 59, 68, /* 112 - 119 */
3564 : 60, 61, 61, 80, 62, 75, 63, 68, /* 120 - 127 */
3565 : 64, 65, 65, 128, 66, 129, 67, 90, /* 128 - 135 */
3566 : 68, 73, 69, 131, 70, 94, 71, 88, /* 136 - 143 */
3567 : 72, 128, 73, 98, 74, 132, 75, 121, /* 144 - 151 */
3568 : 76, 102, 77, 124, 78, 132, 79, 106, /* 152 - 159 */
3569 : 80, 97, 81, 160, 82, 99, 83, 134, /* 160 - 167 */
3570 : 84, 86, 85, 95, 86, 160, 87, 100, /* 168 - 175 */
3571 : 88, 113, 89, 98, 90, 107, 91, 122, /* 176 - 183 */
3572 : 92, 111, 93, 102, 94, 126, 95, 150, /* 184 - 191 */
3573 : 96, 128, 97, 130, 98, 133, 99, 195, /* 192 - 199 */
3574 : 100, 128, 101, 123, 102, 164, 103, 138, /* 200 - 207 */
3575 : 104, 145, 105, 146, 106, 109, 107, 149, /* 208 - 215 */
3576 : 108, 200, 109, 146, 110, 170, 111, 157, /* 216 - 223 */
3577 : 112, 128, 113, 130, 114, 182, 115, 132, /* 224 - 231 */
3578 : 116, 200, 117, 132, 118, 158, 119, 206, /* 232 - 239 */
3579 : 120, 240, 121, 162, 122, 147, 123, 152, /* 240 - 247 */
3580 : 124, 166, 125, 214, 126, 138, 127, 153, /* 248 - 255 */
3581 : };
3582 :
3583 : /* If n is larger than lookup table's max index, we use the "window
3584 : method". */
3585 : #define POWI_WINDOW_SIZE 3
3586 :
3587 : /* Recursive function to expand the power operator. The temporary
3588 : values are put in tmpvar. The function returns tmpvar[1] ** n. */
3589 : static tree
3590 178323 : gfc_conv_powi (gfc_se * se, unsigned HOST_WIDE_INT n, tree * tmpvar)
3591 : {
3592 178323 : tree op0;
3593 178323 : tree op1;
3594 178323 : tree tmp;
3595 178323 : int digit;
3596 :
3597 178323 : if (n < POWI_TABLE_SIZE)
3598 : {
3599 137336 : if (tmpvar[n])
3600 : return tmpvar[n];
3601 :
3602 56612 : op0 = gfc_conv_powi (se, n - powi_table[n], tmpvar);
3603 56612 : op1 = gfc_conv_powi (se, powi_table[n], tmpvar);
3604 : }
3605 40987 : else if (n & 1)
3606 : {
3607 10015 : digit = n & ((1 << POWI_WINDOW_SIZE) - 1);
3608 10015 : op0 = gfc_conv_powi (se, n - digit, tmpvar);
3609 10015 : op1 = gfc_conv_powi (se, digit, tmpvar);
3610 : }
3611 : else
3612 : {
3613 30972 : op0 = gfc_conv_powi (se, n >> 1, tmpvar);
3614 30972 : op1 = op0;
3615 : }
3616 :
3617 97599 : tmp = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (op0), op0, op1);
3618 97599 : tmp = gfc_evaluate_now (tmp, &se->pre);
3619 :
3620 97599 : if (n < POWI_TABLE_SIZE)
3621 56612 : tmpvar[n] = tmp;
3622 :
3623 : return tmp;
3624 : }
3625 :
3626 :
3627 : /* Expand lhs ** rhs. rhs is a constant integer. If it expands successfully,
3628 : return 1. Else return 0 and a call to runtime library functions
3629 : will have to be built. */
3630 : static int
3631 3305 : gfc_conv_cst_int_power (gfc_se * se, tree lhs, tree rhs)
3632 : {
3633 3305 : tree cond;
3634 3305 : tree tmp;
3635 3305 : tree type;
3636 3305 : tree vartmp[POWI_TABLE_SIZE];
3637 3305 : HOST_WIDE_INT m;
3638 3305 : unsigned HOST_WIDE_INT n;
3639 3305 : int sgn;
3640 3305 : wi::tree_to_wide_ref wrhs = wi::to_wide (rhs);
3641 :
3642 : /* If exponent is too large, we won't expand it anyway, so don't bother
3643 : with large integer values. */
3644 3305 : if (!wi::fits_shwi_p (wrhs))
3645 : return 0;
3646 :
3647 2945 : m = wrhs.to_shwi ();
3648 : /* Use the wide_int's routine to reliably get the absolute value on all
3649 : platforms. Then convert it to a HOST_WIDE_INT like above. */
3650 2945 : n = wi::abs (wrhs).to_shwi ();
3651 :
3652 2945 : type = TREE_TYPE (lhs);
3653 2945 : sgn = tree_int_cst_sgn (rhs);
3654 :
3655 2945 : if (((FLOAT_TYPE_P (type) && !flag_unsafe_math_optimizations)
3656 5890 : || optimize_size) && (m > 2 || m < -1))
3657 : return 0;
3658 :
3659 : /* rhs == 0 */
3660 1639 : if (sgn == 0)
3661 : {
3662 282 : se->expr = gfc_build_const (type, integer_one_node);
3663 282 : return 1;
3664 : }
3665 :
3666 : /* If rhs < 0 and lhs is an integer, the result is -1, 0 or 1. */
3667 1357 : if ((sgn == -1) && (TREE_CODE (type) == INTEGER_TYPE))
3668 : {
3669 220 : tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
3670 220 : lhs, build_int_cst (TREE_TYPE (lhs), -1));
3671 220 : cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
3672 220 : lhs, build_int_cst (TREE_TYPE (lhs), 1));
3673 :
3674 : /* If rhs is even,
3675 : result = (lhs == 1 || lhs == -1) ? 1 : 0. */
3676 220 : if ((n & 1) == 0)
3677 : {
3678 104 : tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR,
3679 : logical_type_node, tmp, cond);
3680 104 : se->expr = fold_build3_loc (input_location, COND_EXPR, type,
3681 : tmp, build_int_cst (type, 1),
3682 : build_int_cst (type, 0));
3683 104 : return 1;
3684 : }
3685 : /* If rhs is odd,
3686 : result = (lhs == 1) ? 1 : (lhs == -1) ? -1 : 0. */
3687 116 : tmp = fold_build3_loc (input_location, COND_EXPR, type, tmp,
3688 : build_int_cst (type, -1),
3689 : build_int_cst (type, 0));
3690 116 : se->expr = fold_build3_loc (input_location, COND_EXPR, type,
3691 : cond, build_int_cst (type, 1), tmp);
3692 116 : return 1;
3693 : }
3694 :
3695 1137 : memset (vartmp, 0, sizeof (vartmp));
3696 1137 : vartmp[1] = lhs;
3697 1137 : if (sgn == -1)
3698 : {
3699 141 : tmp = gfc_build_const (type, integer_one_node);
3700 141 : vartmp[1] = fold_build2_loc (input_location, RDIV_EXPR, type, tmp,
3701 : vartmp[1]);
3702 : }
3703 :
3704 1137 : se->expr = gfc_conv_powi (se, n, vartmp);
3705 :
3706 1137 : return 1;
3707 : }
3708 :
3709 : /* Convert lhs**rhs, for constant rhs, when both are unsigned.
3710 : Method:
3711 : if (rhs == 0) ! Checked here.
3712 : return 1;
3713 : if (lhs & 1 == 1) ! odd_cnd
3714 : {
3715 : if (bit_size(rhs) < bit_size(lhs)) ! Checked here.
3716 : return lhs ** rhs;
3717 :
3718 : mask = 1 << (bit_size(a) - 1) / 2;
3719 : return lhs ** (n & rhs);
3720 : }
3721 : if (rhs > bit_size(lhs)) ! Checked here.
3722 : return 0;
3723 :
3724 : return lhs ** rhs;
3725 : */
3726 :
3727 : static int
3728 15120 : gfc_conv_cst_uint_power (gfc_se * se, tree lhs, tree rhs)
3729 : {
3730 15120 : tree type = TREE_TYPE (lhs);
3731 15120 : tree tmp, is_odd, odd_branch, even_branch;
3732 15120 : unsigned HOST_WIDE_INT lhs_prec, rhs_prec;
3733 15120 : wi::tree_to_wide_ref wrhs = wi::to_wide (rhs);
3734 15120 : unsigned HOST_WIDE_INT n, n_odd;
3735 15120 : tree vartmp_odd[POWI_TABLE_SIZE], vartmp_even[POWI_TABLE_SIZE];
3736 :
3737 : /* Anything ** 0 is one. */
3738 15120 : if (integer_zerop (rhs))
3739 : {
3740 1800 : se->expr = build_int_cst (type, 1);
3741 1800 : return 1;
3742 : }
3743 :
3744 13320 : if (!wi::fits_uhwi_p (wrhs))
3745 : return 0;
3746 :
3747 12960 : n = wrhs.to_uhwi ();
3748 :
3749 : /* tmp = a & 1; . */
3750 12960 : tmp = fold_build2_loc (input_location, BIT_AND_EXPR, type,
3751 : lhs, build_int_cst (type, 1));
3752 12960 : is_odd = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
3753 : tmp, build_int_cst (type, 1));
3754 :
3755 12960 : lhs_prec = TYPE_PRECISION (type);
3756 12960 : rhs_prec = TYPE_PRECISION (TREE_TYPE (rhs));
3757 :
3758 12960 : if (rhs_prec >= lhs_prec && lhs_prec <= HOST_BITS_PER_WIDE_INT)
3759 : {
3760 7044 : unsigned HOST_WIDE_INT mask = (HOST_WIDE_INT_1U << (lhs_prec - 1)) - 1;
3761 7044 : n_odd = n & mask;
3762 : }
3763 : else
3764 : n_odd = n;
3765 :
3766 12960 : memset (vartmp_odd, 0, sizeof (vartmp_odd));
3767 12960 : vartmp_odd[0] = build_int_cst (type, 1);
3768 12960 : vartmp_odd[1] = lhs;
3769 12960 : odd_branch = gfc_conv_powi (se, n_odd, vartmp_odd);
3770 12960 : even_branch = NULL_TREE;
3771 :
3772 12960 : if (n > lhs_prec)
3773 4260 : even_branch = build_int_cst (type, 0);
3774 : else
3775 : {
3776 8700 : if (n_odd != n)
3777 : {
3778 0 : memset (vartmp_even, 0, sizeof (vartmp_even));
3779 0 : vartmp_even[0] = build_int_cst (type, 1);
3780 0 : vartmp_even[1] = lhs;
3781 0 : even_branch = gfc_conv_powi (se, n, vartmp_even);
3782 : }
3783 : }
3784 4260 : if (even_branch != NULL_TREE)
3785 4260 : se->expr = fold_build3_loc (input_location, COND_EXPR, type, is_odd,
3786 : odd_branch, even_branch);
3787 : else
3788 8700 : se->expr = odd_branch;
3789 :
3790 : return 1;
3791 : }
3792 :
3793 : /* Power op (**). Constant integer exponent and powers of 2 have special
3794 : handling. */
3795 :
3796 : static void
3797 49177 : gfc_conv_power_op (gfc_se * se, gfc_expr * expr)
3798 : {
3799 49177 : tree gfc_int4_type_node;
3800 49177 : int kind;
3801 49177 : int ikind;
3802 49177 : int res_ikind_1, res_ikind_2;
3803 49177 : gfc_se lse;
3804 49177 : gfc_se rse;
3805 49177 : tree fndecl = NULL;
3806 :
3807 49177 : gfc_init_se (&lse, se);
3808 49177 : gfc_conv_expr_val (&lse, expr->value.op.op1);
3809 49177 : lse.expr = gfc_evaluate_now (lse.expr, &lse.pre);
3810 49177 : gfc_add_block_to_block (&se->pre, &lse.pre);
3811 :
3812 49177 : gfc_init_se (&rse, se);
3813 49177 : gfc_conv_expr_val (&rse, expr->value.op.op2);
3814 49177 : gfc_add_block_to_block (&se->pre, &rse.pre);
3815 :
3816 49177 : if (expr->value.op.op2->expr_type == EXPR_CONSTANT)
3817 : {
3818 17563 : if (expr->value.op.op2->ts.type == BT_INTEGER)
3819 : {
3820 2292 : if (gfc_conv_cst_int_power (se, lse.expr, rse.expr))
3821 20477 : return;
3822 : }
3823 15271 : else if (expr->value.op.op2->ts.type == BT_UNSIGNED)
3824 : {
3825 15120 : if (gfc_conv_cst_uint_power (se, lse.expr, rse.expr))
3826 : return;
3827 : }
3828 : }
3829 :
3830 32778 : if ((expr->value.op.op2->ts.type == BT_INTEGER
3831 31468 : || expr->value.op.op2->ts.type == BT_UNSIGNED)
3832 31910 : && expr->value.op.op2->expr_type == EXPR_CONSTANT)
3833 1013 : if (gfc_conv_cst_int_power (se, lse.expr, rse.expr))
3834 : return;
3835 :
3836 32778 : if (INTEGER_CST_P (lse.expr)
3837 15371 : && TREE_CODE (TREE_TYPE (rse.expr)) == INTEGER_TYPE
3838 48149 : && expr->value.op.op2->ts.type == BT_INTEGER)
3839 : {
3840 251 : wi::tree_to_wide_ref wlhs = wi::to_wide (lse.expr);
3841 251 : HOST_WIDE_INT v;
3842 251 : unsigned HOST_WIDE_INT w;
3843 251 : int kind, ikind, bit_size;
3844 :
3845 251 : v = wlhs.to_shwi ();
3846 251 : w = absu_hwi (v);
3847 :
3848 251 : kind = expr->value.op.op1->ts.kind;
3849 251 : ikind = gfc_validate_kind (BT_INTEGER, kind, false);
3850 251 : bit_size = gfc_integer_kinds[ikind].bit_size;
3851 :
3852 251 : if (v == 1)
3853 : {
3854 : /* 1**something is always 1. */
3855 35 : se->expr = build_int_cst (TREE_TYPE (lse.expr), 1);
3856 239 : return;
3857 : }
3858 216 : else if (v == -1)
3859 : {
3860 : /* (-1)**n is 1 - ((n & 1) << 1) */
3861 34 : tree type;
3862 34 : tree tmp;
3863 :
3864 34 : type = TREE_TYPE (lse.expr);
3865 34 : tmp = fold_build2_loc (input_location, BIT_AND_EXPR, type,
3866 : rse.expr, build_int_cst (type, 1));
3867 34 : tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
3868 : tmp, build_int_cst (type, 1));
3869 34 : tmp = fold_build2_loc (input_location, MINUS_EXPR, type,
3870 : build_int_cst (type, 1), tmp);
3871 34 : se->expr = tmp;
3872 34 : return;
3873 : }
3874 182 : else if (w > 0 && ((w & (w-1)) == 0) && ((w >> (bit_size-1)) == 0))
3875 : {
3876 : /* Here v is +/- 2**e. The further simplification uses
3877 : 2**n = 1<<n, 4**n = 1<<(n+n), 8**n = 1 <<(3*n), 16**n =
3878 : 1<<(4*n), etc., but we have to make sure to return zero
3879 : if the number of bits is too large. */
3880 170 : tree lshift;
3881 170 : tree type;
3882 170 : tree shift;
3883 170 : tree ge;
3884 170 : tree cond;
3885 170 : tree num_bits;
3886 170 : tree cond2;
3887 170 : tree tmp1;
3888 :
3889 170 : type = TREE_TYPE (lse.expr);
3890 :
3891 170 : if (w == 2)
3892 110 : shift = rse.expr;
3893 60 : else if (w == 4)
3894 12 : shift = fold_build2_loc (input_location, PLUS_EXPR,
3895 12 : TREE_TYPE (rse.expr),
3896 : rse.expr, rse.expr);
3897 : else
3898 : {
3899 : /* use popcount for fast log2(w) */
3900 48 : int e = wi::popcount (w-1);
3901 96 : shift = fold_build2_loc (input_location, MULT_EXPR,
3902 48 : TREE_TYPE (rse.expr),
3903 48 : build_int_cst (TREE_TYPE (rse.expr), e),
3904 : rse.expr);
3905 : }
3906 :
3907 170 : lshift = fold_build2_loc (input_location, LSHIFT_EXPR, type,
3908 : build_int_cst (type, 1), shift);
3909 170 : ge = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
3910 : rse.expr, build_int_cst (type, 0));
3911 170 : cond = fold_build3_loc (input_location, COND_EXPR, type, ge, lshift,
3912 : build_int_cst (type, 0));
3913 170 : num_bits = build_int_cst (TREE_TYPE (rse.expr), TYPE_PRECISION (type));
3914 170 : cond2 = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
3915 : rse.expr, num_bits);
3916 170 : tmp1 = fold_build3_loc (input_location, COND_EXPR, type, cond2,
3917 : build_int_cst (type, 0), cond);
3918 170 : if (v > 0)
3919 : {
3920 128 : se->expr = tmp1;
3921 : }
3922 : else
3923 : {
3924 : /* for v < 0, calculate v**n = |v|**n * (-1)**n */
3925 42 : tree tmp2;
3926 42 : tmp2 = fold_build2_loc (input_location, BIT_AND_EXPR, type,
3927 : rse.expr, build_int_cst (type, 1));
3928 42 : tmp2 = fold_build2_loc (input_location, LSHIFT_EXPR, type,
3929 : tmp2, build_int_cst (type, 1));
3930 42 : tmp2 = fold_build2_loc (input_location, MINUS_EXPR, type,
3931 : build_int_cst (type, 1), tmp2);
3932 42 : se->expr = fold_build2_loc (input_location, MULT_EXPR, type,
3933 : tmp1, tmp2);
3934 : }
3935 170 : return;
3936 : }
3937 : }
3938 : /* Handle unsigned separate from signed above, things would be too
3939 : complicated otherwise. */
3940 :
3941 32539 : if (INTEGER_CST_P (lse.expr) && expr->value.op.op1->ts.type == BT_UNSIGNED)
3942 : {
3943 15120 : gfc_expr * op1 = expr->value.op.op1;
3944 15120 : tree type;
3945 :
3946 15120 : type = TREE_TYPE (lse.expr);
3947 :
3948 15120 : if (mpz_cmp_ui (op1->value.integer, 1) == 0)
3949 : {
3950 : /* 1**something is always 1. */
3951 1260 : se->expr = build_int_cst (type, 1);
3952 1260 : return;
3953 : }
3954 :
3955 : /* Simplify 2u**x to a shift, with the value set to zero if it falls
3956 : outside the range. */
3957 26460 : if (mpz_popcount (op1->value.integer) == 1)
3958 : {
3959 2520 : tree prec_m1, lim, shift, lshift, cond, tmp;
3960 2520 : tree rtype = TREE_TYPE (rse.expr);
3961 2520 : int e = mpz_scan1 (op1->value.integer, 0);
3962 :
3963 2520 : shift = fold_build2_loc (input_location, MULT_EXPR,
3964 2520 : rtype, build_int_cst (rtype, e),
3965 : rse.expr);
3966 2520 : lshift = fold_build2_loc (input_location, LSHIFT_EXPR, type,
3967 : build_int_cst (type, 1), shift);
3968 5040 : prec_m1 = fold_build2_loc (input_location, MINUS_EXPR, rtype,
3969 2520 : build_int_cst (rtype, TYPE_PRECISION (type)),
3970 : build_int_cst (rtype, 1));
3971 2520 : lim = fold_build2_loc (input_location, TRUNC_DIV_EXPR, rtype,
3972 2520 : prec_m1, build_int_cst (rtype, e));
3973 2520 : cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3974 : rse.expr, lim);
3975 2520 : tmp = fold_build3_loc (input_location, COND_EXPR, type, cond,
3976 : build_int_cst (type, 0), lshift);
3977 2520 : se->expr = tmp;
3978 2520 : return;
3979 : }
3980 : }
3981 :
3982 28759 : gfc_int4_type_node = gfc_get_int_type (4);
3983 :
3984 : /* In case of integer operands with kinds 1 or 2, we call the integer kind 4
3985 : library routine. But in the end, we have to convert the result back
3986 : if this case applies -- with res_ikind_K, we keep track whether operand K
3987 : falls into this case. */
3988 28759 : res_ikind_1 = -1;
3989 28759 : res_ikind_2 = -1;
3990 :
3991 28759 : kind = expr->value.op.op1->ts.kind;
3992 28759 : switch (expr->value.op.op2->ts.type)
3993 : {
3994 1071 : case BT_INTEGER:
3995 1071 : ikind = expr->value.op.op2->ts.kind;
3996 1071 : switch (ikind)
3997 : {
3998 168 : case 1:
3999 168 : case 2:
4000 168 : rse.expr = convert (gfc_int4_type_node, rse.expr);
4001 168 : res_ikind_2 = ikind;
4002 : /* Fall through. */
4003 :
4004 : case 4:
4005 : ikind = 0;
4006 : break;
4007 :
4008 : case 8:
4009 : ikind = 1;
4010 : break;
4011 :
4012 6 : case 16:
4013 6 : ikind = 2;
4014 6 : break;
4015 :
4016 0 : default:
4017 0 : gcc_unreachable ();
4018 : }
4019 1071 : switch (kind)
4020 : {
4021 0 : case 1:
4022 0 : case 2:
4023 0 : if (expr->value.op.op1->ts.type == BT_INTEGER)
4024 : {
4025 0 : lse.expr = convert (gfc_int4_type_node, lse.expr);
4026 0 : res_ikind_1 = kind;
4027 : }
4028 : else
4029 0 : gcc_unreachable ();
4030 : /* Fall through. */
4031 :
4032 : case 4:
4033 : kind = 0;
4034 : break;
4035 :
4036 : case 8:
4037 : kind = 1;
4038 : break;
4039 :
4040 6 : case 10:
4041 6 : kind = 2;
4042 6 : break;
4043 :
4044 18 : case 16:
4045 18 : kind = 3;
4046 18 : break;
4047 :
4048 0 : default:
4049 0 : gcc_unreachable ();
4050 : }
4051 :
4052 1071 : switch (expr->value.op.op1->ts.type)
4053 : {
4054 129 : case BT_INTEGER:
4055 129 : if (kind == 3) /* Case 16 was not handled properly above. */
4056 : kind = 2;
4057 129 : fndecl = gfor_fndecl_math_powi[kind][ikind].integer;
4058 129 : break;
4059 :
4060 710 : case BT_REAL:
4061 : /* Use builtins for real ** int4. */
4062 :
4063 710 : if (real_minus_onep (lse.expr))
4064 : {
4065 : /* (-1.0)**n is (real) (1 - ((n & 1) << 1)), see the integer case
4066 : above. */
4067 :
4068 59 : tree lhs_type, rhs_type;
4069 59 : tree tmp;
4070 59 : lhs_type = TREE_TYPE (lse.expr);
4071 59 : rhs_type = TREE_TYPE (rse.expr);
4072 59 : tmp = fold_build2_loc (input_location, BIT_AND_EXPR, rhs_type,
4073 : rse.expr, build_int_cst (rhs_type, 1));
4074 59 : tmp = fold_build2_loc (input_location, LSHIFT_EXPR, rhs_type,
4075 : tmp, build_int_cst (rhs_type, 1));
4076 59 : tmp = fold_build2_loc (input_location, MINUS_EXPR, rhs_type,
4077 : build_int_cst (rhs_type, 1), tmp);
4078 59 : se->expr = fold_convert (lhs_type, tmp);
4079 59 : return;
4080 : }
4081 :
4082 651 : if (ikind == 0)
4083 : {
4084 555 : switch (kind)
4085 : {
4086 391 : case 0:
4087 391 : fndecl = builtin_decl_explicit (BUILT_IN_POWIF);
4088 391 : break;
4089 :
4090 146 : case 1:
4091 146 : fndecl = builtin_decl_explicit (BUILT_IN_POWI);
4092 146 : break;
4093 :
4094 6 : case 2:
4095 6 : fndecl = builtin_decl_explicit (BUILT_IN_POWIL);
4096 6 : break;
4097 :
4098 12 : case 3:
4099 : /* Use the __builtin_powil() only if real(kind=16) is
4100 : actually the C long double type. */
4101 12 : if (!gfc_real16_is_float128)
4102 0 : fndecl = builtin_decl_explicit (BUILT_IN_POWIL);
4103 : break;
4104 :
4105 : default:
4106 : gcc_unreachable ();
4107 : }
4108 : }
4109 :
4110 : /* If we don't have a good builtin for this, go for the
4111 : library function. */
4112 543 : if (!fndecl)
4113 108 : fndecl = gfor_fndecl_math_powi[kind][ikind].real;
4114 : break;
4115 :
4116 232 : case BT_COMPLEX:
4117 232 : fndecl = gfor_fndecl_math_powi[kind][ikind].cmplx;
4118 232 : break;
4119 :
4120 0 : default:
4121 0 : gcc_unreachable ();
4122 : }
4123 : break;
4124 :
4125 139 : case BT_REAL:
4126 139 : fndecl = gfc_builtin_decl_for_float_kind (BUILT_IN_POW, kind);
4127 139 : break;
4128 :
4129 729 : case BT_COMPLEX:
4130 729 : fndecl = gfc_builtin_decl_for_float_kind (BUILT_IN_CPOW, kind);
4131 729 : break;
4132 :
4133 26820 : case BT_UNSIGNED:
4134 26820 : {
4135 : /* Valid kinds for unsigned are 1, 2, 4, 8, 16. Instead of using a
4136 : large switch statement, let's just use __builtin_ctz. */
4137 26820 : int base = __builtin_ctz (expr->value.op.op1->ts.kind);
4138 26820 : int expon = __builtin_ctz (expr->value.op.op2->ts.kind);
4139 26820 : fndecl = gfor_fndecl_unsigned_pow_list[base][expon];
4140 : }
4141 26820 : break;
4142 :
4143 0 : default:
4144 0 : gcc_unreachable ();
4145 28700 : break;
4146 : }
4147 :
4148 28700 : se->expr = build_call_expr_loc (input_location,
4149 : fndecl, 2, lse.expr, rse.expr);
4150 :
4151 : /* Convert the result back if it is of wrong integer kind. */
4152 28700 : if (res_ikind_1 != -1 && res_ikind_2 != -1)
4153 : {
4154 : /* We want the maximum of both operand kinds as result. */
4155 0 : if (res_ikind_1 < res_ikind_2)
4156 0 : res_ikind_1 = res_ikind_2;
4157 0 : se->expr = convert (gfc_get_int_type (res_ikind_1), se->expr);
4158 : }
4159 : }
4160 :
4161 :
4162 : /* Generate code to allocate a string temporary. */
4163 :
4164 : tree
4165 4880 : gfc_conv_string_tmp (gfc_se * se, tree type, tree len)
4166 : {
4167 4880 : tree var;
4168 4880 : tree tmp;
4169 :
4170 4880 : if (gfc_can_put_var_on_stack (len))
4171 : {
4172 : /* Create a temporary variable to hold the result. */
4173 4586 : tmp = fold_build2_loc (input_location, MINUS_EXPR,
4174 2293 : TREE_TYPE (len), len,
4175 2293 : build_int_cst (TREE_TYPE (len), 1));
4176 2293 : tmp = build_range_type (gfc_charlen_type_node, size_zero_node, tmp);
4177 :
4178 2293 : if (TREE_CODE (TREE_TYPE (type)) == ARRAY_TYPE)
4179 2293 : tmp = build_array_type (TREE_TYPE (TREE_TYPE (type)), tmp);
4180 : else
4181 0 : tmp = build_array_type (TREE_TYPE (type), tmp);
4182 :
4183 2293 : var = gfc_create_var (tmp, "str");
4184 2293 : var = gfc_build_addr_expr (type, var);
4185 : }
4186 : else
4187 : {
4188 : /* Allocate a temporary to hold the result. */
4189 2587 : var = gfc_create_var (type, "pstr");
4190 2587 : gcc_assert (POINTER_TYPE_P (type));
4191 2587 : tmp = TREE_TYPE (type);
4192 2587 : if (TREE_CODE (tmp) == ARRAY_TYPE)
4193 2587 : tmp = TREE_TYPE (tmp);
4194 2587 : tmp = TYPE_SIZE_UNIT (tmp);
4195 2587 : tmp = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
4196 : fold_convert (size_type_node, len),
4197 : fold_convert (size_type_node, tmp));
4198 2587 : tmp = gfc_call_malloc (&se->pre, type, tmp);
4199 2587 : gfc_add_modify (&se->pre, var, tmp);
4200 :
4201 : /* Free the temporary afterwards. */
4202 2587 : tmp = gfc_call_free (var);
4203 2587 : gfc_add_expr_to_block (&se->post, tmp);
4204 : }
4205 :
4206 4880 : return var;
4207 : }
4208 :
4209 :
4210 : /* Handle a string concatenation operation. A temporary will be allocated to
4211 : hold the result. */
4212 :
4213 : static void
4214 1294 : gfc_conv_concat_op (gfc_se * se, gfc_expr * expr)
4215 : {
4216 1294 : gfc_se lse, rse;
4217 1294 : tree len, type, var, tmp, fndecl;
4218 :
4219 1294 : gcc_assert (expr->value.op.op1->ts.type == BT_CHARACTER
4220 : && expr->value.op.op2->ts.type == BT_CHARACTER);
4221 1294 : gcc_assert (expr->value.op.op1->ts.kind == expr->value.op.op2->ts.kind);
4222 :
4223 1294 : gfc_init_se (&lse, se);
4224 1294 : gfc_conv_expr (&lse, expr->value.op.op1);
4225 1294 : gfc_conv_string_parameter (&lse);
4226 1294 : gfc_init_se (&rse, se);
4227 1294 : gfc_conv_expr (&rse, expr->value.op.op2);
4228 1294 : gfc_conv_string_parameter (&rse);
4229 :
4230 1294 : gfc_add_block_to_block (&se->pre, &lse.pre);
4231 1294 : gfc_add_block_to_block (&se->pre, &rse.pre);
4232 :
4233 1294 : type = gfc_get_character_type (expr->ts.kind, expr->ts.u.cl);
4234 1294 : len = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
4235 1294 : if (len == NULL_TREE)
4236 : {
4237 1075 : len = fold_build2_loc (input_location, PLUS_EXPR,
4238 : gfc_charlen_type_node,
4239 : fold_convert (gfc_charlen_type_node,
4240 : lse.string_length),
4241 : fold_convert (gfc_charlen_type_node,
4242 : rse.string_length));
4243 : }
4244 :
4245 1294 : type = build_pointer_type (type);
4246 :
4247 1294 : var = gfc_conv_string_tmp (se, type, len);
4248 :
4249 : /* Do the actual concatenation. */
4250 1294 : if (expr->ts.kind == 1)
4251 1203 : fndecl = gfor_fndecl_concat_string;
4252 91 : else if (expr->ts.kind == 4)
4253 91 : fndecl = gfor_fndecl_concat_string_char4;
4254 : else
4255 0 : gcc_unreachable ();
4256 :
4257 1294 : tmp = build_call_expr_loc (input_location,
4258 : fndecl, 6, len, var, lse.string_length, lse.expr,
4259 : rse.string_length, rse.expr);
4260 1294 : gfc_add_expr_to_block (&se->pre, tmp);
4261 :
4262 : /* Add the cleanup for the operands. */
4263 1294 : gfc_add_block_to_block (&se->pre, &rse.post);
4264 1294 : gfc_add_block_to_block (&se->pre, &lse.post);
4265 :
4266 1294 : se->expr = var;
4267 1294 : se->string_length = len;
4268 1294 : }
4269 :
4270 : /* Translates an op expression. Common (binary) cases are handled by this
4271 : function, others are passed on. Recursion is used in either case.
4272 : We use the fact that (op1.ts == op2.ts) (except for the power
4273 : operator **).
4274 : Operators need no special handling for scalarized expressions as long as
4275 : they call gfc_conv_simple_val to get their operands.
4276 : Character strings get special handling. */
4277 :
4278 : static void
4279 506740 : gfc_conv_expr_op (gfc_se * se, gfc_expr * expr)
4280 : {
4281 506740 : enum tree_code code;
4282 506740 : gfc_se lse;
4283 506740 : gfc_se rse;
4284 506740 : tree tmp, type;
4285 506740 : int lop;
4286 506740 : int checkstring;
4287 :
4288 506740 : checkstring = 0;
4289 506740 : lop = 0;
4290 506740 : switch (expr->value.op.op)
4291 : {
4292 15088 : case INTRINSIC_PARENTHESES:
4293 15088 : if ((expr->ts.type == BT_REAL || expr->ts.type == BT_COMPLEX)
4294 3801 : && flag_protect_parens)
4295 : {
4296 3668 : gfc_conv_unary_op (PAREN_EXPR, se, expr);
4297 3668 : gcc_assert (FLOAT_TYPE_P (TREE_TYPE (se->expr)));
4298 90750 : return;
4299 : }
4300 :
4301 : /* Fallthrough. */
4302 11426 : case INTRINSIC_UPLUS:
4303 11426 : gfc_conv_expr (se, expr->value.op.op1);
4304 11426 : return;
4305 :
4306 4935 : case INTRINSIC_UMINUS:
4307 4935 : gfc_conv_unary_op (NEGATE_EXPR, se, expr);
4308 4935 : return;
4309 :
4310 20250 : case INTRINSIC_NOT:
4311 20250 : gfc_conv_unary_op (TRUTH_NOT_EXPR, se, expr);
4312 20250 : return;
4313 :
4314 : case INTRINSIC_PLUS:
4315 : code = PLUS_EXPR;
4316 : break;
4317 :
4318 29309 : case INTRINSIC_MINUS:
4319 29309 : code = MINUS_EXPR;
4320 29309 : break;
4321 :
4322 32934 : case INTRINSIC_TIMES:
4323 32934 : code = MULT_EXPR;
4324 32934 : break;
4325 :
4326 7011 : case INTRINSIC_DIVIDE:
4327 : /* If expr is a real or complex expr, use an RDIV_EXPR. If op1 is
4328 : an integer or unsigned, we must round towards zero, so we use a
4329 : TRUNC_DIV_EXPR. */
4330 7011 : if (expr->ts.type == BT_INTEGER || expr->ts.type == BT_UNSIGNED)
4331 : code = TRUNC_DIV_EXPR;
4332 : else
4333 415990 : code = RDIV_EXPR;
4334 : break;
4335 :
4336 49177 : case INTRINSIC_POWER:
4337 49177 : gfc_conv_power_op (se, expr);
4338 49177 : return;
4339 :
4340 1294 : case INTRINSIC_CONCAT:
4341 1294 : gfc_conv_concat_op (se, expr);
4342 1294 : return;
4343 :
4344 4684 : case INTRINSIC_AND:
4345 4684 : code = flag_frontend_optimize ? TRUTH_ANDIF_EXPR : TRUTH_AND_EXPR;
4346 : lop = 1;
4347 : break;
4348 :
4349 55716 : case INTRINSIC_OR:
4350 55716 : code = flag_frontend_optimize ? TRUTH_ORIF_EXPR : TRUTH_OR_EXPR;
4351 : lop = 1;
4352 : break;
4353 :
4354 : /* EQV and NEQV only work on logicals, but since we represent them
4355 : as integers, we can use EQ_EXPR and NE_EXPR for them in GIMPLE. */
4356 12393 : case INTRINSIC_EQ:
4357 12393 : case INTRINSIC_EQ_OS:
4358 12393 : case INTRINSIC_EQV:
4359 12393 : code = EQ_EXPR;
4360 12393 : checkstring = 1;
4361 12393 : lop = 1;
4362 12393 : break;
4363 :
4364 206976 : case INTRINSIC_NE:
4365 206976 : case INTRINSIC_NE_OS:
4366 206976 : case INTRINSIC_NEQV:
4367 206976 : code = NE_EXPR;
4368 206976 : checkstring = 1;
4369 206976 : lop = 1;
4370 206976 : break;
4371 :
4372 12021 : case INTRINSIC_GT:
4373 12021 : case INTRINSIC_GT_OS:
4374 12021 : code = GT_EXPR;
4375 12021 : checkstring = 1;
4376 12021 : lop = 1;
4377 12021 : break;
4378 :
4379 1671 : case INTRINSIC_GE:
4380 1671 : case INTRINSIC_GE_OS:
4381 1671 : code = GE_EXPR;
4382 1671 : checkstring = 1;
4383 1671 : lop = 1;
4384 1671 : break;
4385 :
4386 4355 : case INTRINSIC_LT:
4387 4355 : case INTRINSIC_LT_OS:
4388 4355 : code = LT_EXPR;
4389 4355 : checkstring = 1;
4390 4355 : lop = 1;
4391 4355 : break;
4392 :
4393 2604 : case INTRINSIC_LE:
4394 2604 : case INTRINSIC_LE_OS:
4395 2604 : code = LE_EXPR;
4396 2604 : checkstring = 1;
4397 2604 : lop = 1;
4398 2604 : break;
4399 :
4400 0 : case INTRINSIC_USER:
4401 0 : case INTRINSIC_ASSIGN:
4402 : /* These should be converted into function calls by the frontend. */
4403 0 : gcc_unreachable ();
4404 :
4405 0 : default:
4406 0 : fatal_error (input_location, "Unknown intrinsic op");
4407 415990 : return;
4408 : }
4409 :
4410 : /* The only exception to this is **, which is handled separately anyway. */
4411 415990 : gcc_assert (expr->value.op.op1->ts.type == expr->value.op.op2->ts.type);
4412 :
4413 415990 : if (checkstring && expr->value.op.op1->ts.type != BT_CHARACTER)
4414 381962 : checkstring = 0;
4415 :
4416 : /* lhs */
4417 415990 : gfc_init_se (&lse, se);
4418 415990 : gfc_conv_expr (&lse, expr->value.op.op1);
4419 415990 : gfc_add_block_to_block (&se->pre, &lse.pre);
4420 :
4421 : /* rhs */
4422 415990 : gfc_init_se (&rse, se);
4423 415990 : gfc_conv_expr (&rse, expr->value.op.op2);
4424 415990 : gfc_add_block_to_block (&se->pre, &rse.pre);
4425 :
4426 415990 : if (checkstring)
4427 : {
4428 34028 : gfc_conv_string_parameter (&lse);
4429 34028 : gfc_conv_string_parameter (&rse);
4430 :
4431 68056 : lse.expr = gfc_build_compare_string (lse.string_length, lse.expr,
4432 : rse.string_length, rse.expr,
4433 34028 : expr->value.op.op1->ts.kind,
4434 : code);
4435 34028 : rse.expr = build_int_cst (TREE_TYPE (lse.expr), 0);
4436 34028 : gfc_add_block_to_block (&lse.post, &rse.post);
4437 : }
4438 :
4439 415990 : type = gfc_typenode_for_spec (&expr->ts);
4440 :
4441 415990 : if (lop)
4442 : {
4443 : // Inhibit overeager optimization of Cray pointer comparisons (PR106692).
4444 300420 : if (expr->value.op.op1->expr_type == EXPR_VARIABLE
4445 169920 : && expr->value.op.op1->ts.type == BT_INTEGER
4446 73145 : && expr->value.op.op1->symtree
4447 73145 : && expr->value.op.op1->symtree->n.sym->attr.cray_pointer)
4448 12 : TREE_THIS_VOLATILE (lse.expr) = 1;
4449 :
4450 300420 : if (expr->value.op.op2->expr_type == EXPR_VARIABLE
4451 72330 : && expr->value.op.op2->ts.type == BT_INTEGER
4452 12981 : && expr->value.op.op2->symtree
4453 12981 : && expr->value.op.op2->symtree->n.sym->attr.cray_pointer)
4454 12 : TREE_THIS_VOLATILE (rse.expr) = 1;
4455 :
4456 : /* The result of logical ops is always logical_type_node. */
4457 300420 : tmp = fold_build2_loc (input_location, code, logical_type_node,
4458 : lse.expr, rse.expr);
4459 300420 : se->expr = convert (type, tmp);
4460 : }
4461 : else
4462 115570 : se->expr = fold_build2_loc (input_location, code, type, lse.expr, rse.expr);
4463 :
4464 : /* Add the post blocks. */
4465 415990 : gfc_add_block_to_block (&se->post, &rse.post);
4466 415990 : gfc_add_block_to_block (&se->post, &lse.post);
4467 : }
4468 :
4469 : static void
4470 159 : gfc_conv_conditional_expr (gfc_se *se, gfc_expr *expr)
4471 : {
4472 159 : gfc_se cond_se, true_se, false_se;
4473 159 : tree condition, true_val, false_val;
4474 159 : tree type;
4475 :
4476 159 : gfc_init_se (&cond_se, se);
4477 159 : gfc_init_se (&true_se, se);
4478 159 : gfc_init_se (&false_se, se);
4479 :
4480 159 : gfc_conv_expr (&cond_se, expr->value.conditional.condition);
4481 159 : gfc_add_block_to_block (&se->pre, &cond_se.pre);
4482 159 : condition = gfc_evaluate_now (cond_se.expr, &se->pre);
4483 :
4484 159 : true_se.want_pointer = se->want_pointer;
4485 159 : gfc_conv_expr (&true_se, expr->value.conditional.true_expr);
4486 159 : true_val = true_se.expr;
4487 159 : false_se.want_pointer = se->want_pointer;
4488 159 : gfc_conv_expr (&false_se, expr->value.conditional.false_expr);
4489 159 : false_val = false_se.expr;
4490 :
4491 159 : if (true_se.pre.head != NULL_TREE || false_se.pre.head != NULL_TREE)
4492 24 : gfc_add_expr_to_block (
4493 : &se->pre,
4494 : fold_build3_loc (input_location, COND_EXPR, void_type_node, condition,
4495 24 : true_se.pre.head != NULL_TREE
4496 6 : ? gfc_finish_block (&true_se.pre)
4497 18 : : build_empty_stmt (input_location),
4498 24 : false_se.pre.head != NULL_TREE
4499 24 : ? gfc_finish_block (&false_se.pre)
4500 0 : : build_empty_stmt (input_location)));
4501 :
4502 159 : if (true_se.post.head != NULL_TREE || false_se.post.head != NULL_TREE)
4503 6 : gfc_add_expr_to_block (
4504 : &se->post,
4505 : fold_build3_loc (input_location, COND_EXPR, void_type_node, condition,
4506 6 : true_se.post.head != NULL_TREE
4507 0 : ? gfc_finish_block (&true_se.post)
4508 6 : : build_empty_stmt (input_location),
4509 6 : false_se.post.head != NULL_TREE
4510 6 : ? gfc_finish_block (&false_se.post)
4511 0 : : build_empty_stmt (input_location)));
4512 :
4513 159 : type = gfc_typenode_for_spec (&expr->ts);
4514 159 : if (se->want_pointer)
4515 18 : type = build_pointer_type (type);
4516 :
4517 159 : se->expr = fold_build3_loc (input_location, COND_EXPR, type, condition,
4518 : true_val, false_val);
4519 159 : if (expr->ts.type == BT_CHARACTER)
4520 66 : se->string_length
4521 66 : = fold_build3_loc (input_location, COND_EXPR, gfc_charlen_type_node,
4522 : condition, true_se.string_length,
4523 : false_se.string_length);
4524 159 : }
4525 :
4526 : /* If a string's length is one, we convert it to a single character. */
4527 :
4528 : tree
4529 140318 : gfc_string_to_single_character (tree len, tree str, int kind)
4530 : {
4531 :
4532 140318 : if (len == NULL
4533 140318 : || !tree_fits_uhwi_p (len)
4534 257878 : || !POINTER_TYPE_P (TREE_TYPE (str)))
4535 : return NULL_TREE;
4536 :
4537 117508 : if (TREE_INT_CST_LOW (len) == 1)
4538 : {
4539 22552 : str = fold_convert (gfc_get_pchar_type (kind), str);
4540 22552 : return build_fold_indirect_ref_loc (input_location, str);
4541 : }
4542 :
4543 94956 : if (kind == 1
4544 77586 : && TREE_CODE (str) == ADDR_EXPR
4545 66910 : && TREE_CODE (TREE_OPERAND (str, 0)) == ARRAY_REF
4546 47790 : && TREE_CODE (TREE_OPERAND (TREE_OPERAND (str, 0), 0)) == STRING_CST
4547 29394 : && array_ref_low_bound (TREE_OPERAND (str, 0))
4548 29394 : == TREE_OPERAND (TREE_OPERAND (str, 0), 1)
4549 29394 : && TREE_INT_CST_LOW (len) > 1
4550 122543 : && TREE_INT_CST_LOW (len)
4551 : == (unsigned HOST_WIDE_INT)
4552 27587 : TREE_STRING_LENGTH (TREE_OPERAND (TREE_OPERAND (str, 0), 0)))
4553 : {
4554 27587 : tree ret = fold_convert (gfc_get_pchar_type (kind), str);
4555 27587 : ret = build_fold_indirect_ref_loc (input_location, ret);
4556 27587 : if (TREE_CODE (ret) == INTEGER_CST)
4557 : {
4558 27587 : tree string_cst = TREE_OPERAND (TREE_OPERAND (str, 0), 0);
4559 27587 : int i, length = TREE_STRING_LENGTH (string_cst);
4560 27587 : const char *ptr = TREE_STRING_POINTER (string_cst);
4561 :
4562 41697 : for (i = 1; i < length; i++)
4563 41017 : if (ptr[i] != ' ')
4564 : return NULL_TREE;
4565 :
4566 : return ret;
4567 : }
4568 : }
4569 :
4570 : return NULL_TREE;
4571 : }
4572 :
4573 :
4574 : static void
4575 172 : conv_scalar_char_value (gfc_symbol *sym, gfc_se *se, gfc_expr **expr)
4576 : {
4577 172 : gcc_assert (expr);
4578 :
4579 : /* We used to modify the tree here. Now it is done earlier in
4580 : the front-end, so we only check it here to avoid regressions. */
4581 172 : if (sym->backend_decl)
4582 : {
4583 67 : gcc_assert (TREE_CODE (TREE_TYPE (sym->backend_decl)) == INTEGER_TYPE);
4584 67 : gcc_assert (TYPE_UNSIGNED (TREE_TYPE (sym->backend_decl)) == 1);
4585 67 : gcc_assert (TYPE_PRECISION (TREE_TYPE (sym->backend_decl)) == CHAR_TYPE_SIZE);
4586 67 : gcc_assert (DECL_BY_REFERENCE (sym->backend_decl) == 0);
4587 : }
4588 :
4589 : /* If we have a constant character expression, make it into an
4590 : integer of type C char. */
4591 172 : if ((*expr)->expr_type == EXPR_CONSTANT)
4592 : {
4593 166 : gfc_typespec ts;
4594 166 : gfc_clear_ts (&ts);
4595 :
4596 332 : gfc_expr *tmp = gfc_get_int_expr (gfc_default_character_kind, NULL,
4597 166 : (*expr)->value.character.string[0]);
4598 166 : gfc_replace_expr (*expr, tmp);
4599 : }
4600 6 : else if (se != NULL && (*expr)->expr_type == EXPR_VARIABLE)
4601 : {
4602 6 : if ((*expr)->ref == NULL)
4603 : {
4604 6 : se->expr = gfc_string_to_single_character
4605 6 : (integer_one_node,
4606 6 : gfc_build_addr_expr (gfc_get_pchar_type ((*expr)->ts.kind),
4607 : gfc_get_symbol_decl
4608 6 : ((*expr)->symtree->n.sym)),
4609 : (*expr)->ts.kind);
4610 : }
4611 : else
4612 : {
4613 0 : gfc_conv_variable (se, *expr);
4614 0 : se->expr = gfc_string_to_single_character
4615 0 : (integer_one_node,
4616 : gfc_build_addr_expr (gfc_get_pchar_type ((*expr)->ts.kind),
4617 : se->expr),
4618 0 : (*expr)->ts.kind);
4619 : }
4620 : }
4621 172 : }
4622 :
4623 : /* Helper function for gfc_build_compare_string. Return LEN_TRIM value
4624 : if STR is a string literal, otherwise return -1. */
4625 :
4626 : static int
4627 32326 : gfc_optimize_len_trim (tree len, tree str, int kind)
4628 : {
4629 32326 : if (kind == 1
4630 27284 : && TREE_CODE (str) == ADDR_EXPR
4631 23946 : && TREE_CODE (TREE_OPERAND (str, 0)) == ARRAY_REF
4632 15255 : && TREE_CODE (TREE_OPERAND (TREE_OPERAND (str, 0), 0)) == STRING_CST
4633 9829 : && array_ref_low_bound (TREE_OPERAND (str, 0))
4634 9829 : == TREE_OPERAND (TREE_OPERAND (str, 0), 1)
4635 9829 : && tree_fits_uhwi_p (len)
4636 9829 : && tree_to_uhwi (len) >= 1
4637 32326 : && tree_to_uhwi (len)
4638 9785 : == (unsigned HOST_WIDE_INT)
4639 9785 : TREE_STRING_LENGTH (TREE_OPERAND (TREE_OPERAND (str, 0), 0)))
4640 : {
4641 9785 : tree folded = fold_convert (gfc_get_pchar_type (kind), str);
4642 9785 : folded = build_fold_indirect_ref_loc (input_location, folded);
4643 9785 : if (TREE_CODE (folded) == INTEGER_CST)
4644 : {
4645 9785 : tree string_cst = TREE_OPERAND (TREE_OPERAND (str, 0), 0);
4646 9785 : int length = TREE_STRING_LENGTH (string_cst);
4647 9785 : const char *ptr = TREE_STRING_POINTER (string_cst);
4648 :
4649 14694 : for (; length > 0; length--)
4650 14694 : if (ptr[length - 1] != ' ')
4651 : break;
4652 :
4653 : return length;
4654 : }
4655 : }
4656 : return -1;
4657 : }
4658 :
4659 : /* Helper to build a call to memcmp. */
4660 :
4661 : static tree
4662 13129 : build_memcmp_call (tree s1, tree s2, tree n)
4663 : {
4664 13129 : tree tmp;
4665 :
4666 13129 : if (!POINTER_TYPE_P (TREE_TYPE (s1)))
4667 0 : s1 = gfc_build_addr_expr (pvoid_type_node, s1);
4668 : else
4669 13129 : s1 = fold_convert (pvoid_type_node, s1);
4670 :
4671 13129 : if (!POINTER_TYPE_P (TREE_TYPE (s2)))
4672 0 : s2 = gfc_build_addr_expr (pvoid_type_node, s2);
4673 : else
4674 13129 : s2 = fold_convert (pvoid_type_node, s2);
4675 :
4676 13129 : n = fold_convert (size_type_node, n);
4677 :
4678 13129 : tmp = build_call_expr_loc (input_location,
4679 : builtin_decl_explicit (BUILT_IN_MEMCMP),
4680 : 3, s1, s2, n);
4681 :
4682 13129 : return fold_convert (integer_type_node, tmp);
4683 : }
4684 :
4685 : /* Compare two strings. If they are all single characters, the result is the
4686 : subtraction of them. Otherwise, we build a library call. */
4687 :
4688 : tree
4689 34127 : gfc_build_compare_string (tree len1, tree str1, tree len2, tree str2, int kind,
4690 : enum tree_code code)
4691 : {
4692 34127 : tree sc1;
4693 34127 : tree sc2;
4694 34127 : tree fndecl;
4695 :
4696 34127 : gcc_assert (POINTER_TYPE_P (TREE_TYPE (str1)));
4697 34127 : gcc_assert (POINTER_TYPE_P (TREE_TYPE (str2)));
4698 :
4699 34127 : sc1 = gfc_string_to_single_character (len1, str1, kind);
4700 34127 : sc2 = gfc_string_to_single_character (len2, str2, kind);
4701 :
4702 34127 : if (sc1 != NULL_TREE && sc2 != NULL_TREE)
4703 : {
4704 : /* Deal with single character specially. */
4705 4839 : sc1 = fold_convert (integer_type_node, sc1);
4706 4839 : sc2 = fold_convert (integer_type_node, sc2);
4707 4839 : return fold_build2_loc (input_location, MINUS_EXPR, integer_type_node,
4708 4839 : sc1, sc2);
4709 : }
4710 :
4711 29288 : if ((code == EQ_EXPR || code == NE_EXPR)
4712 28726 : && optimize
4713 24062 : && INTEGER_CST_P (len1) && INTEGER_CST_P (len2))
4714 : {
4715 : /* If one string is a string literal with LEN_TRIM longer
4716 : than the length of the second string, the strings
4717 : compare unequal. */
4718 16163 : int len = gfc_optimize_len_trim (len1, str1, kind);
4719 16163 : if (len > 0 && compare_tree_int (len2, len) < 0)
4720 0 : return integer_one_node;
4721 16163 : len = gfc_optimize_len_trim (len2, str2, kind);
4722 16163 : if (len > 0 && compare_tree_int (len1, len) < 0)
4723 0 : return integer_one_node;
4724 : }
4725 :
4726 : /* We can compare via memcpy if the strings are known to be equal
4727 : in length and they are
4728 : - kind=1
4729 : - kind=4 and the comparison is for (in)equality. */
4730 :
4731 19702 : if (INTEGER_CST_P (len1) && INTEGER_CST_P (len2)
4732 19364 : && tree_int_cst_equal (len1, len2)
4733 42477 : && (kind == 1 || code == EQ_EXPR || code == NE_EXPR))
4734 : {
4735 13129 : tree tmp;
4736 13129 : tree chartype;
4737 :
4738 13129 : chartype = gfc_get_char_type (kind);
4739 13129 : tmp = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE(len1),
4740 13129 : fold_convert (TREE_TYPE(len1),
4741 : TYPE_SIZE_UNIT(chartype)),
4742 : len1);
4743 13129 : return build_memcmp_call (str1, str2, tmp);
4744 : }
4745 :
4746 : /* Build a call for the comparison. */
4747 16159 : if (kind == 1)
4748 13316 : fndecl = gfor_fndecl_compare_string;
4749 2843 : else if (kind == 4)
4750 2843 : fndecl = gfor_fndecl_compare_string_char4;
4751 : else
4752 0 : gcc_unreachable ();
4753 :
4754 16159 : return build_call_expr_loc (input_location, fndecl, 4,
4755 16159 : len1, str1, len2, str2);
4756 : }
4757 :
4758 :
4759 : /* Return the backend_decl for a procedure pointer component. */
4760 :
4761 : static tree
4762 1914 : get_proc_ptr_comp (gfc_expr *e)
4763 : {
4764 1914 : gfc_se comp_se;
4765 1914 : gfc_expr *e2;
4766 1914 : expr_t old_type;
4767 :
4768 1914 : gfc_init_se (&comp_se, NULL);
4769 1914 : e2 = gfc_copy_expr (e);
4770 : /* We have to restore the expr type later so that gfc_free_expr frees
4771 : the exact same thing that was allocated.
4772 : TODO: This is ugly. */
4773 1914 : old_type = e2->expr_type;
4774 1914 : e2->expr_type = EXPR_VARIABLE;
4775 1914 : gfc_conv_expr (&comp_se, e2);
4776 1914 : e2->expr_type = old_type;
4777 1914 : gfc_free_expr (e2);
4778 1914 : return build_fold_addr_expr_loc (input_location, comp_se.expr);
4779 : }
4780 :
4781 :
4782 : /* Convert a typebound function reference from a class object. */
4783 : static void
4784 80 : conv_base_obj_fcn_val (gfc_se * se, tree base_object, gfc_expr * expr)
4785 : {
4786 80 : gfc_ref *ref;
4787 80 : tree var;
4788 :
4789 80 : if (!VAR_P (base_object))
4790 : {
4791 0 : var = gfc_create_var (TREE_TYPE (base_object), NULL);
4792 0 : gfc_add_modify (&se->pre, var, base_object);
4793 : }
4794 80 : se->expr = gfc_class_vptr_get (base_object);
4795 80 : se->expr = build_fold_indirect_ref_loc (input_location, se->expr);
4796 80 : ref = expr->ref;
4797 308 : while (ref && ref->next)
4798 : ref = ref->next;
4799 80 : gcc_assert (ref && ref->type == REF_COMPONENT);
4800 80 : if (ref->u.c.sym->attr.extension)
4801 0 : conv_parent_component_references (se, ref);
4802 80 : gfc_conv_component_ref (se, ref);
4803 80 : se->expr = build_fold_addr_expr_loc (input_location, se->expr);
4804 80 : }
4805 :
4806 : static tree
4807 127810 : get_builtin_fn (gfc_symbol * sym)
4808 : {
4809 127810 : if (!gfc_option.disable_omp_is_initial_device
4810 127806 : && flag_openmp && sym->attr.function && sym->ts.type == BT_LOGICAL
4811 625 : && !strcmp (sym->name, "omp_is_initial_device"))
4812 41 : return builtin_decl_explicit (BUILT_IN_OMP_IS_INITIAL_DEVICE);
4813 :
4814 127769 : if (!gfc_option.disable_omp_get_initial_device
4815 127762 : && flag_openmp && sym->attr.function && sym->ts.type == BT_INTEGER
4816 4001 : && !strcmp (sym->name, "omp_get_initial_device"))
4817 29 : return builtin_decl_explicit (BUILT_IN_OMP_GET_INITIAL_DEVICE);
4818 :
4819 127740 : if (!gfc_option.disable_omp_get_num_devices
4820 127733 : && flag_openmp && sym->attr.function && sym->ts.type == BT_INTEGER
4821 3972 : && !strcmp (sym->name, "omp_get_num_devices"))
4822 107 : return builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_DEVICES);
4823 :
4824 127633 : if (!gfc_option.disable_acc_on_device
4825 127453 : && flag_openacc && sym->attr.function && sym->ts.type == BT_LOGICAL
4826 1163 : && !strcmp (sym->name, "acc_on_device_h"))
4827 390 : return builtin_decl_explicit (BUILT_IN_ACC_ON_DEVICE);
4828 :
4829 : return NULL_TREE;
4830 : }
4831 :
4832 : static tree
4833 567 : update_builtin_function (tree fn_call, gfc_symbol *sym)
4834 : {
4835 567 : tree fn = TREE_OPERAND (CALL_EXPR_FN (fn_call), 0);
4836 :
4837 567 : if (DECL_FUNCTION_CODE (fn) == BUILT_IN_OMP_IS_INITIAL_DEVICE)
4838 : /* In Fortran omp_is_initial_device returns logical(4)
4839 : but the builtin uses 'int'. */
4840 41 : return fold_convert (TREE_TYPE (TREE_TYPE (sym->backend_decl)), fn_call);
4841 :
4842 526 : else if (DECL_FUNCTION_CODE (fn) == BUILT_IN_ACC_ON_DEVICE)
4843 : {
4844 : /* Likewise for the return type; additionally, the argument it a
4845 : call-by-value int, Fortran has a by-reference 'integer(4)'. */
4846 390 : tree arg = build_fold_indirect_ref_loc (input_location,
4847 390 : CALL_EXPR_ARG (fn_call, 0));
4848 390 : CALL_EXPR_ARG (fn_call, 0) = fold_convert (integer_type_node, arg);
4849 390 : return fold_convert (TREE_TYPE (TREE_TYPE (sym->backend_decl)), fn_call);
4850 : }
4851 : return fn_call;
4852 : }
4853 :
4854 : static void
4855 130540 : conv_function_val (gfc_se * se, bool *is_builtin, gfc_symbol * sym,
4856 : gfc_expr * expr, gfc_actual_arglist *actual_args)
4857 : {
4858 130540 : tree tmp;
4859 :
4860 130540 : if (gfc_is_proc_ptr_comp (expr))
4861 1914 : tmp = get_proc_ptr_comp (expr);
4862 128626 : else if (sym->attr.dummy)
4863 : {
4864 816 : tmp = gfc_get_symbol_decl (sym);
4865 816 : if (sym->attr.proc_pointer)
4866 89 : tmp = build_fold_indirect_ref_loc (input_location,
4867 : tmp);
4868 816 : gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == POINTER_TYPE
4869 : && TREE_CODE (TREE_TYPE (TREE_TYPE (tmp))) == FUNCTION_TYPE);
4870 : }
4871 : else
4872 : {
4873 127810 : if (!sym->backend_decl)
4874 32026 : sym->backend_decl = gfc_get_extern_function_decl (sym, actual_args);
4875 :
4876 127810 : if ((tmp = get_builtin_fn (sym)) != NULL_TREE)
4877 567 : *is_builtin = true;
4878 : else
4879 : {
4880 127243 : TREE_USED (sym->backend_decl) = 1;
4881 127243 : tmp = sym->backend_decl;
4882 : }
4883 :
4884 127810 : if (sym->attr.cray_pointee)
4885 : {
4886 : /* TODO - make the cray pointee a pointer to a procedure,
4887 : assign the pointer to it and use it for the call. This
4888 : will do for now! */
4889 19 : tmp = convert (build_pointer_type (TREE_TYPE (tmp)),
4890 19 : gfc_get_symbol_decl (sym->cp_pointer));
4891 19 : tmp = gfc_evaluate_now (tmp, &se->pre);
4892 : }
4893 :
4894 127810 : if (!POINTER_TYPE_P (TREE_TYPE (tmp)))
4895 : {
4896 127182 : gcc_assert (TREE_CODE (tmp) == FUNCTION_DECL);
4897 127182 : tmp = gfc_build_addr_expr (NULL_TREE, tmp);
4898 : }
4899 : }
4900 130540 : se->expr = tmp;
4901 130540 : }
4902 :
4903 :
4904 : /* Initialize MAPPING. */
4905 :
4906 : void
4907 130657 : gfc_init_interface_mapping (gfc_interface_mapping * mapping)
4908 : {
4909 130657 : mapping->syms = NULL;
4910 130657 : mapping->charlens = NULL;
4911 130657 : }
4912 :
4913 :
4914 : /* Free all memory held by MAPPING (but not MAPPING itself). */
4915 :
4916 : void
4917 130657 : gfc_free_interface_mapping (gfc_interface_mapping * mapping)
4918 : {
4919 130657 : gfc_interface_sym_mapping *sym;
4920 130657 : gfc_interface_sym_mapping *nextsym;
4921 130657 : gfc_charlen *cl;
4922 130657 : gfc_charlen *nextcl;
4923 :
4924 171241 : for (sym = mapping->syms; sym; sym = nextsym)
4925 : {
4926 40584 : nextsym = sym->next;
4927 40584 : sym->new_sym->n.sym->formal = NULL;
4928 40584 : gfc_free_symbol (sym->new_sym->n.sym);
4929 40584 : gfc_free_expr (sym->expr);
4930 40584 : free (sym->new_sym);
4931 40584 : free (sym);
4932 : }
4933 135297 : for (cl = mapping->charlens; cl; cl = nextcl)
4934 : {
4935 4640 : nextcl = cl->next;
4936 4640 : gfc_free_expr (cl->length);
4937 4640 : free (cl);
4938 : }
4939 130657 : }
4940 :
4941 :
4942 : /* Return a copy of gfc_charlen CL. Add the returned structure to
4943 : MAPPING so that it will be freed by gfc_free_interface_mapping. */
4944 :
4945 : static gfc_charlen *
4946 4640 : gfc_get_interface_mapping_charlen (gfc_interface_mapping * mapping,
4947 : gfc_charlen * cl)
4948 : {
4949 4640 : gfc_charlen *new_charlen;
4950 :
4951 4640 : new_charlen = gfc_get_charlen ();
4952 4640 : new_charlen->next = mapping->charlens;
4953 4640 : new_charlen->length = gfc_copy_expr (cl->length);
4954 :
4955 4640 : mapping->charlens = new_charlen;
4956 4640 : return new_charlen;
4957 : }
4958 :
4959 :
4960 : /* A subroutine of gfc_add_interface_mapping. Return a descriptorless
4961 : array variable that can be used as the actual argument for dummy
4962 : argument SYM, except in the case of assumed rank dummies of
4963 : non-intrinsic functions where the descriptor must be passed. Add any
4964 : initialization code to BLOCK. PACKED is as for gfc_get_nodesc_array_type
4965 : and DATA points to the first element in the passed array. */
4966 :
4967 : static tree
4968 8394 : gfc_get_interface_mapping_array (stmtblock_t * block, gfc_symbol * sym,
4969 : gfc_packed packed, tree data, tree len,
4970 : bool assumed_rank_formal)
4971 : {
4972 8394 : tree type;
4973 8394 : tree var;
4974 :
4975 8394 : if (len != NULL_TREE && (TREE_CONSTANT (len) || VAR_P (len)))
4976 58 : type = gfc_get_character_type_len (sym->ts.kind, len);
4977 : else
4978 8336 : type = gfc_typenode_for_spec (&sym->ts);
4979 :
4980 8394 : if (assumed_rank_formal)
4981 13 : type = TREE_TYPE (data);
4982 : else
4983 8381 : type = gfc_get_nodesc_array_type (type, sym->as, packed,
4984 8357 : !sym->attr.target && !sym->attr.pointer
4985 16738 : && !sym->attr.proc_pointer);
4986 :
4987 8394 : var = gfc_create_var (type, "ifm");
4988 8394 : gfc_add_modify (block, var, fold_convert (type, data));
4989 :
4990 8394 : return var;
4991 : }
4992 :
4993 :
4994 : /* A subroutine of gfc_add_interface_mapping. Set the stride, upper bounds
4995 : and offset of descriptorless array type TYPE given that it has the same
4996 : size as DESC. Add any set-up code to BLOCK. */
4997 :
4998 : static void
4999 8124 : gfc_set_interface_mapping_bounds (stmtblock_t * block, tree type, tree desc)
5000 : {
5001 8124 : int n;
5002 8124 : tree dim;
5003 8124 : tree offset;
5004 8124 : tree tmp;
5005 :
5006 8124 : offset = gfc_index_zero_node;
5007 9238 : for (n = 0; n < GFC_TYPE_ARRAY_RANK (type); n++)
5008 : {
5009 1114 : dim = gfc_rank_cst[n];
5010 1114 : GFC_TYPE_ARRAY_STRIDE (type, n) = gfc_conv_array_stride (desc, n);
5011 1114 : if (GFC_TYPE_ARRAY_LBOUND (type, n) == NULL_TREE)
5012 : {
5013 1 : GFC_TYPE_ARRAY_LBOUND (type, n)
5014 1 : = gfc_conv_descriptor_lbound_get (desc, dim);
5015 1 : GFC_TYPE_ARRAY_UBOUND (type, n)
5016 2 : = gfc_conv_descriptor_ubound_get (desc, dim);
5017 : }
5018 1113 : else if (GFC_TYPE_ARRAY_UBOUND (type, n) == NULL_TREE)
5019 : {
5020 1087 : tmp = fold_build2_loc (input_location, MINUS_EXPR,
5021 : gfc_array_index_type,
5022 : gfc_conv_descriptor_ubound_get (desc, dim),
5023 : gfc_conv_descriptor_lbound_get (desc, dim));
5024 3261 : tmp = fold_build2_loc (input_location, PLUS_EXPR,
5025 : gfc_array_index_type,
5026 1087 : GFC_TYPE_ARRAY_LBOUND (type, n), tmp);
5027 1087 : tmp = gfc_evaluate_now (tmp, block);
5028 1087 : GFC_TYPE_ARRAY_UBOUND (type, n) = tmp;
5029 : }
5030 4456 : tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
5031 1114 : GFC_TYPE_ARRAY_LBOUND (type, n),
5032 1114 : GFC_TYPE_ARRAY_STRIDE (type, n));
5033 1114 : offset = fold_build2_loc (input_location, MINUS_EXPR,
5034 : gfc_array_index_type, offset, tmp);
5035 : }
5036 8124 : offset = gfc_evaluate_now (offset, block);
5037 8124 : GFC_TYPE_ARRAY_OFFSET (type) = offset;
5038 8124 : }
5039 :
5040 :
5041 : /* Extend MAPPING so that it maps dummy argument SYM to the value stored
5042 : in SE. The caller may still use se->expr and se->string_length after
5043 : calling this function. */
5044 :
5045 : void
5046 40584 : gfc_add_interface_mapping (gfc_interface_mapping * mapping,
5047 : gfc_symbol * sym, gfc_se * se,
5048 : gfc_expr *expr)
5049 : {
5050 40584 : gfc_interface_sym_mapping *sm;
5051 40584 : tree desc;
5052 40584 : tree tmp;
5053 40584 : tree value;
5054 40584 : gfc_symbol *new_sym;
5055 40584 : gfc_symtree *root;
5056 40584 : gfc_symtree *new_symtree;
5057 :
5058 : /* Create a new symbol to represent the actual argument. */
5059 40584 : new_sym = gfc_new_symbol (sym->name, NULL);
5060 40584 : new_sym->ts = sym->ts;
5061 40584 : new_sym->as = gfc_copy_array_spec (sym->as);
5062 40584 : new_sym->attr.referenced = 1;
5063 40584 : new_sym->attr.dimension = sym->attr.dimension;
5064 40584 : new_sym->attr.contiguous = sym->attr.contiguous;
5065 40584 : new_sym->attr.codimension = sym->attr.codimension;
5066 40584 : new_sym->attr.pointer = sym->attr.pointer;
5067 40584 : new_sym->attr.allocatable = sym->attr.allocatable;
5068 40584 : new_sym->attr.flavor = sym->attr.flavor;
5069 40584 : new_sym->attr.function = sym->attr.function;
5070 40584 : new_sym->attr.dummy = 0;
5071 :
5072 : /* Ensure that the interface is available and that
5073 : descriptors are passed for array actual arguments. */
5074 40584 : if (sym->attr.flavor == FL_PROCEDURE)
5075 : {
5076 36 : new_sym->formal = expr->symtree->n.sym->formal;
5077 36 : new_sym->attr.always_explicit
5078 36 : = expr->symtree->n.sym->attr.always_explicit;
5079 : }
5080 :
5081 : /* Create a fake symtree for it. */
5082 40584 : root = NULL;
5083 40584 : new_symtree = gfc_new_symtree (&root, sym->name);
5084 40584 : new_symtree->n.sym = new_sym;
5085 40584 : gcc_assert (new_symtree == root);
5086 :
5087 : /* Create a dummy->actual mapping. */
5088 40584 : sm = XCNEW (gfc_interface_sym_mapping);
5089 40584 : sm->next = mapping->syms;
5090 40584 : sm->old = sym;
5091 40584 : sm->new_sym = new_symtree;
5092 40584 : sm->expr = gfc_copy_expr (expr);
5093 40584 : mapping->syms = sm;
5094 :
5095 : /* Stabilize the argument's value. */
5096 40584 : if (!sym->attr.function && se)
5097 40486 : se->expr = gfc_evaluate_now (se->expr, &se->pre);
5098 :
5099 40584 : if (sym->ts.type == BT_CHARACTER)
5100 : {
5101 : /* Create a copy of the dummy argument's length. */
5102 2856 : new_sym->ts.u.cl = gfc_get_interface_mapping_charlen (mapping, sym->ts.u.cl);
5103 2856 : sm->expr->ts.u.cl = new_sym->ts.u.cl;
5104 :
5105 : /* If the length is specified as "*", record the length that
5106 : the caller is passing. We should use the callee's length
5107 : in all other cases. */
5108 2856 : if (!new_sym->ts.u.cl->length && se)
5109 : {
5110 2628 : se->string_length = gfc_evaluate_now (se->string_length, &se->pre);
5111 2628 : new_sym->ts.u.cl->backend_decl = se->string_length;
5112 : }
5113 : }
5114 :
5115 40570 : if (!se)
5116 62 : return;
5117 :
5118 : /* Use the passed value as-is if the argument is a function. */
5119 40522 : if (sym->attr.flavor == FL_PROCEDURE)
5120 36 : value = se->expr;
5121 :
5122 : /* If the argument is a pass-by-value scalar, use the value as is. */
5123 40486 : else if (!sym->attr.dimension && sym->attr.value)
5124 78 : value = se->expr;
5125 :
5126 : /* If the argument is either a string or a pointer to a string,
5127 : convert it to a boundless character type. */
5128 40408 : else if (!sym->attr.dimension && sym->ts.type == BT_CHARACTER)
5129 : {
5130 1287 : se->string_length = gfc_evaluate_now (se->string_length, &se->pre);
5131 1287 : tmp = gfc_get_character_type_len (sym->ts.kind, se->string_length);
5132 1287 : tmp = build_pointer_type (tmp);
5133 1287 : if (sym->attr.pointer)
5134 126 : value = build_fold_indirect_ref_loc (input_location,
5135 : se->expr);
5136 : else
5137 1161 : value = se->expr;
5138 1287 : value = fold_convert (tmp, value);
5139 : }
5140 :
5141 : /* If the argument is a scalar, a pointer to an array or an allocatable,
5142 : dereference it. */
5143 39121 : else if (!sym->attr.dimension || sym->attr.pointer || sym->attr.allocatable)
5144 29230 : value = build_fold_indirect_ref_loc (input_location,
5145 : se->expr);
5146 :
5147 : /* For character(*), use the actual argument's descriptor. */
5148 9891 : else if (sym->ts.type == BT_CHARACTER && !new_sym->ts.u.cl->length)
5149 1497 : value = build_fold_indirect_ref_loc (input_location,
5150 : se->expr);
5151 :
5152 : /* If the argument is an array descriptor, use it to determine
5153 : information about the actual argument's shape. */
5154 8394 : else if (POINTER_TYPE_P (TREE_TYPE (se->expr))
5155 8394 : && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (se->expr))))
5156 : {
5157 8124 : bool assumed_rank_formal = false;
5158 :
5159 : /* Get the actual argument's descriptor. */
5160 8124 : desc = build_fold_indirect_ref_loc (input_location,
5161 : se->expr);
5162 :
5163 : /* Create the replacement variable. */
5164 8124 : if (sym->as && sym->as->type == AS_ASSUMED_RANK
5165 7334 : && !(sym->ns && sym->ns->proc_name
5166 7334 : && sym->ns->proc_name->attr.proc == PROC_INTRINSIC))
5167 : {
5168 : assumed_rank_formal = true;
5169 : tmp = desc;
5170 : }
5171 : else
5172 8111 : tmp = gfc_conv_descriptor_data_get (desc);
5173 :
5174 8124 : value = gfc_get_interface_mapping_array (&se->pre, sym,
5175 : PACKED_NO, tmp,
5176 : se->string_length,
5177 : assumed_rank_formal);
5178 :
5179 : /* Use DESC to work out the upper bounds, strides and offset. */
5180 8124 : gfc_set_interface_mapping_bounds (&se->pre, TREE_TYPE (value), desc);
5181 : }
5182 : else
5183 : /* Otherwise we have a packed array. */
5184 270 : value = gfc_get_interface_mapping_array (&se->pre, sym,
5185 : PACKED_FULL, se->expr,
5186 : se->string_length,
5187 : false);
5188 :
5189 40522 : new_sym->backend_decl = value;
5190 : }
5191 :
5192 :
5193 : /* Called once all dummy argument mappings have been added to MAPPING,
5194 : but before the mapping is used to evaluate expressions. Pre-evaluate
5195 : the length of each argument, adding any initialization code to PRE and
5196 : any finalization code to POST. */
5197 :
5198 : static void
5199 130620 : gfc_finish_interface_mapping (gfc_interface_mapping * mapping,
5200 : stmtblock_t * pre, stmtblock_t * post)
5201 : {
5202 130620 : gfc_interface_sym_mapping *sym;
5203 130620 : gfc_expr *expr;
5204 130620 : gfc_se se;
5205 :
5206 171142 : for (sym = mapping->syms; sym; sym = sym->next)
5207 40522 : if (sym->new_sym->n.sym->ts.type == BT_CHARACTER
5208 2842 : && !sym->new_sym->n.sym->ts.u.cl->backend_decl)
5209 : {
5210 214 : expr = sym->new_sym->n.sym->ts.u.cl->length;
5211 214 : gfc_apply_interface_mapping_to_expr (mapping, expr);
5212 214 : gfc_init_se (&se, NULL);
5213 214 : gfc_conv_expr (&se, expr);
5214 214 : se.expr = fold_convert (gfc_charlen_type_node, se.expr);
5215 214 : se.expr = gfc_evaluate_now (se.expr, &se.pre);
5216 214 : gfc_add_block_to_block (pre, &se.pre);
5217 214 : gfc_add_block_to_block (post, &se.post);
5218 :
5219 214 : sym->new_sym->n.sym->ts.u.cl->backend_decl = se.expr;
5220 : }
5221 130620 : }
5222 :
5223 :
5224 : /* Like gfc_apply_interface_mapping_to_expr, but applied to
5225 : constructor C. */
5226 :
5227 : static void
5228 47 : gfc_apply_interface_mapping_to_cons (gfc_interface_mapping * mapping,
5229 : gfc_constructor_base base)
5230 : {
5231 47 : gfc_constructor *c;
5232 428 : for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
5233 : {
5234 381 : gfc_apply_interface_mapping_to_expr (mapping, c->expr);
5235 381 : if (c->iterator)
5236 : {
5237 6 : gfc_apply_interface_mapping_to_expr (mapping, c->iterator->start);
5238 6 : gfc_apply_interface_mapping_to_expr (mapping, c->iterator->end);
5239 6 : gfc_apply_interface_mapping_to_expr (mapping, c->iterator->step);
5240 : }
5241 : }
5242 47 : }
5243 :
5244 :
5245 : /* Like gfc_apply_interface_mapping_to_expr, but applied to
5246 : reference REF. */
5247 :
5248 : static void
5249 12585 : gfc_apply_interface_mapping_to_ref (gfc_interface_mapping * mapping,
5250 : gfc_ref * ref)
5251 : {
5252 12585 : int n;
5253 :
5254 14070 : for (; ref; ref = ref->next)
5255 1485 : switch (ref->type)
5256 : {
5257 : case REF_ARRAY:
5258 2915 : for (n = 0; n < ref->u.ar.dimen; n++)
5259 : {
5260 1650 : gfc_apply_interface_mapping_to_expr (mapping, ref->u.ar.start[n]);
5261 1650 : gfc_apply_interface_mapping_to_expr (mapping, ref->u.ar.end[n]);
5262 1650 : gfc_apply_interface_mapping_to_expr (mapping, ref->u.ar.stride[n]);
5263 : }
5264 : break;
5265 :
5266 : case REF_COMPONENT:
5267 : case REF_INQUIRY:
5268 : break;
5269 :
5270 43 : case REF_SUBSTRING:
5271 43 : gfc_apply_interface_mapping_to_expr (mapping, ref->u.ss.start);
5272 43 : gfc_apply_interface_mapping_to_expr (mapping, ref->u.ss.end);
5273 43 : break;
5274 : }
5275 12585 : }
5276 :
5277 :
5278 : /* Convert intrinsic function calls into result expressions. */
5279 :
5280 : static bool
5281 2214 : gfc_map_intrinsic_function (gfc_expr *expr, gfc_interface_mapping *mapping)
5282 : {
5283 2214 : gfc_symbol *sym;
5284 2214 : gfc_expr *new_expr;
5285 2214 : gfc_expr *arg1;
5286 2214 : gfc_expr *arg2;
5287 2214 : int d, dup;
5288 :
5289 2214 : arg1 = expr->value.function.actual->expr;
5290 2214 : if (expr->value.function.actual->next)
5291 2093 : arg2 = expr->value.function.actual->next->expr;
5292 : else
5293 : arg2 = NULL;
5294 :
5295 2214 : sym = arg1->symtree->n.sym;
5296 :
5297 2214 : if (sym->attr.dummy)
5298 : return false;
5299 :
5300 2190 : new_expr = NULL;
5301 :
5302 2190 : switch (expr->value.function.isym->id)
5303 : {
5304 929 : case GFC_ISYM_LEN:
5305 : /* TODO figure out why this condition is necessary. */
5306 929 : if (sym->attr.function
5307 43 : && (arg1->ts.u.cl->length == NULL
5308 42 : || (arg1->ts.u.cl->length->expr_type != EXPR_CONSTANT
5309 42 : && arg1->ts.u.cl->length->expr_type != EXPR_VARIABLE)))
5310 : return false;
5311 :
5312 886 : new_expr = gfc_copy_expr (arg1->ts.u.cl->length);
5313 886 : break;
5314 :
5315 228 : case GFC_ISYM_LEN_TRIM:
5316 228 : new_expr = gfc_copy_expr (arg1);
5317 228 : gfc_apply_interface_mapping_to_expr (mapping, new_expr);
5318 :
5319 228 : if (!new_expr)
5320 : return false;
5321 :
5322 228 : gfc_replace_expr (arg1, new_expr);
5323 228 : return true;
5324 :
5325 606 : case GFC_ISYM_SIZE:
5326 606 : if (!sym->as || sym->as->rank == 0)
5327 : return false;
5328 :
5329 530 : if (arg2 && arg2->expr_type == EXPR_CONSTANT)
5330 : {
5331 360 : dup = mpz_get_si (arg2->value.integer);
5332 360 : d = dup - 1;
5333 : }
5334 : else
5335 : {
5336 530 : dup = sym->as->rank;
5337 530 : d = 0;
5338 : }
5339 :
5340 542 : for (; d < dup; d++)
5341 : {
5342 530 : gfc_expr *tmp;
5343 :
5344 530 : if (!sym->as->upper[d] || !sym->as->lower[d])
5345 : {
5346 518 : gfc_free_expr (new_expr);
5347 518 : return false;
5348 : }
5349 :
5350 12 : tmp = gfc_add (gfc_copy_expr (sym->as->upper[d]),
5351 : gfc_get_int_expr (gfc_default_integer_kind,
5352 : NULL, 1));
5353 12 : tmp = gfc_subtract (tmp, gfc_copy_expr (sym->as->lower[d]));
5354 12 : if (new_expr)
5355 0 : new_expr = gfc_multiply (new_expr, tmp);
5356 : else
5357 : new_expr = tmp;
5358 : }
5359 : break;
5360 :
5361 44 : case GFC_ISYM_LBOUND:
5362 44 : case GFC_ISYM_UBOUND:
5363 : /* TODO These implementations of lbound and ubound do not limit if
5364 : the size < 0, according to F95's 13.14.53 and 13.14.113. */
5365 :
5366 44 : if (!sym->as || sym->as->rank == 0)
5367 : return false;
5368 :
5369 44 : if (arg2 && arg2->expr_type == EXPR_CONSTANT)
5370 38 : d = mpz_get_si (arg2->value.integer) - 1;
5371 : else
5372 : return false;
5373 :
5374 38 : if (expr->value.function.isym->id == GFC_ISYM_LBOUND)
5375 : {
5376 23 : if (sym->as->lower[d])
5377 23 : new_expr = gfc_copy_expr (sym->as->lower[d]);
5378 : }
5379 : else
5380 : {
5381 15 : if (sym->as->upper[d])
5382 9 : new_expr = gfc_copy_expr (sym->as->upper[d]);
5383 : }
5384 : break;
5385 :
5386 : default:
5387 : break;
5388 : }
5389 :
5390 1319 : gfc_apply_interface_mapping_to_expr (mapping, new_expr);
5391 1319 : if (!new_expr)
5392 : return false;
5393 :
5394 113 : gfc_replace_expr (expr, new_expr);
5395 113 : return true;
5396 : }
5397 :
5398 :
5399 : static void
5400 24 : gfc_map_fcn_formal_to_actual (gfc_expr *expr, gfc_expr *map_expr,
5401 : gfc_interface_mapping * mapping)
5402 : {
5403 24 : gfc_formal_arglist *f;
5404 24 : gfc_actual_arglist *actual;
5405 :
5406 24 : actual = expr->value.function.actual;
5407 24 : f = gfc_sym_get_dummy_args (map_expr->symtree->n.sym);
5408 :
5409 72 : for (; f && actual; f = f->next, actual = actual->next)
5410 : {
5411 24 : if (!actual->expr)
5412 0 : continue;
5413 :
5414 24 : gfc_add_interface_mapping (mapping, f->sym, NULL, actual->expr);
5415 : }
5416 :
5417 24 : if (map_expr->symtree->n.sym->attr.dimension)
5418 : {
5419 6 : int d;
5420 6 : gfc_array_spec *as;
5421 :
5422 6 : as = gfc_copy_array_spec (map_expr->symtree->n.sym->as);
5423 :
5424 18 : for (d = 0; d < as->rank; d++)
5425 : {
5426 6 : gfc_apply_interface_mapping_to_expr (mapping, as->lower[d]);
5427 6 : gfc_apply_interface_mapping_to_expr (mapping, as->upper[d]);
5428 : }
5429 :
5430 6 : expr->value.function.esym->as = as;
5431 : }
5432 :
5433 24 : if (map_expr->symtree->n.sym->ts.type == BT_CHARACTER)
5434 : {
5435 0 : expr->value.function.esym->ts.u.cl->length
5436 0 : = gfc_copy_expr (map_expr->symtree->n.sym->ts.u.cl->length);
5437 :
5438 0 : gfc_apply_interface_mapping_to_expr (mapping,
5439 0 : expr->value.function.esym->ts.u.cl->length);
5440 : }
5441 24 : }
5442 :
5443 :
5444 : /* EXPR is a copy of an expression that appeared in the interface
5445 : associated with MAPPING. Walk it recursively looking for references to
5446 : dummy arguments that MAPPING maps to actual arguments. Replace each such
5447 : reference with a reference to the associated actual argument. */
5448 :
5449 : static void
5450 21118 : gfc_apply_interface_mapping_to_expr (gfc_interface_mapping * mapping,
5451 : gfc_expr * expr)
5452 : {
5453 22683 : gfc_interface_sym_mapping *sym;
5454 22683 : gfc_actual_arglist *actual;
5455 :
5456 22683 : if (!expr)
5457 : return;
5458 :
5459 : /* Copying an expression does not copy its length, so do that here. */
5460 12585 : if (expr->ts.type == BT_CHARACTER && expr->ts.u.cl)
5461 : {
5462 1784 : expr->ts.u.cl = gfc_get_interface_mapping_charlen (mapping, expr->ts.u.cl);
5463 1784 : gfc_apply_interface_mapping_to_expr (mapping, expr->ts.u.cl->length);
5464 : }
5465 :
5466 : /* Apply the mapping to any references. */
5467 12585 : gfc_apply_interface_mapping_to_ref (mapping, expr->ref);
5468 :
5469 : /* ...and to the expression's symbol, if it has one. */
5470 : /* TODO Find out why the condition on expr->symtree had to be moved into
5471 : the loop rather than being outside it, as originally. */
5472 29942 : for (sym = mapping->syms; sym; sym = sym->next)
5473 17357 : if (expr->symtree && !strcmp (sym->old->name, expr->symtree->n.sym->name))
5474 : {
5475 3370 : if (sym->new_sym->n.sym->backend_decl)
5476 3326 : expr->symtree = sym->new_sym;
5477 44 : else if (sym->expr)
5478 44 : gfc_replace_expr (expr, gfc_copy_expr (sym->expr));
5479 : }
5480 :
5481 : /* ...and to subexpressions in expr->value. */
5482 12585 : switch (expr->expr_type)
5483 : {
5484 : case EXPR_VARIABLE:
5485 : case EXPR_CONSTANT:
5486 : case EXPR_NULL:
5487 : case EXPR_SUBSTRING:
5488 : break;
5489 :
5490 1565 : case EXPR_OP:
5491 1565 : gfc_apply_interface_mapping_to_expr (mapping, expr->value.op.op1);
5492 1565 : gfc_apply_interface_mapping_to_expr (mapping, expr->value.op.op2);
5493 1565 : break;
5494 :
5495 0 : case EXPR_CONDITIONAL:
5496 0 : gfc_apply_interface_mapping_to_expr (mapping,
5497 0 : expr->value.conditional.true_expr);
5498 0 : gfc_apply_interface_mapping_to_expr (mapping,
5499 0 : expr->value.conditional.false_expr);
5500 0 : break;
5501 :
5502 2957 : case EXPR_FUNCTION:
5503 9502 : for (actual = expr->value.function.actual; actual; actual = actual->next)
5504 6545 : gfc_apply_interface_mapping_to_expr (mapping, actual->expr);
5505 :
5506 2957 : if (expr->value.function.esym == NULL
5507 2644 : && expr->value.function.isym != NULL
5508 2632 : && expr->value.function.actual
5509 2631 : && expr->value.function.actual->expr
5510 2631 : && expr->value.function.actual->expr->symtree
5511 5171 : && gfc_map_intrinsic_function (expr, mapping))
5512 : break;
5513 :
5514 6154 : for (sym = mapping->syms; sym; sym = sym->next)
5515 3538 : if (sym->old == expr->value.function.esym)
5516 : {
5517 24 : expr->value.function.esym = sym->new_sym->n.sym;
5518 24 : gfc_map_fcn_formal_to_actual (expr, sym->expr, mapping);
5519 24 : expr->value.function.esym->result = sym->new_sym->n.sym;
5520 : }
5521 : break;
5522 :
5523 47 : case EXPR_ARRAY:
5524 47 : case EXPR_STRUCTURE:
5525 47 : gfc_apply_interface_mapping_to_cons (mapping, expr->value.constructor);
5526 47 : break;
5527 :
5528 0 : case EXPR_COMPCALL:
5529 0 : case EXPR_PPC:
5530 0 : case EXPR_UNKNOWN:
5531 0 : gcc_unreachable ();
5532 : break;
5533 : }
5534 :
5535 : return;
5536 : }
5537 :
5538 :
5539 : /* Evaluate interface expression EXPR using MAPPING. Store the result
5540 : in SE. */
5541 :
5542 : void
5543 4016 : gfc_apply_interface_mapping (gfc_interface_mapping * mapping,
5544 : gfc_se * se, gfc_expr * expr)
5545 : {
5546 4016 : expr = gfc_copy_expr (expr);
5547 4016 : gfc_apply_interface_mapping_to_expr (mapping, expr);
5548 4016 : gfc_conv_expr (se, expr);
5549 4016 : se->expr = gfc_evaluate_now (se->expr, &se->pre);
5550 4016 : gfc_free_expr (expr);
5551 4016 : }
5552 :
5553 :
5554 : /* Returns a reference to a temporary array into which a component of
5555 : an actual argument derived type array is copied and then returned
5556 : after the function call. */
5557 : void
5558 2631 : gfc_conv_subref_array_arg (gfc_se *se, gfc_expr * expr, int g77,
5559 : sym_intent intent, bool formal_ptr,
5560 : const gfc_symbol *fsym, const char *proc_name,
5561 : gfc_symbol *sym, bool check_contiguous)
5562 : {
5563 2631 : gfc_se lse;
5564 2631 : gfc_se rse;
5565 2631 : gfc_ss *lss;
5566 2631 : gfc_ss *rss;
5567 2631 : gfc_loopinfo loop;
5568 2631 : gfc_loopinfo loop2;
5569 2631 : gfc_array_info *info;
5570 2631 : tree offset;
5571 2631 : tree tmp_index;
5572 2631 : tree tmp;
5573 2631 : tree base_type;
5574 2631 : tree size;
5575 2631 : stmtblock_t body;
5576 2631 : int n;
5577 2631 : int dimen;
5578 2631 : gfc_se work_se;
5579 2631 : gfc_se *parmse;
5580 2631 : bool pass_optional;
5581 2631 : bool readonly;
5582 :
5583 2631 : pass_optional = fsym && fsym->attr.optional && sym && sym->attr.optional;
5584 :
5585 2620 : if (pass_optional || check_contiguous)
5586 : {
5587 1348 : gfc_init_se (&work_se, NULL);
5588 1348 : parmse = &work_se;
5589 : }
5590 : else
5591 : parmse = se;
5592 :
5593 2631 : if (gfc_option.rtcheck & GFC_RTCHECK_ARRAY_TEMPS)
5594 : {
5595 : /* We will create a temporary array, so let us warn. */
5596 868 : char * msg;
5597 :
5598 868 : if (fsym && proc_name)
5599 868 : msg = xasprintf ("An array temporary was created for argument "
5600 868 : "'%s' of procedure '%s'", fsym->name, proc_name);
5601 : else
5602 0 : msg = xasprintf ("An array temporary was created");
5603 :
5604 868 : tmp = build_int_cst (logical_type_node, 1);
5605 868 : gfc_trans_runtime_check (false, true, tmp, &parmse->pre,
5606 : &expr->where, msg);
5607 868 : free (msg);
5608 : }
5609 :
5610 2631 : gfc_init_se (&lse, NULL);
5611 2631 : gfc_init_se (&rse, NULL);
5612 :
5613 : /* Walk the argument expression. */
5614 2631 : rss = gfc_walk_expr (expr);
5615 :
5616 2631 : gcc_assert (rss != gfc_ss_terminator);
5617 :
5618 : /* Initialize the scalarizer. */
5619 2631 : gfc_init_loopinfo (&loop);
5620 2631 : gfc_add_ss_to_loop (&loop, rss);
5621 :
5622 : /* Calculate the bounds of the scalarization. */
5623 2631 : gfc_conv_ss_startstride (&loop);
5624 :
5625 : /* Build an ss for the temporary. */
5626 2631 : if (expr->ts.type == BT_CHARACTER && !expr->ts.u.cl->backend_decl)
5627 136 : gfc_conv_string_length (expr->ts.u.cl, expr, &parmse->pre);
5628 :
5629 2631 : base_type = gfc_typenode_for_spec (&expr->ts);
5630 2631 : if (GFC_ARRAY_TYPE_P (base_type)
5631 2631 : || GFC_DESCRIPTOR_TYPE_P (base_type))
5632 0 : base_type = gfc_get_element_type (base_type);
5633 :
5634 2631 : if (expr->ts.type == BT_CLASS)
5635 121 : base_type = gfc_typenode_for_spec (&CLASS_DATA (expr)->ts);
5636 :
5637 3795 : loop.temp_ss = gfc_get_temp_ss (base_type, ((expr->ts.type == BT_CHARACTER)
5638 1164 : ? expr->ts.u.cl->backend_decl
5639 : : NULL),
5640 : loop.dimen);
5641 :
5642 2631 : parmse->string_length = loop.temp_ss->info->string_length;
5643 :
5644 : /* Associate the SS with the loop. */
5645 2631 : gfc_add_ss_to_loop (&loop, loop.temp_ss);
5646 :
5647 : /* Setup the scalarizing loops. */
5648 2631 : gfc_conv_loop_setup (&loop, &expr->where);
5649 :
5650 : /* Pass the temporary descriptor back to the caller. */
5651 2631 : info = &loop.temp_ss->info->data.array;
5652 2631 : parmse->expr = info->descriptor;
5653 :
5654 : /* Setup the gfc_se structures. */
5655 2631 : gfc_copy_loopinfo_to_se (&lse, &loop);
5656 2631 : gfc_copy_loopinfo_to_se (&rse, &loop);
5657 :
5658 2631 : rse.ss = rss;
5659 2631 : lse.ss = loop.temp_ss;
5660 2631 : gfc_mark_ss_chain_used (rss, 1);
5661 2631 : gfc_mark_ss_chain_used (loop.temp_ss, 1);
5662 :
5663 : /* Start the scalarized loop body. */
5664 2631 : gfc_start_scalarized_body (&loop, &body);
5665 :
5666 : /* Translate the expression. */
5667 2631 : gfc_conv_expr (&rse, expr);
5668 :
5669 2631 : gfc_conv_tmp_array_ref (&lse);
5670 :
5671 2631 : if (intent != INTENT_OUT)
5672 : {
5673 2593 : tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts, false, false);
5674 2593 : gfc_add_expr_to_block (&body, tmp);
5675 2593 : gcc_assert (rse.ss == gfc_ss_terminator);
5676 2593 : gfc_trans_scalarizing_loops (&loop, &body);
5677 : }
5678 : else
5679 : {
5680 : /* Make sure that the temporary declaration survives by merging
5681 : all the loop declarations into the current context. */
5682 85 : for (n = 0; n < loop.dimen; n++)
5683 : {
5684 47 : gfc_merge_block_scope (&body);
5685 47 : body = loop.code[loop.order[n]];
5686 : }
5687 38 : gfc_merge_block_scope (&body);
5688 : }
5689 :
5690 : /* Add the post block after the second loop, so that any
5691 : freeing of allocated memory is done at the right time. */
5692 2631 : gfc_add_block_to_block (&parmse->pre, &loop.pre);
5693 :
5694 : /**********Copy the temporary back again.*********/
5695 :
5696 2631 : gfc_init_se (&lse, NULL);
5697 2631 : gfc_init_se (&rse, NULL);
5698 :
5699 : /* Walk the argument expression. */
5700 2631 : lss = gfc_walk_expr (expr);
5701 2631 : rse.ss = loop.temp_ss;
5702 2631 : lse.ss = lss;
5703 :
5704 : /* Initialize the scalarizer. */
5705 2631 : gfc_init_loopinfo (&loop2);
5706 2631 : gfc_add_ss_to_loop (&loop2, lss);
5707 :
5708 2631 : dimen = rse.ss->dimen;
5709 :
5710 : /* Skip the write-out loop for this case. */
5711 2631 : if (gfc_is_class_array_function (expr))
5712 13 : goto class_array_fcn;
5713 :
5714 : /* Calculate the bounds of the scalarization. */
5715 2618 : gfc_conv_ss_startstride (&loop2);
5716 :
5717 : /* Setup the scalarizing loops. */
5718 2618 : gfc_conv_loop_setup (&loop2, &expr->where);
5719 :
5720 2618 : gfc_copy_loopinfo_to_se (&lse, &loop2);
5721 2618 : gfc_copy_loopinfo_to_se (&rse, &loop2);
5722 :
5723 2618 : gfc_mark_ss_chain_used (lss, 1);
5724 2618 : gfc_mark_ss_chain_used (loop.temp_ss, 1);
5725 :
5726 : /* Declare the variable to hold the temporary offset and start the
5727 : scalarized loop body. */
5728 2618 : offset = gfc_create_var (gfc_array_index_type, NULL);
5729 2618 : gfc_start_scalarized_body (&loop2, &body);
5730 :
5731 : /* Build the offsets for the temporary from the loop variables. The
5732 : temporary array has lbounds of zero and strides of one in all
5733 : dimensions, so this is very simple. The offset is only computed
5734 : outside the innermost loop, so the overall transfer could be
5735 : optimized further. */
5736 2618 : info = &rse.ss->info->data.array;
5737 :
5738 2618 : tmp_index = gfc_index_zero_node;
5739 3989 : for (n = dimen - 1; n > 0; n--)
5740 : {
5741 1371 : tree tmp_str;
5742 1371 : tmp = rse.loop->loopvar[n];
5743 1371 : tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
5744 : tmp, rse.loop->from[n]);
5745 1371 : tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
5746 : tmp, tmp_index);
5747 :
5748 2742 : tmp_str = fold_build2_loc (input_location, MINUS_EXPR,
5749 : gfc_array_index_type,
5750 1371 : rse.loop->to[n-1], rse.loop->from[n-1]);
5751 1371 : tmp_str = fold_build2_loc (input_location, PLUS_EXPR,
5752 : gfc_array_index_type,
5753 : tmp_str, gfc_index_one_node);
5754 :
5755 1371 : tmp_index = fold_build2_loc (input_location, MULT_EXPR,
5756 : gfc_array_index_type, tmp, tmp_str);
5757 : }
5758 :
5759 5236 : tmp_index = fold_build2_loc (input_location, MINUS_EXPR,
5760 : gfc_array_index_type,
5761 2618 : tmp_index, rse.loop->from[0]);
5762 2618 : gfc_add_modify (&rse.loop->code[0], offset, tmp_index);
5763 :
5764 5236 : tmp_index = fold_build2_loc (input_location, PLUS_EXPR,
5765 : gfc_array_index_type,
5766 2618 : rse.loop->loopvar[0], offset);
5767 :
5768 : /* Now use the offset for the reference. */
5769 2618 : tmp = build_fold_indirect_ref_loc (input_location,
5770 : info->data);
5771 2618 : rse.expr = gfc_build_array_ref (tmp, tmp_index, NULL);
5772 :
5773 2618 : if (expr->ts.type == BT_CHARACTER)
5774 1164 : rse.string_length = expr->ts.u.cl->backend_decl;
5775 :
5776 2618 : gfc_conv_expr (&lse, expr);
5777 :
5778 2618 : gcc_assert (lse.ss == gfc_ss_terminator);
5779 :
5780 : /* Do not do deallocations when we are looking at a g77-style argument. */
5781 :
5782 2618 : tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts, false, !g77);
5783 2618 : gfc_add_expr_to_block (&body, tmp);
5784 :
5785 : /* Generate the copying loops. */
5786 2618 : gfc_trans_scalarizing_loops (&loop2, &body);
5787 :
5788 : /* Wrap the whole thing up by adding the second loop to the post-block
5789 : and following it by the post-block of the first loop. In this way,
5790 : if the temporary needs freeing, it is done after use!
5791 : If input expr is read-only, e.g. a PARAMETER array, copying back
5792 : modified values is undefined behavior. */
5793 5236 : readonly = (expr->expr_type == EXPR_VARIABLE
5794 2552 : && expr->symtree
5795 5170 : && expr->symtree->n.sym->attr.flavor == FL_PARAMETER);
5796 :
5797 2618 : if ((intent != INTENT_IN) && !readonly)
5798 : {
5799 1155 : gfc_add_block_to_block (&parmse->post, &loop2.pre);
5800 1155 : gfc_add_block_to_block (&parmse->post, &loop2.post);
5801 : }
5802 :
5803 1463 : class_array_fcn:
5804 :
5805 2631 : gfc_add_block_to_block (&parmse->post, &loop.post);
5806 :
5807 2631 : gfc_cleanup_loop (&loop);
5808 2631 : gfc_cleanup_loop (&loop2);
5809 :
5810 : /* Pass the string length to the argument expression. */
5811 2631 : if (expr->ts.type == BT_CHARACTER)
5812 1164 : parmse->string_length = expr->ts.u.cl->backend_decl;
5813 :
5814 : /* Determine the offset for pointer formal arguments and set the
5815 : lbounds to one. */
5816 2631 : if (formal_ptr)
5817 : {
5818 18 : size = gfc_index_one_node;
5819 18 : offset = gfc_index_zero_node;
5820 36 : for (n = 0; n < dimen; n++)
5821 : {
5822 18 : tmp = gfc_conv_descriptor_ubound_get (parmse->expr,
5823 : gfc_rank_cst[n]);
5824 18 : tmp = fold_build2_loc (input_location, PLUS_EXPR,
5825 : gfc_array_index_type, tmp,
5826 : gfc_index_one_node);
5827 18 : gfc_conv_descriptor_ubound_set (&parmse->pre,
5828 : parmse->expr,
5829 : gfc_rank_cst[n],
5830 : tmp);
5831 18 : gfc_conv_descriptor_lbound_set (&parmse->pre,
5832 : parmse->expr,
5833 : gfc_rank_cst[n],
5834 : gfc_index_one_node);
5835 18 : size = gfc_evaluate_now (size, &parmse->pre);
5836 18 : offset = fold_build2_loc (input_location, MINUS_EXPR,
5837 : gfc_array_index_type,
5838 : offset, size);
5839 18 : offset = gfc_evaluate_now (offset, &parmse->pre);
5840 36 : tmp = fold_build2_loc (input_location, MINUS_EXPR,
5841 : gfc_array_index_type,
5842 18 : rse.loop->to[n], rse.loop->from[n]);
5843 18 : tmp = fold_build2_loc (input_location, PLUS_EXPR,
5844 : gfc_array_index_type,
5845 : tmp, gfc_index_one_node);
5846 18 : size = fold_build2_loc (input_location, MULT_EXPR,
5847 : gfc_array_index_type, size, tmp);
5848 : }
5849 :
5850 18 : gfc_conv_descriptor_offset_set (&parmse->pre, parmse->expr,
5851 : offset);
5852 : }
5853 :
5854 : /* We want either the address for the data or the address of the descriptor,
5855 : depending on the mode of passing array arguments. */
5856 2631 : if (g77)
5857 426 : parmse->expr = gfc_conv_descriptor_data_get (parmse->expr);
5858 : else
5859 2205 : parmse->expr = gfc_build_addr_expr (NULL_TREE, parmse->expr);
5860 :
5861 : /* Basically make this into
5862 :
5863 : if (present)
5864 : {
5865 : if (contiguous)
5866 : {
5867 : pointer = a;
5868 : }
5869 : else
5870 : {
5871 : parmse->pre();
5872 : pointer = parmse->expr;
5873 : }
5874 : }
5875 : else
5876 : pointer = NULL;
5877 :
5878 : foo (pointer);
5879 : if (present && !contiguous)
5880 : se->post();
5881 :
5882 : */
5883 :
5884 2631 : if (pass_optional || check_contiguous)
5885 : {
5886 1348 : tree type;
5887 1348 : stmtblock_t else_block;
5888 1348 : tree pre_stmts, post_stmts;
5889 1348 : tree pointer;
5890 1348 : tree else_stmt;
5891 1348 : tree present_var = NULL_TREE;
5892 1348 : tree cont_var = NULL_TREE;
5893 1348 : tree post_cond;
5894 :
5895 1348 : type = TREE_TYPE (parmse->expr);
5896 1348 : if (POINTER_TYPE_P (type) && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (type)))
5897 1027 : type = TREE_TYPE (type);
5898 1348 : pointer = gfc_create_var (type, "arg_ptr");
5899 :
5900 1348 : if (check_contiguous)
5901 : {
5902 1348 : gfc_se cont_se, array_se;
5903 1348 : stmtblock_t if_block, else_block;
5904 1348 : tree if_stmt, else_stmt;
5905 1348 : mpz_t size;
5906 1348 : bool size_set;
5907 :
5908 1348 : cont_var = gfc_create_var (boolean_type_node, "contiguous");
5909 :
5910 : /* If the size is known to be one at compile-time, set
5911 : cont_var to true unconditionally. This may look
5912 : inelegant, but we're only doing this during
5913 : optimization, so the statements will be optimized away,
5914 : and this saves complexity here. */
5915 :
5916 1348 : size_set = gfc_array_size (expr, &size);
5917 1348 : if (size_set && mpz_cmp_ui (size, 1) == 0)
5918 : {
5919 6 : gfc_add_modify (&se->pre, cont_var,
5920 : build_one_cst (boolean_type_node));
5921 : }
5922 : else
5923 : {
5924 : /* cont_var = is_contiguous (expr); . */
5925 1342 : gfc_init_se (&cont_se, parmse);
5926 1342 : gfc_conv_is_contiguous_expr (&cont_se, expr);
5927 1342 : gfc_add_block_to_block (&se->pre, &(&cont_se)->pre);
5928 1342 : gfc_add_modify (&se->pre, cont_var, cont_se.expr);
5929 1342 : gfc_add_block_to_block (&se->pre, &(&cont_se)->post);
5930 : }
5931 :
5932 1348 : if (size_set)
5933 1149 : mpz_clear (size);
5934 :
5935 : /* arrayse->expr = descriptor of a. */
5936 1348 : gfc_init_se (&array_se, se);
5937 1348 : gfc_conv_expr_descriptor (&array_se, expr);
5938 1348 : gfc_add_block_to_block (&se->pre, &(&array_se)->pre);
5939 1348 : gfc_add_block_to_block (&se->pre, &(&array_se)->post);
5940 :
5941 : /* if_stmt = { descriptor ? pointer = a : pointer = &a[0]; } . */
5942 1348 : gfc_init_block (&if_block);
5943 1348 : if (GFC_DESCRIPTOR_TYPE_P (type))
5944 1027 : gfc_add_modify (&if_block, pointer, array_se.expr);
5945 : else
5946 : {
5947 321 : tmp = gfc_conv_array_data (array_se.expr);
5948 321 : tmp = fold_convert (type, tmp);
5949 321 : gfc_add_modify (&if_block, pointer, tmp);
5950 : }
5951 1348 : if_stmt = gfc_finish_block (&if_block);
5952 :
5953 : /* else_stmt = { parmse->pre(); pointer = parmse->expr; } . */
5954 1348 : gfc_init_block (&else_block);
5955 1348 : gfc_add_block_to_block (&else_block, &parmse->pre);
5956 1669 : tmp = (GFC_DESCRIPTOR_TYPE_P (type)
5957 1348 : ? build_fold_indirect_ref_loc (input_location, parmse->expr)
5958 : : parmse->expr);
5959 1348 : gfc_add_modify (&else_block, pointer, tmp);
5960 1348 : else_stmt = gfc_finish_block (&else_block);
5961 :
5962 : /* And put the above into an if statement. */
5963 1348 : pre_stmts = fold_build3_loc (input_location, COND_EXPR, void_type_node,
5964 : gfc_likely (cont_var,
5965 : PRED_FORTRAN_CONTIGUOUS),
5966 : if_stmt, else_stmt);
5967 : }
5968 : else
5969 : {
5970 : /* pointer = pramse->expr; . */
5971 0 : gfc_add_modify (&parmse->pre, pointer, parmse->expr);
5972 0 : pre_stmts = gfc_finish_block (&parmse->pre);
5973 : }
5974 :
5975 1348 : if (pass_optional)
5976 : {
5977 11 : present_var = gfc_create_var (boolean_type_node, "present");
5978 :
5979 : /* present_var = present(sym); . */
5980 11 : tmp = gfc_conv_expr_present (sym);
5981 11 : tmp = fold_convert (boolean_type_node, tmp);
5982 11 : gfc_add_modify (&se->pre, present_var, tmp);
5983 :
5984 : /* else_stmt = { pointer = NULL; } . */
5985 11 : gfc_init_block (&else_block);
5986 11 : if (GFC_DESCRIPTOR_TYPE_P (type))
5987 0 : gfc_conv_descriptor_data_set (&else_block, pointer,
5988 : null_pointer_node);
5989 : else
5990 11 : gfc_add_modify (&else_block, pointer, build_int_cst (type, 0));
5991 11 : else_stmt = gfc_finish_block (&else_block);
5992 :
5993 11 : tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
5994 : gfc_likely (present_var,
5995 : PRED_FORTRAN_ABSENT_DUMMY),
5996 : pre_stmts, else_stmt);
5997 11 : gfc_add_expr_to_block (&se->pre, tmp);
5998 : }
5999 : else
6000 1337 : gfc_add_expr_to_block (&se->pre, pre_stmts);
6001 :
6002 1348 : post_stmts = gfc_finish_block (&parmse->post);
6003 :
6004 : /* Put together the post stuff, plus the optional
6005 : deallocation. */
6006 1348 : if (check_contiguous)
6007 : {
6008 : /* !cont_var. */
6009 1348 : tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
6010 : cont_var,
6011 : build_zero_cst (boolean_type_node));
6012 1348 : tmp = gfc_unlikely (tmp, PRED_FORTRAN_CONTIGUOUS);
6013 :
6014 1348 : if (pass_optional)
6015 : {
6016 11 : tree present_likely = gfc_likely (present_var,
6017 : PRED_FORTRAN_ABSENT_DUMMY);
6018 11 : post_cond = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
6019 : boolean_type_node, present_likely,
6020 : tmp);
6021 : }
6022 : else
6023 : post_cond = tmp;
6024 : }
6025 : else
6026 : {
6027 0 : gcc_assert (pass_optional);
6028 : post_cond = present_var;
6029 : }
6030 :
6031 1348 : tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, post_cond,
6032 : post_stmts, build_empty_stmt (input_location));
6033 1348 : gfc_add_expr_to_block (&se->post, tmp);
6034 1348 : if (GFC_DESCRIPTOR_TYPE_P (type))
6035 : {
6036 1027 : type = TREE_TYPE (parmse->expr);
6037 1027 : if (POINTER_TYPE_P (type))
6038 : {
6039 1027 : pointer = gfc_build_addr_expr (type, pointer);
6040 1027 : if (pass_optional)
6041 : {
6042 0 : tmp = gfc_likely (present_var, PRED_FORTRAN_ABSENT_DUMMY);
6043 0 : pointer = fold_build3_loc (input_location, COND_EXPR, type,
6044 : tmp, pointer,
6045 : fold_convert (type,
6046 : null_pointer_node));
6047 : }
6048 : }
6049 : else
6050 0 : gcc_assert (!pass_optional);
6051 : }
6052 1348 : se->expr = pointer;
6053 : }
6054 :
6055 2631 : return;
6056 : }
6057 :
6058 :
6059 : /* Generate the code for argument list functions. */
6060 :
6061 : static void
6062 5826 : conv_arglist_function (gfc_se *se, gfc_expr *expr, const char *name)
6063 : {
6064 : /* Pass by value for g77 %VAL(arg), pass the address
6065 : indirectly for %LOC, else by reference. Thus %REF
6066 : is a "do-nothing" and %LOC is the same as an F95
6067 : pointer. */
6068 5826 : if (strcmp (name, "%VAL") == 0)
6069 5814 : gfc_conv_expr (se, expr);
6070 12 : else if (strcmp (name, "%LOC") == 0)
6071 : {
6072 6 : gfc_conv_expr_reference (se, expr);
6073 6 : se->expr = gfc_build_addr_expr (NULL, se->expr);
6074 : }
6075 6 : else if (strcmp (name, "%REF") == 0)
6076 6 : gfc_conv_expr_reference (se, expr);
6077 : else
6078 0 : gfc_error ("Unknown argument list function at %L", &expr->where);
6079 5826 : }
6080 :
6081 :
6082 : /* This function tells whether the middle-end representation of the expression
6083 : E given as input may point to data otherwise accessible through a variable
6084 : (sub-)reference.
6085 : It is assumed that the only expressions that may alias are variables,
6086 : and array constructors if ARRAY_MAY_ALIAS is true and some of its elements
6087 : may alias.
6088 : This function is used to decide whether freeing an expression's allocatable
6089 : components is safe or should be avoided.
6090 :
6091 : If ARRAY_MAY_ALIAS is true, an array constructor may alias if some of
6092 : its elements are copied from a variable. This ARRAY_MAY_ALIAS trick
6093 : is necessary because for array constructors, aliasing depends on how
6094 : the array is used:
6095 : - If E is an array constructor used as argument to an elemental procedure,
6096 : the array, which is generated through shallow copy by the scalarizer,
6097 : is used directly and can alias the expressions it was copied from.
6098 : - If E is an array constructor used as argument to a non-elemental
6099 : procedure,the scalarizer is used in gfc_conv_expr_descriptor to generate
6100 : the array as in the previous case, but then that array is used
6101 : to initialize a new descriptor through deep copy. There is no alias
6102 : possible in that case.
6103 : Thus, the ARRAY_MAY_ALIAS flag is necessary to distinguish the two cases
6104 : above. */
6105 :
6106 : static bool
6107 7654 : expr_may_alias_variables (gfc_expr *e, bool array_may_alias)
6108 : {
6109 7654 : gfc_constructor *c;
6110 :
6111 7654 : if (e->expr_type == EXPR_VARIABLE)
6112 : return true;
6113 562 : else if (e->expr_type == EXPR_FUNCTION)
6114 : {
6115 161 : gfc_symbol *proc_ifc = gfc_get_proc_ifc_for_expr (e);
6116 :
6117 161 : if (proc_ifc->result != NULL
6118 161 : && ((proc_ifc->result->ts.type == BT_CLASS
6119 25 : && proc_ifc->result->ts.u.derived->attr.is_class
6120 25 : && CLASS_DATA (proc_ifc->result)->attr.class_pointer)
6121 161 : || proc_ifc->result->attr.pointer))
6122 : return true;
6123 : else
6124 : return false;
6125 : }
6126 401 : else if (e->expr_type != EXPR_ARRAY || !array_may_alias)
6127 : return false;
6128 :
6129 79 : for (c = gfc_constructor_first (e->value.constructor);
6130 233 : c; c = gfc_constructor_next (c))
6131 189 : if (c->expr
6132 189 : && expr_may_alias_variables (c->expr, array_may_alias))
6133 : return true;
6134 :
6135 : return false;
6136 : }
6137 :
6138 :
6139 : /* A helper function to set the dtype for unallocated or unassociated
6140 : entities. */
6141 :
6142 : static void
6143 891 : set_dtype_for_unallocated (gfc_se *parmse, gfc_expr *e)
6144 : {
6145 891 : tree tmp;
6146 891 : tree desc;
6147 891 : tree cond;
6148 891 : tree type;
6149 891 : stmtblock_t block;
6150 :
6151 : /* TODO Figure out how to handle optional dummies. */
6152 891 : if (e && e->expr_type == EXPR_VARIABLE
6153 807 : && e->symtree->n.sym->attr.optional)
6154 108 : return;
6155 :
6156 819 : desc = parmse->expr;
6157 819 : if (desc == NULL_TREE)
6158 : return;
6159 :
6160 819 : if (POINTER_TYPE_P (TREE_TYPE (desc)))
6161 819 : desc = build_fold_indirect_ref_loc (input_location, desc);
6162 819 : if (GFC_CLASS_TYPE_P (TREE_TYPE (desc)))
6163 192 : desc = gfc_class_data_get (desc);
6164 819 : if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
6165 : return;
6166 :
6167 783 : gfc_init_block (&block);
6168 783 : tmp = gfc_conv_descriptor_data_get (desc);
6169 783 : cond = fold_build2_loc (input_location, EQ_EXPR,
6170 : logical_type_node, tmp,
6171 783 : build_int_cst (TREE_TYPE (tmp), 0));
6172 783 : tmp = gfc_conv_descriptor_dtype (desc);
6173 783 : type = gfc_get_element_type (TREE_TYPE (desc));
6174 1566 : tmp = fold_build2_loc (input_location, MODIFY_EXPR,
6175 783 : TREE_TYPE (tmp), tmp,
6176 : gfc_get_dtype_rank_type (e->rank, type));
6177 783 : gfc_add_expr_to_block (&block, tmp);
6178 783 : cond = build3_v (COND_EXPR, cond,
6179 : gfc_finish_block (&block),
6180 : build_empty_stmt (input_location));
6181 783 : gfc_add_expr_to_block (&parmse->pre, cond);
6182 : }
6183 :
6184 :
6185 :
6186 : /* Provide an interface between gfortran array descriptors and the F2018:18.4
6187 : ISO_Fortran_binding array descriptors. */
6188 :
6189 : static void
6190 6537 : gfc_conv_gfc_desc_to_cfi_desc (gfc_se *parmse, gfc_expr *e, gfc_symbol *fsym)
6191 : {
6192 6537 : stmtblock_t block, block2;
6193 6537 : tree cfi, gfc, tmp, tmp2;
6194 6537 : tree present = NULL;
6195 6537 : tree gfc_strlen = NULL;
6196 6537 : tree rank;
6197 6537 : gfc_se se;
6198 :
6199 6537 : if (fsym->attr.optional
6200 1094 : && e->expr_type == EXPR_VARIABLE
6201 1094 : && e->symtree->n.sym->attr.optional)
6202 103 : present = gfc_conv_expr_present (e->symtree->n.sym);
6203 :
6204 6537 : gfc_init_block (&block);
6205 :
6206 : /* Convert original argument to a tree. */
6207 6537 : gfc_init_se (&se, NULL);
6208 6537 : if (e->rank == 0)
6209 : {
6210 687 : se.want_pointer = 1;
6211 687 : gfc_conv_expr (&se, e);
6212 687 : gfc = se.expr;
6213 : }
6214 : else
6215 : {
6216 : /* If the actual argument can be noncontiguous, copy-in/out is required,
6217 : if the dummy has either the CONTIGUOUS attribute or is an assumed-
6218 : length assumed-length/assumed-size CHARACTER array. This only
6219 : applies if the actual argument is a "variable"; if it's some
6220 : non-lvalue expression, we are going to evaluate it to a
6221 : temporary below anyway. */
6222 5850 : se.force_no_tmp = 1;
6223 5850 : if ((fsym->attr.contiguous
6224 4769 : || (fsym->ts.type == BT_CHARACTER && !fsym->ts.u.cl->length
6225 1375 : && (fsym->as->type == AS_ASSUMED_SIZE
6226 937 : || fsym->as->type == AS_EXPLICIT)))
6227 2023 : && !gfc_is_simply_contiguous (e, false, true)
6228 6883 : && gfc_expr_is_variable (e))
6229 : {
6230 1027 : bool optional = fsym->attr.optional;
6231 1027 : fsym->attr.optional = 0;
6232 1027 : gfc_conv_subref_array_arg (&se, e, false, fsym->attr.intent,
6233 1027 : fsym->attr.pointer, fsym,
6234 1027 : fsym->ns->proc_name->name, NULL,
6235 : /* check_contiguous= */ true);
6236 1027 : fsym->attr.optional = optional;
6237 : }
6238 : else
6239 4823 : gfc_conv_expr_descriptor (&se, e);
6240 5850 : gfc = se.expr;
6241 : /* For dt(:)%var the elem_len*stride != sm, hence, GFC uses
6242 : elem_len = sizeof(dt) and base_addr = dt(lb) instead.
6243 : gfc_get_dataptr_offset fixes the base_addr; for elem_len, see below.
6244 : While sm is fine as it uses span*stride and not elem_len. */
6245 5850 : if (POINTER_TYPE_P (TREE_TYPE (gfc)))
6246 1027 : gfc = build_fold_indirect_ref_loc (input_location, gfc);
6247 4823 : else if (is_subref_array (e) && e->ts.type != BT_CHARACTER)
6248 12 : gfc_get_dataptr_offset (&se.pre, gfc, gfc, NULL, true, e);
6249 : }
6250 6537 : if (e->ts.type == BT_CHARACTER)
6251 : {
6252 3409 : if (se.string_length)
6253 : gfc_strlen = se.string_length;
6254 883 : else if (e->ts.u.cl->backend_decl)
6255 : gfc_strlen = e->ts.u.cl->backend_decl;
6256 : else
6257 0 : gcc_unreachable ();
6258 : }
6259 6537 : gfc_add_block_to_block (&block, &se.pre);
6260 :
6261 : /* Create array descriptor and set version, rank, attribute, type. */
6262 12769 : cfi = gfc_create_var (gfc_get_cfi_type (e->rank < 0
6263 : ? GFC_MAX_DIMENSIONS : e->rank,
6264 : false), "cfi");
6265 : /* Convert to CFI_cdesc_t, which has dim[] to avoid TBAA issues,*/
6266 6537 : if (fsym->attr.dimension && fsym->as->type == AS_ASSUMED_RANK)
6267 : {
6268 2516 : tmp = gfc_get_cfi_type (-1, !fsym->attr.pointer && !fsym->attr.target);
6269 2338 : tmp = build_pointer_type (tmp);
6270 2338 : parmse->expr = cfi = gfc_build_addr_expr (tmp, cfi);
6271 2338 : cfi = build_fold_indirect_ref_loc (input_location, cfi);
6272 : }
6273 : else
6274 4199 : parmse->expr = gfc_build_addr_expr (NULL, cfi);
6275 :
6276 6537 : tmp = gfc_get_cfi_desc_version (cfi);
6277 6537 : gfc_add_modify (&block, tmp,
6278 6537 : build_int_cst (TREE_TYPE (tmp), CFI_VERSION));
6279 6537 : if (e->rank < 0)
6280 305 : rank = gfc_conv_descriptor_rank (gfc);
6281 : else
6282 6232 : rank = gfc_rank_cst[e->rank];
6283 6537 : tmp = gfc_get_cfi_desc_rank (cfi);
6284 6537 : gfc_add_modify (&block, tmp,
6285 6537 : fold_convert (TREE_TYPE (tmp), rank));
6286 6537 : int itype = CFI_type_other;
6287 6537 : if (e->ts.f90_type == BT_VOID)
6288 96 : itype = (e->ts.u.derived->intmod_sym_id == ISOCBINDING_FUNPTR
6289 96 : ? CFI_type_cfunptr : CFI_type_cptr);
6290 : else
6291 : {
6292 6441 : if (e->expr_type == EXPR_NULL && e->ts.type == BT_UNKNOWN)
6293 1 : e->ts = fsym->ts;
6294 6441 : switch (e->ts.type)
6295 : {
6296 2296 : case BT_INTEGER:
6297 2296 : case BT_LOGICAL:
6298 2296 : case BT_REAL:
6299 2296 : case BT_COMPLEX:
6300 2296 : itype = CFI_type_from_type_kind (e->ts.type, e->ts.kind);
6301 2296 : break;
6302 3410 : case BT_CHARACTER:
6303 3410 : itype = CFI_type_from_type_kind (CFI_type_Character, e->ts.kind);
6304 3410 : break;
6305 : case BT_DERIVED:
6306 6537 : itype = CFI_type_struct;
6307 : break;
6308 0 : case BT_VOID:
6309 0 : itype = (e->ts.u.derived->intmod_sym_id == ISOCBINDING_FUNPTR
6310 0 : ? CFI_type_cfunptr : CFI_type_cptr);
6311 : break;
6312 : case BT_ASSUMED:
6313 : itype = CFI_type_other; // FIXME: Or CFI_type_cptr ?
6314 : break;
6315 1 : case BT_CLASS:
6316 1 : if (fsym->ts.type == BT_ASSUMED)
6317 : {
6318 : // F2017: 7.3.2.2: "An entity that is declared using the TYPE(*)
6319 : // type specifier is assumed-type and is an unlimited polymorphic
6320 : // entity." The actual argument _data component is passed.
6321 : itype = CFI_type_other; // FIXME: Or CFI_type_cptr ?
6322 : break;
6323 : }
6324 : else
6325 0 : gcc_unreachable ();
6326 :
6327 0 : case BT_UNSIGNED:
6328 0 : gfc_internal_error ("Unsigned not yet implemented");
6329 :
6330 0 : case BT_PROCEDURE:
6331 0 : case BT_HOLLERITH:
6332 0 : case BT_UNION:
6333 0 : case BT_BOZ:
6334 0 : case BT_UNKNOWN:
6335 : // FIXME: Really unreachable? Or reachable for type(*) ? If so, CFI_type_other?
6336 0 : gcc_unreachable ();
6337 : }
6338 : }
6339 :
6340 6537 : tmp = gfc_get_cfi_desc_type (cfi);
6341 6537 : gfc_add_modify (&block, tmp,
6342 6537 : build_int_cst (TREE_TYPE (tmp), itype));
6343 :
6344 6537 : int attr = CFI_attribute_other;
6345 6537 : if (fsym->attr.pointer)
6346 : attr = CFI_attribute_pointer;
6347 5774 : else if (fsym->attr.allocatable)
6348 433 : attr = CFI_attribute_allocatable;
6349 6537 : tmp = gfc_get_cfi_desc_attribute (cfi);
6350 6537 : gfc_add_modify (&block, tmp,
6351 6537 : build_int_cst (TREE_TYPE (tmp), attr));
6352 :
6353 : /* The cfi-base_addr assignment could be skipped for 'pointer, intent(out)'.
6354 : That is very sensible for undefined pointers, but the C code might assume
6355 : that the pointer retains the value, in particular, if it was NULL. */
6356 6537 : if (e->rank == 0)
6357 : {
6358 687 : tmp = gfc_get_cfi_desc_base_addr (cfi);
6359 687 : gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), gfc));
6360 : }
6361 : else
6362 : {
6363 5850 : tmp = gfc_get_cfi_desc_base_addr (cfi);
6364 5850 : tmp2 = gfc_conv_descriptor_data_get (gfc);
6365 5850 : gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), tmp2));
6366 : }
6367 :
6368 : /* Set elem_len if known - must be before the next if block.
6369 : Note that allocatable implies 'len=:'. */
6370 6537 : if (e->ts.type != BT_ASSUMED && e->ts.type != BT_CHARACTER )
6371 : {
6372 : /* Length is known at compile time; use 'block' for it. */
6373 3073 : tmp = size_in_bytes (gfc_typenode_for_spec (&e->ts));
6374 3073 : tmp2 = gfc_get_cfi_desc_elem_len (cfi);
6375 3073 : gfc_add_modify (&block, tmp2, fold_convert (TREE_TYPE (tmp2), tmp));
6376 : }
6377 :
6378 6537 : if (fsym->attr.pointer && fsym->attr.intent == INTENT_OUT)
6379 91 : goto done;
6380 :
6381 : /* When allocatable + intent out, free the cfi descriptor. */
6382 6446 : if (fsym->attr.allocatable && fsym->attr.intent == INTENT_OUT)
6383 : {
6384 90 : tmp = gfc_get_cfi_desc_base_addr (cfi);
6385 90 : tree call = builtin_decl_explicit (BUILT_IN_FREE);
6386 90 : call = build_call_expr_loc (input_location, call, 1, tmp);
6387 90 : gfc_add_expr_to_block (&block, fold_convert (void_type_node, call));
6388 90 : gfc_add_modify (&block, tmp,
6389 90 : fold_convert (TREE_TYPE (tmp), null_pointer_node));
6390 90 : goto done;
6391 : }
6392 :
6393 : /* If not unallocated/unassociated. */
6394 6356 : gfc_init_block (&block2);
6395 :
6396 : /* Set elem_len, which may be only known at run time. */
6397 6356 : if (e->ts.type == BT_CHARACTER
6398 3410 : && (e->expr_type != EXPR_NULL || gfc_strlen != NULL_TREE))
6399 : {
6400 3408 : gcc_assert (gfc_strlen);
6401 3409 : tmp = gfc_strlen;
6402 3409 : if (e->ts.kind != 1)
6403 1117 : tmp = fold_build2_loc (input_location, MULT_EXPR,
6404 : gfc_charlen_type_node, tmp,
6405 : build_int_cst (gfc_charlen_type_node,
6406 1117 : e->ts.kind));
6407 3409 : tmp2 = gfc_get_cfi_desc_elem_len (cfi);
6408 3409 : gfc_add_modify (&block2, tmp2, fold_convert (TREE_TYPE (tmp2), tmp));
6409 : }
6410 2947 : else if (e->ts.type == BT_ASSUMED)
6411 : {
6412 54 : tmp = gfc_conv_descriptor_elem_len (gfc);
6413 54 : tmp2 = gfc_get_cfi_desc_elem_len (cfi);
6414 54 : gfc_add_modify (&block2, tmp2, fold_convert (TREE_TYPE (tmp2), tmp));
6415 : }
6416 :
6417 6356 : if (e->ts.type == BT_ASSUMED)
6418 : {
6419 : /* Note: type(*) implies assumed-shape/assumed-rank if fsym requires
6420 : an CFI descriptor. Use the type in the descriptor as it provide
6421 : mode information. (Quality of implementation feature.) */
6422 54 : tree cond;
6423 54 : tree ctype = gfc_get_cfi_desc_type (cfi);
6424 54 : tree type = fold_convert (TREE_TYPE (ctype),
6425 : gfc_conv_descriptor_type (gfc));
6426 54 : tree kind = fold_convert (TREE_TYPE (ctype),
6427 : gfc_conv_descriptor_elem_len (gfc));
6428 54 : kind = fold_build2_loc (input_location, LSHIFT_EXPR, TREE_TYPE (type),
6429 54 : kind, build_int_cst (TREE_TYPE (type),
6430 : CFI_type_kind_shift));
6431 :
6432 : /* if (BT_VOID) CFI_type_cptr else CFI_type_other */
6433 : /* Note: BT_VOID is could also be CFI_type_funcptr, but assume c_ptr. */
6434 54 : cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, type,
6435 54 : build_int_cst (TREE_TYPE (type), BT_VOID));
6436 54 : tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node, ctype,
6437 54 : build_int_cst (TREE_TYPE (type), CFI_type_cptr));
6438 54 : tmp2 = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
6439 : ctype,
6440 54 : build_int_cst (TREE_TYPE (type), CFI_type_other));
6441 54 : tmp2 = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
6442 : tmp, tmp2);
6443 : /* if (BT_DERIVED) CFI_type_struct else < tmp2 > */
6444 54 : cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, type,
6445 54 : build_int_cst (TREE_TYPE (type), BT_DERIVED));
6446 54 : tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node, ctype,
6447 54 : build_int_cst (TREE_TYPE (type), CFI_type_struct));
6448 54 : tmp2 = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
6449 : tmp, tmp2);
6450 : /* if (BT_CHARACTER) CFI_type_Character + kind=1 else < tmp2 > */
6451 : /* Note: could also be kind=4, with cfi->elem_len = gfc->elem_len*4. */
6452 54 : cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, type,
6453 54 : build_int_cst (TREE_TYPE (type), BT_CHARACTER));
6454 54 : tmp = build_int_cst (TREE_TYPE (type),
6455 : CFI_type_from_type_kind (CFI_type_Character, 1));
6456 54 : tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
6457 : ctype, tmp);
6458 54 : tmp2 = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
6459 : tmp, tmp2);
6460 : /* if (BT_COMPLEX) CFI_type_Complex + kind/2 else < tmp2 > */
6461 54 : cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, type,
6462 54 : build_int_cst (TREE_TYPE (type), BT_COMPLEX));
6463 54 : tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR, TREE_TYPE (type),
6464 54 : kind, build_int_cst (TREE_TYPE (type), 2));
6465 54 : tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (type), tmp,
6466 54 : build_int_cst (TREE_TYPE (type),
6467 : CFI_type_Complex));
6468 54 : tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
6469 : ctype, tmp);
6470 54 : tmp2 = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
6471 : tmp, tmp2);
6472 : /* if (BT_INTEGER || BT_LOGICAL || BT_REAL) type + kind else <tmp2> */
6473 54 : cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, type,
6474 54 : build_int_cst (TREE_TYPE (type), BT_INTEGER));
6475 54 : tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, type,
6476 54 : build_int_cst (TREE_TYPE (type), BT_LOGICAL));
6477 54 : cond = fold_build2_loc (input_location, TRUTH_OR_EXPR, boolean_type_node,
6478 : cond, tmp);
6479 54 : tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, type,
6480 54 : build_int_cst (TREE_TYPE (type), BT_REAL));
6481 54 : cond = fold_build2_loc (input_location, TRUTH_OR_EXPR, boolean_type_node,
6482 : cond, tmp);
6483 54 : tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (type),
6484 : type, kind);
6485 54 : tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
6486 : ctype, tmp);
6487 54 : tmp2 = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
6488 : tmp, tmp2);
6489 54 : gfc_add_expr_to_block (&block2, tmp2);
6490 : }
6491 :
6492 6356 : if (e->rank != 0)
6493 : {
6494 : /* Loop: for (i = 0; i < rank; ++i). */
6495 5735 : tree idx = gfc_create_var (gfc_array_dim_rank_type, "idx");
6496 : /* Loop body. */
6497 5735 : stmtblock_t loop_body;
6498 5735 : gfc_init_block (&loop_body);
6499 : /* cfi->dim[i].lower_bound = (allocatable/pointer)
6500 : ? gfc->dim[i].lbound : 0 */
6501 5735 : if (fsym->attr.pointer || fsym->attr.allocatable)
6502 648 : tmp = gfc_conv_descriptor_lbound_get (gfc, idx);
6503 : else
6504 5087 : tmp = gfc_index_zero_node;
6505 5735 : gfc_add_modify (&loop_body, gfc_get_cfi_dim_lbound (cfi, idx), tmp);
6506 : /* cfi->dim[i].extent = gfc->dim[i].ubound - gfc->dim[i].lbound + 1. */
6507 5735 : tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
6508 : gfc_conv_descriptor_ubound_get (gfc, idx),
6509 : gfc_conv_descriptor_lbound_get (gfc, idx));
6510 5735 : tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
6511 : tmp, gfc_index_one_node);
6512 5735 : gfc_add_modify (&loop_body, gfc_get_cfi_dim_extent (cfi, idx), tmp);
6513 : /* d->dim[n].sm = gfc->dim[i].stride * gfc->span); */
6514 5735 : tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
6515 : gfc_conv_descriptor_stride_get (gfc, idx),
6516 : gfc_conv_descriptor_span_get (gfc));
6517 5735 : gfc_add_modify (&loop_body, gfc_get_cfi_dim_sm (cfi, idx), tmp);
6518 :
6519 : /* Generate loop. */
6520 5735 : gfc_simple_for_loop (&block2, idx, gfc_rank_cst[0], rank, LT_EXPR,
6521 : gfc_rank_cst[1], gfc_finish_block (&loop_body));
6522 :
6523 5735 : if (e->expr_type == EXPR_VARIABLE
6524 5573 : && e->ref
6525 5573 : && e->ref->u.ar.type == AR_FULL
6526 2732 : && e->symtree->n.sym->attr.dummy
6527 988 : && e->symtree->n.sym->as
6528 988 : && e->symtree->n.sym->as->type == AS_ASSUMED_SIZE)
6529 : {
6530 138 : tmp = gfc_get_cfi_dim_extent (cfi, gfc_rank_cst[e->rank-1]),
6531 138 : gfc_add_modify (&block2, tmp, build_int_cst (TREE_TYPE (tmp), -1));
6532 : }
6533 : }
6534 :
6535 6356 : if (fsym->attr.allocatable || fsym->attr.pointer)
6536 : {
6537 1015 : tmp = gfc_get_cfi_desc_base_addr (cfi),
6538 1015 : tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
6539 : tmp, null_pointer_node);
6540 1015 : tmp = build3_v (COND_EXPR, tmp, gfc_finish_block (&block2),
6541 : build_empty_stmt (input_location));
6542 1015 : gfc_add_expr_to_block (&block, tmp);
6543 : }
6544 : else
6545 5341 : gfc_add_block_to_block (&block, &block2);
6546 :
6547 :
6548 6537 : done:
6549 6537 : if (present)
6550 : {
6551 103 : parmse->expr = build3_loc (input_location, COND_EXPR,
6552 103 : TREE_TYPE (parmse->expr),
6553 : present, parmse->expr, null_pointer_node);
6554 103 : tmp = build3_v (COND_EXPR, present, gfc_finish_block (&block),
6555 : build_empty_stmt (input_location));
6556 103 : gfc_add_expr_to_block (&parmse->pre, tmp);
6557 : }
6558 : else
6559 6434 : gfc_add_block_to_block (&parmse->pre, &block);
6560 :
6561 6537 : gfc_init_block (&block);
6562 :
6563 6537 : if ((!fsym->attr.allocatable && !fsym->attr.pointer)
6564 1196 : || fsym->attr.intent == INTENT_IN)
6565 5550 : goto post_call;
6566 :
6567 987 : gfc_init_block (&block2);
6568 987 : if (e->rank == 0)
6569 : {
6570 428 : tmp = gfc_get_cfi_desc_base_addr (cfi);
6571 428 : gfc_add_modify (&block, gfc, fold_convert (TREE_TYPE (gfc), tmp));
6572 : }
6573 : else
6574 : {
6575 559 : tmp = gfc_get_cfi_desc_base_addr (cfi);
6576 559 : gfc_conv_descriptor_data_set (&block, gfc, tmp);
6577 :
6578 559 : if (fsym->attr.allocatable)
6579 : {
6580 : /* gfc->span = cfi->elem_len. */
6581 252 : tmp = fold_convert (gfc_array_index_type,
6582 : gfc_get_cfi_dim_sm (cfi, gfc_rank_cst[0]));
6583 : }
6584 : else
6585 : {
6586 : /* gfc->span = ((cfi->dim[0].sm % cfi->elem_len)
6587 : ? cfi->dim[0].sm : cfi->elem_len). */
6588 307 : tmp = gfc_get_cfi_dim_sm (cfi, gfc_rank_cst[0]);
6589 307 : tmp2 = fold_convert (gfc_array_index_type,
6590 : gfc_get_cfi_desc_elem_len (cfi));
6591 307 : tmp = fold_build2_loc (input_location, TRUNC_MOD_EXPR,
6592 : gfc_array_index_type, tmp, tmp2);
6593 307 : tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
6594 : tmp, gfc_index_zero_node);
6595 307 : tmp = build3_loc (input_location, COND_EXPR, gfc_array_index_type, tmp,
6596 : gfc_get_cfi_dim_sm (cfi, gfc_rank_cst[0]), tmp2);
6597 : }
6598 559 : gfc_conv_descriptor_span_set (&block2, gfc, tmp);
6599 :
6600 : /* Calculate offset + set lbound, ubound and stride. */
6601 559 : gfc_conv_descriptor_offset_set (&block2, gfc, gfc_index_zero_node);
6602 : /* Loop: for (i = 0; i < rank; ++i). */
6603 559 : tree idx = gfc_create_var (gfc_array_dim_rank_type, "idx");
6604 : /* Loop body. */
6605 559 : stmtblock_t loop_body;
6606 559 : gfc_init_block (&loop_body);
6607 : /* gfc->dim[i].lbound = ... */
6608 559 : tmp = gfc_get_cfi_dim_lbound (cfi, idx);
6609 559 : gfc_conv_descriptor_lbound_set (&loop_body, gfc, idx, tmp);
6610 :
6611 : /* gfc->dim[i].ubound = gfc->dim[i].lbound + cfi->dim[i].extent - 1. */
6612 559 : tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
6613 : gfc_conv_descriptor_lbound_get (gfc, idx),
6614 : gfc_index_one_node);
6615 559 : tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
6616 : gfc_get_cfi_dim_extent (cfi, idx), tmp);
6617 559 : gfc_conv_descriptor_ubound_set (&loop_body, gfc, idx, tmp);
6618 :
6619 : /* gfc->dim[i].stride = cfi->dim[i].sm / cfi>elem_len */
6620 559 : tmp = gfc_get_cfi_dim_sm (cfi, idx);
6621 559 : tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
6622 : gfc_array_index_type, tmp,
6623 : fold_convert (gfc_array_index_type,
6624 : gfc_get_cfi_desc_elem_len (cfi)));
6625 559 : gfc_conv_descriptor_stride_set (&loop_body, gfc, idx, tmp);
6626 :
6627 : /* gfc->offset -= gfc->dim[i].stride * gfc->dim[i].lbound. */
6628 559 : tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
6629 : gfc_conv_descriptor_stride_get (gfc, idx),
6630 : gfc_conv_descriptor_lbound_get (gfc, idx));
6631 559 : tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
6632 : gfc_conv_descriptor_offset_get (gfc), tmp);
6633 559 : gfc_conv_descriptor_offset_set (&loop_body, gfc, tmp);
6634 : /* Generate loop. */
6635 559 : gfc_simple_for_loop (&block2, idx, gfc_rank_cst[0], rank, LT_EXPR,
6636 : gfc_rank_cst[1], gfc_finish_block (&loop_body));
6637 : }
6638 :
6639 987 : if (e->ts.type == BT_CHARACTER && !e->ts.u.cl->length)
6640 : {
6641 60 : tmp = fold_convert (gfc_charlen_type_node,
6642 : gfc_get_cfi_desc_elem_len (cfi));
6643 60 : if (e->ts.kind != 1)
6644 24 : tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
6645 : gfc_charlen_type_node, tmp,
6646 : build_int_cst (gfc_charlen_type_node,
6647 24 : e->ts.kind));
6648 60 : gfc_add_modify (&block2, gfc_strlen, tmp);
6649 : }
6650 :
6651 987 : tmp = gfc_get_cfi_desc_base_addr (cfi),
6652 987 : tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
6653 : tmp, null_pointer_node);
6654 987 : tmp = build3_v (COND_EXPR, tmp, gfc_finish_block (&block2),
6655 : build_empty_stmt (input_location));
6656 987 : gfc_add_expr_to_block (&block, tmp);
6657 :
6658 6537 : post_call:
6659 6537 : gfc_add_block_to_block (&block, &se.post);
6660 6537 : if (present && block.head)
6661 : {
6662 6 : tmp = build3_v (COND_EXPR, present, gfc_finish_block (&block),
6663 : build_empty_stmt (input_location));
6664 6 : gfc_add_expr_to_block (&parmse->post, tmp);
6665 : }
6666 6531 : else if (block.head)
6667 1564 : gfc_add_block_to_block (&parmse->post, &block);
6668 6537 : }
6669 :
6670 :
6671 : /* Create "conditional temporary" to handle scalar dummy variables with the
6672 : OPTIONAL+VALUE attribute that shall not be dereferenced. Use null value
6673 : as fallback. Does not handle CLASS. */
6674 :
6675 : static void
6676 234 : conv_cond_temp (gfc_se * parmse, gfc_expr * e, tree cond)
6677 : {
6678 234 : tree temp;
6679 234 : gcc_assert (e && e->ts.type != BT_CLASS);
6680 234 : gcc_assert (e->rank == 0);
6681 234 : temp = gfc_create_var (TREE_TYPE (parmse->expr), "condtemp");
6682 234 : TREE_STATIC (temp) = 1;
6683 234 : TREE_CONSTANT (temp) = 1;
6684 234 : TREE_READONLY (temp) = 1;
6685 234 : DECL_INITIAL (temp) = build_zero_cst (TREE_TYPE (temp));
6686 234 : parmse->expr = fold_build3_loc (input_location, COND_EXPR,
6687 234 : TREE_TYPE (parmse->expr),
6688 : cond, parmse->expr, temp);
6689 234 : parmse->expr = gfc_evaluate_now (parmse->expr, &parmse->pre);
6690 234 : }
6691 :
6692 :
6693 : /* Returns true if the type specified in TS is a character type whose length
6694 : is constant. Otherwise returns false. */
6695 :
6696 : static bool
6697 22115 : gfc_const_length_character_type_p (gfc_typespec *ts)
6698 : {
6699 22115 : return (ts->type == BT_CHARACTER
6700 467 : && ts->u.cl
6701 467 : && ts->u.cl->length
6702 467 : && ts->u.cl->length->expr_type == EXPR_CONSTANT
6703 22582 : && ts->u.cl->length->ts.type == BT_INTEGER);
6704 : }
6705 :
6706 :
6707 : /* Helper function for the handling of (currently) scalar dummy variables
6708 : with the VALUE attribute. Argument parmse should already be set up. */
6709 : static void
6710 22548 : conv_dummy_value (gfc_se * parmse, gfc_expr * e, gfc_symbol * fsym,
6711 : vec<tree, va_gc> *& optionalargs)
6712 : {
6713 22548 : tree tmp;
6714 :
6715 22548 : gcc_assert (fsym && fsym->attr.value && !fsym->attr.dimension);
6716 :
6717 22548 : if (IS_PDT (e))
6718 : {
6719 6 : tmp = gfc_create_var (TREE_TYPE (parmse->expr), "PDT");
6720 6 : gfc_add_modify (&parmse->pre, tmp, parmse->expr);
6721 6 : gfc_add_expr_to_block (&parmse->pre,
6722 6 : gfc_copy_alloc_comp (e->ts.u.derived,
6723 : parmse->expr, tmp,
6724 : e->rank, 0));
6725 6 : parmse->expr = tmp;
6726 6 : tmp = gfc_deallocate_pdt_comp (e->ts.u.derived, tmp, e->rank);
6727 6 : gfc_add_expr_to_block (&parmse->post, tmp);
6728 6 : return;
6729 : }
6730 :
6731 : /* Absent actual argument for optional scalar dummy. */
6732 22542 : if ((e == NULL || e->expr_type == EXPR_NULL) && fsym->attr.optional)
6733 : {
6734 : /* For scalar arguments with VALUE attribute which are passed by
6735 : value, pass "0" and a hidden argument for the optional status. */
6736 427 : if (fsym->ts.type == BT_CHARACTER)
6737 : {
6738 : /* Pass a NULL pointer for an absent CHARACTER arg and a length of
6739 : zero. */
6740 90 : parmse->expr = null_pointer_node;
6741 90 : parmse->string_length = build_int_cst (gfc_charlen_type_node, 0);
6742 : }
6743 337 : else if (gfc_bt_struct (fsym->ts.type)
6744 30 : && !(fsym->ts.u.derived->from_intmod == INTMOD_ISO_C_BINDING))
6745 : {
6746 : /* Pass null struct. Types c_ptr and c_funptr from ISO_C_BINDING
6747 : are pointers and passed as such below. */
6748 24 : tree temp = gfc_create_var (gfc_sym_type (fsym), "absent");
6749 24 : TREE_CONSTANT (temp) = 1;
6750 24 : TREE_READONLY (temp) = 1;
6751 24 : DECL_INITIAL (temp) = build_zero_cst (TREE_TYPE (temp));
6752 24 : parmse->expr = temp;
6753 24 : }
6754 : else
6755 313 : parmse->expr = fold_convert (gfc_sym_type (fsym),
6756 : integer_zero_node);
6757 427 : vec_safe_push (optionalargs, boolean_false_node);
6758 :
6759 427 : return;
6760 : }
6761 :
6762 : /* Truncate a too long constant character actual argument. */
6763 22115 : if (gfc_const_length_character_type_p (&fsym->ts)
6764 467 : && e->expr_type == EXPR_CONSTANT
6765 22198 : && mpz_cmp_ui (fsym->ts.u.cl->length->value.integer,
6766 : e->value.character.length) < 0)
6767 : {
6768 17 : gfc_charlen_t flen = mpz_get_ui (fsym->ts.u.cl->length->value.integer);
6769 :
6770 : /* Truncate actual string argument. */
6771 17 : gfc_conv_expr (parmse, e);
6772 34 : parmse->expr = gfc_build_wide_string_const (e->ts.kind, flen,
6773 17 : e->value.character.string);
6774 17 : parmse->string_length = build_int_cst (gfc_charlen_type_node, flen);
6775 :
6776 17 : if (flen == 1)
6777 : {
6778 14 : tree slen1 = build_int_cst (gfc_charlen_type_node, 1);
6779 14 : gfc_conv_string_parameter (parmse);
6780 14 : parmse->expr = gfc_string_to_single_character (slen1, parmse->expr,
6781 : e->ts.kind);
6782 : }
6783 :
6784 : /* Indicate value,optional scalar dummy argument as present. */
6785 17 : if (fsym->attr.optional)
6786 1 : vec_safe_push (optionalargs, boolean_true_node);
6787 17 : return;
6788 : }
6789 :
6790 : /* gfortran argument passing conventions:
6791 : actual arguments to CHARACTER(len=1),VALUE
6792 : dummy arguments are actually passed by value.
6793 : Strings are truncated to length 1. */
6794 22098 : if (gfc_length_one_character_type_p (&fsym->ts))
6795 : {
6796 378 : if (e->expr_type == EXPR_CONSTANT
6797 54 : && e->value.character.length > 1)
6798 : {
6799 0 : e->value.character.length = 1;
6800 0 : gfc_conv_expr (parmse, e);
6801 : }
6802 :
6803 378 : tree slen1 = build_int_cst (gfc_charlen_type_node, 1);
6804 378 : gfc_conv_string_parameter (parmse);
6805 378 : parmse->expr = gfc_string_to_single_character (slen1, parmse->expr,
6806 : e->ts.kind);
6807 : /* Truncate resulting string to length 1. */
6808 378 : parmse->string_length = slen1;
6809 : }
6810 :
6811 22098 : if (fsym->attr.optional && fsym->ts.type != BT_CLASS)
6812 : {
6813 : /* F2018:15.5.2.12 Argument presence and
6814 : restrictions on arguments not present. */
6815 823 : if (e->expr_type == EXPR_VARIABLE
6816 650 : && e->rank == 0
6817 1419 : && (gfc_expr_attr (e).allocatable
6818 482 : || gfc_expr_attr (e).pointer))
6819 : {
6820 198 : gfc_se argse;
6821 198 : tree cond;
6822 198 : gfc_init_se (&argse, NULL);
6823 198 : argse.want_pointer = 1;
6824 198 : gfc_conv_expr (&argse, e);
6825 198 : cond = fold_convert (TREE_TYPE (argse.expr), null_pointer_node);
6826 198 : cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
6827 : argse.expr, cond);
6828 198 : if (e->symtree->n.sym->attr.dummy)
6829 24 : cond = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
6830 : logical_type_node,
6831 : gfc_conv_expr_present (e->symtree->n.sym),
6832 : cond);
6833 198 : vec_safe_push (optionalargs, fold_convert (boolean_type_node, cond));
6834 : /* Create "conditional temporary". */
6835 198 : conv_cond_temp (parmse, e, cond);
6836 : }
6837 625 : else if (e->expr_type != EXPR_VARIABLE
6838 452 : || !e->symtree->n.sym->attr.optional
6839 260 : || (e->ref != NULL && e->ref->type != REF_ARRAY))
6840 365 : vec_safe_push (optionalargs, boolean_true_node);
6841 : else
6842 : {
6843 260 : tmp = gfc_conv_expr_present (e->symtree->n.sym);
6844 260 : if (gfc_bt_struct (fsym->ts.type)
6845 36 : && !(fsym->ts.u.derived->from_intmod == INTMOD_ISO_C_BINDING))
6846 36 : conv_cond_temp (parmse, e, tmp);
6847 224 : else if (e->ts.type != BT_CHARACTER && !e->symtree->n.sym->attr.value)
6848 84 : parmse->expr
6849 168 : = fold_build3_loc (input_location, COND_EXPR,
6850 84 : TREE_TYPE (parmse->expr),
6851 : tmp, parmse->expr,
6852 84 : fold_convert (TREE_TYPE (parmse->expr),
6853 : integer_zero_node));
6854 :
6855 520 : vec_safe_push (optionalargs,
6856 260 : fold_convert (boolean_type_node, tmp));
6857 : }
6858 : }
6859 : }
6860 :
6861 :
6862 : /* Helper function for the handling of NULL() actual arguments associated with
6863 : non-optional dummy variables. Argument parmse should already be set up. */
6864 : static void
6865 426 : conv_null_actual (gfc_se * parmse, gfc_expr * e, gfc_symbol * fsym)
6866 : {
6867 426 : gcc_assert (fsym && e->expr_type == EXPR_NULL);
6868 :
6869 : /* Obtain the character length for a NULL() actual with a character
6870 : MOLD argument. Otherwise substitute a suitable dummy length.
6871 : Here we handle only non-optional dummies of non-bind(c) procedures. */
6872 426 : if (fsym->ts.type == BT_CHARACTER)
6873 : {
6874 216 : if (e->ts.type == BT_CHARACTER
6875 162 : && e->symtree->n.sym->ts.type == BT_CHARACTER)
6876 : {
6877 : /* MOLD is present. Substitute a temporary character NULL pointer.
6878 : For an assumed-rank dummy we need a descriptor that passes the
6879 : correct rank. */
6880 162 : if (fsym->as && fsym->as->type == AS_ASSUMED_RANK)
6881 : {
6882 54 : tree rank;
6883 54 : tree tmp = parmse->expr;
6884 54 : tmp = gfc_conv_scalar_to_descriptor (parmse, tmp, fsym->attr);
6885 54 : rank = gfc_conv_descriptor_rank (tmp);
6886 54 : gfc_add_modify (&parmse->pre, rank,
6887 54 : build_int_cst (TREE_TYPE (rank), e->rank));
6888 54 : parmse->expr = gfc_build_addr_expr (NULL_TREE, tmp);
6889 54 : }
6890 : else
6891 : {
6892 108 : tree tmp = gfc_create_var (TREE_TYPE (parmse->expr), "null");
6893 108 : gfc_add_modify (&parmse->pre, tmp,
6894 108 : build_zero_cst (TREE_TYPE (tmp)));
6895 108 : parmse->expr = gfc_build_addr_expr (NULL_TREE, tmp);
6896 : }
6897 :
6898 : /* Ensure that a usable length is available. */
6899 162 : if (parmse->string_length == NULL_TREE)
6900 : {
6901 162 : gfc_typespec *ts = &e->symtree->n.sym->ts;
6902 :
6903 162 : if (ts->u.cl->length != NULL
6904 108 : && ts->u.cl->length->expr_type == EXPR_CONSTANT)
6905 108 : gfc_conv_const_charlen (ts->u.cl);
6906 :
6907 162 : if (ts->u.cl->backend_decl)
6908 162 : parmse->string_length = ts->u.cl->backend_decl;
6909 : }
6910 : }
6911 54 : else if (e->ts.type == BT_UNKNOWN && parmse->string_length == NULL_TREE)
6912 : {
6913 : /* MOLD is not present. Pass length of associated dummy character
6914 : argument if constant, or zero. */
6915 54 : if (fsym->ts.u.cl->length != NULL
6916 18 : && fsym->ts.u.cl->length->expr_type == EXPR_CONSTANT)
6917 : {
6918 18 : gfc_conv_const_charlen (fsym->ts.u.cl);
6919 18 : parmse->string_length = fsym->ts.u.cl->backend_decl;
6920 : }
6921 : else
6922 : {
6923 36 : parmse->string_length = gfc_create_var (gfc_charlen_type_node,
6924 : "slen");
6925 36 : gfc_add_modify (&parmse->pre, parmse->string_length,
6926 : build_zero_cst (gfc_charlen_type_node));
6927 : }
6928 : }
6929 : }
6930 210 : else if (fsym->ts.type == BT_DERIVED)
6931 : {
6932 210 : if (e->ts.type != BT_UNKNOWN)
6933 : /* MOLD is present. Pass a corresponding temporary NULL pointer.
6934 : For an assumed-rank dummy we provide a descriptor that passes
6935 : the correct rank. */
6936 : {
6937 138 : tree rank;
6938 138 : tree tmp = parmse->expr;
6939 :
6940 138 : tmp = gfc_conv_scalar_to_descriptor (parmse, tmp, gfc_expr_attr (e));
6941 138 : rank = gfc_conv_descriptor_rank (tmp);
6942 138 : gfc_add_modify (&parmse->pre, rank,
6943 138 : build_int_cst (TREE_TYPE (rank), e->rank));
6944 138 : gfc_conv_descriptor_data_set (&parmse->pre, tmp, null_pointer_node);
6945 138 : parmse->expr = gfc_build_addr_expr (NULL_TREE, tmp);
6946 : }
6947 : else
6948 : /* MOLD is not present. Use attributes from dummy argument, which is
6949 : not allowed to be assumed-rank. */
6950 : {
6951 72 : int dummy_rank;
6952 72 : tree tmp = parmse->expr;
6953 :
6954 72 : if ((fsym->attr.allocatable || fsym->attr.pointer)
6955 72 : && fsym->attr.intent == INTENT_UNKNOWN)
6956 36 : fsym->attr.intent = INTENT_IN;
6957 72 : tmp = gfc_conv_scalar_to_descriptor (parmse, tmp, fsym->attr);
6958 72 : dummy_rank = fsym->as ? fsym->as->rank : 0;
6959 24 : if (dummy_rank > 0)
6960 : {
6961 24 : tree rank = gfc_conv_descriptor_rank (tmp);
6962 24 : gfc_add_modify (&parmse->pre, rank,
6963 24 : build_int_cst (TREE_TYPE (rank), dummy_rank));
6964 : }
6965 72 : gfc_conv_descriptor_data_set (&parmse->pre, tmp, null_pointer_node);
6966 72 : parmse->expr = gfc_build_addr_expr (NULL_TREE, tmp);
6967 : }
6968 : }
6969 426 : }
6970 :
6971 :
6972 : /* Generate code for a procedure call. Note can return se->post != NULL.
6973 : If se->direct_byref is set then se->expr contains the return parameter.
6974 : Return nonzero, if the call has alternate specifiers.
6975 : 'expr' is only needed for procedure pointer components. */
6976 :
6977 : int
6978 136398 : gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
6979 : gfc_actual_arglist * args, gfc_expr * expr,
6980 : vec<tree, va_gc> *append_args)
6981 : {
6982 136398 : gfc_interface_mapping mapping;
6983 136398 : vec<tree, va_gc> *arglist;
6984 136398 : vec<tree, va_gc> *retargs;
6985 136398 : tree tmp;
6986 136398 : tree fntype;
6987 136398 : gfc_se parmse;
6988 136398 : gfc_array_info *info;
6989 136398 : int byref;
6990 136398 : int parm_kind;
6991 136398 : tree type;
6992 136398 : tree var;
6993 136398 : tree len;
6994 136398 : tree base_object;
6995 136398 : vec<tree, va_gc> *stringargs;
6996 136398 : vec<tree, va_gc> *optionalargs;
6997 136398 : tree result = NULL;
6998 136398 : gfc_formal_arglist *formal;
6999 136398 : gfc_actual_arglist *arg;
7000 136398 : int has_alternate_specifier = 0;
7001 136398 : bool need_interface_mapping;
7002 136398 : bool is_builtin;
7003 136398 : bool callee_alloc;
7004 136398 : bool ulim_copy;
7005 136398 : gfc_typespec ts;
7006 136398 : gfc_charlen cl;
7007 136398 : gfc_expr *e;
7008 136398 : gfc_symbol *fsym;
7009 136398 : enum {MISSING = 0, ELEMENTAL, SCALAR, SCALAR_POINTER, ARRAY};
7010 136398 : gfc_component *comp = NULL;
7011 136398 : int arglen;
7012 136398 : unsigned int argc;
7013 136398 : tree arg1_cntnr = NULL_TREE;
7014 136398 : arglist = NULL;
7015 136398 : retargs = NULL;
7016 136398 : stringargs = NULL;
7017 136398 : optionalargs = NULL;
7018 136398 : var = NULL_TREE;
7019 136398 : len = NULL_TREE;
7020 136398 : gfc_clear_ts (&ts);
7021 136398 : gfc_intrinsic_sym *isym = expr && expr->rank ?
7022 : expr->value.function.isym : NULL;
7023 :
7024 136398 : comp = gfc_get_proc_ptr_comp (expr);
7025 :
7026 272796 : bool elemental_proc = (comp
7027 2043 : && comp->ts.interface
7028 1989 : && comp->ts.interface->attr.elemental)
7029 1844 : || (comp && comp->attr.elemental)
7030 138242 : || sym->attr.elemental;
7031 :
7032 136398 : if (se->ss != NULL)
7033 : {
7034 25053 : if (!elemental_proc)
7035 : {
7036 21494 : gcc_assert (se->ss->info->type == GFC_SS_FUNCTION);
7037 21494 : if (se->ss->info->useflags)
7038 : {
7039 5778 : gcc_assert ((!comp && gfc_return_by_reference (sym)
7040 : && sym->result->attr.dimension)
7041 : || (comp && comp->attr.dimension)
7042 : || gfc_is_class_array_function (expr));
7043 5778 : gcc_assert (se->loop != NULL);
7044 : /* Access the previously obtained result. */
7045 5778 : gfc_conv_tmp_array_ref (se);
7046 5778 : return 0;
7047 : }
7048 : }
7049 19275 : info = &se->ss->info->data.array;
7050 : }
7051 : else
7052 : info = NULL;
7053 :
7054 130620 : stmtblock_t post, clobbers, dealloc_blk;
7055 130620 : gfc_init_block (&post);
7056 130620 : gfc_init_block (&clobbers);
7057 130620 : gfc_init_block (&dealloc_blk);
7058 130620 : gfc_init_interface_mapping (&mapping);
7059 130620 : if (!comp)
7060 : {
7061 128626 : formal = gfc_sym_get_dummy_args (sym);
7062 128626 : need_interface_mapping = sym->attr.dimension ||
7063 113162 : (sym->ts.type == BT_CHARACTER
7064 3180 : && sym->ts.u.cl->length
7065 2434 : && sym->ts.u.cl->length->expr_type
7066 : != EXPR_CONSTANT);
7067 : }
7068 : else
7069 : {
7070 1994 : formal = comp->ts.interface ? comp->ts.interface->formal : NULL;
7071 1994 : need_interface_mapping = comp->attr.dimension ||
7072 1925 : (comp->ts.type == BT_CHARACTER
7073 229 : && comp->ts.u.cl->length
7074 220 : && comp->ts.u.cl->length->expr_type
7075 : != EXPR_CONSTANT);
7076 : }
7077 :
7078 130620 : base_object = NULL_TREE;
7079 : /* For _vprt->_copy () routines no formal symbol is present. Nevertheless
7080 : is the third and fourth argument to such a function call a value
7081 : denoting the number of elements to copy (i.e., most of the time the
7082 : length of a deferred length string). */
7083 261240 : ulim_copy = (formal == NULL)
7084 31956 : && UNLIMITED_POLY (sym)
7085 130700 : && comp && (strcmp ("_copy", comp->name) == 0);
7086 :
7087 : /* Scan for allocatable actual arguments passed to allocatable dummy
7088 : arguments with INTENT(OUT). As the corresponding actual arguments are
7089 : deallocated before execution of the procedure, we evaluate actual
7090 : argument expressions to avoid problems with possible dependencies. */
7091 130620 : bool force_eval_args = false;
7092 130620 : gfc_formal_arglist *tmp_formal;
7093 401376 : for (arg = args, tmp_formal = formal; arg != NULL;
7094 237430 : arg = arg->next, tmp_formal = tmp_formal ? tmp_formal->next : NULL)
7095 : {
7096 271257 : e = arg->expr;
7097 271257 : fsym = tmp_formal ? tmp_formal->sym : NULL;
7098 257841 : if (e && fsym
7099 225942 : && e->expr_type == EXPR_VARIABLE
7100 99252 : && fsym->attr.intent == INTENT_OUT
7101 6337 : && (fsym->ts.type == BT_CLASS && fsym->attr.class_ok
7102 6337 : ? CLASS_DATA (fsym)->attr.allocatable
7103 4809 : : fsym->attr.allocatable)
7104 501 : && e->symtree
7105 501 : && e->symtree->n.sym
7106 529098 : && gfc_variable_attr (e, NULL).allocatable)
7107 : {
7108 : force_eval_args = true;
7109 : break;
7110 : }
7111 : }
7112 :
7113 : /* Evaluate the arguments. */
7114 402279 : for (arg = args, argc = 0; arg != NULL;
7115 271659 : arg = arg->next, formal = formal ? formal->next : NULL, ++argc)
7116 : {
7117 271659 : bool finalized = false;
7118 271659 : tree derived_array = NULL_TREE;
7119 271659 : symbol_attribute *attr;
7120 :
7121 271659 : e = arg->expr;
7122 271659 : fsym = formal ? formal->sym : NULL;
7123 509992 : parm_kind = MISSING;
7124 :
7125 238333 : attr = fsym ? &(fsym->ts.type == BT_CLASS ? CLASS_DATA (fsym)->attr
7126 : : fsym->attr)
7127 : : nullptr;
7128 : /* If the procedure requires an explicit interface, the actual
7129 : argument is passed according to the corresponding formal
7130 : argument. If the corresponding formal argument is a POINTER,
7131 : ALLOCATABLE or assumed shape, we do not use g77's calling
7132 : convention, and pass the address of the array descriptor
7133 : instead. Otherwise we use g77's calling convention, in other words
7134 : pass the array data pointer without descriptor. */
7135 238280 : bool nodesc_arg = fsym != NULL
7136 238280 : && !(fsym->attr.pointer || fsym->attr.allocatable)
7137 229182 : && fsym->as
7138 40894 : && fsym->as->type != AS_ASSUMED_SHAPE
7139 24762 : && fsym->as->type != AS_ASSUMED_RANK;
7140 271659 : if (comp)
7141 2749 : nodesc_arg = nodesc_arg || !comp->attr.always_explicit;
7142 : else
7143 268910 : nodesc_arg
7144 : = nodesc_arg
7145 268910 : || !(sym->attr.always_explicit || (attr && attr->codimension));
7146 :
7147 : /* Class array expressions are sometimes coming completely unadorned
7148 : with either arrayspec or _data component. Correct that here.
7149 : OOP-TODO: Move this to the frontend. */
7150 271659 : if (e && e->expr_type == EXPR_VARIABLE
7151 113357 : && !e->ref
7152 51596 : && e->ts.type == BT_CLASS
7153 2609 : && (CLASS_DATA (e)->attr.codimension
7154 2609 : || CLASS_DATA (e)->attr.dimension))
7155 : {
7156 0 : gfc_typespec temp_ts = e->ts;
7157 0 : gfc_add_class_array_ref (e);
7158 0 : e->ts = temp_ts;
7159 : }
7160 :
7161 271659 : if (e == NULL
7162 258237 : || (e->expr_type == EXPR_NULL
7163 745 : && fsym
7164 745 : && fsym->attr.value
7165 72 : && fsym->attr.optional
7166 72 : && !fsym->attr.dimension
7167 72 : && fsym->ts.type != BT_CLASS))
7168 : {
7169 13494 : if (se->ignore_optional)
7170 : {
7171 : /* Some intrinsics have already been resolved to the correct
7172 : parameters. */
7173 632 : continue;
7174 : }
7175 13296 : else if (arg->label)
7176 : {
7177 224 : has_alternate_specifier = 1;
7178 224 : continue;
7179 : }
7180 : else
7181 : {
7182 13072 : gfc_init_se (&parmse, NULL);
7183 :
7184 : /* For scalar arguments with VALUE attribute which are passed by
7185 : value, pass "0" and a hidden argument gives the optional
7186 : status. */
7187 13072 : if (fsym && fsym->attr.optional && fsym->attr.value
7188 427 : && !fsym->attr.dimension && fsym->ts.type != BT_CLASS)
7189 : {
7190 427 : conv_dummy_value (&parmse, e, fsym, optionalargs);
7191 : }
7192 : else
7193 : {
7194 : /* Pass a NULL pointer for an absent arg. */
7195 12645 : parmse.expr = null_pointer_node;
7196 :
7197 : /* Is it an absent character dummy? */
7198 12645 : bool absent_char = false;
7199 12645 : gfc_dummy_arg * const dummy_arg = arg->associated_dummy;
7200 :
7201 : /* Fall back to inferred type only if no formal. */
7202 12645 : if (fsym)
7203 11587 : absent_char = (fsym->ts.type == BT_CHARACTER);
7204 1058 : else if (dummy_arg)
7205 1058 : absent_char = (gfc_dummy_arg_get_typespec (*dummy_arg).type
7206 : == BT_CHARACTER);
7207 12645 : if (absent_char)
7208 1115 : parmse.string_length = build_int_cst (gfc_charlen_type_node,
7209 : 0);
7210 : }
7211 : }
7212 : }
7213 258165 : else if (e->expr_type == EXPR_NULL
7214 673 : && (e->ts.type == BT_UNKNOWN || e->ts.type == BT_DERIVED)
7215 371 : && fsym && attr && (attr->pointer || attr->allocatable)
7216 293 : && fsym->ts.type == BT_DERIVED)
7217 : {
7218 210 : gfc_init_se (&parmse, NULL);
7219 210 : gfc_conv_expr_reference (&parmse, e);
7220 210 : conv_null_actual (&parmse, e, fsym);
7221 : }
7222 257955 : else if (arg->expr->expr_type == EXPR_NULL
7223 463 : && fsym && !fsym->attr.pointer
7224 163 : && (fsym->ts.type != BT_CLASS
7225 6 : || !CLASS_DATA (fsym)->attr.class_pointer))
7226 : {
7227 : /* Pass a NULL pointer to denote an absent arg. */
7228 163 : gcc_assert (fsym->attr.optional && !fsym->attr.allocatable
7229 : && (fsym->ts.type != BT_CLASS
7230 : || !CLASS_DATA (fsym)->attr.allocatable));
7231 163 : gfc_init_se (&parmse, NULL);
7232 163 : parmse.expr = null_pointer_node;
7233 163 : if (fsym->ts.type == BT_CHARACTER)
7234 42 : parmse.string_length = build_int_cst (gfc_charlen_type_node, 0);
7235 : }
7236 257792 : else if (fsym && fsym->ts.type == BT_CLASS
7237 11273 : && e->ts.type == BT_DERIVED)
7238 : {
7239 : /* The derived type needs to be converted to a temporary
7240 : CLASS object. */
7241 4718 : gfc_init_se (&parmse, se);
7242 4718 : gfc_conv_derived_to_class (&parmse, e, fsym, NULL_TREE,
7243 4718 : fsym->attr.optional
7244 1008 : && e->expr_type == EXPR_VARIABLE
7245 5726 : && e->symtree->n.sym->attr.optional,
7246 4718 : CLASS_DATA (fsym)->attr.class_pointer
7247 4718 : || CLASS_DATA (fsym)->attr.allocatable,
7248 : sym->name, &derived_array);
7249 : }
7250 221175 : else if (UNLIMITED_POLY (fsym) && e->ts.type != BT_CLASS
7251 906 : && e->ts.type != BT_PROCEDURE
7252 882 : && (gfc_expr_attr (e).flavor != FL_PROCEDURE
7253 12 : || gfc_expr_attr (e).proc != PROC_UNKNOWN))
7254 : {
7255 : /* The intrinsic type needs to be converted to a temporary
7256 : CLASS object for the unlimited polymorphic formal. */
7257 882 : gfc_find_vtab (&e->ts);
7258 882 : gfc_init_se (&parmse, se);
7259 882 : gfc_conv_intrinsic_to_class (&parmse, e, fsym->ts);
7260 :
7261 : }
7262 252192 : else if (se->ss && se->ss->info->useflags)
7263 : {
7264 5837 : gfc_ss *ss;
7265 :
7266 5837 : ss = se->ss;
7267 :
7268 : /* An elemental function inside a scalarized loop. */
7269 5837 : gfc_init_se (&parmse, se);
7270 5837 : parm_kind = ELEMENTAL;
7271 :
7272 : /* When no fsym is present, ulim_copy is set and this is a third or
7273 : fourth argument, use call-by-value instead of by reference to
7274 : hand the length properties to the copy routine (i.e., most of the
7275 : time this will be a call to a __copy_character_* routine where the
7276 : third and fourth arguments are the lengths of a deferred length
7277 : char array). */
7278 5837 : if ((fsym && fsym->attr.value)
7279 5603 : || (ulim_copy && (argc == 2 || argc == 3)))
7280 234 : gfc_conv_expr (&parmse, e);
7281 5603 : else if (e->expr_type == EXPR_ARRAY)
7282 : {
7283 306 : gfc_conv_expr (&parmse, e);
7284 306 : if (e->ts.type != BT_CHARACTER)
7285 263 : parmse.expr = gfc_build_addr_expr (NULL_TREE, parmse.expr);
7286 : }
7287 : else
7288 5297 : gfc_conv_expr_reference (&parmse, e);
7289 :
7290 5837 : if (e->ts.type == BT_CHARACTER && !e->rank
7291 174 : && e->expr_type == EXPR_FUNCTION)
7292 12 : parmse.expr = build_fold_indirect_ref_loc (input_location,
7293 : parmse.expr);
7294 :
7295 5787 : if (fsym && fsym->ts.type == BT_DERIVED
7296 7459 : && gfc_is_class_container_ref (e))
7297 : {
7298 24 : parmse.expr = gfc_class_data_get (parmse.expr);
7299 :
7300 24 : if (fsym->attr.optional && e->expr_type == EXPR_VARIABLE
7301 24 : && e->symtree->n.sym->attr.optional)
7302 : {
7303 0 : tree cond = gfc_conv_expr_present (e->symtree->n.sym);
7304 0 : parmse.expr = build3_loc (input_location, COND_EXPR,
7305 0 : TREE_TYPE (parmse.expr),
7306 : cond, parmse.expr,
7307 0 : fold_convert (TREE_TYPE (parmse.expr),
7308 : null_pointer_node));
7309 : }
7310 : }
7311 :
7312 : /* Scalar dummy arguments of intrinsic type or derived type with
7313 : VALUE attribute. */
7314 5837 : if (fsym
7315 5787 : && fsym->attr.value
7316 234 : && fsym->ts.type != BT_CLASS)
7317 234 : conv_dummy_value (&parmse, e, fsym, optionalargs);
7318 :
7319 : /* If we are passing an absent array as optional dummy to an
7320 : elemental procedure, make sure that we pass NULL when the data
7321 : pointer is NULL. We need this extra conditional because of
7322 : scalarization which passes arrays elements to the procedure,
7323 : ignoring the fact that the array can be absent/unallocated/... */
7324 5603 : else if (ss->info->can_be_null_ref
7325 415 : && ss->info->type != GFC_SS_REFERENCE)
7326 : {
7327 193 : tree descriptor_data;
7328 :
7329 193 : descriptor_data = ss->info->data.array.data;
7330 193 : tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
7331 : descriptor_data,
7332 193 : fold_convert (TREE_TYPE (descriptor_data),
7333 : null_pointer_node));
7334 193 : parmse.expr
7335 386 : = fold_build3_loc (input_location, COND_EXPR,
7336 193 : TREE_TYPE (parmse.expr),
7337 : gfc_unlikely (tmp, PRED_FORTRAN_ABSENT_DUMMY),
7338 193 : fold_convert (TREE_TYPE (parmse.expr),
7339 : null_pointer_node),
7340 : parmse.expr);
7341 : }
7342 :
7343 : /* The scalarizer does not repackage the reference to a class
7344 : array - instead it returns a pointer to the data element. */
7345 5837 : if (fsym && fsym->ts.type == BT_CLASS && e->ts.type == BT_CLASS)
7346 186 : gfc_conv_class_to_class (&parmse, e, fsym->ts, true,
7347 186 : fsym->attr.intent != INTENT_IN
7348 186 : && (CLASS_DATA (fsym)->attr.class_pointer
7349 24 : || CLASS_DATA (fsym)->attr.allocatable),
7350 186 : fsym->attr.optional
7351 0 : && e->expr_type == EXPR_VARIABLE
7352 186 : && e->symtree->n.sym->attr.optional,
7353 186 : CLASS_DATA (fsym)->attr.class_pointer
7354 186 : || CLASS_DATA (fsym)->attr.allocatable);
7355 : }
7356 : else
7357 : {
7358 246355 : bool scalar;
7359 246355 : gfc_ss *argss;
7360 :
7361 246355 : gfc_init_se (&parmse, NULL);
7362 :
7363 : /* Check whether the expression is a scalar or not; we cannot use
7364 : e->rank as it can be nonzero for functions arguments. */
7365 246355 : argss = gfc_walk_expr (e);
7366 246355 : scalar = argss == gfc_ss_terminator;
7367 246355 : if (!scalar)
7368 60681 : gfc_free_ss_chain (argss);
7369 :
7370 : /* Special handling for passing scalar polymorphic coarrays;
7371 : otherwise one passes "class->_data.data" instead of "&class". */
7372 246355 : if (e->rank == 0 && e->ts.type == BT_CLASS
7373 3563 : && fsym && fsym->ts.type == BT_CLASS
7374 3141 : && CLASS_DATA (fsym)->attr.codimension
7375 55 : && !CLASS_DATA (fsym)->attr.dimension)
7376 : {
7377 55 : gfc_add_class_array_ref (e);
7378 55 : parmse.want_coarray = 1;
7379 55 : scalar = false;
7380 : }
7381 :
7382 : /* A scalar or transformational function. */
7383 246355 : if (scalar)
7384 : {
7385 185619 : if (e->expr_type == EXPR_VARIABLE
7386 54940 : && e->symtree->n.sym->attr.cray_pointee
7387 390 : && fsym && fsym->attr.flavor == FL_PROCEDURE)
7388 : {
7389 : /* The Cray pointer needs to be converted to a pointer to
7390 : a type given by the expression. */
7391 6 : gfc_conv_expr (&parmse, e);
7392 6 : type = build_pointer_type (TREE_TYPE (parmse.expr));
7393 6 : tmp = gfc_get_symbol_decl (e->symtree->n.sym->cp_pointer);
7394 6 : parmse.expr = convert (type, tmp);
7395 : }
7396 :
7397 185613 : else if (sym->attr.is_bind_c && e && is_CFI_desc (fsym, NULL))
7398 : /* Implement F2018, 18.3.6, list item (5), bullet point 2. */
7399 687 : gfc_conv_gfc_desc_to_cfi_desc (&parmse, e, fsym);
7400 :
7401 184926 : else if (fsym && fsym->attr.value)
7402 : {
7403 22059 : if (fsym->ts.type == BT_CHARACTER
7404 543 : && fsym->ts.is_c_interop
7405 181 : && fsym->ns->proc_name != NULL
7406 181 : && fsym->ns->proc_name->attr.is_bind_c)
7407 : {
7408 172 : parmse.expr = NULL;
7409 172 : conv_scalar_char_value (fsym, &parmse, &e);
7410 172 : if (parmse.expr == NULL)
7411 166 : gfc_conv_expr (&parmse, e);
7412 : }
7413 : else
7414 : {
7415 21887 : gfc_conv_expr (&parmse, e);
7416 21887 : conv_dummy_value (&parmse, e, fsym, optionalargs);
7417 : }
7418 : }
7419 :
7420 162867 : else if (arg->name && arg->name[0] == '%')
7421 : /* Argument list functions %VAL, %LOC and %REF are signalled
7422 : through arg->name. */
7423 5826 : conv_arglist_function (&parmse, arg->expr, arg->name);
7424 157041 : else if ((e->expr_type == EXPR_FUNCTION)
7425 8305 : && ((e->value.function.esym
7426 2154 : && e->value.function.esym->result->attr.pointer)
7427 8210 : || (!e->value.function.esym
7428 6151 : && e->symtree->n.sym->attr.pointer))
7429 95 : && fsym && fsym->attr.target)
7430 : /* Make sure the function only gets called once. */
7431 8 : gfc_conv_expr_reference (&parmse, e);
7432 157033 : else if (e->expr_type == EXPR_FUNCTION
7433 8297 : && e->symtree->n.sym->result
7434 7262 : && e->symtree->n.sym->result != e->symtree->n.sym
7435 138 : && e->symtree->n.sym->result->attr.proc_pointer)
7436 : {
7437 : /* Functions returning procedure pointers. */
7438 18 : gfc_conv_expr (&parmse, e);
7439 18 : if (fsym && fsym->attr.proc_pointer)
7440 6 : parmse.expr = gfc_build_addr_expr (NULL_TREE, parmse.expr);
7441 : }
7442 :
7443 : else
7444 : {
7445 157015 : bool defer_to_dealloc_blk = false;
7446 157015 : if (e->ts.type == BT_CLASS && fsym
7447 3496 : && fsym->ts.type == BT_CLASS
7448 3074 : && (!CLASS_DATA (fsym)->as
7449 356 : || CLASS_DATA (fsym)->as->type != AS_ASSUMED_RANK)
7450 2718 : && CLASS_DATA (e)->attr.codimension)
7451 : {
7452 48 : gcc_assert (!CLASS_DATA (fsym)->attr.codimension);
7453 48 : gcc_assert (!CLASS_DATA (fsym)->as);
7454 48 : gfc_add_class_array_ref (e);
7455 48 : parmse.want_coarray = 1;
7456 48 : gfc_conv_expr_reference (&parmse, e);
7457 48 : class_scalar_coarray_to_class (&parmse, e, fsym->ts,
7458 48 : fsym->attr.optional
7459 48 : && e->expr_type == EXPR_VARIABLE);
7460 : }
7461 156967 : else if (e->ts.type == BT_CLASS && fsym
7462 3448 : && fsym->ts.type == BT_CLASS
7463 3026 : && !CLASS_DATA (fsym)->as
7464 2670 : && !CLASS_DATA (e)->as
7465 2560 : && strcmp (fsym->ts.u.derived->name,
7466 : e->ts.u.derived->name))
7467 : {
7468 1619 : type = gfc_typenode_for_spec (&fsym->ts);
7469 1619 : var = gfc_create_var (type, fsym->name);
7470 1619 : gfc_conv_expr (&parmse, e);
7471 1619 : if (fsym->attr.optional
7472 153 : && e->expr_type == EXPR_VARIABLE
7473 153 : && e->symtree->n.sym->attr.optional)
7474 : {
7475 66 : stmtblock_t block;
7476 66 : tree cond;
7477 66 : tmp = gfc_build_addr_expr (NULL_TREE, parmse.expr);
7478 66 : cond = fold_build2_loc (input_location, NE_EXPR,
7479 : logical_type_node, tmp,
7480 66 : fold_convert (TREE_TYPE (tmp),
7481 : null_pointer_node));
7482 66 : gfc_start_block (&block);
7483 66 : gfc_add_modify (&block, var,
7484 : fold_build1_loc (input_location,
7485 : VIEW_CONVERT_EXPR,
7486 : type, parmse.expr));
7487 66 : gfc_add_expr_to_block (&parmse.pre,
7488 : fold_build3_loc (input_location,
7489 : COND_EXPR, void_type_node,
7490 : cond, gfc_finish_block (&block),
7491 : build_empty_stmt (input_location)));
7492 66 : parmse.expr = gfc_build_addr_expr (NULL_TREE, var);
7493 132 : parmse.expr = build3_loc (input_location, COND_EXPR,
7494 66 : TREE_TYPE (parmse.expr),
7495 : cond, parmse.expr,
7496 66 : fold_convert (TREE_TYPE (parmse.expr),
7497 : null_pointer_node));
7498 66 : }
7499 : else
7500 : {
7501 : /* Since the internal representation of unlimited
7502 : polymorphic expressions includes an extra field
7503 : that other class objects do not, a cast to the
7504 : formal type does not work. */
7505 1553 : if (!UNLIMITED_POLY (e) && UNLIMITED_POLY (fsym))
7506 : {
7507 91 : tree efield;
7508 :
7509 : /* Evaluate arguments just once, when they have
7510 : side effects. */
7511 91 : if (TREE_SIDE_EFFECTS (parmse.expr))
7512 : {
7513 25 : tree cldata, zero;
7514 :
7515 25 : parmse.expr = gfc_evaluate_now (parmse.expr,
7516 : &parmse.pre);
7517 :
7518 : /* Prevent memory leak, when old component
7519 : was allocated already. */
7520 25 : cldata = gfc_class_data_get (parmse.expr);
7521 25 : zero = build_int_cst (TREE_TYPE (cldata),
7522 : 0);
7523 25 : tmp = fold_build2_loc (input_location, NE_EXPR,
7524 : logical_type_node,
7525 : cldata, zero);
7526 25 : tmp = build3_v (COND_EXPR, tmp,
7527 : gfc_call_free (cldata),
7528 : build_empty_stmt (
7529 : input_location));
7530 25 : gfc_add_expr_to_block (&parmse.finalblock,
7531 : tmp);
7532 25 : gfc_add_modify (&parmse.finalblock,
7533 : cldata, zero);
7534 : }
7535 :
7536 : /* Set the _data field. */
7537 91 : tmp = gfc_class_data_get (var);
7538 91 : efield = fold_convert (TREE_TYPE (tmp),
7539 : gfc_class_data_get (parmse.expr));
7540 91 : gfc_add_modify (&parmse.pre, tmp, efield);
7541 :
7542 : /* Set the _vptr field. */
7543 91 : tmp = gfc_class_vptr_get (var);
7544 91 : efield = fold_convert (TREE_TYPE (tmp),
7545 : gfc_class_vptr_get (parmse.expr));
7546 91 : gfc_add_modify (&parmse.pre, tmp, efield);
7547 :
7548 : /* Set the _len field. */
7549 91 : tmp = gfc_class_len_get (var);
7550 91 : gfc_add_modify (&parmse.pre, tmp,
7551 91 : build_int_cst (TREE_TYPE (tmp), 0));
7552 91 : }
7553 : else
7554 : {
7555 1462 : tmp = fold_build1_loc (input_location,
7556 : VIEW_CONVERT_EXPR,
7557 : type, parmse.expr);
7558 1462 : gfc_add_modify (&parmse.pre, var, tmp);
7559 1553 : ;
7560 : }
7561 1553 : parmse.expr = gfc_build_addr_expr (NULL_TREE, var);
7562 : }
7563 : }
7564 : else
7565 : {
7566 155348 : gfc_conv_expr_reference (&parmse, e);
7567 :
7568 155348 : gfc_symbol *dsym = fsym;
7569 155348 : gfc_dummy_arg *dummy;
7570 :
7571 : /* Use associated dummy as fallback for formal
7572 : argument if there is no explicit interface. */
7573 155348 : if (dsym == NULL
7574 27416 : && (dummy = arg->associated_dummy)
7575 24889 : && dummy->intrinsicness == GFC_NON_INTRINSIC_DUMMY_ARG
7576 178830 : && dummy->u.non_intrinsic->sym)
7577 : dsym = dummy->u.non_intrinsic->sym;
7578 :
7579 155348 : if (dsym
7580 151414 : && dsym->attr.intent == INTENT_OUT
7581 3266 : && !dsym->attr.allocatable
7582 3124 : && !dsym->attr.pointer
7583 3106 : && e->expr_type == EXPR_VARIABLE
7584 3105 : && e->ref == NULL
7585 2996 : && e->symtree
7586 2996 : && e->symtree->n.sym
7587 2996 : && !e->symtree->n.sym->attr.dimension
7588 2996 : && e->ts.type != BT_CHARACTER
7589 2894 : && e->ts.type != BT_CLASS
7590 2664 : && (e->ts.type != BT_DERIVED
7591 492 : || (dsym->ts.type == BT_DERIVED
7592 492 : && e->ts.u.derived == dsym->ts.u.derived
7593 : /* Types with allocatable components are
7594 : excluded from clobbering because we need
7595 : the unclobbered pointers to free the
7596 : allocatable components in the callee.
7597 : Same goes for finalizable types or types
7598 : with finalizable components, we need to
7599 : pass the unclobbered values to the
7600 : finalization routines.
7601 : For parameterized types, it's less clear
7602 : but they may not have a constant size
7603 : so better exclude them in any case. */
7604 453 : && !e->ts.u.derived->attr.alloc_comp
7605 327 : && !e->ts.u.derived->attr.pdt_type
7606 327 : && !gfc_is_finalizable (e->ts.u.derived, NULL)))
7607 2457 : && e->ts.type != BT_PROCEDURE
7608 157769 : && !sym->attr.elemental)
7609 : {
7610 1088 : tree var;
7611 1088 : var = build_fold_indirect_ref_loc (input_location,
7612 : parmse.expr);
7613 1088 : tree clobber = build_clobber (TREE_TYPE (var));
7614 1088 : gfc_add_modify (&clobbers, var, clobber);
7615 : }
7616 : }
7617 : /* Catch base objects that are not variables. */
7618 157015 : if (e->ts.type == BT_CLASS
7619 3496 : && e->expr_type != EXPR_VARIABLE
7620 306 : && expr && e == expr->base_expr)
7621 80 : base_object = build_fold_indirect_ref_loc (input_location,
7622 : parmse.expr);
7623 :
7624 : /* If an ALLOCATABLE dummy argument has INTENT(OUT) and is
7625 : allocated on entry, it must be deallocated. */
7626 129599 : if (fsym && fsym->attr.intent == INTENT_OUT
7627 3195 : && (fsym->attr.allocatable
7628 3053 : || (fsym->ts.type == BT_CLASS
7629 259 : && CLASS_DATA (fsym)->attr.allocatable))
7630 157306 : && !is_CFI_desc (fsym, NULL))
7631 : {
7632 291 : stmtblock_t block;
7633 291 : tree ptr;
7634 :
7635 291 : defer_to_dealloc_blk = true;
7636 :
7637 291 : parmse.expr = gfc_evaluate_data_ref_now (parmse.expr,
7638 : &parmse.pre);
7639 :
7640 291 : if (parmse.class_container != NULL_TREE)
7641 156 : parmse.class_container
7642 156 : = gfc_evaluate_data_ref_now (parmse.class_container,
7643 : &parmse.pre);
7644 :
7645 291 : gfc_init_block (&block);
7646 291 : ptr = parmse.expr;
7647 291 : if (e->ts.type == BT_CLASS)
7648 156 : ptr = gfc_class_data_get (ptr);
7649 :
7650 291 : tree cls = parmse.class_container;
7651 291 : tmp = gfc_deallocate_scalar_with_status (ptr, NULL_TREE,
7652 : NULL_TREE, true,
7653 : e, e->ts, cls);
7654 291 : gfc_add_expr_to_block (&block, tmp);
7655 291 : gfc_add_modify (&block, ptr,
7656 291 : fold_convert (TREE_TYPE (ptr),
7657 : null_pointer_node));
7658 :
7659 291 : if (fsym->ts.type == BT_CLASS)
7660 149 : gfc_reset_vptr (&block, nullptr,
7661 : build_fold_indirect_ref (parmse.expr),
7662 149 : fsym->ts.u.derived);
7663 :
7664 291 : if (fsym->attr.optional
7665 42 : && e->expr_type == EXPR_VARIABLE
7666 42 : && e->symtree->n.sym->attr.optional)
7667 : {
7668 36 : tmp = fold_build3_loc (input_location, COND_EXPR,
7669 : void_type_node,
7670 18 : gfc_conv_expr_present (e->symtree->n.sym),
7671 : gfc_finish_block (&block),
7672 : build_empty_stmt (input_location));
7673 : }
7674 : else
7675 273 : tmp = gfc_finish_block (&block);
7676 :
7677 291 : gfc_add_expr_to_block (&dealloc_blk, tmp);
7678 : }
7679 :
7680 : /* A class array element needs converting back to be a
7681 : class object, if the formal argument is a class object. */
7682 157015 : if (fsym && fsym->ts.type == BT_CLASS
7683 3098 : && e->ts.type == BT_CLASS
7684 3074 : && ((CLASS_DATA (fsym)->as
7685 356 : && CLASS_DATA (fsym)->as->type == AS_ASSUMED_RANK)
7686 2718 : || CLASS_DATA (e)->attr.dimension))
7687 : {
7688 466 : gfc_se class_se = parmse;
7689 466 : gfc_init_block (&class_se.pre);
7690 466 : gfc_init_block (&class_se.post);
7691 :
7692 466 : gfc_conv_class_to_class (&class_se, e, fsym->ts, false,
7693 466 : fsym->attr.intent != INTENT_IN
7694 466 : && (CLASS_DATA (fsym)->attr.class_pointer
7695 267 : || CLASS_DATA (fsym)->attr.allocatable),
7696 466 : fsym->attr.optional
7697 198 : && e->expr_type == EXPR_VARIABLE
7698 664 : && e->symtree->n.sym->attr.optional,
7699 466 : CLASS_DATA (fsym)->attr.class_pointer
7700 466 : || CLASS_DATA (fsym)->attr.allocatable);
7701 :
7702 466 : parmse.expr = class_se.expr;
7703 442 : stmtblock_t *class_pre_block = defer_to_dealloc_blk
7704 466 : ? &dealloc_blk
7705 : : &parmse.pre;
7706 466 : gfc_add_block_to_block (class_pre_block, &class_se.pre);
7707 466 : gfc_add_block_to_block (&parmse.post, &class_se.post);
7708 : }
7709 :
7710 129599 : if (fsym && (fsym->ts.type == BT_DERIVED
7711 117665 : || fsym->ts.type == BT_ASSUMED)
7712 12573 : && e->ts.type == BT_CLASS
7713 410 : && !CLASS_DATA (e)->attr.dimension
7714 374 : && !CLASS_DATA (e)->attr.codimension)
7715 : {
7716 374 : parmse.expr = gfc_class_data_get (parmse.expr);
7717 : /* The result is a class temporary, whose _data component
7718 : must be freed to avoid a memory leak. */
7719 374 : if (e->expr_type == EXPR_FUNCTION
7720 23 : && CLASS_DATA (e)->attr.allocatable)
7721 : {
7722 19 : tree zero;
7723 :
7724 : /* Finalize the expression. */
7725 19 : gfc_finalize_tree_expr (&parmse, NULL,
7726 19 : gfc_expr_attr (e), e->rank);
7727 19 : gfc_add_block_to_block (&parmse.post,
7728 : &parmse.finalblock);
7729 :
7730 : /* Then free the class _data. */
7731 19 : zero = build_int_cst (TREE_TYPE (parmse.expr), 0);
7732 19 : tmp = fold_build2_loc (input_location, NE_EXPR,
7733 : logical_type_node,
7734 : parmse.expr, zero);
7735 19 : tmp = build3_v (COND_EXPR, tmp,
7736 : gfc_call_free (parmse.expr),
7737 : build_empty_stmt (input_location));
7738 19 : gfc_add_expr_to_block (&parmse.post, tmp);
7739 19 : gfc_add_modify (&parmse.post, parmse.expr, zero);
7740 : }
7741 : }
7742 :
7743 : /* Wrap scalar variable in a descriptor. We need to convert
7744 : the address of a pointer back to the pointer itself before,
7745 : we can assign it to the data field. */
7746 :
7747 129599 : if (fsym && fsym->as && fsym->as->type == AS_ASSUMED_RANK
7748 1338 : && fsym->ts.type != BT_CLASS && e->expr_type != EXPR_NULL)
7749 : {
7750 1266 : tmp = parmse.expr;
7751 1266 : if (TREE_CODE (tmp) == ADDR_EXPR)
7752 748 : tmp = TREE_OPERAND (tmp, 0);
7753 1266 : parmse.expr = gfc_conv_scalar_to_descriptor (&parmse, tmp,
7754 : fsym->attr);
7755 1266 : parmse.expr = gfc_build_addr_expr (NULL_TREE,
7756 : parmse.expr);
7757 : }
7758 128333 : else if (fsym && e->expr_type != EXPR_NULL
7759 128035 : && ((fsym->attr.pointer
7760 1740 : && fsym->attr.flavor != FL_PROCEDURE)
7761 126301 : || (fsym->attr.proc_pointer
7762 199 : && !(e->expr_type == EXPR_VARIABLE
7763 199 : && e->symtree->n.sym->attr.dummy))
7764 126114 : || (fsym->attr.proc_pointer
7765 12 : && e->expr_type == EXPR_VARIABLE
7766 12 : && gfc_is_proc_ptr_comp (e))
7767 126108 : || (fsym->attr.allocatable
7768 1040 : && fsym->attr.flavor != FL_PROCEDURE)))
7769 : {
7770 : /* Scalar pointer dummy args require an extra level of
7771 : indirection. The null pointer already contains
7772 : this level of indirection. */
7773 2961 : parm_kind = SCALAR_POINTER;
7774 2961 : parmse.expr = gfc_build_addr_expr (NULL_TREE, parmse.expr);
7775 : }
7776 : }
7777 : }
7778 60736 : else if (e->ts.type == BT_CLASS
7779 2723 : && fsym && fsym->ts.type == BT_CLASS
7780 2377 : && (CLASS_DATA (fsym)->attr.dimension
7781 55 : || CLASS_DATA (fsym)->attr.codimension))
7782 : {
7783 : /* Pass a class array. */
7784 2377 : gfc_conv_expr_descriptor (&parmse, e);
7785 2377 : bool defer_to_dealloc_blk = false;
7786 :
7787 2377 : if (fsym->attr.optional
7788 798 : && e->expr_type == EXPR_VARIABLE
7789 798 : && e->symtree->n.sym->attr.optional)
7790 : {
7791 438 : stmtblock_t block;
7792 :
7793 438 : gfc_init_block (&block);
7794 438 : gfc_add_block_to_block (&block, &parmse.pre);
7795 :
7796 876 : tree t = fold_build3_loc (input_location, COND_EXPR,
7797 : void_type_node,
7798 438 : gfc_conv_expr_present (e->symtree->n.sym),
7799 : gfc_finish_block (&block),
7800 : build_empty_stmt (input_location));
7801 :
7802 438 : gfc_add_expr_to_block (&parmse.pre, t);
7803 : }
7804 :
7805 : /* If an ALLOCATABLE dummy argument has INTENT(OUT) and is
7806 : allocated on entry, it must be deallocated. */
7807 2377 : if (fsym->attr.intent == INTENT_OUT
7808 141 : && CLASS_DATA (fsym)->attr.allocatable)
7809 : {
7810 110 : stmtblock_t block;
7811 110 : tree ptr;
7812 :
7813 : /* In case the data reference to deallocate is dependent on
7814 : its own content, save the resulting pointer to a variable
7815 : and only use that variable from now on, before the
7816 : expression becomes invalid. */
7817 110 : parmse.expr = gfc_evaluate_data_ref_now (parmse.expr,
7818 : &parmse.pre);
7819 :
7820 110 : if (parmse.class_container != NULL_TREE)
7821 110 : parmse.class_container
7822 110 : = gfc_evaluate_data_ref_now (parmse.class_container,
7823 : &parmse.pre);
7824 :
7825 110 : gfc_init_block (&block);
7826 110 : ptr = parmse.expr;
7827 110 : ptr = gfc_class_data_get (ptr);
7828 :
7829 110 : tree cls = parmse.class_container;
7830 110 : tmp = gfc_deallocate_with_status (ptr, NULL_TREE,
7831 : NULL_TREE, NULL_TREE,
7832 : NULL_TREE, true, e,
7833 : GFC_CAF_COARRAY_NOCOARRAY,
7834 : cls);
7835 110 : gfc_add_expr_to_block (&block, tmp);
7836 110 : tmp = fold_build2_loc (input_location, MODIFY_EXPR,
7837 : void_type_node, ptr,
7838 : null_pointer_node);
7839 110 : gfc_add_expr_to_block (&block, tmp);
7840 110 : gfc_reset_vptr (&block, e, parmse.class_container);
7841 :
7842 110 : if (fsym->attr.optional
7843 30 : && e->expr_type == EXPR_VARIABLE
7844 30 : && (!e->ref
7845 30 : || (e->ref->type == REF_ARRAY
7846 0 : && e->ref->u.ar.type != AR_FULL))
7847 0 : && e->symtree->n.sym->attr.optional)
7848 : {
7849 0 : tmp = fold_build3_loc (input_location, COND_EXPR,
7850 : void_type_node,
7851 0 : gfc_conv_expr_present (e->symtree->n.sym),
7852 : gfc_finish_block (&block),
7853 : build_empty_stmt (input_location));
7854 : }
7855 : else
7856 110 : tmp = gfc_finish_block (&block);
7857 :
7858 110 : gfc_add_expr_to_block (&dealloc_blk, tmp);
7859 110 : defer_to_dealloc_blk = true;
7860 : }
7861 :
7862 2377 : gfc_se class_se = parmse;
7863 2377 : gfc_init_block (&class_se.pre);
7864 2377 : gfc_init_block (&class_se.post);
7865 :
7866 2377 : if (e->expr_type != EXPR_VARIABLE)
7867 : {
7868 : int n;
7869 : /* Set the bounds and offset correctly. */
7870 60 : for (n = 0; n < e->rank; n++)
7871 30 : gfc_conv_shift_descriptor_lbound (&class_se.pre,
7872 : class_se.expr,
7873 : n, gfc_index_one_node);
7874 : }
7875 :
7876 : /* The conversion does not repackage the reference to a class
7877 : array - _data descriptor. */
7878 2377 : gfc_conv_class_to_class (&class_se, e, fsym->ts, false,
7879 2377 : fsym->attr.intent != INTENT_IN
7880 2377 : && (CLASS_DATA (fsym)->attr.class_pointer
7881 1229 : || CLASS_DATA (fsym)->attr.allocatable),
7882 2377 : fsym->attr.optional
7883 798 : && e->expr_type == EXPR_VARIABLE
7884 3175 : && e->symtree->n.sym->attr.optional,
7885 2377 : CLASS_DATA (fsym)->attr.class_pointer
7886 2377 : || CLASS_DATA (fsym)->attr.allocatable);
7887 :
7888 2377 : parmse.expr = class_se.expr;
7889 2267 : stmtblock_t *class_pre_block = defer_to_dealloc_blk
7890 2377 : ? &dealloc_blk
7891 : : &parmse.pre;
7892 2377 : gfc_add_block_to_block (class_pre_block, &class_se.pre);
7893 2377 : gfc_add_block_to_block (&parmse.post, &class_se.post);
7894 :
7895 2377 : if (e->expr_type == EXPR_OP
7896 12 : && POINTER_TYPE_P (TREE_TYPE (parmse.expr))
7897 2389 : && GFC_CLASS_TYPE_P (TREE_TYPE (TREE_OPERAND (parmse.expr, 0))))
7898 : {
7899 12 : tree cond;
7900 12 : tree dealloc_expr = gfc_finish_block (&parmse.post);
7901 12 : tmp = TREE_OPERAND (parmse.expr, 0);
7902 12 : gfc_init_block (&parmse.post);
7903 12 : cond = gfc_class_data_get (tmp);
7904 12 : tmp = gfc_deallocate_alloc_comp_no_caf (e->ts.u.derived,
7905 : tmp, e->rank, true);
7906 12 : gfc_add_expr_to_block (&parmse.post, tmp);
7907 12 : cond = gfc_class_data_get (TREE_OPERAND (parmse.expr, 0));
7908 12 : cond = gfc_conv_descriptor_data_get (cond);
7909 12 : cond = fold_build2_loc (input_location, NE_EXPR,
7910 : logical_type_node, cond,
7911 12 : build_int_cst (TREE_TYPE (cond), 0));
7912 12 : tmp = build3_v (COND_EXPR, cond, dealloc_expr,
7913 : build_empty_stmt (input_location));
7914 :
7915 : /* This specific case should not be processed further and so
7916 : bundle everything up and proceed to the next argument. */
7917 12 : if (fsym && need_interface_mapping && e)
7918 12 : gfc_add_interface_mapping (&mapping, fsym, &parmse, e);
7919 12 : gfc_add_expr_to_block (&parmse.post, tmp);
7920 12 : gfc_add_block_to_block (&se->pre, &parmse.pre);
7921 12 : gfc_add_block_to_block (&post, &parmse.post);
7922 12 : gfc_add_block_to_block (&se->finalblock, &parmse.finalblock);
7923 12 : vec_safe_push (arglist, parmse.expr);
7924 12 : continue;
7925 12 : }
7926 2365 : }
7927 : else
7928 : {
7929 : /* If the argument is a function call that may not create
7930 : a temporary for the result, we have to check that we
7931 : can do it, i.e. that there is no alias between this
7932 : argument and another one. */
7933 58359 : if (gfc_get_noncopying_intrinsic_argument (e) != NULL)
7934 : {
7935 412 : gfc_expr *iarg;
7936 412 : sym_intent intent;
7937 :
7938 412 : if (fsym != NULL)
7939 403 : intent = fsym->attr.intent;
7940 : else
7941 : intent = INTENT_UNKNOWN;
7942 :
7943 412 : if (gfc_check_fncall_dependency (e, intent, sym, args,
7944 : NOT_ELEMENTAL))
7945 21 : parmse.force_tmp = 1;
7946 :
7947 412 : iarg = e->value.function.actual->expr;
7948 :
7949 : /* Temporary needed if aliasing due to host association. */
7950 412 : if (sym->attr.contained
7951 168 : && !sym->attr.pure
7952 168 : && !sym->attr.implicit_pure
7953 84 : && !sym->attr.use_assoc
7954 84 : && iarg->expr_type == EXPR_VARIABLE
7955 84 : && sym->ns == iarg->symtree->n.sym->ns)
7956 36 : parmse.force_tmp = 1;
7957 :
7958 : /* Ditto within module. */
7959 412 : if (sym->attr.use_assoc
7960 6 : && !sym->attr.pure
7961 6 : && !sym->attr.implicit_pure
7962 0 : && iarg->expr_type == EXPR_VARIABLE
7963 0 : && sym->module == iarg->symtree->n.sym->module)
7964 0 : parmse.force_tmp = 1;
7965 : }
7966 :
7967 : /* Special case for assumed-rank arrays: when passing an
7968 : argument to a nonallocatable/nonpointer dummy, the bounds have
7969 : to be reset as otherwise a last-dim ubound of -1 is
7970 : indistinguishable from an assumed-size array in the callee. */
7971 58359 : if (!sym->attr.is_bind_c && e && fsym && fsym->as
7972 35318 : && fsym->as->type == AS_ASSUMED_RANK
7973 11966 : && e->rank != -1
7974 11652 : && e->expr_type == EXPR_VARIABLE
7975 11187 : && ((fsym->ts.type == BT_CLASS
7976 0 : && !CLASS_DATA (fsym)->attr.class_pointer
7977 0 : && !CLASS_DATA (fsym)->attr.allocatable)
7978 11187 : || (fsym->ts.type != BT_CLASS
7979 11187 : && !fsym->attr.pointer && !fsym->attr.allocatable)))
7980 : {
7981 : /* Change AR_FULL to a (:,:,:) ref to force bounds update. */
7982 10644 : gfc_ref *ref;
7983 10902 : for (ref = e->ref; ref->next; ref = ref->next)
7984 : {
7985 330 : if (ref->next->type == REF_INQUIRY)
7986 : break;
7987 282 : if (ref->type == REF_ARRAY
7988 24 : && ref->u.ar.type != AR_ELEMENT)
7989 : break;
7990 10644 : };
7991 10644 : if (ref->u.ar.type == AR_FULL
7992 9894 : && ref->u.ar.as->type != AS_ASSUMED_SIZE)
7993 9774 : ref->u.ar.type = AR_SECTION;
7994 : }
7995 :
7996 58359 : if (sym->attr.is_bind_c && e && is_CFI_desc (fsym, NULL))
7997 : /* Implement F2018, 18.3.6, list item (5), bullet point 2. */
7998 5850 : gfc_conv_gfc_desc_to_cfi_desc (&parmse, e, fsym);
7999 :
8000 52509 : else if (e->expr_type == EXPR_VARIABLE
8001 40931 : && is_subref_array (e)
8002 53489 : && !(fsym && fsym->attr.pointer))
8003 : /* The actual argument is a component reference to an
8004 : array of derived types. In this case, the argument
8005 : is converted to a temporary, which is passed and then
8006 : written back after the procedure call. */
8007 727 : gfc_conv_subref_array_arg (&parmse, e, nodesc_arg,
8008 685 : fsym ? fsym->attr.intent : INTENT_INOUT,
8009 727 : fsym && fsym->attr.pointer);
8010 :
8011 51782 : else if (e->ts.type == BT_CLASS && CLASS_DATA (e)->as
8012 345 : && CLASS_DATA (e)->as->type == AS_ASSUMED_SIZE
8013 18 : && nodesc_arg && fsym->ts.type == BT_DERIVED)
8014 : /* An assumed size class actual argument being passed to
8015 : a 'no descriptor' formal argument just requires the
8016 : data pointer to be passed. For class dummy arguments
8017 : this is stored in the symbol backend decl.. */
8018 6 : parmse.expr = e->symtree->n.sym->backend_decl;
8019 :
8020 51776 : else if (gfc_is_class_array_ref (e, NULL)
8021 51776 : && fsym && fsym->ts.type == BT_DERIVED)
8022 : /* The actual argument is a component reference to an
8023 : array of derived types. In this case, the argument
8024 : is converted to a temporary, which is passed and then
8025 : written back after the procedure call.
8026 : OOP-TODO: Insert code so that if the dynamic type is
8027 : the same as the declared type, copy-in/copy-out does
8028 : not occur. */
8029 108 : gfc_conv_subref_array_arg (&parmse, e, nodesc_arg,
8030 108 : fsym->attr.intent,
8031 108 : fsym->attr.pointer);
8032 :
8033 51668 : else if (gfc_is_class_array_function (e)
8034 51668 : && fsym && fsym->ts.type == BT_DERIVED)
8035 : /* See previous comment. For function actual argument,
8036 : the write out is not needed so the intent is set as
8037 : intent in. */
8038 : {
8039 13 : e->must_finalize = 1;
8040 13 : gfc_conv_subref_array_arg (&parmse, e, nodesc_arg,
8041 13 : INTENT_IN, fsym->attr.pointer);
8042 : }
8043 48076 : else if (fsym && fsym->attr.contiguous
8044 90 : && (fsym->attr.target
8045 1762 : ? gfc_is_not_contiguous (e)
8046 1672 : : !gfc_is_simply_contiguous (e, false, true))
8047 357 : && gfc_expr_is_variable (e)
8048 53762 : && e->rank != -1)
8049 : {
8050 333 : gfc_conv_subref_array_arg (&parmse, e, nodesc_arg,
8051 333 : fsym->attr.intent,
8052 333 : fsym->attr.pointer);
8053 : }
8054 : else
8055 : /* This is where we introduce a temporary to store the
8056 : result of a non-lvalue array expression. */
8057 51322 : gfc_conv_array_parameter (&parmse, e, nodesc_arg, fsym,
8058 : sym->name, NULL);
8059 :
8060 : /* If an ALLOCATABLE dummy argument has INTENT(OUT) and is
8061 : allocated on entry, it must be deallocated.
8062 : CFI descriptors are handled elsewhere. */
8063 54738 : if (fsym && fsym->attr.allocatable
8064 1784 : && fsym->attr.intent == INTENT_OUT
8065 58105 : && !is_CFI_desc (fsym, NULL))
8066 : {
8067 158 : if (fsym->ts.type == BT_DERIVED
8068 45 : && fsym->ts.u.derived->attr.alloc_comp)
8069 : {
8070 : // deallocate the components first
8071 9 : tmp = gfc_deallocate_alloc_comp (fsym->ts.u.derived,
8072 : parmse.expr, e->rank);
8073 : /* But check whether dummy argument is optional. */
8074 9 : if (tmp != NULL_TREE
8075 9 : && fsym->attr.optional
8076 6 : && e->expr_type == EXPR_VARIABLE
8077 6 : && e->symtree->n.sym->attr.optional)
8078 : {
8079 6 : tree present;
8080 6 : present = gfc_conv_expr_present (e->symtree->n.sym);
8081 6 : tmp = build3_v (COND_EXPR, present, tmp,
8082 : build_empty_stmt (input_location));
8083 : }
8084 9 : if (tmp != NULL_TREE)
8085 9 : gfc_add_expr_to_block (&dealloc_blk, tmp);
8086 : }
8087 :
8088 158 : tmp = parmse.expr;
8089 : /* With bind(C), the actual argument is replaced by a bind-C
8090 : descriptor; in this case, the data component arrives here,
8091 : which shall not be dereferenced, but still freed and
8092 : nullified. */
8093 158 : if (TREE_TYPE(tmp) != pvoid_type_node)
8094 158 : tmp = build_fold_indirect_ref_loc (input_location,
8095 : parmse.expr);
8096 158 : tmp = gfc_deallocate_with_status (tmp, NULL_TREE, NULL_TREE,
8097 : NULL_TREE, NULL_TREE, true,
8098 : e,
8099 : GFC_CAF_COARRAY_NOCOARRAY);
8100 158 : if (fsym->attr.optional
8101 48 : && e->expr_type == EXPR_VARIABLE
8102 48 : && e->symtree->n.sym->attr.optional)
8103 48 : tmp = fold_build3_loc (input_location, COND_EXPR,
8104 : void_type_node,
8105 24 : gfc_conv_expr_present (e->symtree->n.sym),
8106 : tmp, build_empty_stmt (input_location));
8107 158 : gfc_add_expr_to_block (&dealloc_blk, tmp);
8108 : }
8109 : }
8110 : }
8111 : /* Special case for an assumed-rank dummy argument. */
8112 271225 : if (!sym->attr.is_bind_c && e && fsym && e->rank > 0
8113 57040 : && (fsym->ts.type == BT_CLASS
8114 57040 : ? (CLASS_DATA (fsym)->as
8115 4594 : && CLASS_DATA (fsym)->as->type == AS_ASSUMED_RANK)
8116 52446 : : (fsym->as && fsym->as->type == AS_ASSUMED_RANK)))
8117 : {
8118 12803 : if (fsym->ts.type == BT_CLASS
8119 12803 : ? (CLASS_DATA (fsym)->attr.class_pointer
8120 1067 : || CLASS_DATA (fsym)->attr.allocatable)
8121 11736 : : (fsym->attr.pointer || fsym->attr.allocatable))
8122 : {
8123 : /* Unallocated allocatable arrays and unassociated pointer
8124 : arrays need their dtype setting if they are argument
8125 : associated with assumed rank dummies to set the rank. */
8126 891 : set_dtype_for_unallocated (&parmse, e);
8127 : }
8128 11912 : else if (e->expr_type == EXPR_VARIABLE
8129 11409 : && e->symtree->n.sym->attr.dummy
8130 722 : && (e->ts.type == BT_CLASS
8131 915 : ? (e->ref && e->ref->next
8132 193 : && e->ref->next->type == REF_ARRAY
8133 193 : && e->ref->next->u.ar.type == AR_FULL
8134 386 : && e->ref->next->u.ar.as->type == AS_ASSUMED_SIZE)
8135 529 : : (e->ref && e->ref->type == REF_ARRAY
8136 529 : && e->ref->u.ar.type == AR_FULL
8137 757 : && e->ref->u.ar.as->type == AS_ASSUMED_SIZE)))
8138 : {
8139 : /* Assumed-size actual to assumed-rank dummy requires
8140 : dim[rank-1].ubound = -1. */
8141 180 : tree minus_one;
8142 180 : tmp = build_fold_indirect_ref_loc (input_location, parmse.expr);
8143 180 : if (fsym->ts.type == BT_CLASS)
8144 60 : tmp = gfc_class_data_get (tmp);
8145 180 : minus_one = build_int_cst (gfc_array_index_type, -1);
8146 180 : gfc_conv_descriptor_ubound_set (&parmse.pre, tmp,
8147 180 : gfc_rank_cst[e->rank - 1],
8148 : minus_one);
8149 : }
8150 : }
8151 :
8152 : /* The case with fsym->attr.optional is that of a user subroutine
8153 : with an interface indicating an optional argument. When we call
8154 : an intrinsic subroutine, however, fsym is NULL, but we might still
8155 : have an optional argument, so we proceed to the substitution
8156 : just in case. Arguments passed to bind(c) procedures via CFI
8157 : descriptors are handled elsewhere. */
8158 258225 : if (e && (fsym == NULL || fsym->attr.optional)
8159 331649 : && !(sym->attr.is_bind_c && is_CFI_desc (fsym, NULL)))
8160 : {
8161 : /* If an optional argument is itself an optional dummy argument,
8162 : check its presence and substitute a null if absent. This is
8163 : only needed when passing an array to an elemental procedure
8164 : as then array elements are accessed - or no NULL pointer is
8165 : allowed and a "1" or "0" should be passed if not present.
8166 : When passing a non-array-descriptor full array to a
8167 : non-array-descriptor dummy, no check is needed. For
8168 : array-descriptor actual to array-descriptor dummy, see
8169 : PR 41911 for why a check has to be inserted.
8170 : fsym == NULL is checked as intrinsics required the descriptor
8171 : but do not always set fsym.
8172 : Also, it is necessary to pass a NULL pointer to library routines
8173 : which usually ignore optional arguments, so they can handle
8174 : these themselves. */
8175 59330 : if (e->expr_type == EXPR_VARIABLE
8176 26432 : && e->symtree->n.sym->attr.optional
8177 2421 : && (((e->rank != 0 && elemental_proc)
8178 2246 : || e->representation.length || e->ts.type == BT_CHARACTER
8179 2020 : || (e->rank == 0 && e->symtree->n.sym->attr.value)
8180 1910 : || (e->rank != 0
8181 1070 : && (fsym == NULL
8182 1034 : || (fsym->as
8183 272 : && (fsym->as->type == AS_ASSUMED_SHAPE
8184 235 : || fsym->as->type == AS_ASSUMED_RANK
8185 117 : || fsym->as->type == AS_DEFERRED)))))
8186 1685 : || se->ignore_optional))
8187 764 : gfc_conv_missing_dummy (&parmse, e, fsym ? fsym->ts : e->ts,
8188 764 : e->representation.length);
8189 : }
8190 :
8191 : /* Make the class container for the first argument available with class
8192 : valued transformational functions. */
8193 271225 : if (argc == 0 && e && e->ts.type == BT_CLASS
8194 4991 : && isym && isym->transformational
8195 84 : && se->ss && se->ss->info)
8196 : {
8197 84 : arg1_cntnr = parmse.expr;
8198 84 : if (POINTER_TYPE_P (TREE_TYPE (arg1_cntnr)))
8199 84 : arg1_cntnr = build_fold_indirect_ref_loc (input_location, arg1_cntnr);
8200 84 : arg1_cntnr = gfc_get_class_from_expr (arg1_cntnr);
8201 84 : se->ss->info->class_container = arg1_cntnr;
8202 : }
8203 :
8204 : /* Obtain the character length of an assumed character length procedure
8205 : from the typespec of the actual argument. */
8206 271225 : if (e
8207 258225 : && parmse.string_length == NULL_TREE
8208 222627 : && e->ts.type == BT_PROCEDURE
8209 1935 : && e->symtree->n.sym->ts.type == BT_CHARACTER
8210 21 : && e->symtree->n.sym->ts.u.cl->length != NULL
8211 21 : && e->symtree->n.sym->ts.u.cl->length->expr_type == EXPR_CONSTANT)
8212 : {
8213 13 : gfc_conv_const_charlen (e->symtree->n.sym->ts.u.cl);
8214 13 : parmse.string_length = e->symtree->n.sym->ts.u.cl->backend_decl;
8215 : }
8216 :
8217 271225 : if (fsym && e)
8218 : {
8219 : /* Obtain the character length for a NULL() actual with a character
8220 : MOLD argument. Otherwise substitute a suitable dummy length.
8221 : Here we handle non-optional dummies of non-bind(c) procedures. */
8222 226326 : if (e->expr_type == EXPR_NULL
8223 745 : && fsym->ts.type == BT_CHARACTER
8224 296 : && !fsym->attr.optional
8225 226544 : && !(sym->attr.is_bind_c && is_CFI_desc (fsym, NULL)))
8226 216 : conv_null_actual (&parmse, e, fsym);
8227 : }
8228 :
8229 : /* If any actual argument of the procedure is allocatable and passed
8230 : to an allocatable dummy with INTENT(OUT), we conservatively
8231 : evaluate actual argument expressions before deallocations are
8232 : performed and the procedure is executed. May create temporaries.
8233 : This ensures we conform to F2023:15.5.3, 15.5.4. */
8234 258225 : if (e && fsym && force_eval_args
8235 1104 : && fsym->attr.intent != INTENT_OUT
8236 271634 : && !gfc_is_constant_expr (e))
8237 268 : parmse.expr = gfc_evaluate_now (parmse.expr, &parmse.pre);
8238 :
8239 271225 : if (fsym && need_interface_mapping && e)
8240 40510 : gfc_add_interface_mapping (&mapping, fsym, &parmse, e);
8241 :
8242 271225 : gfc_add_block_to_block (&se->pre, &parmse.pre);
8243 271225 : gfc_add_block_to_block (&post, &parmse.post);
8244 271225 : gfc_add_block_to_block (&se->finalblock, &parmse.finalblock);
8245 :
8246 : /* Allocated allocatable components of derived types must be
8247 : deallocated for non-variable scalars, array arguments to elemental
8248 : procedures, and array arguments with descriptor to non-elemental
8249 : procedures. As bounds information for descriptorless arrays is no
8250 : longer available here, they are dealt with in trans-array.cc
8251 : (gfc_conv_array_parameter). */
8252 258225 : if (e && (e->ts.type == BT_DERIVED || e->ts.type == BT_CLASS)
8253 28473 : && e->ts.u.derived->attr.alloc_comp
8254 7603 : && (e->rank == 0 || elemental_proc || !nodesc_arg)
8255 278690 : && !expr_may_alias_variables (e, elemental_proc))
8256 : {
8257 372 : int parm_rank;
8258 : /* It is known the e returns a structure type with at least one
8259 : allocatable component. When e is a function, ensure that the
8260 : function is called once only by using a temporary variable. */
8261 372 : if (!DECL_P (parmse.expr) && e->expr_type == EXPR_FUNCTION)
8262 140 : parmse.expr = gfc_evaluate_now_loc (input_location,
8263 : parmse.expr, &se->pre);
8264 :
8265 372 : if ((fsym && fsym->attr.value) || e->expr_type == EXPR_ARRAY)
8266 152 : tmp = parmse.expr;
8267 : else
8268 220 : tmp = build_fold_indirect_ref_loc (input_location,
8269 : parmse.expr);
8270 :
8271 372 : parm_rank = e->rank;
8272 372 : switch (parm_kind)
8273 : {
8274 : case (ELEMENTAL):
8275 : case (SCALAR):
8276 372 : parm_rank = 0;
8277 : break;
8278 :
8279 0 : case (SCALAR_POINTER):
8280 0 : tmp = build_fold_indirect_ref_loc (input_location,
8281 : tmp);
8282 0 : break;
8283 : }
8284 :
8285 372 : if (e->ts.type == BT_DERIVED && fsym && fsym->ts.type == BT_CLASS)
8286 : {
8287 : /* The derived type is passed to gfc_deallocate_alloc_comp.
8288 : Therefore, class actuals can be handled correctly but derived
8289 : types passed to class formals need the _data component. */
8290 82 : tmp = gfc_class_data_get (tmp);
8291 82 : if (!CLASS_DATA (fsym)->attr.dimension)
8292 : {
8293 56 : if (UNLIMITED_POLY (fsym))
8294 : {
8295 12 : tree type = gfc_typenode_for_spec (&e->ts);
8296 12 : type = build_pointer_type (type);
8297 12 : tmp = fold_convert (type, tmp);
8298 : }
8299 56 : tmp = build_fold_indirect_ref_loc (input_location, tmp);
8300 : }
8301 : }
8302 :
8303 372 : if (e->expr_type == EXPR_OP
8304 24 : && e->value.op.op == INTRINSIC_PARENTHESES
8305 24 : && e->value.op.op1->expr_type == EXPR_VARIABLE)
8306 : {
8307 24 : tree local_tmp;
8308 24 : local_tmp = gfc_evaluate_now (tmp, &se->pre);
8309 24 : local_tmp = gfc_copy_alloc_comp (e->ts.u.derived, local_tmp, tmp,
8310 : parm_rank, 0);
8311 24 : gfc_add_expr_to_block (&se->post, local_tmp);
8312 : }
8313 :
8314 : /* Items of array expressions passed to a polymorphic formal arguments
8315 : create their own clean up, so prevent double free. */
8316 372 : if (!finalized && !e->must_finalize
8317 371 : && !(e->expr_type == EXPR_ARRAY && fsym
8318 86 : && fsym->ts.type == BT_CLASS))
8319 : {
8320 351 : bool scalar_res_outside_loop;
8321 1041 : scalar_res_outside_loop = e->expr_type == EXPR_FUNCTION
8322 151 : && parm_rank == 0
8323 490 : && parmse.loop;
8324 :
8325 : /* Scalars passed to an assumed rank argument are converted to
8326 : a descriptor. Obtain the data field before deallocating any
8327 : allocatable components. */
8328 298 : if (parm_rank == 0 && e->expr_type != EXPR_ARRAY
8329 612 : && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp)))
8330 19 : tmp = gfc_conv_descriptor_data_get (tmp);
8331 :
8332 351 : if (scalar_res_outside_loop)
8333 : {
8334 : /* Go through the ss chain to find the argument and use
8335 : the stored value. */
8336 30 : gfc_ss *tmp_ss = parmse.loop->ss;
8337 72 : for (; tmp_ss; tmp_ss = tmp_ss->next)
8338 60 : if (tmp_ss->info
8339 48 : && tmp_ss->info->expr == e
8340 18 : && tmp_ss->info->data.scalar.value != NULL_TREE)
8341 : {
8342 18 : tmp = tmp_ss->info->data.scalar.value;
8343 18 : break;
8344 : }
8345 : }
8346 :
8347 351 : STRIP_NOPS (tmp);
8348 :
8349 351 : if (derived_array != NULL_TREE)
8350 0 : tmp = gfc_deallocate_alloc_comp (e->ts.u.derived,
8351 : derived_array,
8352 : parm_rank);
8353 351 : else if ((e->ts.type == BT_CLASS
8354 24 : && GFC_CLASS_TYPE_P (TREE_TYPE (tmp)))
8355 351 : || e->ts.type == BT_DERIVED)
8356 351 : tmp = gfc_deallocate_alloc_comp (e->ts.u.derived, tmp,
8357 : parm_rank, 0, true);
8358 0 : else if (e->ts.type == BT_CLASS)
8359 0 : tmp = gfc_deallocate_alloc_comp (CLASS_DATA (e)->ts.u.derived,
8360 : tmp, parm_rank);
8361 :
8362 351 : if (scalar_res_outside_loop)
8363 30 : gfc_add_expr_to_block (&parmse.loop->post, tmp);
8364 : else
8365 321 : gfc_prepend_expr_to_block (&post, tmp);
8366 : }
8367 : }
8368 :
8369 : /* Add argument checking of passing an unallocated/NULL actual to
8370 : a nonallocatable/nonpointer dummy. */
8371 :
8372 271225 : if (gfc_option.rtcheck & GFC_RTCHECK_POINTER && e != NULL)
8373 : {
8374 6546 : symbol_attribute attr;
8375 6546 : char *msg;
8376 6546 : tree cond;
8377 6546 : tree tmp;
8378 6546 : symbol_attribute fsym_attr;
8379 :
8380 6546 : if (fsym)
8381 : {
8382 6385 : if (fsym->ts.type == BT_CLASS)
8383 : {
8384 321 : fsym_attr = CLASS_DATA (fsym)->attr;
8385 321 : fsym_attr.pointer = fsym_attr.class_pointer;
8386 : }
8387 : else
8388 6064 : fsym_attr = fsym->attr;
8389 : }
8390 :
8391 6546 : if (e->expr_type == EXPR_VARIABLE || e->expr_type == EXPR_FUNCTION)
8392 4094 : attr = gfc_expr_attr (e);
8393 : else
8394 6081 : goto end_pointer_check;
8395 :
8396 : /* In Fortran 2008 it's allowed to pass a NULL pointer/nonallocated
8397 : allocatable to an optional dummy, cf. 12.5.2.12. */
8398 4094 : if (fsym != NULL && fsym->attr.optional && !attr.proc_pointer
8399 1038 : && (gfc_option.allow_std & GFC_STD_F2008) != 0)
8400 1032 : goto end_pointer_check;
8401 :
8402 3062 : if (attr.optional)
8403 : {
8404 : /* If the actual argument is an optional pointer/allocatable and
8405 : the formal argument takes an nonpointer optional value,
8406 : it is invalid to pass a non-present argument on, even
8407 : though there is no technical reason for this in gfortran.
8408 : See Fortran 2003, Section 12.4.1.6 item (7)+(8). */
8409 60 : tree present, null_ptr, type;
8410 :
8411 60 : if (attr.allocatable
8412 0 : && (fsym == NULL || !fsym_attr.allocatable))
8413 0 : msg = xasprintf ("Allocatable actual argument '%s' is not "
8414 : "allocated or not present",
8415 0 : e->symtree->n.sym->name);
8416 60 : else if (attr.pointer
8417 12 : && (fsym == NULL || !fsym_attr.pointer))
8418 12 : msg = xasprintf ("Pointer actual argument '%s' is not "
8419 : "associated or not present",
8420 12 : e->symtree->n.sym->name);
8421 48 : else if (attr.proc_pointer && !e->value.function.actual
8422 0 : && (fsym == NULL || !fsym_attr.proc_pointer))
8423 0 : msg = xasprintf ("Proc-pointer actual argument '%s' is not "
8424 : "associated or not present",
8425 0 : e->symtree->n.sym->name);
8426 : else
8427 48 : goto end_pointer_check;
8428 :
8429 12 : present = gfc_conv_expr_present (e->symtree->n.sym);
8430 12 : type = TREE_TYPE (present);
8431 12 : present = fold_build2_loc (input_location, EQ_EXPR,
8432 : logical_type_node, present,
8433 : fold_convert (type,
8434 : null_pointer_node));
8435 12 : type = TREE_TYPE (parmse.expr);
8436 12 : null_ptr = fold_build2_loc (input_location, EQ_EXPR,
8437 : logical_type_node, parmse.expr,
8438 : fold_convert (type,
8439 : null_pointer_node));
8440 12 : cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
8441 : logical_type_node, present, null_ptr);
8442 : }
8443 : else
8444 : {
8445 3002 : if (attr.allocatable
8446 256 : && (fsym == NULL || !fsym_attr.allocatable))
8447 190 : msg = xasprintf ("Allocatable actual argument '%s' is not "
8448 190 : "allocated", e->symtree->n.sym->name);
8449 2812 : else if (attr.pointer
8450 272 : && (fsym == NULL || !fsym_attr.pointer))
8451 184 : msg = xasprintf ("Pointer actual argument '%s' is not "
8452 184 : "associated", e->symtree->n.sym->name);
8453 2628 : else if (attr.proc_pointer && !e->value.function.actual
8454 80 : && (fsym == NULL
8455 50 : || (!fsym_attr.proc_pointer && !fsym_attr.optional)))
8456 79 : msg = xasprintf ("Proc-pointer actual argument '%s' is not "
8457 79 : "associated", e->symtree->n.sym->name);
8458 : else
8459 2549 : goto end_pointer_check;
8460 :
8461 453 : tmp = parmse.expr;
8462 453 : if (fsym && fsym->ts.type == BT_CLASS && !attr.proc_pointer)
8463 : {
8464 76 : if (POINTER_TYPE_P (TREE_TYPE (tmp)))
8465 70 : tmp = build_fold_indirect_ref_loc (input_location, tmp);
8466 76 : tmp = gfc_class_data_get (tmp);
8467 76 : if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp)))
8468 3 : tmp = gfc_conv_descriptor_data_get (tmp);
8469 : }
8470 :
8471 : /* If the argument is passed by value, we need to strip the
8472 : INDIRECT_REF. */
8473 453 : if (!POINTER_TYPE_P (TREE_TYPE (tmp)))
8474 12 : tmp = gfc_build_addr_expr (NULL_TREE, tmp);
8475 :
8476 453 : cond = fold_build2_loc (input_location, EQ_EXPR,
8477 : logical_type_node, tmp,
8478 453 : fold_convert (TREE_TYPE (tmp),
8479 : null_pointer_node));
8480 : }
8481 :
8482 465 : gfc_trans_runtime_check (true, false, cond, &se->pre, &e->where,
8483 : msg);
8484 465 : free (msg);
8485 : }
8486 264679 : end_pointer_check:
8487 :
8488 : /* Deferred length dummies pass the character length by reference
8489 : so that the value can be returned. */
8490 271225 : if (parmse.string_length && fsym && fsym->ts.deferred)
8491 : {
8492 795 : if (INDIRECT_REF_P (parmse.string_length))
8493 : {
8494 : /* In chains of functions/procedure calls the string_length already
8495 : is a pointer to the variable holding the length. Therefore
8496 : remove the deref on call. */
8497 90 : tmp = parmse.string_length;
8498 90 : parmse.string_length = TREE_OPERAND (parmse.string_length, 0);
8499 : }
8500 : else
8501 : {
8502 705 : tmp = parmse.string_length;
8503 705 : if (!VAR_P (tmp) && TREE_CODE (tmp) != COMPONENT_REF)
8504 61 : tmp = gfc_evaluate_now (parmse.string_length, &se->pre);
8505 705 : parmse.string_length = gfc_build_addr_expr (NULL_TREE, tmp);
8506 : }
8507 :
8508 795 : if (e && e->expr_type == EXPR_VARIABLE
8509 638 : && fsym->attr.allocatable
8510 368 : && e->ts.u.cl->backend_decl
8511 368 : && VAR_P (e->ts.u.cl->backend_decl))
8512 : {
8513 284 : if (INDIRECT_REF_P (tmp))
8514 0 : tmp = TREE_OPERAND (tmp, 0);
8515 284 : gfc_add_modify (&se->post, e->ts.u.cl->backend_decl,
8516 : fold_convert (gfc_charlen_type_node, tmp));
8517 : }
8518 : }
8519 :
8520 : /* Character strings are passed as two parameters, a length and a
8521 : pointer - except for Bind(c) and c_ptrs which only pass the pointer.
8522 : An unlimited polymorphic formal argument likewise does not
8523 : need the length. */
8524 271225 : if (parmse.string_length != NULL_TREE
8525 36996 : && !sym->attr.is_bind_c
8526 36300 : && !(fsym && fsym->ts.type == BT_DERIVED && fsym->ts.u.derived
8527 6 : && fsym->ts.u.derived->intmod_sym_id == ISOCBINDING_PTR
8528 6 : && fsym->ts.u.derived->from_intmod == INTMOD_ISO_C_BINDING )
8529 30415 : && !(fsym && fsym->ts.type == BT_ASSUMED)
8530 30306 : && !(fsym && UNLIMITED_POLY (fsym)))
8531 36010 : vec_safe_push (stringargs, parmse.string_length);
8532 :
8533 : /* When calling __copy for character expressions to unlimited
8534 : polymorphic entities, the dst argument needs a string length. */
8535 51900 : if (sym->name[0] == '_' && e && e->ts.type == BT_CHARACTER
8536 5326 : && startswith (sym->name, "__vtab_CHARACTER")
8537 0 : && arg->next && arg->next->expr
8538 0 : && (arg->next->expr->ts.type == BT_DERIVED
8539 0 : || arg->next->expr->ts.type == BT_CLASS)
8540 271225 : && arg->next->expr->ts.u.derived->attr.unlimited_polymorphic)
8541 0 : vec_safe_push (stringargs, parmse.string_length);
8542 :
8543 : /* For descriptorless coarrays and assumed-shape coarray dummies, we
8544 : pass the token and the offset as additional arguments. */
8545 271225 : if (fsym && e == NULL && flag_coarray == GFC_FCOARRAY_LIB
8546 122 : && attr->codimension && !attr->allocatable)
8547 : {
8548 : /* Token and offset. */
8549 5 : vec_safe_push (stringargs, null_pointer_node);
8550 5 : vec_safe_push (stringargs, build_int_cst (gfc_array_index_type, 0));
8551 5 : gcc_assert (fsym->attr.optional);
8552 : }
8553 238263 : else if (fsym && flag_coarray == GFC_FCOARRAY_LIB && attr->codimension
8554 145 : && !attr->allocatable)
8555 : {
8556 123 : tree caf_decl, caf_type, caf_desc = NULL_TREE;
8557 123 : tree offset, tmp2;
8558 :
8559 123 : caf_decl = gfc_get_tree_for_caf_expr (e);
8560 123 : caf_type = TREE_TYPE (caf_decl);
8561 123 : if (POINTER_TYPE_P (caf_type)
8562 123 : && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (caf_type)))
8563 3 : caf_desc = TREE_TYPE (caf_type);
8564 120 : else if (GFC_DESCRIPTOR_TYPE_P (caf_type))
8565 : caf_desc = caf_type;
8566 :
8567 51 : if (caf_desc
8568 51 : && (GFC_TYPE_ARRAY_AKIND (caf_desc) == GFC_ARRAY_ALLOCATABLE
8569 0 : || GFC_TYPE_ARRAY_AKIND (caf_desc) == GFC_ARRAY_POINTER))
8570 : {
8571 102 : tmp = POINTER_TYPE_P (TREE_TYPE (caf_decl))
8572 54 : ? build_fold_indirect_ref (caf_decl)
8573 : : caf_decl;
8574 51 : tmp = gfc_conv_descriptor_token (tmp);
8575 : }
8576 72 : else if (DECL_LANG_SPECIFIC (caf_decl)
8577 72 : && GFC_DECL_TOKEN (caf_decl) != NULL_TREE)
8578 12 : tmp = GFC_DECL_TOKEN (caf_decl);
8579 : else
8580 : {
8581 60 : gcc_assert (GFC_ARRAY_TYPE_P (caf_type)
8582 : && GFC_TYPE_ARRAY_CAF_TOKEN (caf_type) != NULL_TREE);
8583 60 : tmp = GFC_TYPE_ARRAY_CAF_TOKEN (caf_type);
8584 : }
8585 :
8586 123 : vec_safe_push (stringargs, tmp);
8587 :
8588 123 : if (caf_desc
8589 123 : && GFC_TYPE_ARRAY_AKIND (caf_desc) == GFC_ARRAY_ALLOCATABLE)
8590 51 : offset = build_int_cst (gfc_array_index_type, 0);
8591 72 : else if (DECL_LANG_SPECIFIC (caf_decl)
8592 72 : && GFC_DECL_CAF_OFFSET (caf_decl) != NULL_TREE)
8593 12 : offset = GFC_DECL_CAF_OFFSET (caf_decl);
8594 60 : else if (GFC_TYPE_ARRAY_CAF_OFFSET (caf_type) != NULL_TREE)
8595 0 : offset = GFC_TYPE_ARRAY_CAF_OFFSET (caf_type);
8596 : else
8597 60 : offset = build_int_cst (gfc_array_index_type, 0);
8598 :
8599 123 : if (caf_desc)
8600 : {
8601 102 : tmp = POINTER_TYPE_P (TREE_TYPE (caf_decl))
8602 54 : ? build_fold_indirect_ref (caf_decl)
8603 : : caf_decl;
8604 51 : tmp = gfc_conv_descriptor_data_get (tmp);
8605 : }
8606 : else
8607 : {
8608 72 : gcc_assert (POINTER_TYPE_P (caf_type));
8609 72 : tmp = caf_decl;
8610 : }
8611 :
8612 108 : tmp2 = fsym->ts.type == BT_CLASS
8613 123 : ? gfc_class_data_get (parmse.expr) : parmse.expr;
8614 123 : if ((fsym->ts.type != BT_CLASS
8615 108 : && (fsym->as->type == AS_ASSUMED_SHAPE
8616 59 : || fsym->as->type == AS_ASSUMED_RANK))
8617 74 : || (fsym->ts.type == BT_CLASS
8618 15 : && (CLASS_DATA (fsym)->as->type == AS_ASSUMED_SHAPE
8619 10 : || CLASS_DATA (fsym)->as->type == AS_ASSUMED_RANK)))
8620 : {
8621 54 : if (fsym->ts.type == BT_CLASS)
8622 5 : gcc_assert (!POINTER_TYPE_P (TREE_TYPE (tmp2)));
8623 : else
8624 : {
8625 49 : gcc_assert (POINTER_TYPE_P (TREE_TYPE (tmp2)));
8626 49 : tmp2 = build_fold_indirect_ref_loc (input_location, tmp2);
8627 : }
8628 54 : gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp2)));
8629 54 : tmp2 = gfc_conv_descriptor_data_get (tmp2);
8630 : }
8631 69 : else if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp2)))
8632 10 : tmp2 = gfc_conv_descriptor_data_get (tmp2);
8633 : else
8634 : {
8635 59 : gcc_assert (POINTER_TYPE_P (TREE_TYPE (tmp2)));
8636 : }
8637 :
8638 123 : tmp = fold_build2_loc (input_location, MINUS_EXPR,
8639 : gfc_array_index_type,
8640 : fold_convert (gfc_array_index_type, tmp2),
8641 : fold_convert (gfc_array_index_type, tmp));
8642 123 : offset = fold_build2_loc (input_location, PLUS_EXPR,
8643 : gfc_array_index_type, offset, tmp);
8644 :
8645 123 : vec_safe_push (stringargs, offset);
8646 : }
8647 :
8648 271225 : vec_safe_push (arglist, parmse.expr);
8649 : }
8650 :
8651 130620 : gfc_add_block_to_block (&se->pre, &dealloc_blk);
8652 130620 : gfc_add_block_to_block (&se->pre, &clobbers);
8653 130620 : gfc_finish_interface_mapping (&mapping, &se->pre, &se->post);
8654 :
8655 130620 : if (comp)
8656 1994 : ts = comp->ts;
8657 128626 : else if (sym->ts.type == BT_CLASS)
8658 851 : ts = CLASS_DATA (sym)->ts;
8659 : else
8660 127775 : ts = sym->ts;
8661 :
8662 130620 : if (ts.type == BT_CHARACTER && sym->attr.is_bind_c)
8663 210 : se->string_length = build_int_cst (gfc_charlen_type_node, 1);
8664 130410 : else if (ts.type == BT_CHARACTER)
8665 : {
8666 5022 : if (ts.u.cl->length == NULL)
8667 : {
8668 : /* Assumed character length results are not allowed by C418 of the 2003
8669 : standard and are trapped in resolve.cc; except in the case of SPREAD
8670 : (and other intrinsics?) and dummy functions. In the case of SPREAD,
8671 : we take the character length of the first argument for the result.
8672 : For dummies, we have to look through the formal argument list for
8673 : this function and use the character length found there.
8674 : Likewise, we handle the case of deferred-length character dummy
8675 : arguments to intrinsics that determine the characteristics of
8676 : the result, which cannot be deferred-length. */
8677 2309 : if (expr->value.function.isym)
8678 1703 : ts.deferred = false;
8679 2309 : if (ts.deferred)
8680 599 : cl.backend_decl = gfc_create_var (gfc_charlen_type_node, "slen");
8681 1710 : else if (!sym->attr.dummy)
8682 1703 : cl.backend_decl = (*stringargs)[0];
8683 : else
8684 : {
8685 7 : formal = gfc_sym_get_dummy_args (sym->ns->proc_name);
8686 26 : for (; formal; formal = formal->next)
8687 12 : if (strcmp (formal->sym->name, sym->name) == 0)
8688 7 : cl.backend_decl = formal->sym->ts.u.cl->backend_decl;
8689 : }
8690 2309 : len = cl.backend_decl;
8691 : }
8692 : else
8693 : {
8694 2713 : tree tmp;
8695 :
8696 : /* Calculate the length of the returned string. */
8697 2713 : gfc_init_se (&parmse, NULL);
8698 2713 : if (need_interface_mapping)
8699 1867 : gfc_apply_interface_mapping (&mapping, &parmse, ts.u.cl->length);
8700 : else
8701 846 : gfc_conv_expr (&parmse, ts.u.cl->length);
8702 2713 : gfc_add_block_to_block (&se->pre, &parmse.pre);
8703 2713 : gfc_add_block_to_block (&se->post, &parmse.post);
8704 2713 : tmp = parmse.expr;
8705 : /* TODO: It would be better to have the charlens as
8706 : gfc_charlen_type_node already when the interface is
8707 : created instead of converting it here (see PR 84615). */
8708 2713 : tmp = fold_build2_loc (input_location, MAX_EXPR,
8709 : gfc_charlen_type_node,
8710 : fold_convert (gfc_charlen_type_node, tmp),
8711 : build_zero_cst (gfc_charlen_type_node));
8712 2713 : cl.backend_decl = tmp;
8713 : }
8714 :
8715 : /* Set up a charlen structure for it. */
8716 5022 : cl.next = NULL;
8717 5022 : cl.length = NULL;
8718 5022 : ts.u.cl = &cl;
8719 :
8720 5022 : len = cl.backend_decl;
8721 : }
8722 :
8723 1994 : byref = (comp && (comp->attr.dimension
8724 1925 : || (comp->ts.type == BT_CHARACTER && !sym->attr.is_bind_c)))
8725 130620 : || (!comp && gfc_return_by_reference (sym));
8726 :
8727 18793 : if (byref)
8728 : {
8729 18793 : if (se->direct_byref)
8730 : {
8731 : /* Sometimes, too much indirection can be applied; e.g. for
8732 : function_result = array_valued_recursive_function. */
8733 6999 : if (TREE_TYPE (TREE_TYPE (se->expr))
8734 6999 : && TREE_TYPE (TREE_TYPE (TREE_TYPE (se->expr)))
8735 7017 : && GFC_DESCRIPTOR_TYPE_P
8736 : (TREE_TYPE (TREE_TYPE (TREE_TYPE (se->expr)))))
8737 18 : se->expr = build_fold_indirect_ref_loc (input_location,
8738 : se->expr);
8739 :
8740 : /* If the lhs of an assignment x = f(..) is allocatable and
8741 : f2003 is allowed, we must do the automatic reallocation.
8742 : TODO - deal with intrinsics, without using a temporary. */
8743 6999 : if (flag_realloc_lhs
8744 6924 : && se->ss && se->ss->loop_chain
8745 203 : && se->ss->loop_chain->is_alloc_lhs
8746 203 : && !expr->value.function.isym
8747 203 : && sym->result->as != NULL)
8748 : {
8749 : /* Evaluate the bounds of the result, if known. */
8750 203 : gfc_set_loop_bounds_from_array_spec (&mapping, se,
8751 : sym->result->as);
8752 :
8753 : /* Perform the automatic reallocation. */
8754 203 : tmp = gfc_alloc_allocatable_for_assignment (se->loop,
8755 : expr, NULL);
8756 203 : gfc_add_expr_to_block (&se->pre, tmp);
8757 :
8758 : /* Pass the temporary as the first argument. */
8759 203 : result = info->descriptor;
8760 : }
8761 : else
8762 6796 : result = build_fold_indirect_ref_loc (input_location,
8763 : se->expr);
8764 6999 : vec_safe_push (retargs, se->expr);
8765 : }
8766 11794 : else if (comp && comp->attr.dimension)
8767 : {
8768 66 : gcc_assert (se->loop && info);
8769 :
8770 : /* Set the type of the array. vtable charlens are not always reliable.
8771 : Use the interface, if possible. */
8772 66 : if (comp->ts.type == BT_CHARACTER
8773 1 : && expr->symtree->n.sym->ts.type == BT_CLASS
8774 1 : && comp->ts.interface && comp->ts.interface->result)
8775 1 : tmp = gfc_typenode_for_spec (&comp->ts.interface->result->ts);
8776 : else
8777 65 : tmp = gfc_typenode_for_spec (&comp->ts);
8778 66 : gcc_assert (se->ss->dimen == se->loop->dimen);
8779 :
8780 : /* Evaluate the bounds of the result, if known. */
8781 66 : gfc_set_loop_bounds_from_array_spec (&mapping, se, comp->as);
8782 :
8783 : /* If the lhs of an assignment x = f(..) is allocatable and
8784 : f2003 is allowed, we must not generate the function call
8785 : here but should just send back the results of the mapping.
8786 : This is signalled by the function ss being flagged. */
8787 66 : if (flag_realloc_lhs && se->ss && se->ss->is_alloc_lhs)
8788 : {
8789 0 : gfc_free_interface_mapping (&mapping);
8790 0 : return has_alternate_specifier;
8791 : }
8792 :
8793 : /* Create a temporary to store the result. In case the function
8794 : returns a pointer, the temporary will be a shallow copy and
8795 : mustn't be deallocated. */
8796 66 : callee_alloc = comp->attr.allocatable || comp->attr.pointer;
8797 66 : gfc_trans_create_temp_array (&se->pre, &se->post, se->ss,
8798 : tmp, NULL_TREE, false,
8799 : !comp->attr.pointer, callee_alloc,
8800 66 : &se->ss->info->expr->where);
8801 :
8802 : /* Pass the temporary as the first argument. */
8803 66 : result = info->descriptor;
8804 66 : tmp = gfc_build_addr_expr (NULL_TREE, result);
8805 66 : vec_safe_push (retargs, tmp);
8806 : }
8807 11499 : else if (!comp && sym->result->attr.dimension)
8808 : {
8809 8468 : gcc_assert (se->loop && info);
8810 :
8811 : /* Set the type of the array. */
8812 8468 : tmp = gfc_typenode_for_spec (&ts);
8813 8468 : tmp = arg1_cntnr ? TREE_TYPE (arg1_cntnr) : tmp;
8814 8468 : gcc_assert (se->ss->dimen == se->loop->dimen);
8815 :
8816 : /* Evaluate the bounds of the result, if known. */
8817 8468 : gfc_set_loop_bounds_from_array_spec (&mapping, se, sym->result->as);
8818 :
8819 : /* If the lhs of an assignment x = f(..) is allocatable and
8820 : f2003 is allowed, we must not generate the function call
8821 : here but should just send back the results of the mapping.
8822 : This is signalled by the function ss being flagged. */
8823 8468 : if (flag_realloc_lhs && se->ss && se->ss->is_alloc_lhs)
8824 : {
8825 0 : gfc_free_interface_mapping (&mapping);
8826 0 : return has_alternate_specifier;
8827 : }
8828 :
8829 : /* Create a temporary to store the result. In case the function
8830 : returns a pointer, the temporary will be a shallow copy and
8831 : mustn't be deallocated. */
8832 8468 : callee_alloc = sym->attr.allocatable || sym->attr.pointer;
8833 8468 : gfc_trans_create_temp_array (&se->pre, &se->post, se->ss,
8834 : tmp, NULL_TREE, false,
8835 : !sym->attr.pointer, callee_alloc,
8836 8468 : &se->ss->info->expr->where);
8837 :
8838 : /* Pass the temporary as the first argument. */
8839 8468 : result = info->descriptor;
8840 8468 : tmp = gfc_build_addr_expr (NULL_TREE, result);
8841 8468 : vec_safe_push (retargs, tmp);
8842 : }
8843 3260 : else if (ts.type == BT_CHARACTER)
8844 : {
8845 : /* Pass the string length. */
8846 3199 : type = gfc_get_character_type (ts.kind, ts.u.cl);
8847 3199 : type = build_pointer_type (type);
8848 :
8849 : /* Emit a DECL_EXPR for the VLA type. */
8850 3199 : tmp = TREE_TYPE (type);
8851 3199 : if (TYPE_SIZE (tmp)
8852 3199 : && TREE_CODE (TYPE_SIZE (tmp)) != INTEGER_CST)
8853 : {
8854 1929 : tmp = build_decl (input_location, TYPE_DECL, NULL_TREE, tmp);
8855 1929 : DECL_ARTIFICIAL (tmp) = 1;
8856 1929 : DECL_IGNORED_P (tmp) = 1;
8857 1929 : tmp = fold_build1_loc (input_location, DECL_EXPR,
8858 1929 : TREE_TYPE (tmp), tmp);
8859 1929 : gfc_add_expr_to_block (&se->pre, tmp);
8860 : }
8861 :
8862 : /* Return an address to a char[0:len-1]* temporary for
8863 : character pointers. */
8864 3199 : if ((!comp && (sym->attr.pointer || sym->attr.allocatable))
8865 229 : || (comp && (comp->attr.pointer || comp->attr.allocatable)))
8866 : {
8867 642 : var = gfc_create_var (type, "pstr");
8868 :
8869 642 : if ((!comp && sym->attr.allocatable)
8870 21 : || (comp && comp->attr.allocatable))
8871 : {
8872 355 : gfc_add_modify (&se->pre, var,
8873 355 : fold_convert (TREE_TYPE (var),
8874 : null_pointer_node));
8875 355 : tmp = gfc_call_free (var);
8876 355 : gfc_add_expr_to_block (&se->post, tmp);
8877 : }
8878 :
8879 : /* Provide an address expression for the function arguments. */
8880 642 : var = gfc_build_addr_expr (NULL_TREE, var);
8881 : }
8882 : else
8883 2557 : var = gfc_conv_string_tmp (se, type, len);
8884 :
8885 3199 : vec_safe_push (retargs, var);
8886 : }
8887 : else
8888 : {
8889 61 : gcc_assert (flag_f2c && ts.type == BT_COMPLEX);
8890 :
8891 61 : type = gfc_get_complex_type (ts.kind);
8892 61 : var = gfc_build_addr_expr (NULL_TREE, gfc_create_var (type, "cmplx"));
8893 61 : vec_safe_push (retargs, var);
8894 : }
8895 :
8896 : /* Add the string length to the argument list. */
8897 18793 : if (ts.type == BT_CHARACTER && ts.deferred)
8898 : {
8899 599 : tmp = len;
8900 599 : if (!VAR_P (tmp))
8901 0 : tmp = gfc_evaluate_now (len, &se->pre);
8902 599 : TREE_STATIC (tmp) = 1;
8903 599 : gfc_add_modify (&se->pre, tmp,
8904 599 : build_int_cst (TREE_TYPE (tmp), 0));
8905 599 : tmp = gfc_build_addr_expr (NULL_TREE, tmp);
8906 599 : vec_safe_push (retargs, tmp);
8907 : }
8908 18194 : else if (ts.type == BT_CHARACTER)
8909 4423 : vec_safe_push (retargs, len);
8910 : }
8911 :
8912 130620 : gfc_free_interface_mapping (&mapping);
8913 :
8914 : /* We need to glom RETARGS + ARGLIST + STRINGARGS + APPEND_ARGS. */
8915 243160 : arglen = (vec_safe_length (arglist) + vec_safe_length (optionalargs)
8916 156037 : + vec_safe_length (stringargs) + vec_safe_length (append_args));
8917 130620 : vec_safe_reserve (retargs, arglen);
8918 :
8919 : /* Add the return arguments. */
8920 130620 : vec_safe_splice (retargs, arglist);
8921 :
8922 : /* Add the hidden present status for optional+value to the arguments. */
8923 130620 : vec_safe_splice (retargs, optionalargs);
8924 :
8925 : /* Add the hidden string length parameters to the arguments. */
8926 130620 : vec_safe_splice (retargs, stringargs);
8927 :
8928 : /* We may want to append extra arguments here. This is used e.g. for
8929 : calls to libgfortran_matmul_??, which need extra information. */
8930 130620 : vec_safe_splice (retargs, append_args);
8931 :
8932 130620 : arglist = retargs;
8933 :
8934 : /* Generate the actual call. */
8935 130620 : is_builtin = false;
8936 130620 : if (base_object == NULL_TREE)
8937 130540 : conv_function_val (se, &is_builtin, sym, expr, args);
8938 : else
8939 80 : conv_base_obj_fcn_val (se, base_object, expr);
8940 :
8941 : /* If there are alternate return labels, function type should be
8942 : integer. Can't modify the type in place though, since it can be shared
8943 : with other functions. For dummy arguments, the typing is done to
8944 : this result, even if it has to be repeated for each call. */
8945 130620 : if (has_alternate_specifier
8946 130620 : && TREE_TYPE (TREE_TYPE (TREE_TYPE (se->expr))) != integer_type_node)
8947 : {
8948 7 : if (!sym->attr.dummy)
8949 : {
8950 0 : TREE_TYPE (sym->backend_decl)
8951 0 : = build_function_type (integer_type_node,
8952 0 : TYPE_ARG_TYPES (TREE_TYPE (sym->backend_decl)));
8953 0 : se->expr = gfc_build_addr_expr (NULL_TREE, sym->backend_decl);
8954 : }
8955 : else
8956 7 : TREE_TYPE (TREE_TYPE (TREE_TYPE (se->expr))) = integer_type_node;
8957 : }
8958 :
8959 130620 : fntype = TREE_TYPE (TREE_TYPE (se->expr));
8960 130620 : se->expr = build_call_vec (TREE_TYPE (fntype), se->expr, arglist);
8961 :
8962 130620 : if (is_builtin)
8963 567 : se->expr = update_builtin_function (se->expr, sym);
8964 :
8965 : /* Allocatable scalar function results must be freed and nullified
8966 : after use. This necessitates the creation of a temporary to
8967 : hold the result to prevent duplicate calls. */
8968 130620 : symbol_attribute attr = comp ? comp->attr : sym->attr;
8969 130620 : bool allocatable = attr.allocatable && !attr.dimension;
8970 133960 : gfc_symbol *der = comp ?
8971 1994 : comp->ts.type == BT_DERIVED ? comp->ts.u.derived : NULL
8972 : :
8973 128626 : sym->ts.type == BT_DERIVED ? sym->ts.u.derived : NULL;
8974 3340 : bool finalizable = der != NULL && der->ns->proc_name
8975 6677 : && gfc_is_finalizable (der, NULL);
8976 :
8977 130620 : if (!byref && finalizable)
8978 188 : gfc_finalize_tree_expr (se, der, attr, expr->rank);
8979 :
8980 130620 : if (!byref && sym->ts.type != BT_CHARACTER
8981 111617 : && allocatable && !finalizable)
8982 : {
8983 230 : tmp = gfc_create_var (TREE_TYPE (se->expr), NULL);
8984 230 : gfc_add_modify (&se->pre, tmp, se->expr);
8985 230 : se->expr = tmp;
8986 230 : tmp = gfc_call_free (tmp);
8987 230 : gfc_add_expr_to_block (&post, tmp);
8988 230 : gfc_add_modify (&post, se->expr, build_int_cst (TREE_TYPE (se->expr), 0));
8989 : }
8990 :
8991 : /* If we have a pointer function, but we don't want a pointer, e.g.
8992 : something like
8993 : x = f()
8994 : where f is pointer valued, we have to dereference the result. */
8995 130620 : if (!se->want_pointer && !byref
8996 111225 : && ((!comp && (sym->attr.pointer || sym->attr.allocatable))
8997 1652 : || (comp && (comp->attr.pointer || comp->attr.allocatable))))
8998 456 : se->expr = build_fold_indirect_ref_loc (input_location, se->expr);
8999 :
9000 : /* f2c calling conventions require a scalar default real function to
9001 : return a double precision result. Convert this back to default
9002 : real. We only care about the cases that can happen in Fortran 77.
9003 : */
9004 130620 : if (flag_f2c && sym->ts.type == BT_REAL
9005 98 : && sym->ts.kind == gfc_default_real_kind
9006 74 : && !sym->attr.pointer
9007 55 : && !sym->attr.allocatable
9008 43 : && !sym->attr.always_explicit)
9009 43 : se->expr = fold_convert (gfc_get_real_type (sym->ts.kind), se->expr);
9010 :
9011 : /* A pure function may still have side-effects - it may modify its
9012 : parameters. */
9013 130620 : TREE_SIDE_EFFECTS (se->expr) = 1;
9014 : #if 0
9015 : if (!sym->attr.pure)
9016 : TREE_SIDE_EFFECTS (se->expr) = 1;
9017 : #endif
9018 :
9019 130620 : if (byref)
9020 : {
9021 : /* Add the function call to the pre chain. There is no expression. */
9022 18793 : gfc_add_expr_to_block (&se->pre, se->expr);
9023 18793 : se->expr = NULL_TREE;
9024 :
9025 18793 : if (!se->direct_byref)
9026 : {
9027 11794 : if ((sym->attr.dimension && !comp) || (comp && comp->attr.dimension))
9028 : {
9029 8534 : if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
9030 : {
9031 : /* Check the data pointer hasn't been modified. This would
9032 : happen in a function returning a pointer. */
9033 251 : tmp = gfc_conv_descriptor_data_get (info->descriptor);
9034 251 : tmp = fold_build2_loc (input_location, NE_EXPR,
9035 : logical_type_node,
9036 : tmp, info->data);
9037 251 : gfc_trans_runtime_check (true, false, tmp, &se->pre, NULL,
9038 : gfc_msg_fault);
9039 : }
9040 8534 : se->expr = info->descriptor;
9041 : /* Bundle in the string length. */
9042 8534 : se->string_length = len;
9043 :
9044 8534 : if (finalizable)
9045 6 : gfc_finalize_tree_expr (se, der, attr, expr->rank);
9046 : }
9047 3260 : else if (ts.type == BT_CHARACTER)
9048 : {
9049 : /* Dereference for character pointer results. */
9050 3199 : if ((!comp && (sym->attr.pointer || sym->attr.allocatable))
9051 229 : || (comp && (comp->attr.pointer || comp->attr.allocatable)))
9052 642 : se->expr = build_fold_indirect_ref_loc (input_location, var);
9053 : else
9054 2557 : se->expr = var;
9055 :
9056 3199 : se->string_length = len;
9057 : }
9058 : else
9059 : {
9060 61 : gcc_assert (ts.type == BT_COMPLEX && flag_f2c);
9061 61 : se->expr = build_fold_indirect_ref_loc (input_location, var);
9062 : }
9063 : }
9064 : }
9065 :
9066 : /* Associate the rhs class object's meta-data with the result, when the
9067 : result is a temporary. */
9068 112545 : if (args && args->expr && args->expr->ts.type == BT_CLASS
9069 5003 : && sym->ts.type == BT_CLASS && result != NULL_TREE && DECL_P (result)
9070 130652 : && !GFC_CLASS_TYPE_P (TREE_TYPE (result)))
9071 : {
9072 32 : gfc_se parmse;
9073 32 : gfc_expr *class_expr = gfc_find_and_cut_at_last_class_ref (args->expr);
9074 :
9075 32 : gfc_init_se (&parmse, NULL);
9076 32 : parmse.data_not_needed = 1;
9077 32 : gfc_conv_expr (&parmse, class_expr);
9078 32 : if (!DECL_LANG_SPECIFIC (result))
9079 32 : gfc_allocate_lang_decl (result);
9080 32 : GFC_DECL_SAVED_DESCRIPTOR (result) = parmse.expr;
9081 32 : gfc_free_expr (class_expr);
9082 : /* -fcheck= can add diagnostic code, which has to be placed before
9083 : the call. */
9084 32 : if (parmse.pre.head != NULL)
9085 12 : gfc_add_expr_to_block (&se->pre, parmse.pre.head);
9086 32 : gcc_assert (parmse.post.head == NULL_TREE);
9087 : }
9088 :
9089 : /* Follow the function call with the argument post block. */
9090 130620 : if (byref)
9091 : {
9092 : /* Transformational functions of derived types with allocatable
9093 : components must have the result allocatable components copied
9094 : BEFORE the argument post block is appended. Copying the result
9095 : first, then freeing the argument, gives the correct order. */
9096 18793 : arg = expr->value.function.actual;
9097 18793 : if (result && arg && expr->rank
9098 14686 : && isym && isym->transformational
9099 13105 : && isym->id != GFC_ISYM_REDUCE
9100 12979 : && arg->expr
9101 12919 : && arg->expr->ts.type == BT_DERIVED
9102 241 : && arg->expr->ts.u.derived->attr.alloc_comp)
9103 : {
9104 48 : tree tmp2;
9105 : /* Copy the allocatable components. We have to use a
9106 : temporary here to prevent source allocatable components
9107 : from being corrupted. */
9108 48 : tmp2 = gfc_evaluate_now (result, &se->pre);
9109 48 : tmp = gfc_copy_alloc_comp (arg->expr->ts.u.derived,
9110 : result, tmp2, expr->rank, 0);
9111 48 : gfc_add_expr_to_block (&se->pre, tmp);
9112 48 : tmp = gfc_copy_allocatable_data (result, tmp2, TREE_TYPE(tmp2),
9113 : expr->rank);
9114 48 : gfc_add_expr_to_block (&se->pre, tmp);
9115 :
9116 : /* Finally free the temporary's data field. */
9117 48 : tmp = gfc_conv_descriptor_data_get (tmp2);
9118 48 : tmp = gfc_deallocate_with_status (tmp, NULL_TREE, NULL_TREE,
9119 : NULL_TREE, NULL_TREE, true,
9120 : NULL, GFC_CAF_COARRAY_NOCOARRAY);
9121 48 : gfc_add_expr_to_block (&se->pre, tmp);
9122 : }
9123 :
9124 18793 : gfc_add_block_to_block (&se->pre, &post);
9125 : }
9126 : else
9127 : {
9128 : /* For a function with a class array result, save the result as
9129 : a temporary, set the info fields needed by the scalarizer and
9130 : call the finalization function of the temporary. Note that the
9131 : nullification of allocatable components needed by the result
9132 : is done in gfc_trans_assignment_1. */
9133 34618 : if (expr && (gfc_is_class_array_function (expr)
9134 34296 : || gfc_is_alloc_class_scalar_function (expr))
9135 841 : && se->expr && GFC_CLASS_TYPE_P (TREE_TYPE (se->expr))
9136 112656 : && expr->must_finalize)
9137 : {
9138 : /* TODO Eliminate the doubling of temporaries. This
9139 : one is necessary to ensure no memory leakage. */
9140 321 : se->expr = gfc_evaluate_now (se->expr, &se->pre);
9141 :
9142 : /* Finalize the result, if necessary. */
9143 642 : attr = expr->value.function.esym
9144 321 : ? CLASS_DATA (expr->value.function.esym->result)->attr
9145 14 : : CLASS_DATA (expr)->attr;
9146 321 : if (!((gfc_is_class_array_function (expr)
9147 108 : || gfc_is_alloc_class_scalar_function (expr))
9148 321 : && attr.pointer))
9149 276 : gfc_finalize_tree_expr (se, NULL, attr, expr->rank);
9150 : }
9151 111827 : gfc_add_block_to_block (&se->post, &post);
9152 : }
9153 :
9154 : return has_alternate_specifier;
9155 : }
9156 :
9157 :
9158 : /* Fill a character string with spaces. */
9159 :
9160 : static tree
9161 30662 : fill_with_spaces (tree start, tree type, tree size)
9162 : {
9163 30662 : stmtblock_t block, loop;
9164 30662 : tree i, el, exit_label, cond, tmp;
9165 :
9166 : /* For a simple char type, we can call memset(). */
9167 30662 : if (compare_tree_int (TYPE_SIZE_UNIT (type), 1) == 0)
9168 50736 : return build_call_expr_loc (input_location,
9169 : builtin_decl_explicit (BUILT_IN_MEMSET),
9170 : 3, start,
9171 : build_int_cst (gfc_get_int_type (gfc_c_int_kind),
9172 25368 : lang_hooks.to_target_charset (' ')),
9173 : fold_convert (size_type_node, size));
9174 :
9175 : /* Otherwise, we use a loop:
9176 : for (el = start, i = size; i > 0; el--, i+= TYPE_SIZE_UNIT (type))
9177 : *el = (type) ' ';
9178 : */
9179 :
9180 : /* Initialize variables. */
9181 5294 : gfc_init_block (&block);
9182 5294 : i = gfc_create_var (sizetype, "i");
9183 5294 : gfc_add_modify (&block, i, fold_convert (sizetype, size));
9184 5294 : el = gfc_create_var (build_pointer_type (type), "el");
9185 5294 : gfc_add_modify (&block, el, fold_convert (TREE_TYPE (el), start));
9186 5294 : exit_label = gfc_build_label_decl (NULL_TREE);
9187 5294 : TREE_USED (exit_label) = 1;
9188 :
9189 :
9190 : /* Loop body. */
9191 5294 : gfc_init_block (&loop);
9192 :
9193 : /* Exit condition. */
9194 5294 : cond = fold_build2_loc (input_location, LE_EXPR, logical_type_node, i,
9195 : build_zero_cst (sizetype));
9196 5294 : tmp = build1_v (GOTO_EXPR, exit_label);
9197 5294 : tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
9198 : build_empty_stmt (input_location));
9199 5294 : gfc_add_expr_to_block (&loop, tmp);
9200 :
9201 : /* Assignment. */
9202 5294 : gfc_add_modify (&loop,
9203 : fold_build1_loc (input_location, INDIRECT_REF, type, el),
9204 5294 : build_int_cst (type, lang_hooks.to_target_charset (' ')));
9205 :
9206 : /* Increment loop variables. */
9207 5294 : gfc_add_modify (&loop, i,
9208 : fold_build2_loc (input_location, MINUS_EXPR, sizetype, i,
9209 5294 : TYPE_SIZE_UNIT (type)));
9210 5294 : gfc_add_modify (&loop, el,
9211 : fold_build_pointer_plus_loc (input_location,
9212 5294 : el, TYPE_SIZE_UNIT (type)));
9213 :
9214 : /* Making the loop... actually loop! */
9215 5294 : tmp = gfc_finish_block (&loop);
9216 5294 : tmp = build1_v (LOOP_EXPR, tmp);
9217 5294 : gfc_add_expr_to_block (&block, tmp);
9218 :
9219 : /* The exit label. */
9220 5294 : tmp = build1_v (LABEL_EXPR, exit_label);
9221 5294 : gfc_add_expr_to_block (&block, tmp);
9222 :
9223 :
9224 5294 : return gfc_finish_block (&block);
9225 : }
9226 :
9227 :
9228 : /* Generate code to copy a string. */
9229 :
9230 : void
9231 35825 : gfc_trans_string_copy (stmtblock_t * block, tree dlength, tree dest,
9232 : int dkind, tree slength, tree src, int skind)
9233 : {
9234 35825 : tree tmp, dlen, slen;
9235 35825 : tree dsc;
9236 35825 : tree ssc;
9237 35825 : tree cond;
9238 35825 : tree cond2;
9239 35825 : tree tmp2;
9240 35825 : tree tmp3;
9241 35825 : tree tmp4;
9242 35825 : tree chartype;
9243 35825 : stmtblock_t tempblock;
9244 :
9245 35825 : gcc_assert (dkind == skind);
9246 :
9247 35825 : if (slength != NULL_TREE)
9248 : {
9249 35825 : slen = gfc_evaluate_now (fold_convert (gfc_charlen_type_node, slength), block);
9250 35825 : ssc = gfc_string_to_single_character (slen, src, skind);
9251 : }
9252 : else
9253 : {
9254 0 : slen = build_one_cst (gfc_charlen_type_node);
9255 0 : ssc = src;
9256 : }
9257 :
9258 35825 : if (dlength != NULL_TREE)
9259 : {
9260 35825 : dlen = gfc_evaluate_now (fold_convert (gfc_charlen_type_node, dlength), block);
9261 35825 : dsc = gfc_string_to_single_character (dlen, dest, dkind);
9262 : }
9263 : else
9264 : {
9265 0 : dlen = build_one_cst (gfc_charlen_type_node);
9266 0 : dsc = dest;
9267 : }
9268 :
9269 : /* Assign directly if the types are compatible. */
9270 35825 : if (dsc != NULL_TREE && ssc != NULL_TREE
9271 35825 : && TREE_TYPE (dsc) == TREE_TYPE (ssc))
9272 : {
9273 5163 : gfc_add_modify (block, dsc, ssc);
9274 5163 : return;
9275 : }
9276 :
9277 : /* The string copy algorithm below generates code like
9278 :
9279 : if (destlen > 0)
9280 : {
9281 : if (srclen < destlen)
9282 : {
9283 : memmove (dest, src, srclen);
9284 : // Pad with spaces.
9285 : memset (&dest[srclen], ' ', destlen - srclen);
9286 : }
9287 : else
9288 : {
9289 : // Truncate if too long.
9290 : memmove (dest, src, destlen);
9291 : }
9292 : }
9293 : */
9294 :
9295 : /* Do nothing if the destination length is zero. */
9296 30662 : cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node, dlen,
9297 30662 : build_zero_cst (TREE_TYPE (dlen)));
9298 :
9299 : /* For non-default character kinds, we have to multiply the string
9300 : length by the base type size. */
9301 30662 : chartype = gfc_get_char_type (dkind);
9302 30662 : slen = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (slen),
9303 : slen,
9304 30662 : fold_convert (TREE_TYPE (slen),
9305 : TYPE_SIZE_UNIT (chartype)));
9306 30662 : dlen = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (dlen),
9307 : dlen,
9308 30662 : fold_convert (TREE_TYPE (dlen),
9309 : TYPE_SIZE_UNIT (chartype)));
9310 :
9311 30662 : if (dlength && POINTER_TYPE_P (TREE_TYPE (dest)))
9312 30614 : dest = fold_convert (pvoid_type_node, dest);
9313 : else
9314 48 : dest = gfc_build_addr_expr (pvoid_type_node, dest);
9315 :
9316 30662 : if (slength && POINTER_TYPE_P (TREE_TYPE (src)))
9317 30658 : src = fold_convert (pvoid_type_node, src);
9318 : else
9319 4 : src = gfc_build_addr_expr (pvoid_type_node, src);
9320 :
9321 : /* Truncate string if source is too long. */
9322 30662 : cond2 = fold_build2_loc (input_location, LT_EXPR, logical_type_node, slen,
9323 : dlen);
9324 :
9325 : /* Pre-evaluate pointers unless one of the IF arms will be optimized away. */
9326 30662 : if (!CONSTANT_CLASS_P (cond2))
9327 : {
9328 9391 : dest = gfc_evaluate_now (dest, block);
9329 9391 : src = gfc_evaluate_now (src, block);
9330 : }
9331 :
9332 : /* Copy and pad with spaces. */
9333 30662 : tmp3 = build_call_expr_loc (input_location,
9334 : builtin_decl_explicit (BUILT_IN_MEMMOVE),
9335 : 3, dest, src,
9336 : fold_convert (size_type_node, slen));
9337 :
9338 : /* Wstringop-overflow appears at -O3 even though this warning is not
9339 : explicitly available in fortran nor can it be switched off. If the
9340 : source length is a constant, its negative appears as a very large
9341 : positive number and triggers the warning in BUILTIN_MEMSET. Fixing
9342 : the result of the MINUS_EXPR suppresses this spurious warning. */
9343 30662 : tmp = fold_build2_loc (input_location, MINUS_EXPR,
9344 30662 : TREE_TYPE(dlen), dlen, slen);
9345 30662 : if (slength && TREE_CONSTANT (slength))
9346 27131 : tmp = gfc_evaluate_now (tmp, block);
9347 :
9348 30662 : tmp4 = fold_build_pointer_plus_loc (input_location, dest, slen);
9349 30662 : tmp4 = fill_with_spaces (tmp4, chartype, tmp);
9350 :
9351 30662 : gfc_init_block (&tempblock);
9352 30662 : gfc_add_expr_to_block (&tempblock, tmp3);
9353 30662 : gfc_add_expr_to_block (&tempblock, tmp4);
9354 30662 : tmp3 = gfc_finish_block (&tempblock);
9355 :
9356 : /* The truncated memmove if the slen >= dlen. */
9357 30662 : tmp2 = build_call_expr_loc (input_location,
9358 : builtin_decl_explicit (BUILT_IN_MEMMOVE),
9359 : 3, dest, src,
9360 : fold_convert (size_type_node, dlen));
9361 :
9362 : /* The whole copy_string function is there. */
9363 30662 : tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond2,
9364 : tmp3, tmp2);
9365 30662 : tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
9366 : build_empty_stmt (input_location));
9367 30662 : gfc_add_expr_to_block (block, tmp);
9368 : }
9369 :
9370 :
9371 : /* Translate a statement function.
9372 : The value of a statement function reference is obtained by evaluating the
9373 : expression using the values of the actual arguments for the values of the
9374 : corresponding dummy arguments. */
9375 :
9376 : static void
9377 269 : gfc_conv_statement_function (gfc_se * se, gfc_expr * expr)
9378 : {
9379 269 : gfc_symbol *sym;
9380 269 : gfc_symbol *fsym;
9381 269 : gfc_formal_arglist *fargs;
9382 269 : gfc_actual_arglist *args;
9383 269 : gfc_se lse;
9384 269 : gfc_se rse;
9385 269 : gfc_saved_var *saved_vars;
9386 269 : tree *temp_vars;
9387 269 : tree type;
9388 269 : tree tmp;
9389 269 : int n;
9390 :
9391 269 : sym = expr->symtree->n.sym;
9392 269 : args = expr->value.function.actual;
9393 269 : gfc_init_se (&lse, NULL);
9394 269 : gfc_init_se (&rse, NULL);
9395 :
9396 269 : n = 0;
9397 727 : for (fargs = gfc_sym_get_dummy_args (sym); fargs; fargs = fargs->next)
9398 458 : n++;
9399 269 : saved_vars = XCNEWVEC (gfc_saved_var, n);
9400 269 : temp_vars = XCNEWVEC (tree, n);
9401 :
9402 727 : for (fargs = gfc_sym_get_dummy_args (sym), n = 0; fargs;
9403 458 : fargs = fargs->next, n++)
9404 : {
9405 : /* Each dummy shall be specified, explicitly or implicitly, to be
9406 : scalar. */
9407 458 : gcc_assert (fargs->sym->attr.dimension == 0);
9408 458 : fsym = fargs->sym;
9409 :
9410 458 : if (fsym->ts.type == BT_CHARACTER)
9411 : {
9412 : /* Copy string arguments. */
9413 48 : tree arglen;
9414 :
9415 48 : gcc_assert (fsym->ts.u.cl && fsym->ts.u.cl->length
9416 : && fsym->ts.u.cl->length->expr_type == EXPR_CONSTANT);
9417 :
9418 : /* Create a temporary to hold the value. */
9419 48 : if (fsym->ts.u.cl->backend_decl == NULL_TREE)
9420 1 : fsym->ts.u.cl->backend_decl
9421 1 : = gfc_conv_constant_to_tree (fsym->ts.u.cl->length);
9422 :
9423 48 : type = gfc_get_character_type (fsym->ts.kind, fsym->ts.u.cl);
9424 48 : temp_vars[n] = gfc_create_var (type, fsym->name);
9425 :
9426 48 : arglen = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
9427 :
9428 48 : gfc_conv_expr (&rse, args->expr);
9429 48 : gfc_conv_string_parameter (&rse);
9430 48 : gfc_add_block_to_block (&se->pre, &lse.pre);
9431 48 : gfc_add_block_to_block (&se->pre, &rse.pre);
9432 :
9433 48 : gfc_trans_string_copy (&se->pre, arglen, temp_vars[n], fsym->ts.kind,
9434 : rse.string_length, rse.expr, fsym->ts.kind);
9435 48 : gfc_add_block_to_block (&se->pre, &lse.post);
9436 48 : gfc_add_block_to_block (&se->pre, &rse.post);
9437 : }
9438 : else
9439 : {
9440 : /* For everything else, just evaluate the expression. */
9441 :
9442 : /* Create a temporary to hold the value. */
9443 410 : type = gfc_typenode_for_spec (&fsym->ts);
9444 410 : temp_vars[n] = gfc_create_var (type, fsym->name);
9445 :
9446 410 : gfc_conv_expr (&lse, args->expr);
9447 :
9448 410 : gfc_add_block_to_block (&se->pre, &lse.pre);
9449 410 : gfc_add_modify (&se->pre, temp_vars[n], lse.expr);
9450 410 : gfc_add_block_to_block (&se->pre, &lse.post);
9451 : }
9452 :
9453 458 : args = args->next;
9454 : }
9455 :
9456 : /* Use the temporary variables in place of the real ones. */
9457 727 : for (fargs = gfc_sym_get_dummy_args (sym), n = 0; fargs;
9458 458 : fargs = fargs->next, n++)
9459 458 : gfc_shadow_sym (fargs->sym, temp_vars[n], &saved_vars[n]);
9460 :
9461 269 : gfc_conv_expr (se, sym->value);
9462 :
9463 269 : if (sym->ts.type == BT_CHARACTER)
9464 : {
9465 55 : gfc_conv_const_charlen (sym->ts.u.cl);
9466 :
9467 : /* Force the expression to the correct length. */
9468 55 : if (!INTEGER_CST_P (se->string_length)
9469 101 : || tree_int_cst_lt (se->string_length,
9470 46 : sym->ts.u.cl->backend_decl))
9471 : {
9472 31 : type = gfc_get_character_type (sym->ts.kind, sym->ts.u.cl);
9473 31 : tmp = gfc_create_var (type, sym->name);
9474 31 : tmp = gfc_build_addr_expr (build_pointer_type (type), tmp);
9475 31 : gfc_trans_string_copy (&se->pre, sym->ts.u.cl->backend_decl, tmp,
9476 : sym->ts.kind, se->string_length, se->expr,
9477 : sym->ts.kind);
9478 31 : se->expr = tmp;
9479 : }
9480 55 : se->string_length = sym->ts.u.cl->backend_decl;
9481 : }
9482 :
9483 : /* Restore the original variables. */
9484 727 : for (fargs = gfc_sym_get_dummy_args (sym), n = 0; fargs;
9485 458 : fargs = fargs->next, n++)
9486 458 : gfc_restore_sym (fargs->sym, &saved_vars[n]);
9487 269 : free (temp_vars);
9488 269 : free (saved_vars);
9489 269 : }
9490 :
9491 :
9492 : /* Translate a function expression. */
9493 :
9494 : static void
9495 313311 : gfc_conv_function_expr (gfc_se * se, gfc_expr * expr)
9496 : {
9497 313311 : gfc_symbol *sym;
9498 :
9499 313311 : if (expr->value.function.isym)
9500 : {
9501 262899 : gfc_conv_intrinsic_function (se, expr);
9502 262899 : return;
9503 : }
9504 :
9505 : /* expr.value.function.esym is the resolved (specific) function symbol for
9506 : most functions. However this isn't set for dummy procedures. */
9507 50412 : sym = expr->value.function.esym;
9508 50412 : if (!sym)
9509 1630 : sym = expr->symtree->n.sym;
9510 :
9511 : /* The IEEE_ARITHMETIC functions are caught here. */
9512 50412 : if (sym->from_intmod == INTMOD_IEEE_ARITHMETIC)
9513 13939 : if (gfc_conv_ieee_arithmetic_function (se, expr))
9514 : return;
9515 :
9516 : /* We distinguish statement functions from general functions to improve
9517 : runtime performance. */
9518 37955 : if (sym->attr.proc == PROC_ST_FUNCTION)
9519 : {
9520 269 : gfc_conv_statement_function (se, expr);
9521 269 : return;
9522 : }
9523 :
9524 37686 : gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
9525 : NULL);
9526 : }
9527 :
9528 :
9529 : /* Determine whether the given EXPR_CONSTANT is a zero initializer. */
9530 :
9531 : static bool
9532 39857 : is_zero_initializer_p (gfc_expr * expr)
9533 : {
9534 39857 : if (expr->expr_type != EXPR_CONSTANT)
9535 : return false;
9536 :
9537 : /* We ignore constants with prescribed memory representations for now. */
9538 11400 : if (expr->representation.string)
9539 : return false;
9540 :
9541 11382 : switch (expr->ts.type)
9542 : {
9543 5267 : case BT_INTEGER:
9544 5267 : return mpz_cmp_si (expr->value.integer, 0) == 0;
9545 :
9546 4819 : case BT_REAL:
9547 4819 : return mpfr_zero_p (expr->value.real)
9548 4819 : && MPFR_SIGN (expr->value.real) >= 0;
9549 :
9550 919 : case BT_LOGICAL:
9551 919 : return expr->value.logical == 0;
9552 :
9553 243 : case BT_COMPLEX:
9554 243 : return mpfr_zero_p (mpc_realref (expr->value.complex))
9555 155 : && MPFR_SIGN (mpc_realref (expr->value.complex)) >= 0
9556 155 : && mpfr_zero_p (mpc_imagref (expr->value.complex))
9557 386 : && MPFR_SIGN (mpc_imagref (expr->value.complex)) >= 0;
9558 :
9559 : default:
9560 : break;
9561 : }
9562 : return false;
9563 : }
9564 :
9565 :
9566 : static void
9567 35923 : gfc_conv_array_constructor_expr (gfc_se * se, gfc_expr * expr)
9568 : {
9569 35923 : gfc_ss *ss;
9570 :
9571 35923 : ss = se->ss;
9572 35923 : gcc_assert (ss != NULL && ss != gfc_ss_terminator);
9573 35923 : gcc_assert (ss->info->expr == expr && ss->info->type == GFC_SS_CONSTRUCTOR);
9574 :
9575 35923 : gfc_conv_tmp_array_ref (se);
9576 35923 : }
9577 :
9578 :
9579 : /* Build a static initializer. EXPR is the expression for the initial value.
9580 : The other parameters describe the variable of the component being
9581 : initialized. EXPR may be null. */
9582 :
9583 : tree
9584 134720 : gfc_conv_initializer (gfc_expr * expr, gfc_typespec * ts, tree type,
9585 : bool array, bool pointer, bool procptr)
9586 : {
9587 134720 : gfc_se se;
9588 :
9589 134720 : if (flag_coarray != GFC_FCOARRAY_LIB && ts->type == BT_DERIVED
9590 41928 : && ts->u.derived->from_intmod == INTMOD_ISO_FORTRAN_ENV
9591 171 : && ts->u.derived->intmod_sym_id == ISOFORTRAN_EVENT_TYPE)
9592 59 : return build_constructor (type, NULL);
9593 :
9594 134661 : if (!(expr || pointer || procptr))
9595 : return NULL_TREE;
9596 :
9597 : /* Check if we have ISOCBINDING_NULL_PTR or ISOCBINDING_NULL_FUNPTR
9598 : (these are the only two iso_c_binding derived types that can be
9599 : used as initialization expressions). If so, we need to modify
9600 : the 'expr' to be that for a (void *). */
9601 126380 : if (expr != NULL && expr->ts.type == BT_DERIVED
9602 37783 : && expr->ts.is_iso_c && expr->ts.u.derived)
9603 : {
9604 186 : if (TREE_CODE (type) == ARRAY_TYPE)
9605 4 : return build_constructor (type, NULL);
9606 182 : else if (POINTER_TYPE_P (type))
9607 182 : return build_int_cst (type, 0);
9608 : else
9609 0 : gcc_unreachable ();
9610 : }
9611 :
9612 126194 : if (array && !procptr)
9613 : {
9614 8767 : tree ctor;
9615 : /* Arrays need special handling. */
9616 8767 : if (pointer)
9617 776 : ctor = gfc_build_null_descriptor (type);
9618 : /* Special case assigning an array to zero. */
9619 7991 : else if (is_zero_initializer_p (expr))
9620 220 : ctor = build_constructor (type, NULL);
9621 : else
9622 7771 : ctor = gfc_conv_array_initializer (type, expr);
9623 8767 : TREE_STATIC (ctor) = 1;
9624 8767 : return ctor;
9625 : }
9626 117427 : else if (pointer || procptr)
9627 : {
9628 54706 : if (ts->type == BT_CLASS && !procptr)
9629 : {
9630 1762 : gfc_init_se (&se, NULL);
9631 1762 : gfc_conv_structure (&se, gfc_class_initializer (ts, expr), 1);
9632 1762 : gcc_assert (TREE_CODE (se.expr) == CONSTRUCTOR);
9633 1762 : TREE_STATIC (se.expr) = 1;
9634 1762 : return se.expr;
9635 : }
9636 52944 : else if (!expr || expr->expr_type == EXPR_NULL)
9637 28149 : return fold_convert (type, null_pointer_node);
9638 : else
9639 : {
9640 24795 : gfc_init_se (&se, NULL);
9641 24795 : se.want_pointer = 1;
9642 24795 : gfc_conv_expr (&se, expr);
9643 24795 : gcc_assert (TREE_CODE (se.expr) != CONSTRUCTOR);
9644 : return se.expr;
9645 : }
9646 : }
9647 : else
9648 : {
9649 62721 : switch (ts->type)
9650 : {
9651 18168 : case_bt_struct:
9652 18168 : case BT_CLASS:
9653 18168 : gfc_init_se (&se, NULL);
9654 18168 : if (ts->type == BT_CLASS && expr->expr_type == EXPR_NULL)
9655 779 : gfc_conv_structure (&se, gfc_class_initializer (ts, expr), 1);
9656 : else
9657 17389 : gfc_conv_structure (&se, expr, 1);
9658 18168 : gcc_assert (TREE_CODE (se.expr) == CONSTRUCTOR);
9659 18168 : TREE_STATIC (se.expr) = 1;
9660 18168 : return se.expr;
9661 :
9662 2705 : case BT_CHARACTER:
9663 2705 : if (expr->expr_type == EXPR_CONSTANT)
9664 : {
9665 2704 : tree ctor = gfc_conv_string_init (ts->u.cl->backend_decl, expr);
9666 2704 : TREE_STATIC (ctor) = 1;
9667 2704 : return ctor;
9668 : }
9669 :
9670 : /* Fallthrough. */
9671 41849 : default:
9672 41849 : gfc_init_se (&se, NULL);
9673 41849 : gfc_conv_constant (&se, expr);
9674 41849 : gcc_assert (TREE_CODE (se.expr) != CONSTRUCTOR);
9675 : return se.expr;
9676 : }
9677 : }
9678 : }
9679 :
9680 : static tree
9681 956 : gfc_trans_subarray_assign (tree dest, gfc_component * cm, gfc_expr * expr)
9682 : {
9683 956 : gfc_se rse;
9684 956 : gfc_se lse;
9685 956 : gfc_ss *rss;
9686 956 : gfc_ss *lss;
9687 956 : gfc_array_info *lss_array;
9688 956 : stmtblock_t body;
9689 956 : stmtblock_t block;
9690 956 : gfc_loopinfo loop;
9691 956 : int n;
9692 956 : tree tmp;
9693 :
9694 956 : gfc_start_block (&block);
9695 :
9696 : /* Initialize the scalarizer. */
9697 956 : gfc_init_loopinfo (&loop);
9698 :
9699 956 : gfc_init_se (&lse, NULL);
9700 956 : gfc_init_se (&rse, NULL);
9701 :
9702 : /* Walk the rhs. */
9703 956 : rss = gfc_walk_expr (expr);
9704 956 : if (rss == gfc_ss_terminator)
9705 : /* The rhs is scalar. Add a ss for the expression. */
9706 208 : rss = gfc_get_scalar_ss (gfc_ss_terminator, expr);
9707 :
9708 : /* Create a SS for the destination. */
9709 956 : lss = gfc_get_array_ss (gfc_ss_terminator, NULL, cm->as->rank,
9710 : GFC_SS_COMPONENT);
9711 956 : lss_array = &lss->info->data.array;
9712 956 : lss_array->shape = gfc_get_shape (cm->as->rank);
9713 956 : lss_array->descriptor = dest;
9714 956 : lss_array->data = gfc_conv_array_data (dest);
9715 956 : lss_array->offset = gfc_conv_array_offset (dest);
9716 1969 : for (n = 0; n < cm->as->rank; n++)
9717 : {
9718 1013 : lss_array->start[n] = gfc_conv_array_lbound (dest, n);
9719 1013 : lss_array->stride[n] = gfc_index_one_node;
9720 :
9721 1013 : mpz_init (lss_array->shape[n]);
9722 1013 : mpz_sub (lss_array->shape[n], cm->as->upper[n]->value.integer,
9723 1013 : cm->as->lower[n]->value.integer);
9724 1013 : mpz_add_ui (lss_array->shape[n], lss_array->shape[n], 1);
9725 : }
9726 :
9727 : /* Associate the SS with the loop. */
9728 956 : gfc_add_ss_to_loop (&loop, lss);
9729 956 : gfc_add_ss_to_loop (&loop, rss);
9730 :
9731 : /* Calculate the bounds of the scalarization. */
9732 956 : gfc_conv_ss_startstride (&loop);
9733 :
9734 : /* Setup the scalarizing loops. */
9735 956 : gfc_conv_loop_setup (&loop, &expr->where);
9736 :
9737 : /* Setup the gfc_se structures. */
9738 956 : gfc_copy_loopinfo_to_se (&lse, &loop);
9739 956 : gfc_copy_loopinfo_to_se (&rse, &loop);
9740 :
9741 956 : rse.ss = rss;
9742 956 : gfc_mark_ss_chain_used (rss, 1);
9743 956 : lse.ss = lss;
9744 956 : gfc_mark_ss_chain_used (lss, 1);
9745 :
9746 : /* Start the scalarized loop body. */
9747 956 : gfc_start_scalarized_body (&loop, &body);
9748 :
9749 956 : gfc_conv_tmp_array_ref (&lse);
9750 956 : if (cm->ts.type == BT_CHARACTER)
9751 176 : lse.string_length = cm->ts.u.cl->backend_decl;
9752 :
9753 956 : gfc_conv_expr (&rse, expr);
9754 :
9755 956 : tmp = gfc_trans_scalar_assign (&lse, &rse, cm->ts, true, false);
9756 956 : gfc_add_expr_to_block (&body, tmp);
9757 :
9758 956 : gcc_assert (rse.ss == gfc_ss_terminator);
9759 :
9760 : /* Generate the copying loops. */
9761 956 : gfc_trans_scalarizing_loops (&loop, &body);
9762 :
9763 : /* Wrap the whole thing up. */
9764 956 : gfc_add_block_to_block (&block, &loop.pre);
9765 956 : gfc_add_block_to_block (&block, &loop.post);
9766 :
9767 956 : gcc_assert (lss_array->shape != NULL);
9768 956 : gfc_free_shape (&lss_array->shape, cm->as->rank);
9769 956 : gfc_cleanup_loop (&loop);
9770 :
9771 956 : return gfc_finish_block (&block);
9772 : }
9773 :
9774 :
9775 : static stmtblock_t *final_block;
9776 : static tree
9777 1312 : gfc_trans_alloc_subarray_assign (tree dest, gfc_component * cm,
9778 : gfc_expr * expr)
9779 : {
9780 1312 : gfc_se se;
9781 1312 : stmtblock_t block;
9782 1312 : tree offset;
9783 1312 : int n;
9784 1312 : tree tmp;
9785 1312 : tree tmp2;
9786 1312 : gfc_array_spec *as;
9787 1312 : gfc_expr *arg = NULL;
9788 :
9789 1312 : gfc_start_block (&block);
9790 1312 : gfc_init_se (&se, NULL);
9791 :
9792 : /* Get the descriptor for the expressions. */
9793 1312 : se.want_pointer = 0;
9794 1312 : gfc_conv_expr_descriptor (&se, expr);
9795 1312 : gfc_add_block_to_block (&block, &se.pre);
9796 1312 : gfc_add_modify (&block, dest, se.expr);
9797 1312 : if (cm->ts.type == BT_CHARACTER
9798 1312 : && gfc_deferred_strlen (cm, &tmp))
9799 : {
9800 30 : tmp = fold_build3_loc (input_location, COMPONENT_REF,
9801 30 : TREE_TYPE (tmp),
9802 30 : TREE_OPERAND (dest, 0),
9803 : tmp, NULL_TREE);
9804 30 : gfc_add_modify (&block, tmp,
9805 30 : fold_convert (TREE_TYPE (tmp),
9806 : se.string_length));
9807 30 : cm->ts.u.cl->backend_decl = gfc_create_var (gfc_charlen_type_node,
9808 : "slen");
9809 30 : gfc_add_modify (&block, cm->ts.u.cl->backend_decl, se.string_length);
9810 : }
9811 :
9812 : /* Deal with arrays of derived types with allocatable components. */
9813 1312 : if (gfc_bt_struct (cm->ts.type)
9814 199 : && cm->ts.u.derived->attr.alloc_comp)
9815 : // TODO: Fix caf_mode
9816 113 : tmp = gfc_copy_alloc_comp (cm->ts.u.derived,
9817 : se.expr, dest,
9818 113 : cm->as->rank, 0);
9819 1199 : else if (cm->ts.type == BT_CLASS && expr->ts.type == BT_DERIVED
9820 36 : && CLASS_DATA(cm)->attr.allocatable)
9821 : {
9822 36 : if (cm->ts.u.derived->attr.alloc_comp)
9823 : // TODO: Fix caf_mode
9824 0 : tmp = gfc_copy_alloc_comp (expr->ts.u.derived,
9825 : se.expr, dest,
9826 : expr->rank, 0);
9827 : else
9828 : {
9829 36 : tmp = TREE_TYPE (dest);
9830 36 : tmp = gfc_duplicate_allocatable (dest, se.expr,
9831 : tmp, expr->rank, NULL_TREE);
9832 : }
9833 : }
9834 1163 : else if (cm->ts.type == BT_CHARACTER && cm->ts.deferred)
9835 30 : tmp = gfc_duplicate_allocatable (dest, se.expr,
9836 : gfc_typenode_for_spec (&cm->ts),
9837 30 : cm->as->rank, NULL_TREE);
9838 : else
9839 1133 : tmp = gfc_duplicate_allocatable (dest, se.expr,
9840 1133 : TREE_TYPE(cm->backend_decl),
9841 1133 : cm->as->rank, NULL_TREE);
9842 :
9843 :
9844 1312 : gfc_add_expr_to_block (&block, tmp);
9845 1312 : gfc_add_block_to_block (&block, &se.post);
9846 :
9847 1312 : if (final_block && !cm->attr.allocatable
9848 96 : && expr->expr_type == EXPR_ARRAY)
9849 : {
9850 96 : tree data_ptr;
9851 96 : data_ptr = gfc_conv_descriptor_data_get (dest);
9852 96 : gfc_add_expr_to_block (final_block, gfc_call_free (data_ptr));
9853 96 : }
9854 1216 : else if (final_block && cm->attr.allocatable)
9855 162 : gfc_add_block_to_block (final_block, &se.finalblock);
9856 :
9857 1312 : if (expr->expr_type != EXPR_VARIABLE)
9858 : {
9859 1191 : if (gfc_bt_struct (cm->ts.type) && cm->ts.u.derived->attr.alloc_comp)
9860 : {
9861 214 : tmp = gfc_deallocate_alloc_comp_no_caf (cm->ts.u.derived,
9862 107 : se.expr, cm->as->rank, true);
9863 107 : gfc_add_expr_to_block (&block, tmp);
9864 : }
9865 1191 : gfc_conv_descriptor_data_set (&block, se.expr, null_pointer_node);
9866 : }
9867 :
9868 : /* We need to know if the argument of a conversion function is a
9869 : variable, so that the correct lower bound can be used. */
9870 1312 : if (expr->expr_type == EXPR_FUNCTION
9871 68 : && expr->value.function.isym
9872 56 : && expr->value.function.isym->conversion
9873 56 : && expr->value.function.actual->expr
9874 56 : && expr->value.function.actual->expr->expr_type == EXPR_VARIABLE)
9875 56 : arg = expr->value.function.actual->expr;
9876 :
9877 : /* Obtain the array spec of full array references. */
9878 56 : if (arg)
9879 56 : as = gfc_get_full_arrayspec_from_expr (arg);
9880 : else
9881 1256 : as = gfc_get_full_arrayspec_from_expr (expr);
9882 :
9883 : /* Shift the lbound and ubound of temporaries to being unity,
9884 : rather than zero, based. Always calculate the offset. */
9885 1312 : gfc_conv_descriptor_offset_set (&block, dest, gfc_index_zero_node);
9886 1312 : offset = gfc_conv_descriptor_offset_get (dest);
9887 1312 : tmp2 =gfc_create_var (gfc_array_index_type, NULL);
9888 :
9889 2680 : for (n = 0; n < expr->rank; n++)
9890 : {
9891 1368 : tree span;
9892 1368 : tree lbound;
9893 :
9894 : /* Obtain the correct lbound - ISO/IEC TR 15581:2001 page 9.
9895 : TODO It looks as if gfc_conv_expr_descriptor should return
9896 : the correct bounds and that the following should not be
9897 : necessary. This would simplify gfc_conv_intrinsic_bound
9898 : as well. */
9899 1368 : if (as && as->lower[n])
9900 : {
9901 92 : gfc_se lbse;
9902 92 : gfc_init_se (&lbse, NULL);
9903 92 : gfc_conv_expr (&lbse, as->lower[n]);
9904 92 : gfc_add_block_to_block (&block, &lbse.pre);
9905 92 : lbound = gfc_evaluate_now (lbse.expr, &block);
9906 92 : }
9907 1276 : else if (as && arg)
9908 : {
9909 34 : tmp = gfc_get_symbol_decl (arg->symtree->n.sym);
9910 34 : lbound = gfc_conv_descriptor_lbound_get (tmp,
9911 : gfc_rank_cst[n]);
9912 : }
9913 1242 : else if (as)
9914 64 : lbound = gfc_conv_descriptor_lbound_get (dest,
9915 : gfc_rank_cst[n]);
9916 : else
9917 1178 : lbound = gfc_index_one_node;
9918 :
9919 1368 : lbound = fold_convert (gfc_array_index_type, lbound);
9920 :
9921 : /* Shift the bounds and set the offset accordingly. */
9922 1368 : tmp = gfc_conv_descriptor_ubound_get (dest, gfc_rank_cst[n]);
9923 1368 : span = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
9924 : tmp, gfc_conv_descriptor_lbound_get (dest, gfc_rank_cst[n]));
9925 1368 : tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
9926 : span, lbound);
9927 1368 : gfc_conv_descriptor_ubound_set (&block, dest,
9928 : gfc_rank_cst[n], tmp);
9929 1368 : gfc_conv_descriptor_lbound_set (&block, dest,
9930 : gfc_rank_cst[n], lbound);
9931 :
9932 1368 : tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
9933 : gfc_conv_descriptor_lbound_get (dest,
9934 : gfc_rank_cst[n]),
9935 : gfc_conv_descriptor_stride_get (dest,
9936 : gfc_rank_cst[n]));
9937 1368 : gfc_add_modify (&block, tmp2, tmp);
9938 1368 : tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
9939 : offset, tmp2);
9940 1368 : gfc_conv_descriptor_offset_set (&block, dest, tmp);
9941 : }
9942 :
9943 1312 : if (arg)
9944 : {
9945 : /* If a conversion expression has a null data pointer
9946 : argument, nullify the allocatable component. */
9947 56 : tree non_null_expr;
9948 56 : tree null_expr;
9949 :
9950 56 : if (arg->symtree->n.sym->attr.allocatable
9951 24 : || arg->symtree->n.sym->attr.pointer)
9952 : {
9953 32 : non_null_expr = gfc_finish_block (&block);
9954 32 : gfc_start_block (&block);
9955 32 : gfc_conv_descriptor_data_set (&block, dest,
9956 : null_pointer_node);
9957 32 : null_expr = gfc_finish_block (&block);
9958 32 : tmp = gfc_conv_descriptor_data_get (arg->symtree->n.sym->backend_decl);
9959 32 : tmp = build2_loc (input_location, EQ_EXPR, logical_type_node, tmp,
9960 32 : fold_convert (TREE_TYPE (tmp), null_pointer_node));
9961 32 : return build3_v (COND_EXPR, tmp,
9962 : null_expr, non_null_expr);
9963 : }
9964 : }
9965 :
9966 1280 : return gfc_finish_block (&block);
9967 : }
9968 :
9969 :
9970 : /* Allocate or reallocate scalar component, as necessary. */
9971 :
9972 : static void
9973 416 : alloc_scalar_allocatable_subcomponent (stmtblock_t *block, tree comp,
9974 : gfc_component *cm, gfc_expr *expr2,
9975 : tree slen)
9976 : {
9977 416 : tree tmp;
9978 416 : tree ptr;
9979 416 : tree size;
9980 416 : tree size_in_bytes;
9981 416 : tree lhs_cl_size = NULL_TREE;
9982 416 : gfc_se se;
9983 :
9984 416 : if (!comp)
9985 0 : return;
9986 :
9987 416 : if (!expr2 || expr2->rank)
9988 : return;
9989 :
9990 416 : realloc_lhs_warning (expr2->ts.type, false, &expr2->where);
9991 :
9992 416 : if (cm->ts.type == BT_CHARACTER && cm->ts.deferred)
9993 : {
9994 145 : gcc_assert (expr2->ts.type == BT_CHARACTER);
9995 145 : size = expr2->ts.u.cl->backend_decl;
9996 145 : if (!size || !VAR_P (size))
9997 145 : size = gfc_create_var (TREE_TYPE (slen), "slen");
9998 145 : gfc_add_modify (block, size, slen);
9999 :
10000 145 : gfc_deferred_strlen (cm, &tmp);
10001 145 : lhs_cl_size = fold_build3_loc (input_location, COMPONENT_REF,
10002 : gfc_charlen_type_node,
10003 145 : TREE_OPERAND (comp, 0),
10004 : tmp, NULL_TREE);
10005 :
10006 145 : tmp = TREE_TYPE (gfc_typenode_for_spec (&cm->ts));
10007 145 : tmp = TYPE_SIZE_UNIT (tmp);
10008 290 : size_in_bytes = fold_build2_loc (input_location, MULT_EXPR,
10009 145 : TREE_TYPE (tmp), tmp,
10010 145 : fold_convert (TREE_TYPE (tmp), size));
10011 : }
10012 271 : else if (cm->ts.type == BT_CLASS)
10013 : {
10014 103 : if (expr2->ts.type != BT_CLASS)
10015 : {
10016 103 : if (expr2->ts.type == BT_CHARACTER)
10017 : {
10018 24 : gfc_init_se (&se, NULL);
10019 24 : gfc_conv_expr (&se, expr2);
10020 24 : size = build_int_cst (gfc_charlen_type_node, expr2->ts.kind);
10021 24 : size = fold_build2_loc (input_location, MULT_EXPR,
10022 : gfc_charlen_type_node,
10023 : se.string_length, size);
10024 24 : size = fold_convert (size_type_node, size);
10025 : }
10026 : else
10027 : {
10028 79 : if (expr2->ts.type == BT_DERIVED)
10029 48 : tmp = gfc_get_symbol_decl (expr2->ts.u.derived);
10030 : else
10031 31 : tmp = gfc_typenode_for_spec (&expr2->ts);
10032 79 : size = TYPE_SIZE_UNIT (tmp);
10033 : }
10034 : }
10035 : else
10036 : {
10037 0 : gfc_expr *e2vtab;
10038 0 : e2vtab = gfc_find_and_cut_at_last_class_ref (expr2);
10039 0 : gfc_add_vptr_component (e2vtab);
10040 0 : gfc_add_size_component (e2vtab);
10041 0 : gfc_init_se (&se, NULL);
10042 0 : gfc_conv_expr (&se, e2vtab);
10043 0 : gfc_add_block_to_block (block, &se.pre);
10044 0 : size = fold_convert (size_type_node, se.expr);
10045 0 : gfc_free_expr (e2vtab);
10046 : }
10047 : size_in_bytes = size;
10048 : }
10049 : else
10050 : {
10051 : /* Otherwise use the length in bytes of the rhs. */
10052 168 : size = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&cm->ts));
10053 168 : size_in_bytes = size;
10054 : }
10055 :
10056 416 : size_in_bytes = fold_build2_loc (input_location, MAX_EXPR, size_type_node,
10057 : size_in_bytes, size_one_node);
10058 :
10059 416 : if (cm->ts.type == BT_DERIVED && cm->ts.u.derived->attr.alloc_comp)
10060 : {
10061 0 : tmp = build_call_expr_loc (input_location,
10062 : builtin_decl_explicit (BUILT_IN_CALLOC),
10063 : 2, build_one_cst (size_type_node),
10064 : size_in_bytes);
10065 0 : tmp = fold_convert (TREE_TYPE (comp), tmp);
10066 0 : gfc_add_modify (block, comp, tmp);
10067 : }
10068 : else
10069 : {
10070 416 : tmp = build_call_expr_loc (input_location,
10071 : builtin_decl_explicit (BUILT_IN_MALLOC),
10072 : 1, size_in_bytes);
10073 416 : if (GFC_CLASS_TYPE_P (TREE_TYPE (comp)))
10074 103 : ptr = gfc_class_data_get (comp);
10075 : else
10076 : ptr = comp;
10077 416 : tmp = fold_convert (TREE_TYPE (ptr), tmp);
10078 416 : gfc_add_modify (block, ptr, tmp);
10079 : }
10080 :
10081 416 : if (cm->ts.type == BT_CHARACTER && cm->ts.deferred)
10082 : /* Update the lhs character length. */
10083 145 : gfc_add_modify (block, lhs_cl_size,
10084 145 : fold_convert (TREE_TYPE (lhs_cl_size), size));
10085 : }
10086 :
10087 :
10088 : /* Assign a single component of a derived type constructor. */
10089 :
10090 : static tree
10091 29419 : gfc_trans_subcomponent_assign (tree dest, gfc_component * cm,
10092 : gfc_expr * expr, bool init)
10093 : {
10094 29419 : gfc_se se;
10095 29419 : gfc_se lse;
10096 29419 : stmtblock_t block;
10097 29419 : tree tmp;
10098 29419 : tree vtab;
10099 :
10100 29419 : gfc_start_block (&block);
10101 :
10102 29419 : if (cm->attr.pointer || cm->attr.proc_pointer)
10103 : {
10104 : /* Only care about pointers here, not about allocatables. */
10105 2668 : gfc_init_se (&se, NULL);
10106 : /* Pointer component. */
10107 2668 : if ((cm->attr.dimension || cm->attr.codimension)
10108 682 : && !cm->attr.proc_pointer)
10109 : {
10110 : /* Array pointer. */
10111 666 : if (expr->expr_type == EXPR_NULL)
10112 660 : gfc_conv_descriptor_data_set (&block, dest, null_pointer_node);
10113 : else
10114 : {
10115 6 : se.direct_byref = 1;
10116 6 : se.expr = dest;
10117 6 : gfc_conv_expr_descriptor (&se, expr);
10118 6 : gfc_add_block_to_block (&block, &se.pre);
10119 6 : gfc_add_block_to_block (&block, &se.post);
10120 : }
10121 : }
10122 : else
10123 : {
10124 : /* Scalar pointers. */
10125 2002 : se.want_pointer = 1;
10126 2002 : gfc_conv_expr (&se, expr);
10127 2002 : gfc_add_block_to_block (&block, &se.pre);
10128 :
10129 2002 : if (expr->symtree && expr->symtree->n.sym->attr.proc_pointer
10130 12 : && expr->symtree->n.sym->attr.dummy)
10131 12 : se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
10132 :
10133 2002 : gfc_add_modify (&block, dest,
10134 2002 : fold_convert (TREE_TYPE (dest), se.expr));
10135 2002 : gfc_add_block_to_block (&block, &se.post);
10136 : }
10137 : }
10138 26751 : else if (cm->ts.type == BT_CLASS && expr->expr_type == EXPR_NULL)
10139 : {
10140 : /* NULL initialization for CLASS components. */
10141 940 : tmp = gfc_trans_structure_assign (dest,
10142 : gfc_class_initializer (&cm->ts, expr),
10143 : false);
10144 940 : gfc_add_expr_to_block (&block, tmp);
10145 : }
10146 25811 : else if ((cm->attr.dimension || cm->attr.codimension)
10147 : && !cm->attr.proc_pointer)
10148 : {
10149 4984 : if (cm->attr.allocatable && expr->expr_type == EXPR_NULL)
10150 : {
10151 2752 : gfc_conv_descriptor_data_set (&block, dest, null_pointer_node);
10152 2752 : if (cm->attr.codimension && flag_coarray == GFC_FCOARRAY_LIB)
10153 2 : gfc_add_modify (&block, gfc_conv_descriptor_token (dest),
10154 : null_pointer_node);
10155 : }
10156 2232 : else if (cm->attr.allocatable || cm->attr.pdt_array)
10157 : {
10158 1276 : tmp = gfc_trans_alloc_subarray_assign (dest, cm, expr);
10159 1276 : gfc_add_expr_to_block (&block, tmp);
10160 : }
10161 : else
10162 : {
10163 956 : tmp = gfc_trans_subarray_assign (dest, cm, expr);
10164 956 : gfc_add_expr_to_block (&block, tmp);
10165 : }
10166 : }
10167 20827 : else if (cm->ts.type == BT_CLASS
10168 145 : && CLASS_DATA (cm)->attr.dimension
10169 36 : && CLASS_DATA (cm)->attr.allocatable
10170 36 : && expr->ts.type == BT_DERIVED)
10171 : {
10172 36 : vtab = gfc_get_symbol_decl (gfc_find_vtab (&expr->ts));
10173 36 : vtab = gfc_build_addr_expr (NULL_TREE, vtab);
10174 36 : tmp = gfc_class_vptr_get (dest);
10175 36 : gfc_add_modify (&block, tmp,
10176 36 : fold_convert (TREE_TYPE (tmp), vtab));
10177 36 : tmp = gfc_class_data_get (dest);
10178 36 : tmp = gfc_trans_alloc_subarray_assign (tmp, cm, expr);
10179 36 : gfc_add_expr_to_block (&block, tmp);
10180 : }
10181 20791 : else if (cm->attr.allocatable && expr->expr_type == EXPR_NULL
10182 1772 : && (init
10183 1645 : || (cm->ts.type == BT_CHARACTER
10184 131 : && !(cm->ts.deferred || cm->attr.pdt_string))))
10185 : {
10186 : /* NULL initialization for allocatable components.
10187 : Deferred-length character is dealt with later. */
10188 151 : gfc_add_modify (&block, dest, fold_convert (TREE_TYPE (dest),
10189 : null_pointer_node));
10190 : }
10191 20640 : else if (init && (cm->attr.allocatable
10192 13461 : || (cm->ts.type == BT_CLASS && CLASS_DATA (cm)->attr.allocatable
10193 109 : && expr->ts.type != BT_CLASS)))
10194 : {
10195 416 : tree size;
10196 :
10197 416 : gfc_init_se (&se, NULL);
10198 416 : gfc_conv_expr (&se, expr);
10199 :
10200 : /* The remainder of these instructions follow the if (cm->attr.pointer)
10201 : if (!cm->attr.dimension) part above. */
10202 416 : gfc_add_block_to_block (&block, &se.pre);
10203 : /* Take care about non-array allocatable components here. The alloc_*
10204 : routine below is motivated by the alloc_scalar_allocatable_for_
10205 : assignment() routine, but with the realloc portions removed and
10206 : different input. */
10207 416 : alloc_scalar_allocatable_subcomponent (&block, dest, cm, expr,
10208 : se.string_length);
10209 :
10210 416 : if (expr->symtree && expr->symtree->n.sym->attr.proc_pointer
10211 0 : && expr->symtree->n.sym->attr.dummy)
10212 0 : se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
10213 :
10214 416 : if (cm->ts.type == BT_CLASS)
10215 : {
10216 103 : tmp = gfc_class_data_get (dest);
10217 103 : tmp = build_fold_indirect_ref_loc (input_location, tmp);
10218 103 : vtab = gfc_get_symbol_decl (gfc_find_vtab (&expr->ts));
10219 103 : vtab = gfc_build_addr_expr (NULL_TREE, vtab);
10220 103 : gfc_add_modify (&block, gfc_class_vptr_get (dest),
10221 103 : fold_convert (TREE_TYPE (gfc_class_vptr_get (dest)), vtab));
10222 : }
10223 : else
10224 313 : tmp = build_fold_indirect_ref_loc (input_location, dest);
10225 :
10226 : /* For deferred strings insert a memcpy. */
10227 416 : if (cm->ts.type == BT_CHARACTER && cm->ts.deferred)
10228 : {
10229 145 : gcc_assert (se.string_length || expr->ts.u.cl->backend_decl);
10230 145 : size = size_of_string_in_bytes (cm->ts.kind, se.string_length
10231 : ? se.string_length
10232 0 : : expr->ts.u.cl->backend_decl);
10233 145 : tmp = gfc_build_memcpy_call (tmp, se.expr, size);
10234 145 : gfc_add_expr_to_block (&block, tmp);
10235 : }
10236 271 : else if (cm->ts.type == BT_CLASS)
10237 : {
10238 : /* Fix the expression for memcpy. */
10239 103 : if (expr->expr_type != EXPR_VARIABLE)
10240 73 : se.expr = gfc_evaluate_now (se.expr, &block);
10241 :
10242 103 : if (expr->ts.type == BT_CHARACTER)
10243 : {
10244 24 : size = build_int_cst (gfc_charlen_type_node, expr->ts.kind);
10245 24 : size = fold_build2_loc (input_location, MULT_EXPR,
10246 : gfc_charlen_type_node,
10247 : se.string_length, size);
10248 24 : size = fold_convert (size_type_node, size);
10249 : }
10250 : else
10251 79 : size = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&expr->ts));
10252 :
10253 : /* Now copy the expression to the constructor component _data. */
10254 103 : gfc_add_expr_to_block (&block,
10255 : gfc_build_memcpy_call (tmp, se.expr, size));
10256 :
10257 : /* Fill the unlimited polymorphic _len field. */
10258 103 : if (UNLIMITED_POLY (cm) && expr->ts.type == BT_CHARACTER)
10259 : {
10260 24 : tmp = gfc_class_len_get (gfc_get_class_from_expr (tmp));
10261 24 : gfc_add_modify (&block, tmp,
10262 24 : fold_convert (TREE_TYPE (tmp),
10263 : se.string_length));
10264 : }
10265 : }
10266 : else
10267 168 : gfc_add_modify (&block, tmp,
10268 168 : fold_convert (TREE_TYPE (tmp), se.expr));
10269 416 : gfc_add_block_to_block (&block, &se.post);
10270 416 : }
10271 20224 : else if (expr->ts.type == BT_UNION)
10272 : {
10273 13 : tree tmp;
10274 13 : gfc_constructor *c = gfc_constructor_first (expr->value.constructor);
10275 : /* We mark that the entire union should be initialized with a contrived
10276 : EXPR_NULL expression at the beginning. */
10277 13 : if (c != NULL && c->n.component == NULL
10278 7 : && c->expr != NULL && c->expr->expr_type == EXPR_NULL)
10279 : {
10280 6 : tmp = build2_loc (input_location, MODIFY_EXPR, void_type_node,
10281 6 : dest, build_constructor (TREE_TYPE (dest), NULL));
10282 6 : gfc_add_expr_to_block (&block, tmp);
10283 6 : c = gfc_constructor_next (c);
10284 : }
10285 : /* The following constructor expression, if any, represents a specific
10286 : map initializer, as given by the user. */
10287 13 : if (c != NULL && c->expr != NULL)
10288 : {
10289 6 : gcc_assert (expr->expr_type == EXPR_STRUCTURE);
10290 6 : tmp = gfc_trans_structure_assign (dest, expr, expr->symtree != NULL);
10291 6 : gfc_add_expr_to_block (&block, tmp);
10292 : }
10293 : }
10294 20211 : else if (expr->ts.type == BT_DERIVED && expr->ts.f90_type != BT_VOID)
10295 : {
10296 3123 : if (expr->expr_type != EXPR_STRUCTURE)
10297 : {
10298 452 : tree dealloc = NULL_TREE;
10299 452 : gfc_init_se (&se, NULL);
10300 452 : gfc_conv_expr (&se, expr);
10301 452 : gfc_add_block_to_block (&block, &se.pre);
10302 : /* Prevent repeat evaluations in gfc_copy_alloc_comp by fixing the
10303 : expression in a temporary variable and deallocate the allocatable
10304 : components. Then we can the copy the expression to the result. */
10305 452 : if (cm->ts.u.derived->attr.alloc_comp
10306 330 : && expr->expr_type != EXPR_VARIABLE)
10307 : {
10308 300 : se.expr = gfc_evaluate_now (se.expr, &block);
10309 300 : dealloc = gfc_deallocate_alloc_comp (cm->ts.u.derived, se.expr,
10310 : expr->rank);
10311 : }
10312 452 : gfc_add_modify (&block, dest,
10313 452 : fold_convert (TREE_TYPE (dest), se.expr));
10314 452 : if (cm->ts.u.derived->attr.alloc_comp
10315 330 : && expr->expr_type != EXPR_NULL)
10316 : {
10317 : // TODO: Fix caf_mode
10318 48 : tmp = gfc_copy_alloc_comp (cm->ts.u.derived, se.expr,
10319 : dest, expr->rank, 0);
10320 48 : gfc_add_expr_to_block (&block, tmp);
10321 48 : if (dealloc != NULL_TREE)
10322 18 : gfc_add_expr_to_block (&block, dealloc);
10323 : }
10324 452 : gfc_add_block_to_block (&block, &se.post);
10325 : }
10326 : else
10327 : {
10328 : /* Nested constructors. */
10329 2671 : tmp = gfc_trans_structure_assign (dest, expr, expr->symtree != NULL);
10330 2671 : gfc_add_expr_to_block (&block, tmp);
10331 : }
10332 : }
10333 17088 : else if (gfc_deferred_strlen (cm, &tmp))
10334 : {
10335 125 : tree strlen;
10336 125 : strlen = tmp;
10337 125 : gcc_assert (strlen);
10338 125 : strlen = fold_build3_loc (input_location, COMPONENT_REF,
10339 125 : TREE_TYPE (strlen),
10340 125 : TREE_OPERAND (dest, 0),
10341 : strlen, NULL_TREE);
10342 :
10343 125 : if (expr->expr_type == EXPR_NULL)
10344 : {
10345 107 : tmp = build_int_cst (TREE_TYPE (cm->backend_decl), 0);
10346 107 : gfc_add_modify (&block, dest, tmp);
10347 107 : tmp = build_int_cst (TREE_TYPE (strlen), 0);
10348 107 : gfc_add_modify (&block, strlen, tmp);
10349 : }
10350 : else
10351 : {
10352 18 : tree size;
10353 18 : gfc_init_se (&se, NULL);
10354 18 : gfc_conv_expr (&se, expr);
10355 18 : size = size_of_string_in_bytes (cm->ts.kind, se.string_length);
10356 18 : size = fold_convert (size_type_node, size);
10357 18 : tmp = build_call_expr_loc (input_location,
10358 : builtin_decl_explicit (BUILT_IN_MALLOC),
10359 : 1, size);
10360 18 : gfc_add_modify (&block, dest,
10361 18 : fold_convert (TREE_TYPE (dest), tmp));
10362 18 : gfc_add_modify (&block, strlen,
10363 18 : fold_convert (TREE_TYPE (strlen), se.string_length));
10364 18 : tmp = gfc_build_memcpy_call (dest, se.expr, size);
10365 18 : gfc_add_expr_to_block (&block, tmp);
10366 : }
10367 : }
10368 16963 : else if (!cm->attr.artificial)
10369 : {
10370 : /* Scalar component (excluding deferred parameters). */
10371 16842 : gfc_init_se (&se, NULL);
10372 16842 : gfc_init_se (&lse, NULL);
10373 :
10374 16842 : gfc_conv_expr (&se, expr);
10375 16842 : if (cm->ts.type == BT_CHARACTER)
10376 1057 : lse.string_length = cm->ts.u.cl->backend_decl;
10377 16842 : lse.expr = dest;
10378 16842 : tmp = gfc_trans_scalar_assign (&lse, &se, cm->ts, false, false);
10379 16842 : gfc_add_expr_to_block (&block, tmp);
10380 : }
10381 29419 : return gfc_finish_block (&block);
10382 : }
10383 :
10384 : /* Assign a derived type constructor to a variable. */
10385 :
10386 : tree
10387 20558 : gfc_trans_structure_assign (tree dest, gfc_expr * expr, bool init, bool coarray)
10388 : {
10389 20558 : gfc_constructor *c;
10390 20558 : gfc_component *cm;
10391 20558 : stmtblock_t block;
10392 20558 : tree field;
10393 20558 : tree tmp;
10394 20558 : gfc_se se;
10395 :
10396 20558 : gfc_start_block (&block);
10397 :
10398 20558 : if (expr->ts.u.derived->from_intmod == INTMOD_ISO_C_BINDING
10399 179 : && (expr->ts.u.derived->intmod_sym_id == ISOCBINDING_PTR
10400 13 : || expr->ts.u.derived->intmod_sym_id == ISOCBINDING_FUNPTR))
10401 : {
10402 179 : gfc_se lse;
10403 :
10404 179 : gfc_init_se (&se, NULL);
10405 179 : gfc_init_se (&lse, NULL);
10406 179 : gfc_conv_expr (&se, gfc_constructor_first (expr->value.constructor)->expr);
10407 179 : lse.expr = dest;
10408 179 : gfc_add_modify (&block, lse.expr,
10409 179 : fold_convert (TREE_TYPE (lse.expr), se.expr));
10410 :
10411 179 : return gfc_finish_block (&block);
10412 : }
10413 :
10414 : /* Make sure that the derived type has been completely built. */
10415 20379 : if (!expr->ts.u.derived->backend_decl
10416 20379 : || !TYPE_FIELDS (expr->ts.u.derived->backend_decl))
10417 : {
10418 224 : tmp = gfc_typenode_for_spec (&expr->ts);
10419 224 : gcc_assert (tmp);
10420 : }
10421 :
10422 20379 : cm = expr->ts.u.derived->components;
10423 :
10424 :
10425 20379 : if (coarray)
10426 225 : gfc_init_se (&se, NULL);
10427 :
10428 20379 : for (c = gfc_constructor_first (expr->value.constructor);
10429 52948 : c; c = gfc_constructor_next (c), cm = cm->next)
10430 : {
10431 : /* Skip absent members in default initializers. */
10432 32569 : if (!c->expr && !cm->attr.allocatable)
10433 3150 : continue;
10434 :
10435 : /* Register the component with the caf-lib before it is initialized.
10436 : Register only allocatable components, that are not coarray'ed
10437 : components (%comp[*]). Only register when the constructor is the
10438 : null-expression. */
10439 29419 : if (coarray && !cm->attr.codimension
10440 515 : && (cm->attr.allocatable || cm->attr.pointer)
10441 179 : && (!c->expr || c->expr->expr_type == EXPR_NULL))
10442 : {
10443 177 : tree token, desc, size;
10444 354 : bool is_array = cm->ts.type == BT_CLASS
10445 177 : ? CLASS_DATA (cm)->attr.dimension : cm->attr.dimension;
10446 :
10447 177 : field = cm->backend_decl;
10448 177 : field = fold_build3_loc (input_location, COMPONENT_REF,
10449 177 : TREE_TYPE (field), dest, field, NULL_TREE);
10450 177 : if (cm->ts.type == BT_CLASS)
10451 0 : field = gfc_class_data_get (field);
10452 :
10453 177 : token
10454 : = is_array
10455 177 : ? gfc_conv_descriptor_token (field)
10456 52 : : fold_build3_loc (input_location, COMPONENT_REF,
10457 52 : TREE_TYPE (gfc_comp_caf_token (cm)), dest,
10458 52 : gfc_comp_caf_token (cm), NULL_TREE);
10459 :
10460 177 : if (is_array)
10461 : {
10462 : /* The _caf_register routine looks at the rank of the array
10463 : descriptor to decide whether the data registered is an array
10464 : or not. */
10465 125 : int rank = cm->ts.type == BT_CLASS ? CLASS_DATA (cm)->as->rank
10466 125 : : cm->as->rank;
10467 : /* When the rank is not known just set a positive rank, which
10468 : suffices to recognize the data as array. */
10469 125 : if (rank < 0)
10470 0 : rank = 1;
10471 125 : size = build_zero_cst (size_type_node);
10472 125 : desc = field;
10473 125 : gfc_add_modify (&block, gfc_conv_descriptor_rank (desc),
10474 : gfc_rank_cst[rank]);
10475 : }
10476 : else
10477 : {
10478 52 : desc = gfc_conv_scalar_to_descriptor (&se, field,
10479 52 : cm->ts.type == BT_CLASS
10480 52 : ? CLASS_DATA (cm)->attr
10481 : : cm->attr);
10482 52 : size = TYPE_SIZE_UNIT (TREE_TYPE (field));
10483 : }
10484 177 : gfc_add_block_to_block (&block, &se.pre);
10485 177 : tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_register,
10486 : 7, size, build_int_cst (
10487 : integer_type_node,
10488 : GFC_CAF_COARRAY_ALLOC_REGISTER_ONLY),
10489 : gfc_build_addr_expr (pvoid_type_node,
10490 : token),
10491 : gfc_build_addr_expr (NULL_TREE, desc),
10492 : null_pointer_node, null_pointer_node,
10493 : integer_zero_node);
10494 177 : gfc_add_expr_to_block (&block, tmp);
10495 : }
10496 29419 : field = cm->backend_decl;
10497 29419 : gcc_assert(field);
10498 29419 : tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
10499 : dest, field, NULL_TREE);
10500 29419 : if (!c->expr)
10501 : {
10502 0 : gfc_expr *e = gfc_get_null_expr (NULL);
10503 0 : tmp = gfc_trans_subcomponent_assign (tmp, cm, e, init);
10504 0 : gfc_free_expr (e);
10505 : }
10506 : else
10507 29419 : tmp = gfc_trans_subcomponent_assign (tmp, cm, c->expr, init);
10508 29419 : gfc_add_expr_to_block (&block, tmp);
10509 : }
10510 20379 : return gfc_finish_block (&block);
10511 : }
10512 :
10513 : static void
10514 21 : gfc_conv_union_initializer (vec<constructor_elt, va_gc> *&v,
10515 : gfc_component *un, gfc_expr *init)
10516 : {
10517 21 : gfc_constructor *ctor;
10518 :
10519 21 : if (un->ts.type != BT_UNION || un == NULL || init == NULL)
10520 : return;
10521 :
10522 21 : ctor = gfc_constructor_first (init->value.constructor);
10523 :
10524 21 : if (ctor == NULL || ctor->expr == NULL)
10525 : return;
10526 :
10527 21 : gcc_assert (init->expr_type == EXPR_STRUCTURE);
10528 :
10529 : /* If we have an 'initialize all' constructor, do it first. */
10530 21 : if (ctor->expr->expr_type == EXPR_NULL)
10531 : {
10532 9 : tree union_type = TREE_TYPE (un->backend_decl);
10533 9 : tree val = build_constructor (union_type, NULL);
10534 9 : CONSTRUCTOR_APPEND_ELT (v, un->backend_decl, val);
10535 9 : ctor = gfc_constructor_next (ctor);
10536 : }
10537 :
10538 : /* Add the map initializer on top. */
10539 21 : if (ctor != NULL && ctor->expr != NULL)
10540 : {
10541 12 : gcc_assert (ctor->expr->expr_type == EXPR_STRUCTURE);
10542 12 : tree val = gfc_conv_initializer (ctor->expr, &un->ts,
10543 12 : TREE_TYPE (un->backend_decl),
10544 12 : un->attr.dimension, un->attr.pointer,
10545 12 : un->attr.proc_pointer);
10546 12 : CONSTRUCTOR_APPEND_ELT (v, un->backend_decl, val);
10547 : }
10548 : }
10549 :
10550 : /* Build an expression for a constructor. If init is nonzero then
10551 : this is part of a static variable initializer. */
10552 :
10553 : void
10554 38316 : gfc_conv_structure (gfc_se * se, gfc_expr * expr, int init)
10555 : {
10556 38316 : gfc_constructor *c;
10557 38316 : gfc_component *cm;
10558 38316 : tree val;
10559 38316 : tree type;
10560 38316 : tree tmp;
10561 38316 : vec<constructor_elt, va_gc> *v = NULL;
10562 :
10563 38316 : gcc_assert (se->ss == NULL);
10564 38316 : gcc_assert (expr->expr_type == EXPR_STRUCTURE);
10565 38316 : type = gfc_typenode_for_spec (&expr->ts);
10566 :
10567 38316 : if (!init)
10568 : {
10569 16138 : if (IS_PDT (expr) && expr->must_finalize)
10570 276 : final_block = &se->finalblock;
10571 :
10572 : /* Create a temporary variable and fill it in. */
10573 16138 : se->expr = gfc_create_var (type, expr->ts.u.derived->name);
10574 : /* The symtree in expr is NULL, if the code to generate is for
10575 : initializing the static members only. */
10576 32276 : tmp = gfc_trans_structure_assign (se->expr, expr, expr->symtree != NULL,
10577 16138 : se->want_coarray);
10578 16138 : gfc_add_expr_to_block (&se->pre, tmp);
10579 16138 : final_block = NULL;
10580 16138 : return;
10581 : }
10582 :
10583 22178 : cm = expr->ts.u.derived->components;
10584 :
10585 22178 : for (c = gfc_constructor_first (expr->value.constructor);
10586 113294 : c && cm; c = gfc_constructor_next (c), cm = cm->next)
10587 : {
10588 : /* Skip absent members in default initializers and allocatable
10589 : components. Although the latter have a default initializer
10590 : of EXPR_NULL,... by default, the static nullify is not needed
10591 : since this is done every time we come into scope. */
10592 99789 : if (!c->expr
10593 88698 : || (cm->attr.allocatable && cm->attr.flavor != FL_PROCEDURE)
10594 173649 : || (IS_PDT (cm) && has_parameterized_comps (cm->ts.u.derived)))
10595 8673 : continue;
10596 :
10597 82443 : if (cm->initializer && cm->initializer->expr_type != EXPR_NULL
10598 47923 : && strcmp (cm->name, "_extends") == 0
10599 1308 : && cm->initializer->symtree)
10600 : {
10601 1308 : tree vtab;
10602 1308 : gfc_symbol *vtabs;
10603 1308 : vtabs = cm->initializer->symtree->n.sym;
10604 1308 : vtab = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtabs));
10605 1308 : vtab = unshare_expr_without_location (vtab);
10606 1308 : CONSTRUCTOR_APPEND_ELT (v, cm->backend_decl, vtab);
10607 1308 : }
10608 81135 : else if (cm->ts.u.derived && strcmp (cm->name, "_size") == 0)
10609 : {
10610 8746 : val = TYPE_SIZE_UNIT (gfc_get_derived_type (cm->ts.u.derived));
10611 8746 : CONSTRUCTOR_APPEND_ELT (v, cm->backend_decl,
10612 : fold_convert (TREE_TYPE (cm->backend_decl),
10613 : val));
10614 8746 : }
10615 72389 : else if (cm->ts.type == BT_INTEGER && strcmp (cm->name, "_len") == 0)
10616 413 : CONSTRUCTOR_APPEND_ELT (v, cm->backend_decl,
10617 : fold_convert (TREE_TYPE (cm->backend_decl),
10618 413 : integer_zero_node));
10619 71976 : else if (cm->ts.type == BT_UNION)
10620 21 : gfc_conv_union_initializer (v, cm, c->expr);
10621 : else
10622 : {
10623 71955 : val = gfc_conv_initializer (c->expr, &cm->ts,
10624 71955 : TREE_TYPE (cm->backend_decl),
10625 71955 : cm->attr.dimension, cm->attr.pointer,
10626 71955 : cm->attr.proc_pointer);
10627 71955 : val = unshare_expr_without_location (val);
10628 :
10629 : /* Append it to the constructor list. */
10630 163071 : CONSTRUCTOR_APPEND_ELT (v, cm->backend_decl, val);
10631 : }
10632 : }
10633 :
10634 22178 : se->expr = build_constructor (type, v);
10635 22178 : if (init)
10636 22178 : TREE_CONSTANT (se->expr) = 1;
10637 : }
10638 :
10639 :
10640 : /* Translate a substring expression. */
10641 :
10642 : static void
10643 258 : gfc_conv_substring_expr (gfc_se * se, gfc_expr * expr)
10644 : {
10645 258 : gfc_ref *ref;
10646 :
10647 258 : ref = expr->ref;
10648 :
10649 258 : gcc_assert (ref == NULL || ref->type == REF_SUBSTRING);
10650 :
10651 516 : se->expr = gfc_build_wide_string_const (expr->ts.kind,
10652 258 : expr->value.character.length,
10653 258 : expr->value.character.string);
10654 :
10655 258 : se->string_length = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (se->expr)));
10656 258 : TYPE_STRING_FLAG (TREE_TYPE (se->expr)) = 1;
10657 :
10658 258 : if (ref)
10659 258 : gfc_conv_substring (se, ref, expr->ts.kind, NULL, &expr->where);
10660 258 : }
10661 :
10662 :
10663 : /* Entry point for expression translation. Evaluates a scalar quantity.
10664 : EXPR is the expression to be translated, and SE is the state structure if
10665 : called from within the scalarized. */
10666 :
10667 : void
10668 3658083 : gfc_conv_expr (gfc_se * se, gfc_expr * expr)
10669 : {
10670 3658083 : gfc_ss *ss;
10671 :
10672 3658083 : ss = se->ss;
10673 3658083 : if (ss && ss->info->expr == expr
10674 239218 : && (ss->info->type == GFC_SS_SCALAR
10675 : || ss->info->type == GFC_SS_REFERENCE))
10676 : {
10677 40643 : gfc_ss_info *ss_info;
10678 :
10679 40643 : ss_info = ss->info;
10680 : /* Substitute a scalar expression evaluated outside the scalarization
10681 : loop. */
10682 40643 : se->expr = ss_info->data.scalar.value;
10683 40643 : if (gfc_scalar_elemental_arg_saved_as_reference (ss_info))
10684 844 : se->expr = build_fold_indirect_ref_loc (input_location, se->expr);
10685 :
10686 40643 : se->string_length = ss_info->string_length;
10687 40643 : gfc_advance_se_ss_chain (se);
10688 40643 : return;
10689 : }
10690 :
10691 : /* We need to convert the expressions for the iso_c_binding derived types.
10692 : C_NULL_PTR and C_NULL_FUNPTR will be made EXPR_NULL, which evaluates to
10693 : null_pointer_node. C_PTR and C_FUNPTR are converted to match the
10694 : typespec for the C_PTR and C_FUNPTR symbols, which has already been
10695 : updated to be an integer with a kind equal to the size of a (void *). */
10696 3617440 : if (expr->ts.type == BT_DERIVED && expr->ts.u.derived->ts.f90_type == BT_VOID
10697 14823 : && expr->ts.u.derived->attr.is_bind_c)
10698 : {
10699 13974 : if (expr->expr_type == EXPR_VARIABLE
10700 9526 : && (expr->symtree->n.sym->intmod_sym_id == ISOCBINDING_NULL_PTR
10701 9526 : || expr->symtree->n.sym->intmod_sym_id
10702 : == ISOCBINDING_NULL_FUNPTR))
10703 : {
10704 : /* Set expr_type to EXPR_NULL, which will result in
10705 : null_pointer_node being used below. */
10706 0 : expr->expr_type = EXPR_NULL;
10707 : }
10708 : else
10709 : {
10710 : /* Update the type/kind of the expression to be what the new
10711 : type/kind are for the updated symbols of C_PTR/C_FUNPTR. */
10712 13974 : expr->ts.type = BT_INTEGER;
10713 13974 : expr->ts.f90_type = BT_VOID;
10714 13974 : expr->ts.kind = gfc_index_integer_kind;
10715 : }
10716 : }
10717 :
10718 3617440 : gfc_fix_class_refs (expr);
10719 :
10720 3617440 : switch (expr->expr_type)
10721 : {
10722 506740 : case EXPR_OP:
10723 506740 : gfc_conv_expr_op (se, expr);
10724 506740 : break;
10725 :
10726 159 : case EXPR_CONDITIONAL:
10727 159 : gfc_conv_conditional_expr (se, expr);
10728 159 : break;
10729 :
10730 306395 : case EXPR_FUNCTION:
10731 306395 : gfc_conv_function_expr (se, expr);
10732 306395 : break;
10733 :
10734 1139978 : case EXPR_CONSTANT:
10735 1139978 : gfc_conv_constant (se, expr);
10736 1139978 : break;
10737 :
10738 1607638 : case EXPR_VARIABLE:
10739 1607638 : gfc_conv_variable (se, expr);
10740 1607638 : break;
10741 :
10742 4211 : case EXPR_NULL:
10743 4211 : se->expr = null_pointer_node;
10744 4211 : break;
10745 :
10746 258 : case EXPR_SUBSTRING:
10747 258 : gfc_conv_substring_expr (se, expr);
10748 258 : break;
10749 :
10750 16138 : case EXPR_STRUCTURE:
10751 16138 : gfc_conv_structure (se, expr, 0);
10752 : /* F2008 4.5.6.3 para 5: If an executable construct references a
10753 : structure constructor or array constructor, the entity created by
10754 : the constructor is finalized after execution of the innermost
10755 : executable construct containing the reference. This, in fact,
10756 : was later deleted by the Combined Technical Corrigenda 1 TO 4 for
10757 : fortran 2008 (f08/0011). */
10758 16138 : if ((gfc_option.allow_std & (GFC_STD_F2008 | GFC_STD_F2003))
10759 16138 : && !(gfc_option.allow_std & GFC_STD_GNU)
10760 139 : && expr->must_finalize
10761 16150 : && gfc_may_be_finalized (expr->ts))
10762 : {
10763 12 : locus loc;
10764 12 : gfc_locus_from_location (&loc, input_location);
10765 12 : gfc_warning (0, "The structure constructor at %L has been"
10766 : " finalized. This feature was removed by f08/0011."
10767 : " Use -std=f2018 or -std=gnu to eliminate the"
10768 : " finalization.", &loc);
10769 12 : symbol_attribute attr;
10770 12 : attr.allocatable = attr.pointer = 0;
10771 12 : gfc_finalize_tree_expr (se, expr->ts.u.derived, attr, 0);
10772 12 : gfc_add_block_to_block (&se->post, &se->finalblock);
10773 : }
10774 : break;
10775 :
10776 35923 : case EXPR_ARRAY:
10777 35923 : gfc_conv_array_constructor_expr (se, expr);
10778 35923 : gfc_add_block_to_block (&se->post, &se->finalblock);
10779 35923 : break;
10780 :
10781 0 : default:
10782 0 : gcc_unreachable ();
10783 3658083 : break;
10784 : }
10785 : }
10786 :
10787 : /* Like gfc_conv_expr_val, but the value is also suitable for use in the lhs
10788 : of an assignment. */
10789 : void
10790 374441 : gfc_conv_expr_lhs (gfc_se * se, gfc_expr * expr)
10791 : {
10792 374441 : gfc_conv_expr (se, expr);
10793 : /* All numeric lvalues should have empty post chains. If not we need to
10794 : figure out a way of rewriting an lvalue so that it has no post chain. */
10795 374441 : gcc_assert (expr->ts.type == BT_CHARACTER || !se->post.head);
10796 374441 : }
10797 :
10798 : /* Like gfc_conv_expr, but the POST block is guaranteed to be empty for
10799 : numeric expressions. Used for scalar values where inserting cleanup code
10800 : is inconvenient. */
10801 : void
10802 1036819 : gfc_conv_expr_val (gfc_se * se, gfc_expr * expr)
10803 : {
10804 1036819 : tree val;
10805 :
10806 1036819 : gcc_assert (expr->ts.type != BT_CHARACTER);
10807 1036819 : gfc_conv_expr (se, expr);
10808 1036819 : if (se->post.head)
10809 : {
10810 2551 : val = gfc_create_var (TREE_TYPE (se->expr), NULL);
10811 2551 : gfc_add_modify (&se->pre, val, se->expr);
10812 2551 : se->expr = val;
10813 2551 : gfc_add_block_to_block (&se->pre, &se->post);
10814 : }
10815 1036819 : }
10816 :
10817 : /* Helper to translate an expression and convert it to a particular type. */
10818 : void
10819 293323 : gfc_conv_expr_type (gfc_se * se, gfc_expr * expr, tree type)
10820 : {
10821 293323 : gfc_conv_expr_val (se, expr);
10822 293323 : se->expr = convert (type, se->expr);
10823 293323 : }
10824 :
10825 :
10826 : /* Converts an expression so that it can be passed by reference. Scalar
10827 : values only. */
10828 :
10829 : void
10830 228358 : gfc_conv_expr_reference (gfc_se * se, gfc_expr * expr)
10831 : {
10832 228358 : gfc_ss *ss;
10833 228358 : tree var;
10834 :
10835 228358 : ss = se->ss;
10836 228358 : if (ss && ss->info->expr == expr
10837 8023 : && ss->info->type == GFC_SS_REFERENCE)
10838 : {
10839 : /* Returns a reference to the scalar evaluated outside the loop
10840 : for this case. */
10841 907 : gfc_conv_expr (se, expr);
10842 :
10843 907 : if (expr->ts.type == BT_CHARACTER
10844 114 : && expr->expr_type != EXPR_FUNCTION)
10845 102 : gfc_conv_string_parameter (se);
10846 : else
10847 805 : se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
10848 :
10849 907 : return;
10850 : }
10851 :
10852 227451 : if (expr->ts.type == BT_CHARACTER)
10853 : {
10854 49855 : gfc_conv_expr (se, expr);
10855 49855 : gfc_conv_string_parameter (se);
10856 49855 : return;
10857 : }
10858 :
10859 177596 : if (expr->expr_type == EXPR_VARIABLE)
10860 : {
10861 70756 : se->want_pointer = 1;
10862 70756 : gfc_conv_expr (se, expr);
10863 70756 : if (se->post.head)
10864 : {
10865 0 : var = gfc_create_var (TREE_TYPE (se->expr), NULL);
10866 0 : gfc_add_modify (&se->pre, var, se->expr);
10867 0 : gfc_add_block_to_block (&se->pre, &se->post);
10868 0 : se->expr = var;
10869 : }
10870 70756 : return;
10871 : }
10872 :
10873 106840 : if (expr->expr_type == EXPR_CONDITIONAL)
10874 : {
10875 18 : se->want_pointer = 1;
10876 18 : gfc_conv_expr (se, expr);
10877 18 : return;
10878 : }
10879 :
10880 106822 : if (expr->expr_type == EXPR_FUNCTION
10881 13782 : && ((expr->value.function.esym
10882 2101 : && expr->value.function.esym->result
10883 2100 : && expr->value.function.esym->result->attr.pointer
10884 83 : && !expr->value.function.esym->result->attr.dimension)
10885 13705 : || (!expr->value.function.esym && !expr->ref
10886 11575 : && expr->symtree->n.sym->attr.pointer
10887 0 : && !expr->symtree->n.sym->attr.dimension)))
10888 : {
10889 77 : se->want_pointer = 1;
10890 77 : gfc_conv_expr (se, expr);
10891 77 : var = gfc_create_var (TREE_TYPE (se->expr), NULL);
10892 77 : gfc_add_modify (&se->pre, var, se->expr);
10893 77 : se->expr = var;
10894 77 : return;
10895 : }
10896 :
10897 106745 : gfc_conv_expr (se, expr);
10898 :
10899 : /* Create a temporary var to hold the value. */
10900 106745 : if (TREE_CONSTANT (se->expr))
10901 : {
10902 : tree tmp = se->expr;
10903 84404 : STRIP_TYPE_NOPS (tmp);
10904 84404 : var = build_decl (input_location,
10905 84404 : CONST_DECL, NULL, TREE_TYPE (tmp));
10906 84404 : DECL_INITIAL (var) = tmp;
10907 84404 : TREE_STATIC (var) = 1;
10908 84404 : pushdecl (var);
10909 : }
10910 : else
10911 : {
10912 22341 : var = gfc_create_var (TREE_TYPE (se->expr), NULL);
10913 22341 : gfc_add_modify (&se->pre, var, se->expr);
10914 : }
10915 :
10916 106745 : if (!expr->must_finalize)
10917 106649 : gfc_add_block_to_block (&se->pre, &se->post);
10918 :
10919 : /* Take the address of that value. */
10920 106745 : se->expr = gfc_build_addr_expr (NULL_TREE, var);
10921 : }
10922 :
10923 :
10924 : /* Get the _len component for an unlimited polymorphic expression. */
10925 :
10926 : static tree
10927 1800 : trans_get_upoly_len (stmtblock_t *block, gfc_expr *expr)
10928 : {
10929 1800 : gfc_se se;
10930 1800 : gfc_ref *ref = expr->ref;
10931 :
10932 1800 : gfc_init_se (&se, NULL);
10933 3714 : while (ref && ref->next)
10934 : ref = ref->next;
10935 1800 : gfc_add_len_component (expr);
10936 1800 : gfc_conv_expr (&se, expr);
10937 1800 : gfc_add_block_to_block (block, &se.pre);
10938 1800 : gcc_assert (se.post.head == NULL_TREE);
10939 1800 : if (ref)
10940 : {
10941 262 : gfc_free_ref_list (ref->next);
10942 262 : ref->next = NULL;
10943 : }
10944 : else
10945 : {
10946 1538 : gfc_free_ref_list (expr->ref);
10947 1538 : expr->ref = NULL;
10948 : }
10949 1800 : return se.expr;
10950 : }
10951 :
10952 :
10953 : /* Assign _vptr and _len components as appropriate. BLOCK should be a
10954 : statement-list outside of the scalarizer-loop. When code is generated, that
10955 : depends on the scalarized expression, it is added to RSE.PRE.
10956 : Returns le's _vptr tree and when set the len expressions in to_lenp and
10957 : from_lenp to form a le%_vptr%_copy (re, le, [from_lenp, to_lenp])
10958 : expression. */
10959 :
10960 : static tree
10961 4535 : trans_class_vptr_len_assignment (stmtblock_t *block, gfc_expr * le,
10962 : gfc_expr * re, gfc_se *rse,
10963 : tree * to_lenp, tree * from_lenp,
10964 : tree * from_vptrp)
10965 : {
10966 4535 : gfc_se se;
10967 4535 : gfc_expr * vptr_expr;
10968 4535 : tree tmp, to_len = NULL_TREE, from_len = NULL_TREE, lhs_vptr;
10969 4535 : bool set_vptr = false, temp_rhs = false;
10970 4535 : stmtblock_t *pre = block;
10971 4535 : tree class_expr = NULL_TREE;
10972 4535 : tree from_vptr = NULL_TREE;
10973 :
10974 : /* Create a temporary for complicated expressions. */
10975 4535 : if (re->expr_type != EXPR_VARIABLE && re->expr_type != EXPR_NULL
10976 1263 : && rse->expr != NULL_TREE)
10977 : {
10978 1263 : if (!DECL_P (rse->expr))
10979 : {
10980 392 : if (re->ts.type == BT_CLASS && !GFC_CLASS_TYPE_P (TREE_TYPE (rse->expr)))
10981 37 : class_expr = gfc_get_class_from_expr (rse->expr);
10982 :
10983 392 : if (rse->loop)
10984 159 : pre = &rse->loop->pre;
10985 : else
10986 233 : pre = &rse->pre;
10987 :
10988 392 : if (class_expr != NULL_TREE && UNLIMITED_POLY (re))
10989 37 : tmp = gfc_evaluate_now (TREE_OPERAND (rse->expr, 0), &rse->pre);
10990 : else
10991 355 : tmp = gfc_evaluate_now (rse->expr, &rse->pre);
10992 :
10993 392 : rse->expr = tmp;
10994 : }
10995 : else
10996 871 : pre = &rse->pre;
10997 :
10998 : temp_rhs = true;
10999 : }
11000 :
11001 : /* Get the _vptr for the left-hand side expression. */
11002 4535 : gfc_init_se (&se, NULL);
11003 4535 : vptr_expr = gfc_find_and_cut_at_last_class_ref (le);
11004 4535 : if (vptr_expr != NULL && gfc_expr_attr (vptr_expr).class_ok)
11005 : {
11006 : /* Care about _len for unlimited polymorphic entities. */
11007 4535 : if (UNLIMITED_POLY (vptr_expr)
11008 3503 : || (vptr_expr->ts.type == BT_DERIVED
11009 2479 : && vptr_expr->ts.u.derived->attr.unlimited_polymorphic))
11010 1516 : to_len = trans_get_upoly_len (block, vptr_expr);
11011 4535 : gfc_add_vptr_component (vptr_expr);
11012 4535 : set_vptr = true;
11013 : }
11014 : else
11015 0 : vptr_expr = gfc_lval_expr_from_sym (gfc_find_vtab (&le->ts));
11016 4535 : se.want_pointer = 1;
11017 4535 : gfc_conv_expr (&se, vptr_expr);
11018 4535 : gfc_free_expr (vptr_expr);
11019 4535 : gfc_add_block_to_block (block, &se.pre);
11020 4535 : gcc_assert (se.post.head == NULL_TREE);
11021 4535 : lhs_vptr = se.expr;
11022 4535 : STRIP_NOPS (lhs_vptr);
11023 :
11024 : /* Set the _vptr only when the left-hand side of the assignment is a
11025 : class-object. */
11026 4535 : if (set_vptr)
11027 : {
11028 : /* Get the vptr from the rhs expression only, when it is variable.
11029 : Functions are expected to be assigned to a temporary beforehand. */
11030 3143 : vptr_expr = (re->expr_type == EXPR_VARIABLE && re->ts.type == BT_CLASS)
11031 5316 : ? gfc_find_and_cut_at_last_class_ref (re)
11032 : : NULL;
11033 781 : if (vptr_expr != NULL && vptr_expr->ts.type == BT_CLASS)
11034 : {
11035 781 : if (to_len != NULL_TREE)
11036 : {
11037 : /* Get the _len information from the rhs. */
11038 299 : if (UNLIMITED_POLY (vptr_expr)
11039 : || (vptr_expr->ts.type == BT_DERIVED
11040 : && vptr_expr->ts.u.derived->attr.unlimited_polymorphic))
11041 272 : from_len = trans_get_upoly_len (block, vptr_expr);
11042 : }
11043 781 : gfc_add_vptr_component (vptr_expr);
11044 : }
11045 : else
11046 : {
11047 3754 : if (re->expr_type == EXPR_VARIABLE
11048 2362 : && DECL_P (re->symtree->n.sym->backend_decl)
11049 2362 : && DECL_LANG_SPECIFIC (re->symtree->n.sym->backend_decl)
11050 834 : && GFC_DECL_SAVED_DESCRIPTOR (re->symtree->n.sym->backend_decl)
11051 3821 : && GFC_CLASS_TYPE_P (TREE_TYPE (GFC_DECL_SAVED_DESCRIPTOR (
11052 : re->symtree->n.sym->backend_decl))))
11053 : {
11054 43 : vptr_expr = NULL;
11055 43 : se.expr = gfc_class_vptr_get (GFC_DECL_SAVED_DESCRIPTOR (
11056 : re->symtree->n.sym->backend_decl));
11057 43 : if (to_len && UNLIMITED_POLY (re))
11058 0 : from_len = gfc_class_len_get (GFC_DECL_SAVED_DESCRIPTOR (
11059 : re->symtree->n.sym->backend_decl));
11060 : }
11061 3711 : else if (temp_rhs && re->ts.type == BT_CLASS)
11062 : {
11063 215 : vptr_expr = NULL;
11064 215 : if (class_expr)
11065 : tmp = class_expr;
11066 178 : else if (!GFC_CLASS_TYPE_P (TREE_TYPE (rse->expr)))
11067 0 : tmp = gfc_get_class_from_expr (rse->expr);
11068 : else
11069 : tmp = rse->expr;
11070 :
11071 215 : se.expr = gfc_class_vptr_get (tmp);
11072 215 : from_vptr = se.expr;
11073 215 : if (UNLIMITED_POLY (re))
11074 74 : from_len = gfc_class_len_get (tmp);
11075 :
11076 : }
11077 3496 : else if (re->expr_type != EXPR_NULL)
11078 : /* Only when rhs is non-NULL use its declared type for vptr
11079 : initialisation. */
11080 3367 : vptr_expr = gfc_lval_expr_from_sym (gfc_find_vtab (&re->ts));
11081 : else
11082 : /* When the rhs is NULL use the vtab of lhs' declared type. */
11083 129 : vptr_expr = gfc_lval_expr_from_sym (gfc_find_vtab (&le->ts));
11084 : }
11085 :
11086 4351 : if (vptr_expr)
11087 : {
11088 4277 : gfc_init_se (&se, NULL);
11089 4277 : se.want_pointer = 1;
11090 4277 : gfc_conv_expr (&se, vptr_expr);
11091 4277 : gfc_free_expr (vptr_expr);
11092 4277 : gfc_add_block_to_block (block, &se.pre);
11093 4277 : gcc_assert (se.post.head == NULL_TREE);
11094 4277 : from_vptr = se.expr;
11095 : }
11096 4535 : gfc_add_modify (pre, lhs_vptr, fold_convert (TREE_TYPE (lhs_vptr),
11097 : se.expr));
11098 :
11099 4535 : if (to_len != NULL_TREE)
11100 : {
11101 : /* The _len component needs to be set. Figure how to get the
11102 : value of the right-hand side. */
11103 1516 : if (from_len == NULL_TREE)
11104 : {
11105 1170 : if (rse->string_length != NULL_TREE)
11106 : from_len = rse->string_length;
11107 712 : else if (re->ts.type == BT_CHARACTER && re->ts.u.cl->length)
11108 : {
11109 0 : gfc_init_se (&se, NULL);
11110 0 : gfc_conv_expr (&se, re->ts.u.cl->length);
11111 0 : gfc_add_block_to_block (block, &se.pre);
11112 0 : gcc_assert (se.post.head == NULL_TREE);
11113 0 : from_len = gfc_evaluate_now (se.expr, block);
11114 : }
11115 : else
11116 712 : from_len = build_zero_cst (gfc_charlen_type_node);
11117 : }
11118 1516 : gfc_add_modify (pre, to_len, fold_convert (TREE_TYPE (to_len),
11119 : from_len));
11120 : }
11121 : }
11122 :
11123 : /* Return the _len and _vptr trees only, when requested. */
11124 4535 : if (to_lenp)
11125 3319 : *to_lenp = to_len;
11126 4535 : if (from_lenp)
11127 3319 : *from_lenp = from_len;
11128 4535 : if (from_vptrp)
11129 3319 : *from_vptrp = from_vptr;
11130 4535 : return lhs_vptr;
11131 : }
11132 :
11133 :
11134 : /* Assign tokens for pointer components. */
11135 :
11136 : static void
11137 12 : trans_caf_token_assign (gfc_se *lse, gfc_se *rse, gfc_expr *expr1,
11138 : gfc_expr *expr2)
11139 : {
11140 12 : symbol_attribute lhs_attr, rhs_attr;
11141 12 : tree tmp, lhs_tok, rhs_tok;
11142 : /* Flag to indicated component refs on the rhs. */
11143 12 : bool rhs_cr;
11144 :
11145 12 : lhs_attr = gfc_caf_attr (expr1);
11146 12 : if (expr2->expr_type != EXPR_NULL)
11147 : {
11148 8 : rhs_attr = gfc_caf_attr (expr2, false, &rhs_cr);
11149 8 : if (lhs_attr.codimension && rhs_attr.codimension)
11150 : {
11151 4 : lhs_tok = gfc_get_ultimate_alloc_ptr_comps_caf_token (lse, expr1);
11152 4 : lhs_tok = build_fold_indirect_ref (lhs_tok);
11153 :
11154 4 : if (rhs_cr)
11155 0 : rhs_tok = gfc_get_ultimate_alloc_ptr_comps_caf_token (rse, expr2);
11156 : else
11157 : {
11158 4 : tree caf_decl;
11159 4 : caf_decl = gfc_get_tree_for_caf_expr (expr2);
11160 4 : gfc_get_caf_token_offset (rse, &rhs_tok, NULL, caf_decl,
11161 : NULL_TREE, NULL);
11162 : }
11163 4 : tmp = build2_loc (input_location, MODIFY_EXPR, void_type_node,
11164 : lhs_tok,
11165 4 : fold_convert (TREE_TYPE (lhs_tok), rhs_tok));
11166 4 : gfc_prepend_expr_to_block (&lse->post, tmp);
11167 : }
11168 : }
11169 4 : else if (lhs_attr.codimension)
11170 : {
11171 4 : lhs_tok = gfc_get_ultimate_alloc_ptr_comps_caf_token (lse, expr1);
11172 4 : if (!lhs_tok)
11173 : {
11174 2 : lhs_tok = gfc_get_tree_for_caf_expr (expr1);
11175 2 : lhs_tok = GFC_TYPE_ARRAY_CAF_TOKEN (TREE_TYPE (lhs_tok));
11176 : }
11177 : else
11178 2 : lhs_tok = build_fold_indirect_ref (lhs_tok);
11179 4 : tmp = build2_loc (input_location, MODIFY_EXPR, void_type_node,
11180 : lhs_tok, null_pointer_node);
11181 4 : gfc_prepend_expr_to_block (&lse->post, tmp);
11182 : }
11183 12 : }
11184 :
11185 :
11186 : /* Do everything that is needed for a CLASS function expr2. */
11187 :
11188 : static tree
11189 18 : trans_class_pointer_fcn (stmtblock_t *block, gfc_se *lse, gfc_se *rse,
11190 : gfc_expr *expr1, gfc_expr *expr2)
11191 : {
11192 18 : tree expr1_vptr = NULL_TREE;
11193 18 : tree tmp;
11194 :
11195 18 : gfc_conv_function_expr (rse, expr2);
11196 18 : rse->expr = gfc_evaluate_now (rse->expr, &rse->pre);
11197 :
11198 18 : if (expr1->ts.type != BT_CLASS)
11199 12 : rse->expr = gfc_class_data_get (rse->expr);
11200 : else
11201 : {
11202 6 : expr1_vptr = trans_class_vptr_len_assignment (block, expr1,
11203 : expr2, rse,
11204 : NULL, NULL, NULL);
11205 6 : gfc_add_block_to_block (block, &rse->pre);
11206 6 : tmp = gfc_create_var (TREE_TYPE (rse->expr), "ptrtemp");
11207 6 : gfc_add_modify (&lse->pre, tmp, rse->expr);
11208 :
11209 12 : gfc_add_modify (&lse->pre, expr1_vptr,
11210 6 : fold_convert (TREE_TYPE (expr1_vptr),
11211 : gfc_class_vptr_get (tmp)));
11212 6 : rse->expr = gfc_class_data_get (tmp);
11213 : }
11214 :
11215 18 : return expr1_vptr;
11216 : }
11217 :
11218 :
11219 : tree
11220 10151 : gfc_trans_pointer_assign (gfc_code * code)
11221 : {
11222 10151 : return gfc_trans_pointer_assignment (code->expr1, code->expr2);
11223 : }
11224 :
11225 :
11226 : /* Generate code for a pointer assignment. */
11227 :
11228 : tree
11229 10206 : gfc_trans_pointer_assignment (gfc_expr * expr1, gfc_expr * expr2)
11230 : {
11231 10206 : gfc_se lse;
11232 10206 : gfc_se rse;
11233 10206 : stmtblock_t block;
11234 10206 : tree desc;
11235 10206 : tree tmp;
11236 10206 : tree expr1_vptr = NULL_TREE;
11237 10206 : bool scalar, non_proc_ptr_assign;
11238 10206 : gfc_ss *ss;
11239 :
11240 10206 : gfc_start_block (&block);
11241 :
11242 10206 : gfc_init_se (&lse, NULL);
11243 :
11244 : /* Usually testing whether this is not a proc pointer assignment. */
11245 10206 : non_proc_ptr_assign
11246 10206 : = !(gfc_expr_attr (expr1).proc_pointer
11247 1207 : && ((expr2->expr_type == EXPR_VARIABLE
11248 975 : && expr2->symtree->n.sym->attr.flavor == FL_PROCEDURE)
11249 282 : || expr2->expr_type == EXPR_NULL));
11250 :
11251 : /* Check whether the expression is a scalar or not; we cannot use
11252 : expr1->rank as it can be nonzero for proc pointers. */
11253 10206 : ss = gfc_walk_expr (expr1);
11254 10206 : scalar = ss == gfc_ss_terminator;
11255 10206 : if (!scalar)
11256 4384 : gfc_free_ss_chain (ss);
11257 :
11258 10206 : if (expr1->ts.type == BT_DERIVED && expr2->ts.type == BT_CLASS
11259 90 : && expr2->expr_type != EXPR_FUNCTION && non_proc_ptr_assign)
11260 : {
11261 66 : gfc_add_data_component (expr2);
11262 : /* The following is required as gfc_add_data_component doesn't
11263 : update ts.type if there is a trailing REF_ARRAY. */
11264 66 : expr2->ts.type = BT_DERIVED;
11265 : }
11266 :
11267 10206 : if (scalar)
11268 : {
11269 : /* Scalar pointers. */
11270 5822 : lse.want_pointer = 1;
11271 5822 : gfc_conv_expr (&lse, expr1);
11272 5822 : gfc_init_se (&rse, NULL);
11273 5822 : rse.want_pointer = 1;
11274 5822 : if (expr2->expr_type == EXPR_FUNCTION && expr2->ts.type == BT_CLASS)
11275 6 : trans_class_pointer_fcn (&block, &lse, &rse, expr1, expr2);
11276 : else
11277 5816 : gfc_conv_expr (&rse, expr2);
11278 :
11279 5822 : if (non_proc_ptr_assign && expr1->ts.type == BT_CLASS)
11280 : {
11281 769 : trans_class_vptr_len_assignment (&block, expr1, expr2, &rse, NULL,
11282 : NULL, NULL);
11283 769 : lse.expr = gfc_class_data_get (lse.expr);
11284 : }
11285 :
11286 5822 : if (expr1->symtree->n.sym->attr.proc_pointer
11287 863 : && expr1->symtree->n.sym->attr.dummy)
11288 49 : lse.expr = build_fold_indirect_ref_loc (input_location,
11289 : lse.expr);
11290 :
11291 5822 : if (expr2->symtree && expr2->symtree->n.sym->attr.proc_pointer
11292 47 : && expr2->symtree->n.sym->attr.dummy)
11293 20 : rse.expr = build_fold_indirect_ref_loc (input_location,
11294 : rse.expr);
11295 :
11296 5822 : gfc_add_block_to_block (&block, &lse.pre);
11297 5822 : gfc_add_block_to_block (&block, &rse.pre);
11298 :
11299 : /* Check character lengths if character expression. The test is only
11300 : really added if -fbounds-check is enabled. Exclude deferred
11301 : character length lefthand sides. */
11302 954 : if (expr1->ts.type == BT_CHARACTER && expr2->expr_type != EXPR_NULL
11303 780 : && !expr1->ts.deferred
11304 365 : && !expr1->symtree->n.sym->attr.proc_pointer
11305 6180 : && !gfc_is_proc_ptr_comp (expr1))
11306 : {
11307 339 : gcc_assert (expr2->ts.type == BT_CHARACTER);
11308 339 : gcc_assert (lse.string_length && rse.string_length);
11309 339 : gfc_trans_same_strlen_check ("pointer assignment", &expr1->where,
11310 : lse.string_length, rse.string_length,
11311 : &block);
11312 : }
11313 :
11314 : /* The assignment to an deferred character length sets the string
11315 : length to that of the rhs. */
11316 5822 : if (expr1->ts.deferred)
11317 : {
11318 530 : if (expr2->expr_type != EXPR_NULL && lse.string_length != NULL)
11319 413 : gfc_add_modify (&block, lse.string_length,
11320 413 : fold_convert (TREE_TYPE (lse.string_length),
11321 : rse.string_length));
11322 117 : else if (lse.string_length != NULL)
11323 115 : gfc_add_modify (&block, lse.string_length,
11324 115 : build_zero_cst (TREE_TYPE (lse.string_length)));
11325 : }
11326 :
11327 5822 : gfc_add_modify (&block, lse.expr,
11328 5822 : fold_convert (TREE_TYPE (lse.expr), rse.expr));
11329 :
11330 5822 : if (flag_coarray == GFC_FCOARRAY_LIB)
11331 : {
11332 342 : if (expr1->ref)
11333 : /* Also set the tokens for pointer components in derived typed
11334 : coarrays. */
11335 12 : trans_caf_token_assign (&lse, &rse, expr1, expr2);
11336 330 : else if (gfc_caf_attr (expr1).codimension)
11337 : {
11338 0 : tree lhs_caf_decl, rhs_caf_decl, lhs_tok, rhs_tok;
11339 :
11340 0 : lhs_caf_decl = gfc_get_tree_for_caf_expr (expr1);
11341 0 : rhs_caf_decl = gfc_get_tree_for_caf_expr (expr2);
11342 0 : gfc_get_caf_token_offset (&lse, &lhs_tok, nullptr, lhs_caf_decl,
11343 : NULL_TREE, expr1);
11344 0 : gfc_get_caf_token_offset (&rse, &rhs_tok, nullptr, rhs_caf_decl,
11345 : NULL_TREE, expr2);
11346 0 : gfc_add_modify (&block, lhs_tok, rhs_tok);
11347 : }
11348 : }
11349 :
11350 5822 : gfc_add_block_to_block (&block, &rse.post);
11351 5822 : gfc_add_block_to_block (&block, &lse.post);
11352 : }
11353 : else
11354 : {
11355 4384 : gfc_ref* remap;
11356 4384 : bool rank_remap;
11357 4384 : tree strlen_lhs;
11358 4384 : tree strlen_rhs = NULL_TREE;
11359 :
11360 : /* Array pointer. Find the last reference on the LHS and if it is an
11361 : array section ref, we're dealing with bounds remapping. In this case,
11362 : set it to AR_FULL so that gfc_conv_expr_descriptor does
11363 : not see it and process the bounds remapping afterwards explicitly. */
11364 14130 : for (remap = expr1->ref; remap; remap = remap->next)
11365 5741 : if (!remap->next && remap->type == REF_ARRAY
11366 4384 : && remap->u.ar.type == AR_SECTION)
11367 : break;
11368 4384 : rank_remap = (remap && remap->u.ar.end[0]);
11369 :
11370 379 : if (remap && expr2->expr_type == EXPR_NULL)
11371 : {
11372 2 : gfc_error ("If bounds remapping is specified at %L, "
11373 : "the pointer target shall not be NULL", &expr1->where);
11374 2 : return NULL_TREE;
11375 : }
11376 :
11377 4382 : gfc_init_se (&lse, NULL);
11378 4382 : if (remap)
11379 377 : lse.descriptor_only = 1;
11380 4382 : gfc_conv_expr_descriptor (&lse, expr1);
11381 4382 : strlen_lhs = lse.string_length;
11382 4382 : desc = lse.expr;
11383 :
11384 4382 : if (expr2->expr_type == EXPR_NULL)
11385 : {
11386 : /* Just set the data pointer to null. */
11387 692 : gfc_conv_descriptor_data_set (&lse.pre, lse.expr, null_pointer_node);
11388 : }
11389 3690 : else if (rank_remap)
11390 : {
11391 : /* If we are rank-remapping, just get the RHS's descriptor and
11392 : process this later on. */
11393 254 : gfc_init_se (&rse, NULL);
11394 254 : rse.direct_byref = 1;
11395 254 : rse.byref_noassign = 1;
11396 :
11397 254 : if (expr2->expr_type == EXPR_FUNCTION && expr2->ts.type == BT_CLASS)
11398 12 : expr1_vptr = trans_class_pointer_fcn (&block, &lse, &rse,
11399 : expr1, expr2);
11400 242 : else if (expr2->expr_type == EXPR_FUNCTION)
11401 : {
11402 : tree bound[GFC_MAX_DIMENSIONS];
11403 : int i;
11404 :
11405 26 : for (i = 0; i < expr2->rank; i++)
11406 13 : bound[i] = NULL_TREE;
11407 13 : tmp = gfc_typenode_for_spec (&expr2->ts);
11408 13 : tmp = gfc_get_array_type_bounds (tmp, expr2->rank, 0,
11409 : bound, bound, 0,
11410 : GFC_ARRAY_POINTER_CONT, false);
11411 13 : tmp = gfc_create_var (tmp, "ptrtemp");
11412 13 : rse.descriptor_only = 0;
11413 13 : rse.expr = tmp;
11414 13 : rse.direct_byref = 1;
11415 13 : gfc_conv_expr_descriptor (&rse, expr2);
11416 13 : strlen_rhs = rse.string_length;
11417 13 : rse.expr = tmp;
11418 : }
11419 : else
11420 : {
11421 229 : gfc_conv_expr_descriptor (&rse, expr2);
11422 229 : strlen_rhs = rse.string_length;
11423 229 : if (expr1->ts.type == BT_CLASS)
11424 60 : expr1_vptr = trans_class_vptr_len_assignment (&block, expr1,
11425 : expr2, &rse,
11426 : NULL, NULL,
11427 : NULL);
11428 : }
11429 : }
11430 3436 : else if (expr2->expr_type == EXPR_VARIABLE)
11431 : {
11432 : /* Assign directly to the LHS's descriptor. */
11433 3304 : lse.descriptor_only = 0;
11434 3304 : lse.direct_byref = 1;
11435 3304 : gfc_conv_expr_descriptor (&lse, expr2);
11436 3304 : strlen_rhs = lse.string_length;
11437 3304 : gfc_init_se (&rse, NULL);
11438 :
11439 3304 : if (expr1->ts.type == BT_CLASS)
11440 : {
11441 368 : rse.expr = NULL_TREE;
11442 368 : rse.string_length = strlen_rhs;
11443 368 : trans_class_vptr_len_assignment (&block, expr1, expr2, &rse,
11444 : NULL, NULL, NULL);
11445 : }
11446 :
11447 3304 : if (remap == NULL)
11448 : {
11449 : /* If the target is not a whole array, use the target array
11450 : reference for remap. */
11451 6781 : for (remap = expr2->ref; remap; remap = remap->next)
11452 3750 : if (remap->type == REF_ARRAY
11453 3241 : && remap->u.ar.type == AR_FULL
11454 2548 : && remap->next)
11455 : break;
11456 : }
11457 : }
11458 132 : else if (expr2->expr_type == EXPR_FUNCTION && expr2->ts.type == BT_CLASS)
11459 : {
11460 25 : gfc_init_se (&rse, NULL);
11461 25 : rse.want_pointer = 1;
11462 25 : gfc_conv_function_expr (&rse, expr2);
11463 25 : if (expr1->ts.type != BT_CLASS)
11464 : {
11465 12 : rse.expr = gfc_class_data_get (rse.expr);
11466 12 : gfc_add_modify (&lse.pre, desc, rse.expr);
11467 : }
11468 : else
11469 : {
11470 13 : expr1_vptr = trans_class_vptr_len_assignment (&block, expr1,
11471 : expr2, &rse, NULL,
11472 : NULL, NULL);
11473 13 : gfc_add_block_to_block (&block, &rse.pre);
11474 13 : tmp = gfc_create_var (TREE_TYPE (rse.expr), "ptrtemp");
11475 13 : gfc_add_modify (&lse.pre, tmp, rse.expr);
11476 :
11477 26 : gfc_add_modify (&lse.pre, expr1_vptr,
11478 13 : fold_convert (TREE_TYPE (expr1_vptr),
11479 : gfc_class_vptr_get (tmp)));
11480 13 : rse.expr = gfc_class_data_get (tmp);
11481 13 : gfc_add_modify (&lse.pre, desc, rse.expr);
11482 : }
11483 : }
11484 : else
11485 : {
11486 : /* Assign to a temporary descriptor and then copy that
11487 : temporary to the pointer. */
11488 107 : tmp = gfc_create_var (TREE_TYPE (desc), "ptrtemp");
11489 107 : lse.descriptor_only = 0;
11490 107 : lse.expr = tmp;
11491 107 : lse.direct_byref = 1;
11492 107 : gfc_conv_expr_descriptor (&lse, expr2);
11493 107 : strlen_rhs = lse.string_length;
11494 107 : gfc_add_modify (&lse.pre, desc, tmp);
11495 : }
11496 :
11497 4382 : if (expr1->ts.type == BT_CHARACTER
11498 596 : && expr1->ts.deferred)
11499 : {
11500 338 : gfc_symbol *psym = expr1->symtree->n.sym;
11501 338 : tmp = NULL_TREE;
11502 338 : if (psym->ts.type == BT_CHARACTER
11503 337 : && psym->ts.u.cl->backend_decl)
11504 337 : tmp = psym->ts.u.cl->backend_decl;
11505 1 : else if (expr1->ts.u.cl->backend_decl
11506 1 : && VAR_P (expr1->ts.u.cl->backend_decl))
11507 0 : tmp = expr1->ts.u.cl->backend_decl;
11508 1 : else if (TREE_CODE (lse.expr) == COMPONENT_REF)
11509 : {
11510 1 : gfc_ref *ref = expr1->ref;
11511 3 : for (;ref; ref = ref->next)
11512 : {
11513 2 : if (ref->type == REF_COMPONENT
11514 1 : && ref->u.c.component->ts.type == BT_CHARACTER
11515 3 : && gfc_deferred_strlen (ref->u.c.component, &tmp))
11516 1 : tmp = fold_build3_loc (input_location, COMPONENT_REF,
11517 1 : TREE_TYPE (tmp),
11518 1 : TREE_OPERAND (lse.expr, 0),
11519 : tmp, NULL_TREE);
11520 : }
11521 : }
11522 :
11523 338 : gcc_assert (tmp);
11524 :
11525 338 : if (expr2->expr_type != EXPR_NULL)
11526 326 : gfc_add_modify (&block, tmp,
11527 326 : fold_convert (TREE_TYPE (tmp), strlen_rhs));
11528 : else
11529 12 : gfc_add_modify (&block, tmp, build_zero_cst (TREE_TYPE (tmp)));
11530 : }
11531 :
11532 4382 : gfc_add_block_to_block (&block, &lse.pre);
11533 4382 : if (rank_remap)
11534 254 : gfc_add_block_to_block (&block, &rse.pre);
11535 :
11536 : /* If we do bounds remapping, update LHS descriptor accordingly. */
11537 4382 : if (remap)
11538 : {
11539 527 : int dim;
11540 527 : gcc_assert (remap->u.ar.dimen == expr1->rank);
11541 :
11542 : /* Always set dtype. */
11543 527 : tree dtype = gfc_conv_descriptor_dtype (desc);
11544 527 : tmp = gfc_get_dtype (TREE_TYPE (desc));
11545 527 : gfc_add_modify (&block, dtype, tmp);
11546 :
11547 : /* For unlimited polymorphic LHS use elem_len from RHS. */
11548 527 : if (UNLIMITED_POLY (expr1) && expr2->ts.type != BT_CLASS)
11549 : {
11550 60 : tree elem_len;
11551 60 : tmp = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&expr2->ts));
11552 60 : elem_len = fold_convert (gfc_array_index_type, tmp);
11553 60 : elem_len = gfc_evaluate_now (elem_len, &block);
11554 60 : tmp = gfc_conv_descriptor_elem_len (desc);
11555 60 : gfc_add_modify (&block, tmp,
11556 60 : fold_convert (TREE_TYPE (tmp), elem_len));
11557 : }
11558 :
11559 527 : if (rank_remap)
11560 : {
11561 : /* Do rank remapping. We already have the RHS's descriptor
11562 : converted in rse and now have to build the correct LHS
11563 : descriptor for it. */
11564 :
11565 254 : tree data, span;
11566 254 : tree offs, stride;
11567 254 : tree lbound, ubound;
11568 :
11569 : /* Copy data pointer. */
11570 254 : data = gfc_conv_descriptor_data_get (rse.expr);
11571 254 : gfc_conv_descriptor_data_set (&block, desc, data);
11572 :
11573 : /* Copy the span. */
11574 254 : if (VAR_P (rse.expr)
11575 254 : && GFC_DECL_PTR_ARRAY_P (rse.expr))
11576 12 : span = gfc_conv_descriptor_span_get (rse.expr);
11577 : else
11578 : {
11579 242 : tmp = TREE_TYPE (rse.expr);
11580 242 : tmp = TYPE_SIZE_UNIT (gfc_get_element_type (tmp));
11581 242 : span = fold_convert (gfc_array_index_type, tmp);
11582 : }
11583 254 : gfc_conv_descriptor_span_set (&block, desc, span);
11584 :
11585 : /* Copy offset but adjust it such that it would correspond
11586 : to a lbound of zero. */
11587 254 : if (expr2->rank == -1)
11588 42 : gfc_conv_descriptor_offset_set (&block, desc,
11589 : gfc_index_zero_node);
11590 : else
11591 : {
11592 212 : offs = gfc_conv_descriptor_offset_get (rse.expr);
11593 654 : for (dim = 0; dim < expr2->rank; ++dim)
11594 : {
11595 230 : stride = gfc_conv_descriptor_stride_get (rse.expr,
11596 : gfc_rank_cst[dim]);
11597 230 : lbound = gfc_conv_descriptor_lbound_get (rse.expr,
11598 : gfc_rank_cst[dim]);
11599 230 : tmp = fold_build2_loc (input_location, MULT_EXPR,
11600 : gfc_array_index_type, stride,
11601 : lbound);
11602 230 : offs = fold_build2_loc (input_location, PLUS_EXPR,
11603 : gfc_array_index_type, offs, tmp);
11604 : }
11605 212 : gfc_conv_descriptor_offset_set (&block, desc, offs);
11606 : }
11607 : /* Set the bounds as declared for the LHS and calculate strides as
11608 : well as another offset update accordingly. */
11609 254 : stride = gfc_conv_descriptor_stride_get (rse.expr,
11610 : gfc_rank_cst[0]);
11611 641 : for (dim = 0; dim < expr1->rank; ++dim)
11612 : {
11613 387 : gfc_se lower_se;
11614 387 : gfc_se upper_se;
11615 :
11616 387 : gcc_assert (remap->u.ar.start[dim] && remap->u.ar.end[dim]);
11617 :
11618 387 : if (remap->u.ar.start[dim]->expr_type != EXPR_CONSTANT
11619 : || remap->u.ar.start[dim]->expr_type != EXPR_VARIABLE)
11620 387 : gfc_resolve_expr (remap->u.ar.start[dim]);
11621 387 : if (remap->u.ar.end[dim]->expr_type != EXPR_CONSTANT
11622 : || remap->u.ar.end[dim]->expr_type != EXPR_VARIABLE)
11623 387 : gfc_resolve_expr (remap->u.ar.end[dim]);
11624 :
11625 : /* Convert declared bounds. */
11626 387 : gfc_init_se (&lower_se, NULL);
11627 387 : gfc_init_se (&upper_se, NULL);
11628 387 : gfc_conv_expr (&lower_se, remap->u.ar.start[dim]);
11629 387 : gfc_conv_expr (&upper_se, remap->u.ar.end[dim]);
11630 :
11631 387 : gfc_add_block_to_block (&block, &lower_se.pre);
11632 387 : gfc_add_block_to_block (&block, &upper_se.pre);
11633 :
11634 387 : lbound = fold_convert (gfc_array_index_type, lower_se.expr);
11635 387 : ubound = fold_convert (gfc_array_index_type, upper_se.expr);
11636 :
11637 387 : lbound = gfc_evaluate_now (lbound, &block);
11638 387 : ubound = gfc_evaluate_now (ubound, &block);
11639 :
11640 387 : gfc_add_block_to_block (&block, &lower_se.post);
11641 387 : gfc_add_block_to_block (&block, &upper_se.post);
11642 :
11643 : /* Set bounds in descriptor. */
11644 387 : gfc_conv_descriptor_lbound_set (&block, desc,
11645 : gfc_rank_cst[dim], lbound);
11646 387 : gfc_conv_descriptor_ubound_set (&block, desc,
11647 : gfc_rank_cst[dim], ubound);
11648 :
11649 : /* Set stride. */
11650 387 : stride = gfc_evaluate_now (stride, &block);
11651 387 : gfc_conv_descriptor_stride_set (&block, desc,
11652 : gfc_rank_cst[dim], stride);
11653 :
11654 : /* Update offset. */
11655 387 : offs = gfc_conv_descriptor_offset_get (desc);
11656 387 : tmp = fold_build2_loc (input_location, MULT_EXPR,
11657 : gfc_array_index_type, lbound, stride);
11658 387 : offs = fold_build2_loc (input_location, MINUS_EXPR,
11659 : gfc_array_index_type, offs, tmp);
11660 387 : offs = gfc_evaluate_now (offs, &block);
11661 387 : gfc_conv_descriptor_offset_set (&block, desc, offs);
11662 :
11663 : /* Update stride. */
11664 387 : tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL);
11665 387 : stride = fold_build2_loc (input_location, MULT_EXPR,
11666 : gfc_array_index_type, stride, tmp);
11667 : }
11668 : }
11669 : else
11670 : {
11671 : /* Bounds remapping. Just shift the lower bounds. */
11672 :
11673 273 : gcc_assert (expr1->rank == expr2->rank);
11674 :
11675 654 : for (dim = 0; dim < remap->u.ar.dimen; ++dim)
11676 : {
11677 381 : gfc_se lbound_se;
11678 :
11679 381 : gcc_assert (!remap->u.ar.end[dim]);
11680 381 : gfc_init_se (&lbound_se, NULL);
11681 381 : if (remap->u.ar.start[dim])
11682 : {
11683 225 : gfc_conv_expr (&lbound_se, remap->u.ar.start[dim]);
11684 225 : gfc_add_block_to_block (&block, &lbound_se.pre);
11685 : }
11686 : else
11687 : /* This remap arises from a target that is not a whole
11688 : array. The start expressions will be NULL but we need
11689 : the lbounds to be one. */
11690 156 : lbound_se.expr = gfc_index_one_node;
11691 381 : gfc_conv_shift_descriptor_lbound (&block, desc,
11692 : dim, lbound_se.expr);
11693 381 : gfc_add_block_to_block (&block, &lbound_se.post);
11694 : }
11695 : }
11696 : }
11697 :
11698 : /* If rank remapping was done, check with -fcheck=bounds that
11699 : the target is at least as large as the pointer. */
11700 4382 : if (rank_remap && (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
11701 72 : && expr2->rank != -1)
11702 : {
11703 54 : tree lsize, rsize;
11704 54 : tree fault;
11705 54 : const char* msg;
11706 :
11707 54 : lsize = gfc_conv_descriptor_size (lse.expr, expr1->rank);
11708 54 : rsize = gfc_conv_descriptor_size (rse.expr, expr2->rank);
11709 :
11710 54 : lsize = gfc_evaluate_now (lsize, &block);
11711 54 : rsize = gfc_evaluate_now (rsize, &block);
11712 54 : fault = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
11713 : rsize, lsize);
11714 :
11715 54 : msg = _("Target of rank remapping is too small (%ld < %ld)");
11716 54 : gfc_trans_runtime_check (true, false, fault, &block, &expr2->where,
11717 : msg, rsize, lsize);
11718 : }
11719 :
11720 : /* Check string lengths if applicable. The check is only really added
11721 : to the output code if -fbounds-check is enabled. */
11722 4382 : if (expr1->ts.type == BT_CHARACTER && expr2->expr_type != EXPR_NULL)
11723 : {
11724 530 : gcc_assert (expr2->ts.type == BT_CHARACTER);
11725 530 : gcc_assert (strlen_lhs && strlen_rhs);
11726 530 : gfc_trans_same_strlen_check ("pointer assignment", &expr1->where,
11727 : strlen_lhs, strlen_rhs, &block);
11728 : }
11729 :
11730 4382 : gfc_add_block_to_block (&block, &lse.post);
11731 4382 : if (rank_remap)
11732 254 : gfc_add_block_to_block (&block, &rse.post);
11733 : }
11734 :
11735 10204 : return gfc_finish_block (&block);
11736 : }
11737 :
11738 :
11739 : /* Makes sure se is suitable for passing as a function string parameter. */
11740 : /* TODO: Need to check all callers of this function. It may be abused. */
11741 :
11742 : void
11743 246946 : gfc_conv_string_parameter (gfc_se * se)
11744 : {
11745 246946 : tree type;
11746 :
11747 246946 : if (TREE_CODE (TREE_TYPE (se->expr)) == INTEGER_TYPE
11748 246946 : && integer_onep (se->string_length))
11749 : {
11750 691 : se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
11751 691 : return;
11752 : }
11753 :
11754 246255 : if (TREE_CODE (se->expr) == STRING_CST)
11755 : {
11756 102871 : type = TREE_TYPE (TREE_TYPE (se->expr));
11757 102871 : se->expr = gfc_build_addr_expr (build_pointer_type (type), se->expr);
11758 102871 : return;
11759 : }
11760 :
11761 143384 : if (TREE_CODE (se->expr) == COND_EXPR)
11762 : {
11763 478 : tree cond = TREE_OPERAND (se->expr, 0);
11764 478 : tree lhs = TREE_OPERAND (se->expr, 1);
11765 478 : tree rhs = TREE_OPERAND (se->expr, 2);
11766 :
11767 478 : gfc_se lse, rse;
11768 478 : gfc_init_se (&lse, NULL);
11769 478 : gfc_init_se (&rse, NULL);
11770 :
11771 478 : lse.expr = lhs;
11772 478 : lse.string_length = se->string_length;
11773 478 : gfc_conv_string_parameter (&lse);
11774 :
11775 478 : rse.expr = rhs;
11776 478 : rse.string_length = se->string_length;
11777 478 : gfc_conv_string_parameter (&rse);
11778 :
11779 478 : se->expr
11780 478 : = fold_build3_loc (input_location, COND_EXPR, TREE_TYPE (lse.expr),
11781 : cond, lse.expr, rse.expr);
11782 : }
11783 :
11784 143384 : if ((TREE_CODE (TREE_TYPE (se->expr)) == ARRAY_TYPE
11785 55994 : || TREE_CODE (TREE_TYPE (se->expr)) == INTEGER_TYPE)
11786 143480 : && TYPE_STRING_FLAG (TREE_TYPE (se->expr)))
11787 : {
11788 87486 : type = TREE_TYPE (se->expr);
11789 87486 : if (TREE_CODE (se->expr) != INDIRECT_REF)
11790 82411 : se->expr = gfc_build_addr_expr (build_pointer_type (type), se->expr);
11791 : else
11792 : {
11793 5075 : if (TREE_CODE (type) == ARRAY_TYPE)
11794 5075 : type = TREE_TYPE (type);
11795 5075 : type = gfc_get_character_type_len_for_eltype (type,
11796 : se->string_length);
11797 5075 : type = build_pointer_type (type);
11798 5075 : se->expr = gfc_build_addr_expr (type, se->expr);
11799 : }
11800 : }
11801 :
11802 143384 : gcc_assert (POINTER_TYPE_P (TREE_TYPE (se->expr)));
11803 : }
11804 :
11805 :
11806 : /* Generate code for assignment of scalar variables. Includes character
11807 : strings and derived types with allocatable components.
11808 : If you know that the LHS has no allocations, set dealloc to false.
11809 :
11810 : DEEP_COPY has no effect if the typespec TS is not a derived type with
11811 : allocatable components. Otherwise, if it is set, an explicit copy of each
11812 : allocatable component is made. This is necessary as a simple copy of the
11813 : whole object would copy array descriptors as is, so that the lhs's
11814 : allocatable components would point to the rhs's after the assignment.
11815 : Typically, setting DEEP_COPY is necessary if the rhs is a variable, and not
11816 : necessary if the rhs is a non-pointer function, as the allocatable components
11817 : are not accessible by other means than the function's result after the
11818 : function has returned. It is even more subtle when temporaries are involved,
11819 : as the two following examples show:
11820 : 1. When we evaluate an array constructor, a temporary is created. Thus
11821 : there is theoretically no alias possible. However, no deep copy is
11822 : made for this temporary, so that if the constructor is made of one or
11823 : more variable with allocatable components, those components still point
11824 : to the variable's: DEEP_COPY should be set for the assignment from the
11825 : temporary to the lhs in that case.
11826 : 2. When assigning a scalar to an array, we evaluate the scalar value out
11827 : of the loop, store it into a temporary variable, and assign from that.
11828 : In that case, deep copying when assigning to the temporary would be a
11829 : waste of resources; however deep copies should happen when assigning from
11830 : the temporary to each array element: again DEEP_COPY should be set for
11831 : the assignment from the temporary to the lhs. */
11832 :
11833 : tree
11834 339246 : gfc_trans_scalar_assign (gfc_se *lse, gfc_se *rse, gfc_typespec ts,
11835 : bool deep_copy, bool dealloc, bool in_coarray,
11836 : bool assoc_assign)
11837 : {
11838 339246 : stmtblock_t block;
11839 339246 : tree tmp;
11840 339246 : tree cond;
11841 339246 : int caf_mode;
11842 :
11843 339246 : gfc_init_block (&block);
11844 :
11845 339246 : if (ts.type == BT_CHARACTER)
11846 : {
11847 33417 : tree rlen = NULL;
11848 33417 : tree llen = NULL;
11849 :
11850 33417 : if (lse->string_length != NULL_TREE)
11851 : {
11852 33417 : gfc_conv_string_parameter (lse);
11853 33417 : gfc_add_block_to_block (&block, &lse->pre);
11854 33417 : llen = lse->string_length;
11855 : }
11856 :
11857 33417 : if (rse->string_length != NULL_TREE)
11858 : {
11859 33417 : gfc_conv_string_parameter (rse);
11860 33417 : gfc_add_block_to_block (&block, &rse->pre);
11861 33417 : rlen = rse->string_length;
11862 : }
11863 :
11864 33417 : gfc_trans_string_copy (&block, llen, lse->expr, ts.kind, rlen,
11865 : rse->expr, ts.kind);
11866 : }
11867 286508 : else if (gfc_bt_struct (ts.type)
11868 305829 : && (ts.u.derived->attr.alloc_comp
11869 12612 : || (deep_copy && has_parameterized_comps (ts.u.derived))))
11870 : {
11871 6871 : tree tmp_var = NULL_TREE;
11872 6871 : cond = NULL_TREE;
11873 :
11874 : /* Are the rhs and the lhs the same? */
11875 6871 : if (deep_copy)
11876 : {
11877 4127 : if (!TREE_CONSTANT (rse->expr) && !VAR_P (rse->expr))
11878 2999 : rse->expr = gfc_evaluate_now (rse->expr, &rse->pre);
11879 4127 : cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
11880 : gfc_build_addr_expr (NULL_TREE, lse->expr),
11881 : gfc_build_addr_expr (NULL_TREE, rse->expr));
11882 4127 : cond = gfc_evaluate_now (cond, &lse->pre);
11883 : }
11884 :
11885 : /* Deallocate the lhs allocated components as long as it is not
11886 : the same as the rhs. This must be done following the assignment
11887 : to prevent deallocating data that could be used in the rhs
11888 : expression. */
11889 6871 : if (dealloc)
11890 : {
11891 1959 : tmp_var = gfc_evaluate_now (lse->expr, &lse->pre);
11892 1959 : tmp = gfc_deallocate_alloc_comp_no_caf (ts.u.derived, tmp_var,
11893 1959 : 0, gfc_may_be_finalized (ts));
11894 1959 : if (deep_copy)
11895 833 : tmp = build3_v (COND_EXPR, cond, build_empty_stmt (input_location),
11896 : tmp);
11897 1959 : gfc_add_expr_to_block (&lse->post, tmp);
11898 : }
11899 :
11900 6871 : gfc_add_block_to_block (&block, &rse->pre);
11901 :
11902 : /* Skip finalization for self-assignment. */
11903 6871 : if (deep_copy && lse->finalblock.head)
11904 : {
11905 24 : tmp = build3_v (COND_EXPR, cond, build_empty_stmt (input_location),
11906 : gfc_finish_block (&lse->finalblock));
11907 24 : gfc_add_expr_to_block (&block, tmp);
11908 : }
11909 : else
11910 6847 : gfc_add_block_to_block (&block, &lse->finalblock);
11911 :
11912 6871 : gfc_add_block_to_block (&block, &lse->pre);
11913 :
11914 6871 : if (TYPE_MAIN_VARIANT (TREE_TYPE (lse->expr))
11915 6871 : == TYPE_MAIN_VARIANT (TREE_TYPE (rse->expr)))
11916 6565 : gfc_add_modify (&block, lse->expr,
11917 6565 : fold_convert (TREE_TYPE (lse->expr), rse->expr));
11918 : else
11919 : {
11920 306 : tmp = fold_build1_loc (input_location, VIEW_CONVERT_EXPR,
11921 306 : TREE_TYPE (lse->expr), rse->expr);
11922 306 : gfc_add_modify (&block, lse->expr, tmp);
11923 : }
11924 :
11925 : /* Restore pointer address of coarray components. */
11926 6871 : if (ts.u.derived->attr.coarray_comp && deep_copy && tmp_var != NULL_TREE)
11927 : {
11928 5 : tmp = gfc_reassign_alloc_comp_caf (ts.u.derived, tmp_var, lse->expr);
11929 5 : tmp = build3_v (COND_EXPR, cond, build_empty_stmt (input_location),
11930 : tmp);
11931 5 : gfc_add_expr_to_block (&block, tmp);
11932 : }
11933 :
11934 : /* Do a deep copy if the rhs is a variable, if it is not the
11935 : same as the lhs. */
11936 6871 : if (deep_copy)
11937 : {
11938 4127 : caf_mode = in_coarray ? (GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY
11939 : | GFC_STRUCTURE_CAF_MODE_IN_COARRAY) : 0;
11940 4127 : tmp = gfc_copy_alloc_comp (ts.u.derived, rse->expr, lse->expr, 0,
11941 : caf_mode);
11942 4127 : tmp = build3_v (COND_EXPR, cond, build_empty_stmt (input_location),
11943 : tmp);
11944 4127 : gfc_add_expr_to_block (&block, tmp);
11945 : }
11946 : }
11947 298958 : else if (gfc_bt_struct (ts.type))
11948 : {
11949 12450 : gfc_add_block_to_block (&block, &rse->pre);
11950 12450 : gfc_add_block_to_block (&block, &lse->finalblock);
11951 12450 : gfc_add_block_to_block (&block, &lse->pre);
11952 12450 : tmp = fold_build1_loc (input_location, VIEW_CONVERT_EXPR,
11953 12450 : TREE_TYPE (lse->expr), rse->expr);
11954 12450 : gfc_add_modify (&block, lse->expr, tmp);
11955 : }
11956 : /* If possible use the rhs vptr copy with trans_scalar_class_assign.... */
11957 286508 : else if (ts.type == BT_CLASS)
11958 : {
11959 788 : gfc_add_block_to_block (&block, &lse->pre);
11960 788 : gfc_add_block_to_block (&block, &rse->pre);
11961 788 : gfc_add_block_to_block (&block, &lse->finalblock);
11962 :
11963 788 : if (!trans_scalar_class_assign (&block, lse, rse))
11964 : {
11965 : /* ..otherwise assignment suffices. Note the use of VIEW_CONVERT_EXPR
11966 : for the lhs which ensures that class data rhs cast as a string
11967 : assigns correctly. */
11968 642 : tmp = fold_build1_loc (input_location, VIEW_CONVERT_EXPR,
11969 642 : TREE_TYPE (rse->expr), lse->expr);
11970 642 : gfc_add_modify (&block, tmp, rse->expr);
11971 :
11972 : /* Copy allocatable components but guard against class pointer
11973 : assign, which arrives here. */
11974 : #define DATA_DT ts.u.derived->components->ts.u.derived
11975 642 : if (deep_copy
11976 195 : && !(GFC_CLASS_TYPE_P (TREE_TYPE (lse->expr))
11977 43 : && GFC_CLASS_TYPE_P (TREE_TYPE (rse->expr)))
11978 152 : && ts.u.derived->components
11979 794 : && DATA_DT && DATA_DT->attr.alloc_comp)
11980 : {
11981 6 : caf_mode = in_coarray ? (GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY
11982 : | GFC_STRUCTURE_CAF_MODE_IN_COARRAY)
11983 : : 0;
11984 6 : tmp = gfc_copy_alloc_comp (DATA_DT, rse->expr, lse->expr, 0,
11985 : caf_mode);
11986 6 : gfc_add_expr_to_block (&block, tmp);
11987 : }
11988 : #undef DATA_DT
11989 : }
11990 : }
11991 285720 : else if (ts.type != BT_CLASS)
11992 : {
11993 285720 : gfc_add_block_to_block (&block, &lse->pre);
11994 285720 : gfc_add_block_to_block (&block, &rse->pre);
11995 :
11996 285720 : if (in_coarray)
11997 : {
11998 847 : if (flag_coarray == GFC_FCOARRAY_LIB && assoc_assign)
11999 : {
12000 0 : gfc_add_modify (&block, gfc_conv_descriptor_token (lse->expr),
12001 0 : TYPE_LANG_SPECIFIC (
12002 : TREE_TYPE (TREE_TYPE (rse->expr)))
12003 : ->caf_token);
12004 : }
12005 847 : if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (lse->expr)))
12006 0 : lse->expr = gfc_conv_array_data (lse->expr);
12007 276 : if (flag_coarray == GFC_FCOARRAY_SINGLE && assoc_assign
12008 847 : && !POINTER_TYPE_P (TREE_TYPE (rse->expr)))
12009 0 : rse->expr = gfc_build_addr_expr (NULL_TREE, rse->expr);
12010 : }
12011 285720 : gfc_add_modify (&block, lse->expr,
12012 285720 : fold_convert (TREE_TYPE (lse->expr), rse->expr));
12013 : }
12014 :
12015 339246 : gfc_add_block_to_block (&block, &lse->post);
12016 339246 : gfc_add_block_to_block (&block, &rse->post);
12017 :
12018 339246 : return gfc_finish_block (&block);
12019 : }
12020 :
12021 :
12022 : /* There are quite a lot of restrictions on the optimisation in using an
12023 : array function assign without a temporary. */
12024 :
12025 : static bool
12026 14472 : arrayfunc_assign_needs_temporary (gfc_expr * expr1, gfc_expr * expr2)
12027 : {
12028 14472 : gfc_ref * ref;
12029 14472 : bool seen_array_ref;
12030 14472 : bool c = false;
12031 14472 : gfc_symbol *sym = expr1->symtree->n.sym;
12032 :
12033 : /* Play it safe with class functions assigned to a derived type. */
12034 14472 : if (gfc_is_class_array_function (expr2)
12035 14472 : && expr1->ts.type == BT_DERIVED)
12036 : return true;
12037 :
12038 : /* The caller has already checked rank>0 and expr_type == EXPR_FUNCTION. */
12039 14448 : if (expr2->value.function.isym && !gfc_is_intrinsic_libcall (expr2))
12040 : return true;
12041 :
12042 : /* Elemental functions are scalarized so that they don't need a
12043 : temporary in gfc_trans_assignment_1, so return a true. Otherwise,
12044 : they would need special treatment in gfc_trans_arrayfunc_assign. */
12045 8531 : if (expr2->value.function.esym != NULL
12046 1589 : && expr2->value.function.esym->attr.elemental)
12047 : return true;
12048 :
12049 : /* Need a temporary if rhs is not FULL or a contiguous section. */
12050 8172 : if (expr1->ref && !(gfc_full_array_ref_p (expr1->ref, &c) || c))
12051 : return true;
12052 :
12053 : /* Need a temporary if EXPR1 can't be expressed as a descriptor. */
12054 7922 : if (gfc_ref_needs_temporary_p (expr1->ref))
12055 : return true;
12056 :
12057 : /* Functions returning pointers or allocatables need temporaries. */
12058 7910 : if (gfc_expr_attr (expr2).pointer
12059 7910 : || gfc_expr_attr (expr2).allocatable)
12060 376 : return true;
12061 :
12062 : /* Character array functions need temporaries unless the
12063 : character lengths are the same. */
12064 7534 : if (expr2->ts.type == BT_CHARACTER && expr2->rank > 0)
12065 : {
12066 562 : if (UNLIMITED_POLY (expr1))
12067 : return true;
12068 :
12069 556 : if (expr1->ts.u.cl->length == NULL
12070 507 : || expr1->ts.u.cl->length->expr_type != EXPR_CONSTANT)
12071 : return true;
12072 :
12073 493 : if (expr2->ts.u.cl->length == NULL
12074 487 : || expr2->ts.u.cl->length->expr_type != EXPR_CONSTANT)
12075 : return true;
12076 :
12077 475 : if (mpz_cmp (expr1->ts.u.cl->length->value.integer,
12078 475 : expr2->ts.u.cl->length->value.integer) != 0)
12079 : return true;
12080 : }
12081 :
12082 : /* Check that no LHS component references appear during an array
12083 : reference. This is needed because we do not have the means to
12084 : span any arbitrary stride with an array descriptor. This check
12085 : is not needed for the rhs because the function result has to be
12086 : a complete type. */
12087 7441 : seen_array_ref = false;
12088 14882 : for (ref = expr1->ref; ref; ref = ref->next)
12089 : {
12090 7454 : if (ref->type == REF_ARRAY)
12091 : seen_array_ref= true;
12092 13 : else if (ref->type == REF_COMPONENT && seen_array_ref)
12093 : return true;
12094 : }
12095 :
12096 : /* Check for a dependency. */
12097 7428 : if (gfc_check_fncall_dependency (expr1, INTENT_OUT,
12098 : expr2->value.function.esym,
12099 : expr2->value.function.actual,
12100 : NOT_ELEMENTAL))
12101 : return true;
12102 :
12103 : /* If we have reached here with an intrinsic function, we do not
12104 : need a temporary except in the particular case that reallocation
12105 : on assignment is active and the lhs is allocatable and a target,
12106 : or a pointer which may be a subref pointer. FIXME: The last
12107 : condition can go away when we use span in the intrinsics
12108 : directly.*/
12109 6991 : if (expr2->value.function.isym)
12110 6113 : return (flag_realloc_lhs && sym->attr.allocatable && sym->attr.target)
12111 12313 : || (sym->attr.pointer && sym->attr.subref_array_pointer);
12112 :
12113 : /* If the LHS is a dummy, we need a temporary if it is not
12114 : INTENT(OUT). */
12115 803 : if (sym->attr.dummy && sym->attr.intent != INTENT_OUT)
12116 : return true;
12117 :
12118 : /* If the lhs has been host_associated, is in common, a pointer or is
12119 : a target and the function is not using a RESULT variable, aliasing
12120 : can occur and a temporary is needed. */
12121 797 : if ((sym->attr.host_assoc
12122 743 : || sym->attr.in_common
12123 737 : || sym->attr.pointer
12124 731 : || sym->attr.cray_pointee
12125 731 : || sym->attr.target)
12126 66 : && expr2->symtree != NULL
12127 66 : && expr2->symtree->n.sym == expr2->symtree->n.sym->result)
12128 : return true;
12129 :
12130 : /* A PURE function can unconditionally be called without a temporary. */
12131 755 : if (expr2->value.function.esym != NULL
12132 730 : && expr2->value.function.esym->attr.pure)
12133 : return false;
12134 :
12135 : /* Implicit_pure functions are those which could legally be declared
12136 : to be PURE. */
12137 727 : if (expr2->value.function.esym != NULL
12138 702 : && expr2->value.function.esym->attr.implicit_pure)
12139 : return false;
12140 :
12141 444 : if (!sym->attr.use_assoc
12142 444 : && !sym->attr.in_common
12143 444 : && !sym->attr.pointer
12144 438 : && !sym->attr.target
12145 438 : && !sym->attr.cray_pointee
12146 438 : && expr2->value.function.esym)
12147 : {
12148 : /* A temporary is not needed if the function is not contained and
12149 : the variable is local or host associated and not a pointer or
12150 : a target. */
12151 413 : if (!expr2->value.function.esym->attr.contained)
12152 : return false;
12153 :
12154 : /* A temporary is not needed if the lhs has never been host
12155 : associated and the procedure is contained. */
12156 164 : else if (!sym->attr.host_assoc)
12157 : return false;
12158 :
12159 : /* A temporary is not needed if the variable is local and not
12160 : a pointer, a target or a result. */
12161 6 : if (sym->ns->parent
12162 0 : && expr2->value.function.esym->ns == sym->ns->parent)
12163 : return false;
12164 : }
12165 :
12166 : /* Default to temporary use. */
12167 : return true;
12168 : }
12169 :
12170 :
12171 : /* Provide the loop info so that the lhs descriptor can be built for
12172 : reallocatable assignments from extrinsic function calls. */
12173 :
12174 : static void
12175 203 : realloc_lhs_loop_for_fcn_call (gfc_se *se, locus *where, gfc_ss **ss,
12176 : gfc_loopinfo *loop)
12177 : {
12178 : /* Signal that the function call should not be made by
12179 : gfc_conv_loop_setup. */
12180 203 : se->ss->is_alloc_lhs = 1;
12181 203 : gfc_init_loopinfo (loop);
12182 203 : gfc_add_ss_to_loop (loop, *ss);
12183 203 : gfc_add_ss_to_loop (loop, se->ss);
12184 203 : gfc_conv_ss_startstride (loop);
12185 203 : gfc_conv_loop_setup (loop, where);
12186 203 : gfc_copy_loopinfo_to_se (se, loop);
12187 203 : gfc_add_block_to_block (&se->pre, &loop->pre);
12188 203 : gfc_add_block_to_block (&se->pre, &loop->post);
12189 203 : se->ss->is_alloc_lhs = 0;
12190 203 : }
12191 :
12192 :
12193 : /* For assignment to a reallocatable lhs from intrinsic functions,
12194 : replace the se.expr (ie. the result) with a temporary descriptor.
12195 : Null the data field so that the library allocates space for the
12196 : result. Free the data of the original descriptor after the function,
12197 : in case it appears in an argument expression and transfer the
12198 : result to the original descriptor. */
12199 :
12200 : static void
12201 2138 : fcncall_realloc_result (gfc_se *se, int rank, tree dtype)
12202 : {
12203 2138 : tree desc;
12204 2138 : tree res_desc;
12205 2138 : tree tmp;
12206 2138 : tree offset;
12207 2138 : tree zero_cond;
12208 2138 : tree not_same_shape;
12209 2138 : stmtblock_t shape_block;
12210 2138 : int n;
12211 :
12212 : /* Use the allocation done by the library. Substitute the lhs
12213 : descriptor with a copy, whose data field is nulled.*/
12214 2138 : desc = build_fold_indirect_ref_loc (input_location, se->expr);
12215 2138 : if (POINTER_TYPE_P (TREE_TYPE (desc)))
12216 9 : desc = build_fold_indirect_ref_loc (input_location, desc);
12217 :
12218 : /* Unallocated, the descriptor does not have a dtype. */
12219 2138 : tmp = gfc_conv_descriptor_dtype (desc);
12220 2138 : if (dtype != NULL_TREE)
12221 13 : gfc_add_modify (&se->pre, tmp, dtype);
12222 : else
12223 2125 : gfc_add_modify (&se->pre, tmp, gfc_get_dtype (TREE_TYPE (desc)));
12224 :
12225 2138 : res_desc = gfc_evaluate_now (desc, &se->pre);
12226 2138 : gfc_conv_descriptor_data_set (&se->pre, res_desc, null_pointer_node);
12227 2138 : se->expr = gfc_build_addr_expr (NULL_TREE, res_desc);
12228 :
12229 : /* Free the lhs after the function call and copy the result data to
12230 : the lhs descriptor. */
12231 2138 : tmp = gfc_conv_descriptor_data_get (desc);
12232 2138 : zero_cond = fold_build2_loc (input_location, EQ_EXPR,
12233 : logical_type_node, tmp,
12234 2138 : build_int_cst (TREE_TYPE (tmp), 0));
12235 2138 : zero_cond = gfc_evaluate_now (zero_cond, &se->post);
12236 2138 : tmp = gfc_call_free (tmp);
12237 2138 : gfc_add_expr_to_block (&se->post, tmp);
12238 :
12239 2138 : tmp = gfc_conv_descriptor_data_get (res_desc);
12240 2138 : gfc_conv_descriptor_data_set (&se->post, desc, tmp);
12241 :
12242 : /* Check that the shapes are the same between lhs and expression.
12243 : The evaluation of the shape is done in 'shape_block' to avoid
12244 : uninitialized warnings from the lhs bounds. */
12245 2138 : not_same_shape = boolean_false_node;
12246 2138 : gfc_start_block (&shape_block);
12247 6880 : for (n = 0 ; n < rank; n++)
12248 : {
12249 4742 : tree tmp1;
12250 4742 : tmp = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[n]);
12251 4742 : tmp1 = gfc_conv_descriptor_lbound_get (res_desc, gfc_rank_cst[n]);
12252 4742 : tmp = fold_build2_loc (input_location, MINUS_EXPR,
12253 : gfc_array_index_type, tmp, tmp1);
12254 4742 : tmp1 = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[n]);
12255 4742 : tmp = fold_build2_loc (input_location, MINUS_EXPR,
12256 : gfc_array_index_type, tmp, tmp1);
12257 4742 : tmp1 = gfc_conv_descriptor_ubound_get (res_desc, gfc_rank_cst[n]);
12258 4742 : tmp = fold_build2_loc (input_location, PLUS_EXPR,
12259 : gfc_array_index_type, tmp, tmp1);
12260 4742 : tmp = fold_build2_loc (input_location, NE_EXPR,
12261 : logical_type_node, tmp,
12262 : gfc_index_zero_node);
12263 4742 : tmp = gfc_evaluate_now (tmp, &shape_block);
12264 4742 : if (n == 0)
12265 : not_same_shape = tmp;
12266 : else
12267 2604 : not_same_shape = fold_build2_loc (input_location, TRUTH_OR_EXPR,
12268 : logical_type_node, tmp,
12269 : not_same_shape);
12270 : }
12271 :
12272 : /* 'zero_cond' being true is equal to lhs not being allocated or the
12273 : shapes being different. */
12274 2138 : tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR, logical_type_node,
12275 : zero_cond, not_same_shape);
12276 2138 : gfc_add_modify (&shape_block, zero_cond, tmp);
12277 2138 : tmp = gfc_finish_block (&shape_block);
12278 2138 : tmp = build3_v (COND_EXPR, zero_cond,
12279 : build_empty_stmt (input_location), tmp);
12280 2138 : gfc_add_expr_to_block (&se->post, tmp);
12281 :
12282 : /* Now reset the bounds returned from the function call to bounds based
12283 : on the lhs lbounds, except where the lhs is not allocated or the shapes
12284 : of 'variable and 'expr' are different. Set the offset accordingly. */
12285 2138 : offset = gfc_index_zero_node;
12286 6880 : for (n = 0 ; n < rank; n++)
12287 : {
12288 4742 : tree lbound;
12289 :
12290 4742 : lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[n]);
12291 4742 : lbound = fold_build3_loc (input_location, COND_EXPR,
12292 : gfc_array_index_type, zero_cond,
12293 : gfc_index_one_node, lbound);
12294 4742 : lbound = gfc_evaluate_now (lbound, &se->post);
12295 :
12296 4742 : tmp = gfc_conv_descriptor_ubound_get (res_desc, gfc_rank_cst[n]);
12297 4742 : tmp = fold_build2_loc (input_location, PLUS_EXPR,
12298 : gfc_array_index_type, tmp, lbound);
12299 4742 : gfc_conv_descriptor_lbound_set (&se->post, desc,
12300 : gfc_rank_cst[n], lbound);
12301 4742 : gfc_conv_descriptor_ubound_set (&se->post, desc,
12302 : gfc_rank_cst[n], tmp);
12303 :
12304 : /* Set stride and accumulate the offset. */
12305 4742 : tmp = gfc_conv_descriptor_stride_get (res_desc, gfc_rank_cst[n]);
12306 4742 : gfc_conv_descriptor_stride_set (&se->post, desc,
12307 : gfc_rank_cst[n], tmp);
12308 4742 : tmp = fold_build2_loc (input_location, MULT_EXPR,
12309 : gfc_array_index_type, lbound, tmp);
12310 4742 : offset = fold_build2_loc (input_location, MINUS_EXPR,
12311 : gfc_array_index_type, offset, tmp);
12312 4742 : offset = gfc_evaluate_now (offset, &se->post);
12313 : }
12314 :
12315 2138 : gfc_conv_descriptor_offset_set (&se->post, desc, offset);
12316 2138 : }
12317 :
12318 :
12319 :
12320 : /* Try to translate array(:) = func (...), where func is a transformational
12321 : array function, without using a temporary. Returns NULL if this isn't the
12322 : case. */
12323 :
12324 : static tree
12325 14512 : gfc_trans_arrayfunc_assign (gfc_expr * expr1, gfc_expr * expr2)
12326 : {
12327 14512 : gfc_se se;
12328 14512 : gfc_ss *ss = NULL;
12329 14512 : gfc_component *comp = NULL;
12330 14512 : gfc_loopinfo loop;
12331 14512 : tree tmp;
12332 14512 : tree lhs;
12333 14512 : gfc_se final_se;
12334 14512 : gfc_symbol *sym = expr1->symtree->n.sym;
12335 14512 : bool finalizable = gfc_may_be_finalized (expr1->ts);
12336 :
12337 : /* If the symbol is host associated and has not been referenced in its name
12338 : space, it might be lacking a backend_decl and vtable. */
12339 14512 : if (sym->backend_decl == NULL_TREE)
12340 : return NULL_TREE;
12341 :
12342 14472 : if (arrayfunc_assign_needs_temporary (expr1, expr2))
12343 : return NULL_TREE;
12344 :
12345 : /* The frontend doesn't seem to bother filling in expr->symtree for intrinsic
12346 : functions. */
12347 6873 : comp = gfc_get_proc_ptr_comp (expr2);
12348 :
12349 6873 : if (!(expr2->value.function.isym
12350 718 : || (comp && comp->attr.dimension)
12351 718 : || (!comp && gfc_return_by_reference (expr2->value.function.esym)
12352 718 : && expr2->value.function.esym->result->attr.dimension)))
12353 0 : return NULL_TREE;
12354 :
12355 6873 : gfc_init_se (&se, NULL);
12356 6873 : gfc_start_block (&se.pre);
12357 6873 : se.want_pointer = 1;
12358 :
12359 : /* First the lhs must be finalized, if necessary. We use a copy of the symbol
12360 : backend decl, stash the original away for the finalization so that the
12361 : value used is that before the assignment. This is necessary because
12362 : evaluation of the rhs expression using direct by reference can change
12363 : the value. However, the standard mandates that the finalization must occur
12364 : after evaluation of the rhs. */
12365 6873 : gfc_init_se (&final_se, NULL);
12366 :
12367 6873 : if (finalizable)
12368 : {
12369 45 : tmp = sym->backend_decl;
12370 45 : lhs = sym->backend_decl;
12371 45 : if (INDIRECT_REF_P (tmp))
12372 0 : tmp = TREE_OPERAND (tmp, 0);
12373 45 : sym->backend_decl = gfc_create_var (TREE_TYPE (tmp), "lhs");
12374 45 : gfc_add_modify (&se.pre, sym->backend_decl, tmp);
12375 45 : if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp)))
12376 : {
12377 0 : tmp = gfc_copy_alloc_comp (expr1->ts.u.derived, tmp, sym->backend_decl,
12378 : expr1->rank, 0);
12379 0 : gfc_add_expr_to_block (&final_se.pre, tmp);
12380 : }
12381 : }
12382 :
12383 45 : if (finalizable && gfc_assignment_finalizer_call (&final_se, expr1, false))
12384 : {
12385 45 : gfc_add_block_to_block (&se.pre, &final_se.pre);
12386 45 : gfc_add_block_to_block (&se.post, &final_se.finalblock);
12387 : }
12388 :
12389 6873 : if (finalizable)
12390 45 : sym->backend_decl = lhs;
12391 :
12392 6873 : gfc_conv_array_parameter (&se, expr1, false, NULL, NULL, NULL);
12393 :
12394 6873 : if (expr1->ts.type == BT_DERIVED
12395 264 : && expr1->ts.u.derived->attr.alloc_comp)
12396 : {
12397 110 : tmp = build_fold_indirect_ref_loc (input_location, se.expr);
12398 110 : tmp = gfc_deallocate_alloc_comp_no_caf (expr1->ts.u.derived, tmp,
12399 : expr1->rank);
12400 110 : gfc_add_expr_to_block (&se.pre, tmp);
12401 : }
12402 :
12403 6873 : se.direct_byref = 1;
12404 6873 : se.ss = gfc_walk_expr (expr2);
12405 6873 : gcc_assert (se.ss != gfc_ss_terminator);
12406 :
12407 : /* Since this is a direct by reference call, references to the lhs can be
12408 : used for finalization of the function result just as long as the blocks
12409 : from final_se are added at the right time. */
12410 6873 : gfc_init_se (&final_se, NULL);
12411 6873 : if (finalizable && expr2->value.function.esym)
12412 : {
12413 32 : final_se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
12414 32 : gfc_finalize_tree_expr (&final_se, expr2->ts.u.derived,
12415 32 : expr2->value.function.esym->attr,
12416 : expr2->rank);
12417 : }
12418 :
12419 : /* Reallocate on assignment needs the loopinfo for extrinsic functions.
12420 : This is signalled to gfc_conv_procedure_call by setting is_alloc_lhs.
12421 : Clearly, this cannot be done for an allocatable function result, since
12422 : the shape of the result is unknown and, in any case, the function must
12423 : correctly take care of the reallocation internally. For intrinsic
12424 : calls, the array data is freed and the library takes care of allocation.
12425 : TODO: Add logic of trans-array.cc: gfc_alloc_allocatable_for_assignment
12426 : to the library. */
12427 6873 : if (flag_realloc_lhs
12428 6798 : && gfc_is_reallocatable_lhs (expr1)
12429 9214 : && !gfc_expr_attr (expr1).codimension
12430 2341 : && !gfc_is_coindexed (expr1)
12431 9214 : && !(expr2->value.function.esym
12432 203 : && expr2->value.function.esym->result->attr.allocatable))
12433 : {
12434 2341 : realloc_lhs_warning (expr1->ts.type, true, &expr1->where);
12435 :
12436 2341 : if (!expr2->value.function.isym)
12437 : {
12438 203 : ss = gfc_walk_expr (expr1);
12439 203 : gcc_assert (ss != gfc_ss_terminator);
12440 :
12441 203 : realloc_lhs_loop_for_fcn_call (&se, &expr1->where, &ss, &loop);
12442 203 : ss->is_alloc_lhs = 1;
12443 : }
12444 : else
12445 : {
12446 2138 : tree dtype = NULL_TREE;
12447 2138 : tree type = gfc_typenode_for_spec (&expr2->ts);
12448 2138 : if (expr1->ts.type == BT_CLASS)
12449 : {
12450 13 : tmp = gfc_class_vptr_get (sym->backend_decl);
12451 13 : tree tmp2 = gfc_get_symbol_decl (gfc_find_vtab (&expr2->ts));
12452 13 : tmp2 = gfc_build_addr_expr (TREE_TYPE (tmp), tmp2);
12453 13 : gfc_add_modify (&se.pre, tmp, tmp2);
12454 13 : dtype = gfc_get_dtype_rank_type (expr1->rank,type);
12455 : }
12456 2138 : fcncall_realloc_result (&se, expr1->rank, dtype);
12457 : }
12458 : }
12459 :
12460 6873 : gfc_conv_function_expr (&se, expr2);
12461 :
12462 : /* Fix the result. */
12463 6873 : gfc_add_block_to_block (&se.pre, &se.post);
12464 6873 : if (finalizable)
12465 45 : gfc_add_block_to_block (&se.pre, &final_se.pre);
12466 :
12467 : /* Do the finalization, including final calls from function arguments. */
12468 45 : if (finalizable)
12469 : {
12470 45 : gfc_add_block_to_block (&se.pre, &final_se.post);
12471 45 : gfc_add_block_to_block (&se.pre, &se.finalblock);
12472 45 : gfc_add_block_to_block (&se.pre, &final_se.finalblock);
12473 : }
12474 :
12475 6873 : if (ss)
12476 203 : gfc_cleanup_loop (&loop);
12477 : else
12478 6670 : gfc_free_ss_chain (se.ss);
12479 :
12480 6873 : return gfc_finish_block (&se.pre);
12481 : }
12482 :
12483 :
12484 : /* Try to efficiently translate array(:) = 0. Return NULL if this
12485 : can't be done. */
12486 :
12487 : static tree
12488 3951 : gfc_trans_zero_assign (gfc_expr * expr)
12489 : {
12490 3951 : tree dest, len, type;
12491 3951 : tree tmp;
12492 3951 : gfc_symbol *sym;
12493 :
12494 3951 : sym = expr->symtree->n.sym;
12495 3951 : dest = gfc_get_symbol_decl (sym);
12496 :
12497 3951 : type = TREE_TYPE (dest);
12498 3951 : if (POINTER_TYPE_P (type))
12499 249 : type = TREE_TYPE (type);
12500 3951 : if (GFC_ARRAY_TYPE_P (type))
12501 : {
12502 : /* Determine the length of the array. */
12503 2772 : len = GFC_TYPE_ARRAY_SIZE (type);
12504 2772 : if (!len || TREE_CODE (len) != INTEGER_CST)
12505 : return NULL_TREE;
12506 : }
12507 1179 : else if (GFC_DESCRIPTOR_TYPE_P (type)
12508 1179 : && gfc_is_simply_contiguous (expr, false, false))
12509 : {
12510 1079 : if (POINTER_TYPE_P (TREE_TYPE (dest)))
12511 4 : dest = build_fold_indirect_ref_loc (input_location, dest);
12512 1079 : len = gfc_conv_descriptor_size (dest, GFC_TYPE_ARRAY_RANK (type));
12513 1079 : dest = gfc_conv_descriptor_data_get (dest);
12514 : }
12515 : else
12516 100 : return NULL_TREE;
12517 :
12518 : /* If we are zeroing a local array avoid taking its address by emitting
12519 : a = {} instead. */
12520 3672 : if (!POINTER_TYPE_P (TREE_TYPE (dest)))
12521 2550 : return build2_loc (input_location, MODIFY_EXPR, void_type_node,
12522 2550 : dest, build_constructor (TREE_TYPE (dest),
12523 2550 : NULL));
12524 :
12525 : /* Multiply len by element size. */
12526 1122 : tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
12527 1122 : len = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
12528 : len, fold_convert (gfc_array_index_type, tmp));
12529 :
12530 : /* Convert arguments to the correct types. */
12531 1122 : dest = fold_convert (pvoid_type_node, dest);
12532 1122 : len = fold_convert (size_type_node, len);
12533 :
12534 : /* Construct call to __builtin_memset. */
12535 1122 : tmp = build_call_expr_loc (input_location,
12536 : builtin_decl_explicit (BUILT_IN_MEMSET),
12537 : 3, dest, integer_zero_node, len);
12538 1122 : return fold_convert (void_type_node, tmp);
12539 : }
12540 :
12541 :
12542 : /* Helper for gfc_trans_array_copy and gfc_trans_array_constructor_copy
12543 : that constructs the call to __builtin_memcpy. */
12544 :
12545 : tree
12546 8016 : gfc_build_memcpy_call (tree dst, tree src, tree len)
12547 : {
12548 8016 : tree tmp;
12549 :
12550 : /* Convert arguments to the correct types. */
12551 8016 : if (!POINTER_TYPE_P (TREE_TYPE (dst)))
12552 7715 : dst = gfc_build_addr_expr (pvoid_type_node, dst);
12553 : else
12554 301 : dst = fold_convert (pvoid_type_node, dst);
12555 :
12556 8016 : if (!POINTER_TYPE_P (TREE_TYPE (src)))
12557 7608 : src = gfc_build_addr_expr (pvoid_type_node, src);
12558 : else
12559 408 : src = fold_convert (pvoid_type_node, src);
12560 :
12561 8016 : len = fold_convert (size_type_node, len);
12562 :
12563 : /* Construct call to __builtin_memcpy. */
12564 8016 : tmp = build_call_expr_loc (input_location,
12565 : builtin_decl_explicit (BUILT_IN_MEMCPY),
12566 : 3, dst, src, len);
12567 8016 : return fold_convert (void_type_node, tmp);
12568 : }
12569 :
12570 :
12571 : /* Try to efficiently translate dst(:) = src(:). Return NULL if this
12572 : can't be done. EXPR1 is the destination/lhs and EXPR2 is the
12573 : source/rhs, both are gfc_full_array_ref_p which have been checked for
12574 : dependencies. */
12575 :
12576 : static tree
12577 2603 : gfc_trans_array_copy (gfc_expr * expr1, gfc_expr * expr2)
12578 : {
12579 2603 : tree dst, dlen, dtype;
12580 2603 : tree src, slen, stype;
12581 2603 : tree tmp;
12582 :
12583 2603 : dst = gfc_get_symbol_decl (expr1->symtree->n.sym);
12584 2603 : src = gfc_get_symbol_decl (expr2->symtree->n.sym);
12585 :
12586 2603 : dtype = TREE_TYPE (dst);
12587 2603 : if (POINTER_TYPE_P (dtype))
12588 265 : dtype = TREE_TYPE (dtype);
12589 2603 : stype = TREE_TYPE (src);
12590 2603 : if (POINTER_TYPE_P (stype))
12591 293 : stype = TREE_TYPE (stype);
12592 :
12593 2603 : if (!GFC_ARRAY_TYPE_P (dtype) || !GFC_ARRAY_TYPE_P (stype))
12594 : return NULL_TREE;
12595 :
12596 : /* Determine the lengths of the arrays. */
12597 1581 : dlen = GFC_TYPE_ARRAY_SIZE (dtype);
12598 1581 : if (!dlen || TREE_CODE (dlen) != INTEGER_CST)
12599 : return NULL_TREE;
12600 1492 : tmp = TYPE_SIZE_UNIT (gfc_get_element_type (dtype));
12601 1492 : dlen = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
12602 : dlen, fold_convert (gfc_array_index_type, tmp));
12603 :
12604 1492 : slen = GFC_TYPE_ARRAY_SIZE (stype);
12605 1492 : if (!slen || TREE_CODE (slen) != INTEGER_CST)
12606 : return NULL_TREE;
12607 1486 : tmp = TYPE_SIZE_UNIT (gfc_get_element_type (stype));
12608 1486 : slen = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
12609 : slen, fold_convert (gfc_array_index_type, tmp));
12610 :
12611 : /* Sanity check that they are the same. This should always be
12612 : the case, as we should already have checked for conformance. */
12613 1486 : if (!tree_int_cst_equal (slen, dlen))
12614 : return NULL_TREE;
12615 :
12616 1486 : return gfc_build_memcpy_call (dst, src, dlen);
12617 : }
12618 :
12619 :
12620 : /* Try to efficiently translate array(:) = (/ ... /). Return NULL if
12621 : this can't be done. EXPR1 is the destination/lhs for which
12622 : gfc_full_array_ref_p is true, and EXPR2 is the source/rhs. */
12623 :
12624 : static tree
12625 8243 : gfc_trans_array_constructor_copy (gfc_expr * expr1, gfc_expr * expr2)
12626 : {
12627 8243 : unsigned HOST_WIDE_INT nelem;
12628 8243 : tree dst, dtype;
12629 8243 : tree src, stype;
12630 8243 : tree len;
12631 8243 : tree tmp;
12632 :
12633 8243 : nelem = gfc_constant_array_constructor_p (expr2->value.constructor);
12634 8243 : if (nelem == 0)
12635 : return NULL_TREE;
12636 :
12637 6850 : dst = gfc_get_symbol_decl (expr1->symtree->n.sym);
12638 6850 : dtype = TREE_TYPE (dst);
12639 6850 : if (POINTER_TYPE_P (dtype))
12640 265 : dtype = TREE_TYPE (dtype);
12641 6850 : if (!GFC_ARRAY_TYPE_P (dtype))
12642 : return NULL_TREE;
12643 :
12644 : /* Determine the lengths of the array. */
12645 6003 : len = GFC_TYPE_ARRAY_SIZE (dtype);
12646 6003 : if (!len || TREE_CODE (len) != INTEGER_CST)
12647 : return NULL_TREE;
12648 :
12649 : /* Confirm that the constructor is the same size. */
12650 5899 : if (compare_tree_int (len, nelem) != 0)
12651 : return NULL_TREE;
12652 :
12653 5899 : tmp = TYPE_SIZE_UNIT (gfc_get_element_type (dtype));
12654 5899 : len = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type, len,
12655 : fold_convert (gfc_array_index_type, tmp));
12656 :
12657 5899 : stype = gfc_typenode_for_spec (&expr2->ts);
12658 5899 : src = gfc_build_constant_array_constructor (expr2, stype);
12659 :
12660 5899 : return gfc_build_memcpy_call (dst, src, len);
12661 : }
12662 :
12663 :
12664 : /* Tells whether the expression is to be treated as a variable reference. */
12665 :
12666 : bool
12667 315609 : gfc_expr_is_variable (gfc_expr *expr)
12668 : {
12669 315881 : gfc_expr *arg;
12670 315881 : gfc_component *comp;
12671 315881 : gfc_symbol *func_ifc;
12672 :
12673 315881 : if (expr->expr_type == EXPR_VARIABLE)
12674 : return true;
12675 :
12676 280480 : arg = gfc_get_noncopying_intrinsic_argument (expr);
12677 280480 : if (arg)
12678 : {
12679 272 : gcc_assert (expr->value.function.isym->id == GFC_ISYM_TRANSPOSE);
12680 : return gfc_expr_is_variable (arg);
12681 : }
12682 :
12683 : /* A data-pointer-returning function should be considered as a variable
12684 : too. */
12685 280208 : if (expr->expr_type == EXPR_FUNCTION
12686 37319 : && expr->ref == NULL)
12687 : {
12688 36930 : if (expr->value.function.isym != NULL)
12689 : return false;
12690 :
12691 9634 : if (expr->value.function.esym != NULL)
12692 : {
12693 9625 : func_ifc = expr->value.function.esym;
12694 9625 : goto found_ifc;
12695 : }
12696 9 : gcc_assert (expr->symtree);
12697 9 : func_ifc = expr->symtree->n.sym;
12698 9 : goto found_ifc;
12699 : }
12700 :
12701 243278 : comp = gfc_get_proc_ptr_comp (expr);
12702 243278 : if ((expr->expr_type == EXPR_PPC || expr->expr_type == EXPR_FUNCTION)
12703 389 : && comp)
12704 : {
12705 275 : func_ifc = comp->ts.interface;
12706 275 : goto found_ifc;
12707 : }
12708 :
12709 243003 : if (expr->expr_type == EXPR_COMPCALL)
12710 : {
12711 0 : gcc_assert (!expr->value.compcall.tbp->is_generic);
12712 0 : func_ifc = expr->value.compcall.tbp->u.specific->n.sym;
12713 0 : goto found_ifc;
12714 : }
12715 :
12716 : return false;
12717 :
12718 9909 : found_ifc:
12719 9909 : gcc_assert (func_ifc->attr.function
12720 : && func_ifc->result != NULL);
12721 9909 : return func_ifc->result->attr.pointer;
12722 : }
12723 :
12724 :
12725 : /* Is the lhs OK for automatic reallocation? */
12726 :
12727 : static bool
12728 266950 : is_scalar_reallocatable_lhs (gfc_expr *expr)
12729 : {
12730 266950 : gfc_ref * ref;
12731 :
12732 : /* An allocatable variable with no reference. */
12733 266950 : if (expr->symtree->n.sym->attr.allocatable
12734 6801 : && !expr->ref)
12735 : return true;
12736 :
12737 : /* All that can be left are allocatable components. However, we do
12738 : not check for allocatable components here because the expression
12739 : could be an allocatable component of a pointer component. */
12740 264147 : if (expr->symtree->n.sym->ts.type != BT_DERIVED
12741 241364 : && expr->symtree->n.sym->ts.type != BT_CLASS)
12742 : return false;
12743 :
12744 : /* Find an allocatable component ref last. */
12745 40280 : for (ref = expr->ref; ref; ref = ref->next)
12746 16541 : if (ref->type == REF_COMPONENT
12747 12221 : && !ref->next
12748 9419 : && ref->u.c.component->attr.allocatable)
12749 : return true;
12750 :
12751 : return false;
12752 : }
12753 :
12754 :
12755 : /* Allocate or reallocate scalar lhs, as necessary. */
12756 :
12757 : static void
12758 3655 : alloc_scalar_allocatable_for_assignment (stmtblock_t *block,
12759 : tree string_length,
12760 : gfc_expr *expr1,
12761 : gfc_expr *expr2)
12762 :
12763 : {
12764 3655 : tree cond;
12765 3655 : tree tmp;
12766 3655 : tree size;
12767 3655 : tree size_in_bytes;
12768 3655 : tree jump_label1;
12769 3655 : tree jump_label2;
12770 3655 : gfc_se lse;
12771 3655 : gfc_ref *ref;
12772 :
12773 3655 : if (!expr1 || expr1->rank)
12774 0 : return;
12775 :
12776 3655 : if (!expr2 || expr2->rank)
12777 : return;
12778 :
12779 5115 : for (ref = expr1->ref; ref; ref = ref->next)
12780 1460 : if (ref->type == REF_SUBSTRING)
12781 : return;
12782 :
12783 3655 : realloc_lhs_warning (expr2->ts.type, false, &expr2->where);
12784 :
12785 : /* Since this is a scalar lhs, we can afford to do this. That is,
12786 : there is no risk of side effects being repeated. */
12787 3655 : gfc_init_se (&lse, NULL);
12788 3655 : lse.want_pointer = 1;
12789 3655 : gfc_conv_expr (&lse, expr1);
12790 :
12791 3655 : jump_label1 = gfc_build_label_decl (NULL_TREE);
12792 3655 : jump_label2 = gfc_build_label_decl (NULL_TREE);
12793 :
12794 : /* Do the allocation if the lhs is NULL. Otherwise go to label 1. */
12795 3655 : tmp = build_int_cst (TREE_TYPE (lse.expr), 0);
12796 3655 : cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
12797 : lse.expr, tmp);
12798 3655 : tmp = build3_v (COND_EXPR, cond,
12799 : build1_v (GOTO_EXPR, jump_label1),
12800 : build_empty_stmt (input_location));
12801 3655 : gfc_add_expr_to_block (block, tmp);
12802 :
12803 3655 : if (expr1->ts.type == BT_CHARACTER && expr1->ts.deferred)
12804 : {
12805 : /* Use the rhs string length and the lhs element size. Note that 'size' is
12806 : used below for the string-length comparison, only. */
12807 1518 : size = string_length;
12808 1518 : tmp = TYPE_SIZE_UNIT (gfc_get_char_type (expr1->ts.kind));
12809 3036 : size_in_bytes = fold_build2_loc (input_location, MULT_EXPR,
12810 1518 : TREE_TYPE (tmp), tmp,
12811 1518 : fold_convert (TREE_TYPE (tmp), size));
12812 : }
12813 : else
12814 : {
12815 : /* Otherwise use the length in bytes of the rhs. */
12816 2137 : size = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&expr1->ts));
12817 2137 : size_in_bytes = size;
12818 : }
12819 :
12820 3655 : size_in_bytes = fold_build2_loc (input_location, MAX_EXPR, size_type_node,
12821 : size_in_bytes, size_one_node);
12822 :
12823 3655 : if (gfc_caf_attr (expr1).codimension && flag_coarray == GFC_FCOARRAY_LIB)
12824 : {
12825 32 : tree caf_decl, token;
12826 32 : gfc_se caf_se;
12827 32 : symbol_attribute attr;
12828 :
12829 32 : gfc_clear_attr (&attr);
12830 32 : gfc_init_se (&caf_se, NULL);
12831 :
12832 32 : caf_decl = gfc_get_tree_for_caf_expr (expr1);
12833 32 : gfc_get_caf_token_offset (&caf_se, &token, NULL, caf_decl, NULL_TREE,
12834 : NULL);
12835 32 : gfc_add_block_to_block (block, &caf_se.pre);
12836 32 : gfc_allocate_allocatable (block, lse.expr, size_in_bytes,
12837 : gfc_build_addr_expr (NULL_TREE, token),
12838 : NULL_TREE, NULL_TREE, NULL_TREE, jump_label1,
12839 : expr1, 1);
12840 : }
12841 3623 : else if (expr1->ts.type == BT_DERIVED
12842 3623 : && (expr1->ts.u.derived->attr.alloc_comp
12843 220 : || has_parameterized_comps (expr1->ts.u.derived)))
12844 : {
12845 116 : tmp = build_call_expr_loc (input_location,
12846 : builtin_decl_explicit (BUILT_IN_CALLOC),
12847 : 2, build_one_cst (size_type_node),
12848 : size_in_bytes);
12849 116 : tmp = fold_convert (TREE_TYPE (lse.expr), tmp);
12850 116 : gfc_add_modify (block, lse.expr, tmp);
12851 : }
12852 : else
12853 : {
12854 3507 : tmp = build_call_expr_loc (input_location,
12855 : builtin_decl_explicit (BUILT_IN_MALLOC),
12856 : 1, size_in_bytes);
12857 3507 : tmp = fold_convert (TREE_TYPE (lse.expr), tmp);
12858 3507 : gfc_add_modify (block, lse.expr, tmp);
12859 : }
12860 :
12861 3655 : if (expr1->ts.type == BT_CHARACTER && expr1->ts.deferred)
12862 : {
12863 : /* Deferred characters need checking for lhs and rhs string
12864 : length. Other deferred parameter variables will have to
12865 : come here too. */
12866 1518 : tmp = build1_v (GOTO_EXPR, jump_label2);
12867 1518 : gfc_add_expr_to_block (block, tmp);
12868 : }
12869 3655 : tmp = build1_v (LABEL_EXPR, jump_label1);
12870 3655 : gfc_add_expr_to_block (block, tmp);
12871 :
12872 : /* For a deferred length character, reallocate if lengths of lhs and
12873 : rhs are different. */
12874 3655 : if (expr1->ts.type == BT_CHARACTER && expr1->ts.deferred)
12875 : {
12876 1518 : cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
12877 : lse.string_length,
12878 1518 : fold_convert (TREE_TYPE (lse.string_length),
12879 : size));
12880 : /* Jump past the realloc if the lengths are the same. */
12881 1518 : tmp = build3_v (COND_EXPR, cond,
12882 : build1_v (GOTO_EXPR, jump_label2),
12883 : build_empty_stmt (input_location));
12884 1518 : gfc_add_expr_to_block (block, tmp);
12885 1518 : tmp = build_call_expr_loc (input_location,
12886 : builtin_decl_explicit (BUILT_IN_REALLOC),
12887 : 2, fold_convert (pvoid_type_node, lse.expr),
12888 : size_in_bytes);
12889 1518 : tree omp_cond = NULL_TREE;
12890 1518 : if (flag_openmp_allocators)
12891 : {
12892 1 : tree omp_tmp;
12893 1 : omp_cond = gfc_omp_call_is_alloc (lse.expr);
12894 1 : omp_cond = gfc_evaluate_now (omp_cond, block);
12895 :
12896 1 : omp_tmp = builtin_decl_explicit (BUILT_IN_GOMP_REALLOC);
12897 1 : omp_tmp = build_call_expr_loc (input_location, omp_tmp, 4,
12898 : fold_convert (pvoid_type_node,
12899 : lse.expr), size_in_bytes,
12900 : build_zero_cst (ptr_type_node),
12901 : build_zero_cst (ptr_type_node));
12902 1 : tmp = build3_loc (input_location, COND_EXPR, TREE_TYPE (tmp),
12903 : omp_cond, omp_tmp, tmp);
12904 : }
12905 1518 : tmp = fold_convert (TREE_TYPE (lse.expr), tmp);
12906 1518 : gfc_add_modify (block, lse.expr, tmp);
12907 1518 : if (omp_cond)
12908 1 : gfc_add_expr_to_block (block,
12909 : build3_loc (input_location, COND_EXPR,
12910 : void_type_node, omp_cond,
12911 : gfc_omp_call_add_alloc (lse.expr),
12912 : build_empty_stmt (input_location)));
12913 1518 : tmp = build1_v (LABEL_EXPR, jump_label2);
12914 1518 : gfc_add_expr_to_block (block, tmp);
12915 :
12916 : /* Update the lhs character length. */
12917 1518 : size = string_length;
12918 1518 : gfc_add_modify (block, lse.string_length,
12919 1518 : fold_convert (TREE_TYPE (lse.string_length), size));
12920 : }
12921 : }
12922 :
12923 : /* Check for assignments of the type
12924 :
12925 : a = a + 4
12926 :
12927 : to make sure we do not check for reallocation unnecessarily. */
12928 :
12929 :
12930 : /* Strip parentheses from an expression to get the underlying variable.
12931 : This is needed for self-assignment detection since (a) creates a
12932 : parentheses operator node. */
12933 :
12934 : static gfc_expr *
12935 7972 : strip_parentheses (gfc_expr *expr)
12936 : {
12937 0 : while (expr->expr_type == EXPR_OP
12938 317146 : && expr->value.op.op == INTRINSIC_PARENTHESES)
12939 590 : expr = expr->value.op.op1;
12940 315885 : return expr;
12941 : }
12942 :
12943 :
12944 : static bool
12945 7495 : is_runtime_conformable (gfc_expr *expr1, gfc_expr *expr2)
12946 : {
12947 7972 : gfc_actual_arglist *a;
12948 7972 : gfc_expr *e1, *e2;
12949 :
12950 : /* Strip parentheses to handle cases like a = (a). */
12951 15995 : expr1 = strip_parentheses (expr1);
12952 7972 : expr2 = strip_parentheses (expr2);
12953 :
12954 7972 : switch (expr2->expr_type)
12955 : {
12956 2176 : case EXPR_VARIABLE:
12957 2176 : return gfc_dep_compare_expr (expr1, expr2) == 0;
12958 :
12959 2839 : case EXPR_FUNCTION:
12960 2839 : if (expr2->value.function.esym
12961 305 : && expr2->value.function.esym->attr.elemental)
12962 : {
12963 75 : for (a = expr2->value.function.actual; a != NULL; a = a->next)
12964 : {
12965 74 : e1 = a->expr;
12966 74 : if (e1 && e1->rank > 0 && !is_runtime_conformable (expr1, e1))
12967 : return false;
12968 : }
12969 : return true;
12970 : }
12971 2777 : else if (expr2->value.function.isym
12972 2520 : && expr2->value.function.isym->elemental)
12973 : {
12974 332 : for (a = expr2->value.function.actual; a != NULL; a = a->next)
12975 : {
12976 322 : e1 = a->expr;
12977 322 : if (e1 && e1->rank > 0 && !is_runtime_conformable (expr1, e1))
12978 : return false;
12979 : }
12980 : return true;
12981 : }
12982 :
12983 : break;
12984 :
12985 671 : case EXPR_OP:
12986 671 : switch (expr2->value.op.op)
12987 : {
12988 19 : case INTRINSIC_NOT:
12989 19 : case INTRINSIC_UPLUS:
12990 19 : case INTRINSIC_UMINUS:
12991 19 : case INTRINSIC_PARENTHESES:
12992 19 : return is_runtime_conformable (expr1, expr2->value.op.op1);
12993 :
12994 627 : case INTRINSIC_PLUS:
12995 627 : case INTRINSIC_MINUS:
12996 627 : case INTRINSIC_TIMES:
12997 627 : case INTRINSIC_DIVIDE:
12998 627 : case INTRINSIC_POWER:
12999 627 : case INTRINSIC_AND:
13000 627 : case INTRINSIC_OR:
13001 627 : case INTRINSIC_EQV:
13002 627 : case INTRINSIC_NEQV:
13003 627 : case INTRINSIC_EQ:
13004 627 : case INTRINSIC_NE:
13005 627 : case INTRINSIC_GT:
13006 627 : case INTRINSIC_GE:
13007 627 : case INTRINSIC_LT:
13008 627 : case INTRINSIC_LE:
13009 627 : case INTRINSIC_EQ_OS:
13010 627 : case INTRINSIC_NE_OS:
13011 627 : case INTRINSIC_GT_OS:
13012 627 : case INTRINSIC_GE_OS:
13013 627 : case INTRINSIC_LT_OS:
13014 627 : case INTRINSIC_LE_OS:
13015 :
13016 627 : e1 = expr2->value.op.op1;
13017 627 : e2 = expr2->value.op.op2;
13018 :
13019 627 : if (e1->rank == 0 && e2->rank > 0)
13020 : return is_runtime_conformable (expr1, e2);
13021 569 : else if (e1->rank > 0 && e2->rank == 0)
13022 : return is_runtime_conformable (expr1, e1);
13023 169 : else if (e1->rank > 0 && e2->rank > 0)
13024 169 : return is_runtime_conformable (expr1, e1)
13025 169 : && is_runtime_conformable (expr1, e2);
13026 : break;
13027 :
13028 : default:
13029 : break;
13030 :
13031 : }
13032 :
13033 : break;
13034 :
13035 : default:
13036 : break;
13037 : }
13038 : return false;
13039 : }
13040 :
13041 :
13042 : static tree
13043 3319 : trans_class_assignment (stmtblock_t *block, gfc_expr *lhs, gfc_expr *rhs,
13044 : gfc_se *lse, gfc_se *rse, bool use_vptr_copy,
13045 : bool class_realloc)
13046 : {
13047 3319 : tree tmp, fcn, stdcopy, to_len, from_len, vptr, old_vptr, rhs_vptr;
13048 3319 : vec<tree, va_gc> *args = NULL;
13049 3319 : bool final_expr;
13050 :
13051 3319 : final_expr = gfc_assignment_finalizer_call (lse, lhs, false);
13052 3319 : if (final_expr)
13053 : {
13054 473 : if (rse->loop)
13055 226 : gfc_prepend_expr_to_block (&rse->loop->pre,
13056 : gfc_finish_block (&lse->finalblock));
13057 : else
13058 247 : gfc_add_block_to_block (block, &lse->finalblock);
13059 : }
13060 :
13061 : /* Store the old vptr so that dynamic types can be compared for
13062 : reallocation to occur or not. */
13063 3319 : if (class_realloc)
13064 : {
13065 283 : tmp = lse->expr;
13066 283 : if (!GFC_CLASS_TYPE_P (TREE_TYPE (tmp)))
13067 0 : tmp = gfc_get_class_from_expr (tmp);
13068 : }
13069 :
13070 3319 : vptr = trans_class_vptr_len_assignment (block, lhs, rhs, rse, &to_len,
13071 : &from_len, &rhs_vptr);
13072 3319 : if (rhs_vptr == NULL_TREE)
13073 43 : rhs_vptr = vptr;
13074 :
13075 : /* Generate (re)allocation of the lhs. */
13076 3319 : if (class_realloc)
13077 : {
13078 283 : stmtblock_t alloc, re_alloc;
13079 283 : tree class_han, re, size;
13080 :
13081 283 : if (tmp && GFC_CLASS_TYPE_P (TREE_TYPE (tmp)))
13082 283 : old_vptr = gfc_evaluate_now (gfc_class_vptr_get (tmp), block);
13083 : else
13084 0 : old_vptr = build_int_cst (TREE_TYPE (vptr), 0);
13085 :
13086 283 : size = gfc_vptr_size_get (rhs_vptr);
13087 :
13088 : /* Take into account _len of unlimited polymorphic entities.
13089 : TODO: handle class(*) allocatable function results on rhs. */
13090 283 : if (UNLIMITED_POLY (rhs))
13091 : {
13092 18 : tree len;
13093 18 : if (rhs->expr_type == EXPR_VARIABLE)
13094 12 : len = trans_get_upoly_len (block, rhs);
13095 : else
13096 6 : len = gfc_class_len_get (tmp);
13097 18 : len = fold_build2_loc (input_location, MAX_EXPR, size_type_node,
13098 : fold_convert (size_type_node, len),
13099 : size_one_node);
13100 18 : size = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (size),
13101 18 : size, fold_convert (TREE_TYPE (size), len));
13102 18 : }
13103 265 : else if (rhs->ts.type == BT_CHARACTER && rse->string_length)
13104 27 : size = fold_build2_loc (input_location, MULT_EXPR,
13105 : gfc_charlen_type_node, size,
13106 : rse->string_length);
13107 :
13108 :
13109 283 : tmp = lse->expr;
13110 283 : class_han = GFC_CLASS_TYPE_P (TREE_TYPE (tmp))
13111 283 : ? gfc_class_data_get (tmp) : tmp;
13112 :
13113 283 : if (!POINTER_TYPE_P (TREE_TYPE (class_han)))
13114 0 : class_han = gfc_build_addr_expr (NULL_TREE, class_han);
13115 :
13116 : /* Allocate block. */
13117 283 : gfc_init_block (&alloc);
13118 283 : gfc_allocate_using_malloc (&alloc, class_han, size, NULL_TREE);
13119 :
13120 : /* Reallocate if dynamic types are different. */
13121 283 : gfc_init_block (&re_alloc);
13122 283 : if (UNLIMITED_POLY (lhs) && rhs->ts.type == BT_CHARACTER)
13123 : {
13124 27 : gfc_add_expr_to_block (&re_alloc, gfc_call_free (class_han));
13125 27 : gfc_allocate_using_malloc (&re_alloc, class_han, size, NULL_TREE);
13126 : }
13127 : else
13128 : {
13129 256 : tmp = fold_convert (pvoid_type_node, class_han);
13130 256 : re = build_call_expr_loc (input_location,
13131 : builtin_decl_explicit (BUILT_IN_REALLOC),
13132 : 2, tmp, size);
13133 256 : re = fold_build2_loc (input_location, MODIFY_EXPR, TREE_TYPE (tmp),
13134 : tmp, re);
13135 256 : tmp = fold_build2_loc (input_location, NE_EXPR,
13136 : logical_type_node, rhs_vptr, old_vptr);
13137 256 : re = fold_build3_loc (input_location, COND_EXPR, void_type_node,
13138 : tmp, re, build_empty_stmt (input_location));
13139 256 : gfc_add_expr_to_block (&re_alloc, re);
13140 : }
13141 283 : tree realloc_expr = lhs->ts.type == BT_CLASS ?
13142 283 : gfc_finish_block (&re_alloc) :
13143 0 : build_empty_stmt (input_location);
13144 :
13145 : /* Allocate if _data is NULL, reallocate otherwise. */
13146 283 : tmp = fold_build2_loc (input_location, EQ_EXPR,
13147 : logical_type_node, class_han,
13148 : build_int_cst (prvoid_type_node, 0));
13149 283 : tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
13150 : gfc_unlikely (tmp,
13151 : PRED_FORTRAN_FAIL_ALLOC),
13152 : gfc_finish_block (&alloc),
13153 : realloc_expr);
13154 283 : gfc_add_expr_to_block (&lse->pre, tmp);
13155 : }
13156 :
13157 3319 : fcn = gfc_vptr_copy_get (vptr);
13158 :
13159 3319 : tmp = GFC_CLASS_TYPE_P (TREE_TYPE (rse->expr))
13160 3319 : ? gfc_class_data_get (rse->expr) : rse->expr;
13161 3319 : if (use_vptr_copy)
13162 : {
13163 5584 : if (!POINTER_TYPE_P (TREE_TYPE (tmp))
13164 524 : || INDIRECT_REF_P (tmp)
13165 403 : || (rhs->ts.type == BT_DERIVED
13166 0 : && rhs->ts.u.derived->attr.unlimited_polymorphic
13167 0 : && !rhs->ts.u.derived->attr.pointer
13168 0 : && !rhs->ts.u.derived->attr.allocatable)
13169 3454 : || (UNLIMITED_POLY (rhs)
13170 134 : && !CLASS_DATA (rhs)->attr.pointer
13171 43 : && !CLASS_DATA (rhs)->attr.allocatable))
13172 2648 : vec_safe_push (args, gfc_build_addr_expr (NULL_TREE, tmp));
13173 : else
13174 403 : vec_safe_push (args, tmp);
13175 3051 : tmp = GFC_CLASS_TYPE_P (TREE_TYPE (lse->expr))
13176 3051 : ? gfc_class_data_get (lse->expr) : lse->expr;
13177 5322 : if (!POINTER_TYPE_P (TREE_TYPE (tmp))
13178 780 : || INDIRECT_REF_P (tmp)
13179 283 : || (lhs->ts.type == BT_DERIVED
13180 0 : && lhs->ts.u.derived->attr.unlimited_polymorphic
13181 0 : && !lhs->ts.u.derived->attr.pointer
13182 0 : && !lhs->ts.u.derived->attr.allocatable)
13183 3334 : || (UNLIMITED_POLY (lhs)
13184 119 : && !CLASS_DATA (lhs)->attr.pointer
13185 119 : && !CLASS_DATA (lhs)->attr.allocatable))
13186 2768 : vec_safe_push (args, gfc_build_addr_expr (NULL_TREE, tmp));
13187 : else
13188 283 : vec_safe_push (args, tmp);
13189 :
13190 3051 : stdcopy = build_call_vec (TREE_TYPE (TREE_TYPE (fcn)), fcn, args);
13191 :
13192 3051 : if (to_len != NULL_TREE && !integer_zerop (from_len))
13193 : {
13194 406 : tree extcopy;
13195 406 : vec_safe_push (args, from_len);
13196 406 : vec_safe_push (args, to_len);
13197 406 : extcopy = build_call_vec (TREE_TYPE (TREE_TYPE (fcn)), fcn, args);
13198 :
13199 406 : tmp = fold_build2_loc (input_location, GT_EXPR,
13200 : logical_type_node, from_len,
13201 406 : build_zero_cst (TREE_TYPE (from_len)));
13202 406 : return fold_build3_loc (input_location, COND_EXPR,
13203 : void_type_node, tmp,
13204 406 : extcopy, stdcopy);
13205 : }
13206 : else
13207 2645 : return stdcopy;
13208 : }
13209 : else
13210 : {
13211 268 : tree rhst = GFC_CLASS_TYPE_P (TREE_TYPE (lse->expr))
13212 268 : ? gfc_class_data_get (lse->expr) : lse->expr;
13213 268 : stmtblock_t tblock;
13214 268 : gfc_init_block (&tblock);
13215 268 : if (!POINTER_TYPE_P (TREE_TYPE (tmp)))
13216 0 : tmp = gfc_build_addr_expr (NULL_TREE, tmp);
13217 268 : if (!POINTER_TYPE_P (TREE_TYPE (rhst)))
13218 0 : rhst = gfc_build_addr_expr (NULL_TREE, rhst);
13219 : /* When coming from a ptr_copy lhs and rhs are swapped. */
13220 268 : gfc_add_modify_loc (input_location, &tblock, rhst,
13221 268 : fold_convert (TREE_TYPE (rhst), tmp));
13222 268 : return gfc_finish_block (&tblock);
13223 : }
13224 : }
13225 :
13226 : bool
13227 309845 : is_assoc_assign (gfc_expr *lhs, gfc_expr *rhs)
13228 : {
13229 309845 : if (lhs->expr_type != EXPR_VARIABLE || rhs->expr_type != EXPR_VARIABLE)
13230 : return false;
13231 :
13232 31902 : return lhs->symtree->n.sym->assoc
13233 31902 : && lhs->symtree->n.sym->assoc->target == rhs;
13234 : }
13235 :
13236 : /* Subroutine of gfc_trans_assignment that actually scalarizes the
13237 : assignment. EXPR1 is the destination/LHS and EXPR2 is the source/RHS.
13238 : init_flag indicates initialization expressions and dealloc that no
13239 : deallocate prior assignment is needed (if in doubt, set true).
13240 : When PTR_COPY is set and expr1 is a class type, then use the _vptr-copy
13241 : routine instead of a pointer assignment. Alias resolution is only done,
13242 : when MAY_ALIAS is set (the default). This flag is used by ALLOCATE()
13243 : where it is known, that newly allocated memory on the lhs can never be
13244 : an alias of the rhs. */
13245 :
13246 : static tree
13247 309845 : gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag,
13248 : bool dealloc, bool use_vptr_copy, bool may_alias)
13249 : {
13250 309845 : gfc_se lse;
13251 309845 : gfc_se rse;
13252 309845 : gfc_ss *lss;
13253 309845 : gfc_ss *lss_section;
13254 309845 : gfc_ss *rss;
13255 309845 : gfc_loopinfo loop;
13256 309845 : tree tmp;
13257 309845 : stmtblock_t block;
13258 309845 : stmtblock_t body;
13259 309845 : bool final_expr;
13260 309845 : bool l_is_temp;
13261 309845 : bool scalar_to_array;
13262 309845 : tree string_length;
13263 309845 : int n;
13264 309845 : bool maybe_workshare = false, lhs_refs_comp = false, rhs_refs_comp = false;
13265 309845 : symbol_attribute lhs_caf_attr, rhs_caf_attr, lhs_attr, rhs_attr;
13266 309845 : bool is_poly_assign;
13267 309845 : bool realloc_flag;
13268 309845 : bool assoc_assign = false;
13269 309845 : bool dummy_class_array_copy;
13270 :
13271 : /* Assignment of the form lhs = rhs. */
13272 309845 : gfc_start_block (&block);
13273 :
13274 309845 : gfc_init_se (&lse, NULL);
13275 309845 : gfc_init_se (&rse, NULL);
13276 :
13277 309845 : gfc_fix_class_refs (expr1);
13278 :
13279 619690 : realloc_flag = flag_realloc_lhs
13280 303747 : && gfc_is_reallocatable_lhs (expr1)
13281 8302 : && expr2->rank
13282 316680 : && !is_runtime_conformable (expr1, expr2);
13283 :
13284 : /* Walk the lhs. */
13285 309845 : lss = gfc_walk_expr (expr1);
13286 309845 : if (realloc_flag)
13287 : {
13288 6452 : lss->no_bounds_check = 1;
13289 6452 : lss->is_alloc_lhs = 1;
13290 : }
13291 : else
13292 303393 : lss->no_bounds_check = expr1->no_bounds_check;
13293 :
13294 309845 : rss = NULL;
13295 :
13296 309845 : if (expr2->expr_type != EXPR_VARIABLE
13297 309845 : && expr2->expr_type != EXPR_CONSTANT
13298 309845 : && (expr2->ts.type == BT_CLASS || gfc_may_be_finalized (expr2->ts)))
13299 : {
13300 894 : expr2->must_finalize = 1;
13301 : /* F2023 7.5.6.3: If an executable construct references a nonpointer
13302 : function, the result is finalized after execution of the innermost
13303 : executable construct containing the reference. */
13304 894 : if (expr2->expr_type == EXPR_FUNCTION
13305 894 : && (gfc_expr_attr (expr2).pointer
13306 298 : || (expr2->ts.type == BT_CLASS && CLASS_DATA (expr2)->attr.class_pointer)))
13307 147 : expr2->must_finalize = 0;
13308 : /* F2008 4.5.6.3 para 5: If an executable construct references a
13309 : structure constructor or array constructor, the entity created by
13310 : the constructor is finalized after execution of the innermost
13311 : executable construct containing the reference.
13312 : These finalizations were later deleted by the Combined Technical
13313 : Corrigenda 1 TO 4 for fortran 2008 (f08/0011). */
13314 747 : else if (gfc_notification_std (GFC_STD_F2018_DEL)
13315 747 : && (expr2->expr_type == EXPR_STRUCTURE
13316 704 : || expr2->expr_type == EXPR_ARRAY))
13317 387 : expr2->must_finalize = 0;
13318 : }
13319 :
13320 :
13321 : /* Checking whether a class assignment is desired is quite complicated and
13322 : needed at two locations, so do it once only before the information is
13323 : needed. */
13324 309845 : lhs_attr = gfc_expr_attr (expr1);
13325 309845 : rhs_attr = gfc_expr_attr (expr2);
13326 309845 : dummy_class_array_copy
13327 619690 : = (expr2->expr_type == EXPR_VARIABLE
13328 31902 : && expr2->rank > 0
13329 8384 : && expr2->symtree != NULL
13330 8384 : && expr2->symtree->n.sym->attr.dummy
13331 1471 : && expr2->ts.type == BT_CLASS
13332 127 : && !rhs_attr.pointer
13333 127 : && !rhs_attr.allocatable
13334 114 : && !CLASS_DATA (expr2)->attr.class_pointer
13335 309959 : && !CLASS_DATA (expr2)->attr.allocatable);
13336 :
13337 : /* What can be sent to trans_class_assignment includes all the obvious
13338 : candidates but scalar assignment of a class expression to a derived type
13339 : must be done using gfc_trans_scalar_assign; partly because it is simpler
13340 : and partly because some cases fail, eg. class assignment to derived_type
13341 : select type temporaries. */
13342 309845 : is_poly_assign
13343 309845 : = (use_vptr_copy
13344 292848 : || ((lhs_attr.pointer || lhs_attr.allocatable) && !lhs_attr.dimension))
13345 22922 : && (expr1->ts.type == BT_CLASS || gfc_is_class_array_ref (expr1, NULL)
13346 20847 : || gfc_is_class_scalar_expr (expr1)
13347 19536 : || gfc_is_class_array_ref (expr2, NULL)
13348 19536 : || (gfc_is_class_scalar_expr (expr2)
13349 30 : && !(expr1->ts.type == BT_DERIVED && !lhs_attr.dimension)))
13350 313231 : && lhs_attr.flavor != FL_PROCEDURE;
13351 :
13352 309845 : assoc_assign = is_assoc_assign (expr1, expr2);
13353 :
13354 : /* Only analyze the expressions for coarray properties, when in coarray-lib
13355 : mode. Avoid false-positive uninitialized diagnostics with initializing
13356 : the codimension flag unconditionally. */
13357 309845 : lhs_caf_attr.codimension = false;
13358 309845 : rhs_caf_attr.codimension = false;
13359 309845 : if (flag_coarray == GFC_FCOARRAY_LIB)
13360 : {
13361 6687 : lhs_caf_attr = gfc_caf_attr (expr1, false, &lhs_refs_comp);
13362 6687 : rhs_caf_attr = gfc_caf_attr (expr2, false, &rhs_refs_comp);
13363 : }
13364 :
13365 309845 : tree reallocation = NULL_TREE;
13366 309845 : if (lss != gfc_ss_terminator)
13367 : {
13368 : /* The assignment needs scalarization. */
13369 : lss_section = lss;
13370 :
13371 : /* Find a non-scalar SS from the lhs. */
13372 : while (lss_section != gfc_ss_terminator
13373 40139 : && lss_section->info->type != GFC_SS_SECTION)
13374 0 : lss_section = lss_section->next;
13375 :
13376 40139 : gcc_assert (lss_section != gfc_ss_terminator);
13377 :
13378 : /* Initialize the scalarizer. */
13379 40139 : gfc_init_loopinfo (&loop);
13380 :
13381 : /* Walk the rhs. */
13382 40139 : rss = gfc_walk_expr (expr2);
13383 40139 : if (rss == gfc_ss_terminator)
13384 : {
13385 : /* The rhs is scalar. Add a ss for the expression. */
13386 15024 : rss = gfc_get_scalar_ss (gfc_ss_terminator, expr2);
13387 15024 : lss->is_alloc_lhs = 0;
13388 : }
13389 :
13390 : /* When doing a class assign, then the handle to the rhs needs to be a
13391 : pointer to allow for polymorphism. */
13392 40139 : if (is_poly_assign && expr2->rank == 0 && !UNLIMITED_POLY (expr2))
13393 509 : rss->info->type = GFC_SS_REFERENCE;
13394 :
13395 40139 : rss->no_bounds_check = expr2->no_bounds_check;
13396 : /* Associate the SS with the loop. */
13397 40139 : gfc_add_ss_to_loop (&loop, lss);
13398 40139 : gfc_add_ss_to_loop (&loop, rss);
13399 :
13400 : /* Calculate the bounds of the scalarization. */
13401 40139 : gfc_conv_ss_startstride (&loop);
13402 : /* Enable loop reversal. */
13403 682363 : for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
13404 602085 : loop.reverse[n] = GFC_ENABLE_REVERSE;
13405 : /* Resolve any data dependencies in the statement. */
13406 40139 : if (may_alias)
13407 37854 : gfc_conv_resolve_dependencies (&loop, lss, rss);
13408 : /* Setup the scalarizing loops. */
13409 40139 : gfc_conv_loop_setup (&loop, &expr2->where);
13410 :
13411 : /* Setup the gfc_se structures. */
13412 40139 : gfc_copy_loopinfo_to_se (&lse, &loop);
13413 40139 : gfc_copy_loopinfo_to_se (&rse, &loop);
13414 :
13415 40139 : rse.ss = rss;
13416 40139 : gfc_mark_ss_chain_used (rss, 1);
13417 40139 : if (loop.temp_ss == NULL)
13418 : {
13419 39025 : lse.ss = lss;
13420 39025 : gfc_mark_ss_chain_used (lss, 1);
13421 : }
13422 : else
13423 : {
13424 1114 : lse.ss = loop.temp_ss;
13425 1114 : gfc_mark_ss_chain_used (lss, 3);
13426 1114 : gfc_mark_ss_chain_used (loop.temp_ss, 3);
13427 : }
13428 :
13429 : /* Allow the scalarizer to workshare array assignments. */
13430 40139 : if ((ompws_flags & (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_BODY))
13431 : == OMPWS_WORKSHARE_FLAG
13432 85 : && loop.temp_ss == NULL)
13433 : {
13434 73 : maybe_workshare = true;
13435 73 : ompws_flags |= OMPWS_SCALARIZER_WS | OMPWS_SCALARIZER_BODY;
13436 : }
13437 :
13438 : /* F2003: Allocate or reallocate lhs of allocatable array. */
13439 40139 : if (realloc_flag)
13440 : {
13441 6452 : realloc_lhs_warning (expr1->ts.type, true, &expr1->where);
13442 6452 : ompws_flags &= ~OMPWS_SCALARIZER_WS;
13443 6452 : reallocation = gfc_alloc_allocatable_for_assignment (&loop, expr1,
13444 : expr2);
13445 : }
13446 :
13447 : /* Start the scalarized loop body. */
13448 40139 : gfc_start_scalarized_body (&loop, &body);
13449 : }
13450 : else
13451 269706 : gfc_init_block (&body);
13452 :
13453 309845 : l_is_temp = (lss != gfc_ss_terminator && loop.temp_ss != NULL);
13454 :
13455 : /* Translate the expression. */
13456 619690 : rse.want_coarray = flag_coarray == GFC_FCOARRAY_LIB
13457 309845 : && (init_flag || assoc_assign) && lhs_caf_attr.codimension;
13458 309845 : rse.want_pointer = rse.want_coarray && !init_flag && !lhs_caf_attr.dimension;
13459 309845 : gfc_conv_expr (&rse, expr2);
13460 :
13461 : /* Deal with the case of a scalar class function assigned to a derived type.
13462 : */
13463 309845 : if (gfc_is_alloc_class_scalar_function (expr2)
13464 309845 : && expr1->ts.type == BT_DERIVED)
13465 : {
13466 60 : rse.expr = gfc_class_data_get (rse.expr);
13467 60 : rse.expr = build_fold_indirect_ref_loc (input_location, rse.expr);
13468 : }
13469 :
13470 : /* Stabilize a string length for temporaries. */
13471 309845 : if (expr2->ts.type == BT_CHARACTER && !expr1->ts.deferred
13472 24647 : && !(VAR_P (rse.string_length)
13473 : || TREE_CODE (rse.string_length) == PARM_DECL
13474 : || INDIRECT_REF_P (rse.string_length)))
13475 23777 : string_length = gfc_evaluate_now (rse.string_length, &rse.pre);
13476 286068 : else if (expr2->ts.type == BT_CHARACTER)
13477 : {
13478 4382 : if (expr1->ts.deferred
13479 6803 : && gfc_expr_attr (expr1).allocatable
13480 6923 : && gfc_check_dependency (expr1, expr2, true))
13481 120 : rse.string_length =
13482 120 : gfc_evaluate_now_function_scope (rse.string_length, &rse.pre);
13483 4382 : string_length = rse.string_length;
13484 : }
13485 : else
13486 : string_length = NULL_TREE;
13487 :
13488 309845 : if (l_is_temp)
13489 : {
13490 1114 : gfc_conv_tmp_array_ref (&lse);
13491 1114 : if (expr2->ts.type == BT_CHARACTER)
13492 123 : lse.string_length = string_length;
13493 : }
13494 : else
13495 : {
13496 308731 : gfc_conv_expr (&lse, expr1);
13497 : /* For some expression (e.g. complex numbers) fold_convert uses a
13498 : SAVE_EXPR, which is hazardous on the lhs, because the value is
13499 : not updated when assigned to. */
13500 308731 : if (TREE_CODE (lse.expr) == SAVE_EXPR)
13501 8 : lse.expr = TREE_OPERAND (lse.expr, 0);
13502 :
13503 6153 : if (gfc_option.rtcheck & GFC_RTCHECK_MEM && !init_flag
13504 314884 : && gfc_expr_attr (expr1).allocatable && expr1->rank && !expr2->rank)
13505 : {
13506 36 : tree cond;
13507 36 : const char* msg;
13508 :
13509 36 : tmp = INDIRECT_REF_P (lse.expr)
13510 36 : ? gfc_build_addr_expr (NULL_TREE, lse.expr) : lse.expr;
13511 36 : STRIP_NOPS (tmp);
13512 :
13513 : /* We should only get array references here. */
13514 36 : gcc_assert (TREE_CODE (tmp) == POINTER_PLUS_EXPR
13515 : || TREE_CODE (tmp) == ARRAY_REF);
13516 :
13517 : /* 'tmp' is either the pointer to the array(POINTER_PLUS_EXPR)
13518 : or the array itself(ARRAY_REF). */
13519 36 : tmp = TREE_OPERAND (tmp, 0);
13520 :
13521 : /* Provide the address of the array. */
13522 36 : if (TREE_CODE (lse.expr) == ARRAY_REF)
13523 18 : tmp = gfc_build_addr_expr (NULL_TREE, tmp);
13524 :
13525 36 : cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
13526 36 : tmp, build_int_cst (TREE_TYPE (tmp), 0));
13527 36 : msg = _("Assignment of scalar to unallocated array");
13528 36 : gfc_trans_runtime_check (true, false, cond, &loop.pre,
13529 : &expr1->where, msg);
13530 : }
13531 :
13532 : /* Deallocate the lhs parameterized components if required. */
13533 308731 : if (dealloc
13534 290175 : && !expr1->symtree->n.sym->attr.associate_var
13535 288194 : && expr2->expr_type != EXPR_ARRAY
13536 282180 : && (IS_PDT (expr1) || IS_CLASS_PDT (expr1)))
13537 : {
13538 361 : bool pdt_dep = gfc_check_dependency (expr1, expr2, true);
13539 :
13540 361 : tmp = lse.expr;
13541 361 : if (pdt_dep)
13542 : {
13543 : /* Create a temporary for deallocation after assignment. */
13544 168 : tmp = gfc_create_var (TREE_TYPE (lse.expr), "pdt_tmp");
13545 168 : gfc_add_modify (&lse.pre, tmp, lse.expr);
13546 : }
13547 :
13548 361 : if (expr1->ts.type == BT_DERIVED)
13549 361 : tmp = gfc_deallocate_pdt_comp (expr1->ts.u.derived, tmp,
13550 : expr1->rank);
13551 0 : else if (expr1->ts.type == BT_CLASS)
13552 : {
13553 0 : tmp = gfc_class_data_get (tmp);
13554 0 : tmp = gfc_deallocate_pdt_comp (CLASS_DATA (expr1)->ts.u.derived,
13555 : tmp, expr1->rank);
13556 : }
13557 :
13558 361 : if (tmp && pdt_dep)
13559 92 : gfc_add_expr_to_block (&rse.post, tmp);
13560 269 : else if (tmp)
13561 67 : gfc_add_expr_to_block (&lse.pre, tmp);
13562 : }
13563 : }
13564 :
13565 : /* Assignments of scalar derived types with allocatable components
13566 : to arrays must be done with a deep copy and the rhs temporary
13567 : must have its components deallocated afterwards. */
13568 619690 : scalar_to_array = (expr2->ts.type == BT_DERIVED
13569 19626 : && expr2->ts.u.derived->attr.alloc_comp
13570 6789 : && !gfc_expr_is_variable (expr2)
13571 313547 : && expr1->rank && !expr2->rank);
13572 619690 : scalar_to_array |= (expr1->ts.type == BT_DERIVED
13573 19909 : && expr1->rank
13574 3833 : && expr1->ts.u.derived->attr.alloc_comp
13575 311273 : && gfc_is_alloc_class_scalar_function (expr2));
13576 309845 : if (scalar_to_array && dealloc)
13577 : {
13578 59 : tmp = gfc_deallocate_alloc_comp_no_caf (expr2->ts.u.derived, rse.expr, 0);
13579 59 : gfc_prepend_expr_to_block (&loop.post, tmp);
13580 : }
13581 :
13582 : /* When assigning a character function result to a deferred-length variable,
13583 : the function call must happen before the (re)allocation of the lhs -
13584 : otherwise the character length of the result is not known.
13585 : NOTE 1: This relies on having the exact dependence of the length type
13586 : parameter available to the caller; gfortran saves it in the .mod files.
13587 : NOTE 2: Vector array references generate an index temporary that must
13588 : not go outside the loop. Otherwise, variables should not generate
13589 : a pre block.
13590 : NOTE 3: The concatenation operation generates a temporary pointer,
13591 : whose allocation must go to the innermost loop.
13592 : NOTE 4: Elemental functions may generate a temporary, too. */
13593 309845 : if (flag_realloc_lhs
13594 303747 : && expr2->ts.type == BT_CHARACTER && expr1->ts.deferred
13595 2984 : && !(lss != gfc_ss_terminator
13596 928 : && rss != gfc_ss_terminator
13597 928 : && ((expr2->expr_type == EXPR_VARIABLE && expr2->rank)
13598 741 : || (expr2->expr_type == EXPR_FUNCTION
13599 160 : && expr2->value.function.esym != NULL
13600 26 : && expr2->value.function.esym->attr.elemental)
13601 728 : || (expr2->expr_type == EXPR_FUNCTION
13602 147 : && expr2->value.function.isym != NULL
13603 134 : && expr2->value.function.isym->elemental)
13604 672 : || (expr2->expr_type == EXPR_OP
13605 31 : && expr2->value.op.op == INTRINSIC_CONCAT))))
13606 2703 : gfc_add_block_to_block (&block, &rse.pre);
13607 :
13608 : /* Nullify the allocatable components corresponding to those of the lhs
13609 : derived type, so that the finalization of the function result does not
13610 : affect the lhs of the assignment. Prepend is used to ensure that the
13611 : nullification occurs before the call to the finalizer. In the case of
13612 : a scalar to array assignment, this is done in gfc_trans_scalar_assign
13613 : as part of the deep copy. */
13614 309018 : if (!scalar_to_array && expr1->ts.type == BT_DERIVED
13615 328927 : && (gfc_is_class_array_function (expr2)
13616 19058 : || gfc_is_alloc_class_scalar_function (expr2)))
13617 : {
13618 78 : tmp = gfc_nullify_alloc_comp (expr1->ts.u.derived, rse.expr, 0);
13619 78 : gfc_prepend_expr_to_block (&rse.post, tmp);
13620 78 : if (lss != gfc_ss_terminator && rss == gfc_ss_terminator)
13621 0 : gfc_add_block_to_block (&loop.post, &rse.post);
13622 : }
13623 :
13624 309845 : tmp = NULL_TREE;
13625 :
13626 309845 : if (is_poly_assign)
13627 : {
13628 3319 : tmp = trans_class_assignment (&body, expr1, expr2, &lse, &rse,
13629 3319 : use_vptr_copy || (lhs_attr.allocatable
13630 283 : && !lhs_attr.dimension),
13631 3063 : !realloc_flag && flag_realloc_lhs
13632 3870 : && !lhs_attr.pointer);
13633 3319 : if (expr2->expr_type == EXPR_FUNCTION
13634 220 : && expr2->ts.type == BT_DERIVED
13635 18 : && expr2->ts.u.derived->attr.alloc_comp)
13636 : {
13637 18 : tree tmp2 = gfc_deallocate_alloc_comp (expr2->ts.u.derived,
13638 : rse.expr, expr2->rank);
13639 18 : if (lss == gfc_ss_terminator)
13640 18 : gfc_add_expr_to_block (&rse.post, tmp2);
13641 : else
13642 0 : gfc_add_expr_to_block (&loop.post, tmp2);
13643 : }
13644 :
13645 3319 : expr1->must_finalize = 0;
13646 : }
13647 306526 : else if (!is_poly_assign
13648 306526 : && expr1->ts.type == BT_CLASS
13649 442 : && expr2->ts.type == BT_CLASS
13650 255 : && (expr2->must_finalize || dummy_class_array_copy))
13651 : {
13652 : /* This case comes about when the scalarizer provides array element
13653 : references to class temporaries or nonpointer dummy arrays. Use the
13654 : vptr copy function, since this does a deep copy of allocatable
13655 : components. */
13656 132 : tmp = gfc_get_vptr_from_expr (rse.expr);
13657 132 : if (tmp == NULL_TREE && dummy_class_array_copy)
13658 12 : tmp = gfc_get_vptr_from_expr (gfc_get_class_from_gfc_expr (expr2));
13659 132 : if (tmp != NULL_TREE)
13660 : {
13661 132 : tree fcn = gfc_vptr_copy_get (tmp);
13662 132 : if (POINTER_TYPE_P (TREE_TYPE (fcn)))
13663 132 : fcn = build_fold_indirect_ref_loc (input_location, fcn);
13664 132 : tmp = build_call_expr_loc (input_location,
13665 : fcn, 2,
13666 : gfc_build_addr_expr (NULL, rse.expr),
13667 : gfc_build_addr_expr (NULL, lse.expr));
13668 : }
13669 : }
13670 :
13671 : /* Comply with F2018 (7.5.6.3). Make sure that any finalization code is added
13672 : after evaluation of the rhs and before reallocation.
13673 : Skip finalization for self-assignment to avoid use-after-free.
13674 : Strip parentheses from both sides to handle cases like a = (a). */
13675 309845 : final_expr = gfc_assignment_finalizer_call (&lse, expr1, init_flag);
13676 309845 : if (final_expr
13677 666 : && gfc_dep_compare_expr (strip_parentheses (expr1),
13678 : strip_parentheses (expr2)) != 0
13679 310487 : && !(strip_parentheses (expr2)->expr_type == EXPR_VARIABLE
13680 211 : && strip_parentheses (expr2)->symtree->n.sym->attr.artificial))
13681 : {
13682 642 : if (lss == gfc_ss_terminator)
13683 : {
13684 183 : gfc_add_block_to_block (&block, &rse.pre);
13685 183 : gfc_add_block_to_block (&block, &lse.finalblock);
13686 : }
13687 : else
13688 : {
13689 459 : gfc_add_block_to_block (&body, &rse.pre);
13690 459 : gfc_add_block_to_block (&loop.code[expr1->rank - 1],
13691 : &lse.finalblock);
13692 : }
13693 : }
13694 : else
13695 309203 : gfc_add_block_to_block (&body, &rse.pre);
13696 :
13697 309845 : if (flag_coarray != GFC_FCOARRAY_NONE && expr1->ts.type == BT_CHARACTER
13698 2994 : && assoc_assign)
13699 0 : tmp = gfc_trans_pointer_assignment (expr1, expr2);
13700 :
13701 : /* If nothing else works, do it the old fashioned way! */
13702 309845 : if (tmp == NULL_TREE)
13703 : {
13704 : /* Strip parentheses to detect cases like a = (a) which need deep_copy. */
13705 306394 : gfc_expr *expr2_stripped = strip_parentheses (expr2);
13706 306394 : tmp
13707 306394 : = gfc_trans_scalar_assign (&lse, &rse, expr1->ts,
13708 306394 : gfc_expr_is_variable (expr2_stripped)
13709 276233 : || scalar_to_array
13710 581890 : || expr2->expr_type == EXPR_ARRAY,
13711 306394 : !(l_is_temp || init_flag) && dealloc,
13712 306394 : expr1->symtree->n.sym->attr.codimension,
13713 : assoc_assign);
13714 : }
13715 :
13716 : /* Add the lse pre block to the body */
13717 309845 : gfc_add_block_to_block (&body, &lse.pre);
13718 309845 : gfc_add_expr_to_block (&body, tmp);
13719 :
13720 : /* Add the post blocks to the body. Scalar finalization must appear before
13721 : the post block in case any dellocations are done. */
13722 309845 : if (rse.finalblock.head
13723 309845 : && (!l_is_temp || (expr2->expr_type == EXPR_FUNCTION
13724 14 : && gfc_expr_attr (expr2).elemental)))
13725 : {
13726 142 : gfc_add_block_to_block (&body, &rse.finalblock);
13727 142 : gfc_add_block_to_block (&body, &rse.post);
13728 : }
13729 : else
13730 309703 : gfc_add_block_to_block (&body, &rse.post);
13731 :
13732 309845 : gfc_add_block_to_block (&body, &lse.post);
13733 :
13734 309845 : if (lss == gfc_ss_terminator)
13735 : {
13736 : /* F2003: Add the code for reallocation on assignment. */
13737 266950 : if (flag_realloc_lhs && is_scalar_reallocatable_lhs (expr1)
13738 273361 : && !is_poly_assign)
13739 3655 : alloc_scalar_allocatable_for_assignment (&block, string_length,
13740 : expr1, expr2);
13741 :
13742 : /* Use the scalar assignment as is. */
13743 269706 : gfc_add_block_to_block (&block, &body);
13744 : }
13745 : else
13746 : {
13747 40139 : gcc_assert (lse.ss == gfc_ss_terminator
13748 : && rse.ss == gfc_ss_terminator);
13749 :
13750 40139 : if (l_is_temp)
13751 : {
13752 1114 : gfc_trans_scalarized_loop_boundary (&loop, &body);
13753 :
13754 : /* We need to copy the temporary to the actual lhs. */
13755 1114 : gfc_init_se (&lse, NULL);
13756 1114 : gfc_init_se (&rse, NULL);
13757 1114 : gfc_copy_loopinfo_to_se (&lse, &loop);
13758 1114 : gfc_copy_loopinfo_to_se (&rse, &loop);
13759 :
13760 1114 : rse.ss = loop.temp_ss;
13761 1114 : lse.ss = lss;
13762 :
13763 1114 : gfc_conv_tmp_array_ref (&rse);
13764 1114 : gfc_conv_expr (&lse, expr1);
13765 :
13766 1114 : gcc_assert (lse.ss == gfc_ss_terminator
13767 : && rse.ss == gfc_ss_terminator);
13768 :
13769 1114 : if (expr2->ts.type == BT_CHARACTER)
13770 123 : rse.string_length = string_length;
13771 :
13772 1114 : tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts,
13773 : false, dealloc);
13774 1114 : gfc_add_expr_to_block (&body, tmp);
13775 : }
13776 :
13777 40139 : if (reallocation != NULL_TREE)
13778 6452 : gfc_add_expr_to_block (&loop.code[loop.dimen - 1], reallocation);
13779 :
13780 40139 : if (maybe_workshare)
13781 73 : ompws_flags &= ~OMPWS_SCALARIZER_BODY;
13782 :
13783 : /* Generate the copying loops. */
13784 40139 : gfc_trans_scalarizing_loops (&loop, &body);
13785 :
13786 : /* Wrap the whole thing up. */
13787 40139 : gfc_add_block_to_block (&block, &loop.pre);
13788 40139 : gfc_add_block_to_block (&block, &loop.post);
13789 :
13790 40139 : gfc_cleanup_loop (&loop);
13791 : }
13792 :
13793 : /* Since parameterized components cannot have default initializers,
13794 : the default PDT constructor leaves them unallocated. Do the
13795 : allocation now. */
13796 309845 : if (init_flag && IS_PDT (expr1)
13797 359 : && !expr1->symtree->n.sym->attr.allocatable
13798 359 : && !expr1->symtree->n.sym->attr.dummy)
13799 : {
13800 73 : gfc_symbol *sym = expr1->symtree->n.sym;
13801 73 : tmp = gfc_allocate_pdt_comp (sym->ts.u.derived,
13802 : sym->backend_decl,
13803 73 : sym->as ? sym->as->rank : 0,
13804 73 : sym->param_list);
13805 73 : gfc_add_expr_to_block (&block, tmp);
13806 : }
13807 :
13808 309845 : return gfc_finish_block (&block);
13809 : }
13810 :
13811 :
13812 : /* Check whether EXPR is a copyable array. */
13813 :
13814 : static bool
13815 982070 : copyable_array_p (gfc_expr * expr)
13816 : {
13817 982070 : if (expr->expr_type != EXPR_VARIABLE)
13818 : return false;
13819 :
13820 : /* First check it's an array. */
13821 958213 : if (expr->rank < 1 || !expr->ref || expr->ref->next)
13822 : return false;
13823 :
13824 148125 : if (!gfc_full_array_ref_p (expr->ref, NULL))
13825 : return false;
13826 :
13827 : /* Next check that it's of a simple enough type. */
13828 116563 : switch (expr->ts.type)
13829 : {
13830 : case BT_INTEGER:
13831 : case BT_REAL:
13832 : case BT_COMPLEX:
13833 : case BT_LOGICAL:
13834 : return true;
13835 :
13836 : case BT_CHARACTER:
13837 : return false;
13838 :
13839 6701 : case_bt_struct:
13840 6701 : return (!expr->ts.u.derived->attr.alloc_comp
13841 6701 : && !expr->ts.u.derived->attr.pdt_type);
13842 :
13843 : default:
13844 : break;
13845 : }
13846 :
13847 : return false;
13848 : }
13849 :
13850 : /* Translate an assignment. */
13851 :
13852 : tree
13853 327775 : gfc_trans_assignment (gfc_expr * expr1, gfc_expr * expr2, bool init_flag,
13854 : bool dealloc, bool use_vptr_copy, bool may_alias)
13855 : {
13856 327775 : tree tmp;
13857 :
13858 : /* Special case a single function returning an array. */
13859 327775 : if (expr2->expr_type == EXPR_FUNCTION && expr2->rank > 0)
13860 : {
13861 14512 : tmp = gfc_trans_arrayfunc_assign (expr1, expr2);
13862 14512 : if (tmp)
13863 : return tmp;
13864 : }
13865 :
13866 : /* Special case assigning an array to zero. */
13867 320902 : if (copyable_array_p (expr1)
13868 320902 : && is_zero_initializer_p (expr2))
13869 : {
13870 3951 : tmp = gfc_trans_zero_assign (expr1);
13871 3951 : if (tmp)
13872 : return tmp;
13873 : }
13874 :
13875 : /* Special case copying one array to another. */
13876 317230 : if (copyable_array_p (expr1)
13877 28194 : && copyable_array_p (expr2)
13878 2699 : && gfc_compare_types (&expr1->ts, &expr2->ts)
13879 319929 : && !gfc_check_dependency (expr1, expr2, 0))
13880 : {
13881 2603 : tmp = gfc_trans_array_copy (expr1, expr2);
13882 2603 : if (tmp)
13883 : return tmp;
13884 : }
13885 :
13886 : /* Special case initializing an array from a constant array constructor. */
13887 315744 : if (copyable_array_p (expr1)
13888 26708 : && expr2->expr_type == EXPR_ARRAY
13889 323987 : && gfc_compare_types (&expr1->ts, &expr2->ts))
13890 : {
13891 8243 : tmp = gfc_trans_array_constructor_copy (expr1, expr2);
13892 8243 : if (tmp)
13893 : return tmp;
13894 : }
13895 :
13896 309845 : if (UNLIMITED_POLY (expr1) && expr1->rank)
13897 309845 : use_vptr_copy = true;
13898 :
13899 : /* Fallback to the scalarizer to generate explicit loops. */
13900 309845 : return gfc_trans_assignment_1 (expr1, expr2, init_flag, dealloc,
13901 309845 : use_vptr_copy, may_alias);
13902 : }
13903 :
13904 : tree
13905 13169 : gfc_trans_init_assign (gfc_code * code)
13906 : {
13907 13169 : return gfc_trans_assignment (code->expr1, code->expr2, true, false, true);
13908 : }
13909 :
13910 : tree
13911 306242 : gfc_trans_assign (gfc_code * code)
13912 : {
13913 306242 : return gfc_trans_assignment (code->expr1, code->expr2, false, true);
13914 : }
13915 :
13916 : /* Generate a simple loop for internal use of the form
13917 : for (var = begin; var <cond> end; var += step)
13918 : body; */
13919 : void
13920 12171 : gfc_simple_for_loop (stmtblock_t *block, tree var, tree begin, tree end,
13921 : enum tree_code cond, tree step, tree body)
13922 : {
13923 12171 : tree tmp;
13924 :
13925 : /* var = begin. */
13926 12171 : gfc_add_modify (block, var, begin);
13927 :
13928 : /* Loop: for (var = begin; var <cond> end; var += step). */
13929 12171 : tree label_loop = gfc_build_label_decl (NULL_TREE);
13930 12171 : tree label_cond = gfc_build_label_decl (NULL_TREE);
13931 12171 : TREE_USED (label_loop) = 1;
13932 12171 : TREE_USED (label_cond) = 1;
13933 :
13934 12171 : gfc_add_expr_to_block (block, build1_v (GOTO_EXPR, label_cond));
13935 12171 : gfc_add_expr_to_block (block, build1_v (LABEL_EXPR, label_loop));
13936 :
13937 : /* Loop body. */
13938 12171 : gfc_add_expr_to_block (block, body);
13939 :
13940 : /* End of loop body. */
13941 12171 : tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (var), var, step);
13942 12171 : gfc_add_modify (block, var, tmp);
13943 12171 : gfc_add_expr_to_block (block, build1_v (LABEL_EXPR, label_cond));
13944 12171 : tmp = fold_build2_loc (input_location, cond, boolean_type_node, var, end);
13945 12171 : tmp = build3_v (COND_EXPR, tmp, build1_v (GOTO_EXPR, label_loop),
13946 : build_empty_stmt (input_location));
13947 12171 : gfc_add_expr_to_block (block, tmp);
13948 12171 : }
|