OSDN Git Service

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