OSDN Git Service

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