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