OSDN Git Service

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