OSDN Git Service

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