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