1 /* Supporting functions for resolving DATA statement.
2    Copyright (C) 2002-2021 Free Software Foundation, Inc.
3    Contributed by Lifang Zeng <zlf605@hotmail.com>
4 
5 This file is part of GCC.
6 
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
11 
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3.  If not see
19 <http://www.gnu.org/licenses/>.  */
20 
21 
22 /* Notes for DATA statement implementation:
23 
24    We first assign initial value to each symbol by gfc_assign_data_value
25    during resolving DATA statement. Refer to check_data_variable and
26    traverse_data_list in resolve.c.
27 
28    The complexity exists in the handling of array section, implied do
29    and array of struct appeared in DATA statement.
30 
31    We call gfc_conv_structure, gfc_con_array_array_initializer,
32    etc., to convert the initial value. Refer to trans-expr.c and
33    trans-array.c.  */
34 
35 #include "config.h"
36 #include "system.h"
37 #include "coretypes.h"
38 #include "gfortran.h"
39 #include "data.h"
40 #include "constructor.h"
41 
42 static void formalize_init_expr (gfc_expr *);
43 
44 /* Calculate the array element offset.  */
45 
46 static void
get_array_index(gfc_array_ref * ar,mpz_t * offset)47 get_array_index (gfc_array_ref *ar, mpz_t *offset)
48 {
49   gfc_expr *e;
50   int i;
51   mpz_t delta;
52   mpz_t tmp;
53 
54   mpz_init (tmp);
55   mpz_set_si (*offset, 0);
56   mpz_init_set_si (delta, 1);
57   for (i = 0; i < ar->dimen; i++)
58     {
59       e = gfc_copy_expr (ar->start[i]);
60       gfc_simplify_expr (e, 1);
61 
62       if ((gfc_is_constant_expr (ar->as->lower[i]) == 0)
63 	  || (gfc_is_constant_expr (ar->as->upper[i]) == 0)
64 	  || (gfc_is_constant_expr (e) == 0))
65 	gfc_error ("non-constant array in DATA statement %L", &ar->where);
66 
67       mpz_set (tmp, e->value.integer);
68       gfc_free_expr (e);
69       mpz_sub (tmp, tmp, ar->as->lower[i]->value.integer);
70       mpz_mul (tmp, tmp, delta);
71       mpz_add (*offset, tmp, *offset);
72 
73       mpz_sub (tmp, ar->as->upper[i]->value.integer,
74 	       ar->as->lower[i]->value.integer);
75       mpz_add_ui (tmp, tmp, 1);
76       mpz_mul (delta, tmp, delta);
77     }
78   mpz_clear (delta);
79   mpz_clear (tmp);
80 }
81 
82 /* Find if there is a constructor which component is equal to COM.
83    TODO: remove this, use symbol.c(gfc_find_component) instead.  */
84 
85 static gfc_constructor *
find_con_by_component(gfc_component * com,gfc_constructor_base base)86 find_con_by_component (gfc_component *com, gfc_constructor_base base)
87 {
88   gfc_constructor *c;
89 
90   for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
91     if (com == c->n.component)
92       return c;
93 
94   return NULL;
95 }
96 
97 
98 /* Create a character type initialization expression from RVALUE.
99    TS [and REF] describe [the substring of] the variable being initialized.
100    INIT is the existing initializer, not NULL.  Initialization is performed
101    according to normal assignment rules.  */
102 
103 static gfc_expr *
create_character_initializer(gfc_expr * init,gfc_typespec * ts,gfc_ref * ref,gfc_expr * rvalue)104 create_character_initializer (gfc_expr *init, gfc_typespec *ts,
105 			      gfc_ref *ref, gfc_expr *rvalue)
106 {
107   HOST_WIDE_INT len, start, end, tlen;
108   gfc_char_t *dest;
109   bool alloced_init = false;
110 
111   if (init && init->ts.type != BT_CHARACTER)
112     return NULL;
113 
114   gfc_extract_hwi (ts->u.cl->length, &len);
115 
116   if (init == NULL)
117     {
118       /* Create a new initializer.  */
119       init = gfc_get_character_expr (ts->kind, NULL, NULL, len);
120       init->ts = *ts;
121       alloced_init = true;
122     }
123 
124   dest = init->value.character.string;
125 
126   if (ref)
127     {
128       gfc_expr *start_expr, *end_expr;
129 
130       gcc_assert (ref->type == REF_SUBSTRING);
131 
132       /* Only set a substring of the destination.  Fortran substring bounds
133 	 are one-based [start, end], we want zero based [start, end).  */
134       start_expr = gfc_copy_expr (ref->u.ss.start);
135       end_expr = gfc_copy_expr (ref->u.ss.end);
136 
137       if ((!gfc_simplify_expr(start_expr, 1))
138 	  || !(gfc_simplify_expr(end_expr, 1)))
139 	{
140 	  gfc_error ("failure to simplify substring reference in DATA "
141 		     "statement at %L", &ref->u.ss.start->where);
142 	  gfc_free_expr (start_expr);
143 	  gfc_free_expr (end_expr);
144 	  if (alloced_init)
145 	    gfc_free_expr (init);
146 	  return NULL;
147 	}
148 
149       gfc_extract_hwi (start_expr, &start);
150       gfc_free_expr (start_expr);
151       start--;
152       gfc_extract_hwi (end_expr, &end);
153       gfc_free_expr (end_expr);
154     }
155   else
156     {
157       /* Set the whole string.  */
158       start = 0;
159       end = len;
160     }
161 
162   /* Copy the initial value.  */
163   if (rvalue->ts.type == BT_HOLLERITH)
164     len = rvalue->representation.length - rvalue->ts.u.pad;
165   else
166     len = rvalue->value.character.length;
167 
168   tlen = end - start;
169   if (len > tlen)
170     {
171       if (tlen < 0)
172 	{
173 	  gfc_warning_now (0, "Unused initialization string at %L because "
174 			   "variable has zero length", &rvalue->where);
175 	  len = 0;
176 	}
177       else
178 	{
179 	  gfc_warning_now (0, "Initialization string at %L was truncated to "
180 			   "fit the variable (%ld/%ld)", &rvalue->where,
181 			   (long) tlen, (long) len);
182 	  len = tlen;
183 	}
184     }
185 
186   if (start < 0)
187     {
188       gfc_error ("Substring start index at %L is less than one",
189 		 &ref->u.ss.start->where);
190       return NULL;
191     }
192   if (end > init->value.character.length)
193     {
194       gfc_error ("Substring end index at %L exceeds the string length",
195 		 &ref->u.ss.end->where);
196       return NULL;
197     }
198 
199   if (rvalue->ts.type == BT_HOLLERITH)
200     {
201       for (size_t i = 0; i < (size_t) len; i++)
202 	dest[start+i] = rvalue->representation.string[i];
203     }
204   else
205     memcpy (&dest[start], rvalue->value.character.string,
206 	    len * sizeof (gfc_char_t));
207 
208   /* Pad with spaces.  Substrings will already be blanked.  */
209   if (len < tlen && ref == NULL)
210     gfc_wide_memset (&dest[start + len], ' ', end - (start + len));
211 
212   if (rvalue->ts.type == BT_HOLLERITH)
213     {
214       init->representation.length = init->value.character.length;
215       init->representation.string
216 	= gfc_widechar_to_char (init->value.character.string,
217 				init->value.character.length);
218     }
219 
220   return init;
221 }
222 
223 
224 /* Assign the initial value RVALUE to  LVALUE's symbol->value. If the
225    LVALUE already has an initialization, we extend this, otherwise we
226    create a new one.  If REPEAT is non-NULL, initialize *REPEAT
227    consecutive values in LVALUE the same value in RVALUE.  In that case,
228    LVALUE must refer to a full array, not an array section.  */
229 
230 bool
gfc_assign_data_value(gfc_expr * lvalue,gfc_expr * rvalue,mpz_t index,mpz_t * repeat)231 gfc_assign_data_value (gfc_expr *lvalue, gfc_expr *rvalue, mpz_t index,
232 		       mpz_t *repeat)
233 {
234   gfc_ref *ref;
235   gfc_expr *init;
236   gfc_expr *expr = NULL;
237   gfc_expr *rexpr;
238   gfc_constructor *con;
239   gfc_constructor *last_con;
240   gfc_symbol *symbol;
241   gfc_typespec *last_ts;
242   mpz_t offset;
243   const char *msg = "F18(R841): data-implied-do object at %L is neither an "
244 		    "array-element nor a scalar-structure-component";
245 
246   symbol = lvalue->symtree->n.sym;
247   if (symbol->attr.flavor == FL_PARAMETER)
248     {
249       gfc_error ("PARAMETER %qs shall not appear in a DATA statement at %L",
250 		 symbol->name, &lvalue->where);
251       return false;
252     }
253 
254   init = symbol->value;
255   last_ts = &symbol->ts;
256   last_con = NULL;
257   mpz_init_set_si (offset, 0);
258 
259   /* Find/create the parent expressions for subobject references.  */
260   for (ref = lvalue->ref; ref; ref = ref->next)
261     {
262       /* Break out of the loop if we find a substring.  */
263       if (ref->type == REF_SUBSTRING)
264 	{
265 	  /* A substring should always be the last subobject reference.  */
266 	  gcc_assert (ref->next == NULL);
267 	  break;
268 	}
269 
270       /* Use the existing initializer expression if it exists.  Otherwise
271 	 create a new one.  */
272       if (init == NULL)
273 	expr = gfc_get_expr ();
274       else
275 	expr = init;
276 
277       /* Find or create this element.  */
278       switch (ref->type)
279 	{
280 	case REF_ARRAY:
281 	  if (ref->u.ar.as->rank == 0)
282 	    {
283 	      gcc_assert (ref->u.ar.as->corank > 0);
284 	      if (init == NULL)
285 		free (expr);
286 	      continue;
287 	    }
288 
289 	  if (init && expr->expr_type != EXPR_ARRAY)
290 	    {
291 	      gfc_error ("%qs at %L already is initialized at %L",
292 			 lvalue->symtree->n.sym->name, &lvalue->where,
293 			 &init->where);
294 	      goto abort;
295 	    }
296 
297 	  if (init == NULL)
298 	    {
299 	      /* The element typespec will be the same as the array
300 		 typespec.  */
301 	      expr->ts = *last_ts;
302 	      /* Setup the expression to hold the constructor.  */
303 	      expr->expr_type = EXPR_ARRAY;
304 	      expr->rank = ref->u.ar.as->rank;
305 	    }
306 
307 	  if (ref->u.ar.type == AR_ELEMENT)
308 	    get_array_index (&ref->u.ar, &offset);
309 	  else
310 	    mpz_set (offset, index);
311 
312 	  /* Check the bounds.  */
313 	  if (mpz_cmp_si (offset, 0) < 0)
314 	    {
315 	      gfc_error ("Data element below array lower bound at %L",
316 			 &lvalue->where);
317 	      goto abort;
318 	    }
319 	  else if (repeat != NULL
320 		   && ref->u.ar.type != AR_ELEMENT)
321 	    {
322 	      mpz_t size, end;
323 	      gcc_assert (ref->u.ar.type == AR_FULL
324 			  && ref->next == NULL);
325 	      mpz_init_set (end, offset);
326 	      mpz_add (end, end, *repeat);
327 	      if (spec_size (ref->u.ar.as, &size))
328 		{
329 		  if (mpz_cmp (end, size) > 0)
330 		    {
331 		      mpz_clear (size);
332 		      gfc_error ("Data element above array upper bound at %L",
333 				 &lvalue->where);
334 		      goto abort;
335 		    }
336 		  mpz_clear (size);
337 		}
338 
339 	      con = gfc_constructor_lookup (expr->value.constructor,
340 					    mpz_get_si (offset));
341 	      if (!con)
342 		{
343 		  con = gfc_constructor_lookup_next (expr->value.constructor,
344 						     mpz_get_si (offset));
345 		  if (con != NULL && mpz_cmp (con->offset, end) >= 0)
346 		    con = NULL;
347 		}
348 
349 	      /* Overwriting an existing initializer is non-standard but
350 		 usually only provokes a warning from other compilers.  */
351 	      if (con != NULL && con->expr != NULL)
352 		{
353 		  /* Order in which the expressions arrive here depends on
354 		     whether they are from data statements or F95 style
355 		     declarations.  Therefore, check which is the most
356 		     recent.  */
357 		  gfc_expr *exprd;
358 		  exprd = (LOCATION_LINE (con->expr->where.lb->location)
359 			   > LOCATION_LINE (rvalue->where.lb->location))
360 			  ? con->expr : rvalue;
361 		  if (gfc_notify_std (GFC_STD_GNU,
362 				      "re-initialization of %qs at %L",
363 				      symbol->name, &exprd->where) == false)
364 		    return false;
365 		}
366 
367 	      while (con != NULL)
368 		{
369 		  gfc_constructor *next_con = gfc_constructor_next (con);
370 
371 		  if (mpz_cmp (con->offset, end) >= 0)
372 		    break;
373 		  if (mpz_cmp (con->offset, offset) < 0)
374 		    {
375 		      gcc_assert (mpz_cmp_si (con->repeat, 1) > 0);
376 		      mpz_sub (con->repeat, offset, con->offset);
377 		    }
378 		  else if (mpz_cmp_si (con->repeat, 1) > 0
379 			   && mpz_get_si (con->offset)
380 			      + mpz_get_si (con->repeat) > mpz_get_si (end))
381 		    {
382 		      int endi;
383 		      splay_tree_node node
384 			= splay_tree_lookup (con->base,
385 					     mpz_get_si (con->offset));
386 		      gcc_assert (node
387 				  && con == (gfc_constructor *) node->value
388 				  && node->key == (splay_tree_key)
389 						  mpz_get_si (con->offset));
390 		      endi = mpz_get_si (con->offset)
391 			     + mpz_get_si (con->repeat);
392 		      if (endi > mpz_get_si (end) + 1)
393 			mpz_set_si (con->repeat, endi - mpz_get_si (end));
394 		      else
395 			mpz_set_si (con->repeat, 1);
396 		      mpz_set (con->offset, end);
397 		      node->key = (splay_tree_key) mpz_get_si (end);
398 		      break;
399 		    }
400 		  else
401 		    gfc_constructor_remove (con);
402 		  con = next_con;
403 		}
404 
405 	      con = gfc_constructor_insert_expr (&expr->value.constructor,
406 						 NULL, &rvalue->where,
407 						 mpz_get_si (offset));
408 	      mpz_set (con->repeat, *repeat);
409 	      repeat = NULL;
410 	      mpz_clear (end);
411 	      break;
412 	    }
413 	  else
414 	    {
415 	      mpz_t size;
416 	      if (spec_size (ref->u.ar.as, &size))
417 		{
418 		  if (mpz_cmp (offset, size) >= 0)
419 		    {
420 		      mpz_clear (size);
421 		      gfc_error ("Data element above array upper bound at %L",
422 		                 &lvalue->where);
423 		      goto abort;
424 		    }
425 		  mpz_clear (size);
426 		}
427 	    }
428 
429 	  con = gfc_constructor_lookup (expr->value.constructor,
430 					mpz_get_si (offset));
431 	  if (!con)
432 	    {
433 	      con = gfc_constructor_insert_expr (&expr->value.constructor,
434 						 NULL, &rvalue->where,
435 						 mpz_get_si (offset));
436 	    }
437 	  else if (mpz_cmp_si (con->repeat, 1) > 0)
438 	    {
439 	      /* Need to split a range.  */
440 	      if (mpz_cmp (con->offset, offset) < 0)
441 		{
442 		  gfc_constructor *pred_con = con;
443 		  con = gfc_constructor_insert_expr (&expr->value.constructor,
444 						     NULL, &con->where,
445 						     mpz_get_si (offset));
446 		  con->expr = gfc_copy_expr (pred_con->expr);
447 		  mpz_add (con->repeat, pred_con->offset, pred_con->repeat);
448 		  mpz_sub (con->repeat, con->repeat, offset);
449 		  mpz_sub (pred_con->repeat, offset, pred_con->offset);
450 		}
451 	      if (mpz_cmp_si (con->repeat, 1) > 0)
452 		{
453 		  gfc_constructor *succ_con;
454 		  succ_con
455 		    = gfc_constructor_insert_expr (&expr->value.constructor,
456 						   NULL, &con->where,
457 						   mpz_get_si (offset) + 1);
458 		  succ_con->expr = gfc_copy_expr (con->expr);
459 		  mpz_sub_ui (succ_con->repeat, con->repeat, 1);
460 		  mpz_set_si (con->repeat, 1);
461 		}
462 	    }
463 	  break;
464 
465 	case REF_COMPONENT:
466 	  if (init == NULL)
467 	    {
468 	      /* Setup the expression to hold the constructor.  */
469 	      expr->expr_type = EXPR_STRUCTURE;
470 	      expr->ts.type = BT_DERIVED;
471 	      expr->ts.u.derived = ref->u.c.sym;
472 	    }
473 	  else
474 	    gcc_assert (expr->expr_type == EXPR_STRUCTURE);
475 	  last_ts = &ref->u.c.component->ts;
476 
477 	  /* Find the same element in the existing constructor.  */
478 	  con = find_con_by_component (ref->u.c.component,
479 				       expr->value.constructor);
480 
481 	  if (con == NULL)
482 	    {
483 	      /* Create a new constructor.  */
484 	      con = gfc_constructor_append_expr (&expr->value.constructor,
485 						 NULL, NULL);
486 	      con->n.component = ref->u.c.component;
487 	    }
488 	  break;
489 
490 	case REF_INQUIRY:
491 
492 	  /* After some discussion on clf it was determined that the following
493 	     violates F18(R841). If the error is removed, the expected result
494 	     is obtained. Leaving the code in place ensures a clean error
495 	     recovery.  */
496 	  gfc_error (msg, &lvalue->where);
497 
498 	  /* This breaks with the other reference types in that the output
499 	     constructor has to be of type COMPLEX, whereas the lvalue is
500 	     of type REAL.  The rvalue is copied to the real or imaginary
501 	     part as appropriate.  In addition, for all except scalar
502 	     complex variables, a complex expression has to provided, where
503 	     the constructor does not have it, and the expression modified
504 	     with a new value for the real or imaginary part.  */
505 	  gcc_assert (ref->next == NULL && last_ts->type == BT_COMPLEX);
506 	  rexpr = gfc_copy_expr (rvalue);
507 	  if (!gfc_compare_types (&lvalue->ts, &rexpr->ts))
508 	    gfc_convert_type (rexpr, &lvalue->ts, 0);
509 
510 	  /* This is the scalar, complex case, where an initializer exists.  */
511 	  if (init && ref == lvalue->ref)
512 	    expr = symbol->value;
513 	  /* Then all cases, where a complex expression does not exist.  */
514 	  else if (!last_con || !last_con->expr)
515 	    {
516 	      expr = gfc_get_constant_expr (BT_COMPLEX, lvalue->ts.kind,
517 					    &lvalue->where);
518 	      if (last_con)
519 		last_con->expr = expr;
520 	    }
521 	  else
522 	    /* Finally, and existing constructor expression to be modified.  */
523 	    expr = last_con->expr;
524 
525 	  /* Rejection of LEN and KIND inquiry references is handled
526 	     elsewhere. The error here is added as backup. The assertion
527 	     of F2008 for RE and IM is also done elsewhere.  */
528 	  switch (ref->u.i)
529 	    {
530 	    case INQUIRY_LEN:
531 	    case INQUIRY_KIND:
532 	      gfc_error ("LEN or KIND inquiry ref in DATA statement at %L",
533 			 &lvalue->where);
534 	      goto abort;
535 	    case INQUIRY_RE:
536 	      mpfr_set (mpc_realref (expr->value.complex),
537 			rexpr->value.real,
538 			GFC_RND_MODE);
539 	      break;
540 	    case INQUIRY_IM:
541 	      mpfr_set (mpc_imagref (expr->value.complex),
542 			rexpr->value.real,
543 			GFC_RND_MODE);
544 	      break;
545 	    }
546 
547 	  /* Only the scalar, complex expression needs to be saved as the
548 	     symbol value since the last constructor expression is already
549 	     provided as the initializer in the code after the reference
550 	     cases.  */
551 	  if (ref == lvalue->ref)
552 	    symbol->value = expr;
553 
554 	  gfc_free_expr (rexpr);
555 	  mpz_clear (offset);
556 	  return true;
557 
558 	default:
559 	  gcc_unreachable ();
560 	}
561 
562       if (init == NULL)
563 	{
564 	  /* Point the container at the new expression.  */
565 	  if (last_con == NULL)
566 	    symbol->value = expr;
567 	  else
568 	    last_con->expr = expr;
569 	}
570       init = con->expr;
571       last_con = con;
572     }
573 
574   mpz_clear (offset);
575   gcc_assert (repeat == NULL);
576 
577   /* Overwriting an existing initializer is non-standard but usually only
578      provokes a warning from other compilers.  */
579   if (init != NULL && init->where.lb && rvalue->where.lb)
580     {
581       /* Order in which the expressions arrive here depends on whether
582 	 they are from data statements or F95 style declarations.
583 	 Therefore, check which is the most recent.  */
584       expr = (LOCATION_LINE (init->where.lb->location)
585 	      > LOCATION_LINE (rvalue->where.lb->location))
586 	   ? init : rvalue;
587       if (gfc_notify_std (GFC_STD_GNU, "re-initialization of %qs at %L",
588 			  symbol->name, &expr->where) == false)
589 	return false;
590     }
591 
592   if (ref || (last_ts->type == BT_CHARACTER
593 	      && rvalue->expr_type == EXPR_CONSTANT))
594     {
595       /* An initializer has to be constant.  */
596       if (lvalue->ts.u.cl->length == NULL && !(ref && ref->u.ss.length != NULL))
597 	return false;
598       if (lvalue->ts.u.cl->length
599 	  && lvalue->ts.u.cl->length->expr_type != EXPR_CONSTANT)
600 	return false;
601       expr = create_character_initializer (init, last_ts, ref, rvalue);
602       if (!expr)
603 	return false;
604     }
605   else
606     {
607       if (lvalue->ts.type == BT_DERIVED
608 	  && gfc_has_default_initializer (lvalue->ts.u.derived))
609 	{
610 	  gfc_error ("Nonpointer object %qs with default initialization "
611 		     "shall not appear in a DATA statement at %L",
612 		     symbol->name, &lvalue->where);
613 	  return false;
614 	}
615 
616       expr = gfc_copy_expr (rvalue);
617       if (!gfc_compare_types (&lvalue->ts, &expr->ts))
618 	gfc_convert_type (expr, &lvalue->ts, 0);
619     }
620 
621   if (last_con == NULL)
622     symbol->value = expr;
623   else
624     last_con->expr = expr;
625 
626   return true;
627 
628 abort:
629   if (!init)
630     gfc_free_expr (expr);
631   mpz_clear (offset);
632   return false;
633 }
634 
635 
636 /* Modify the index of array section and re-calculate the array offset.  */
637 
638 void
gfc_advance_section(mpz_t * section_index,gfc_array_ref * ar,mpz_t * offset_ret)639 gfc_advance_section (mpz_t *section_index, gfc_array_ref *ar,
640 		     mpz_t *offset_ret)
641 {
642   int i;
643   mpz_t delta;
644   mpz_t tmp;
645   bool forwards;
646   int cmp;
647   gfc_expr *start, *end, *stride;
648 
649   for (i = 0; i < ar->dimen; i++)
650     {
651       if (ar->dimen_type[i] != DIMEN_RANGE)
652 	continue;
653 
654       if (ar->stride[i])
655 	{
656 	  stride = gfc_copy_expr(ar->stride[i]);
657 	  if(!gfc_simplify_expr(stride, 1))
658 	    gfc_internal_error("Simplification error");
659 	  mpz_add (section_index[i], section_index[i],
660 		   stride->value.integer);
661 	  if (mpz_cmp_si (stride->value.integer, 0) >= 0)
662 	    forwards = true;
663 	  else
664 	    forwards = false;
665 	  gfc_free_expr(stride);
666 	}
667       else
668 	{
669 	  mpz_add_ui (section_index[i], section_index[i], 1);
670 	  forwards = true;
671 	}
672 
673       if (ar->end[i])
674         {
675 	  end = gfc_copy_expr(ar->end[i]);
676 	  if(!gfc_simplify_expr(end, 1))
677 	    gfc_internal_error("Simplification error");
678 	  cmp = mpz_cmp (section_index[i], end->value.integer);
679 	  gfc_free_expr(end);
680 	}
681       else
682 	cmp = mpz_cmp (section_index[i], ar->as->upper[i]->value.integer);
683 
684       if ((cmp > 0 && forwards) || (cmp < 0 && !forwards))
685 	{
686 	  /* Reset index to start, then loop to advance the next index.  */
687 	  if (ar->start[i])
688 	    {
689 	      start = gfc_copy_expr(ar->start[i]);
690 	      if(!gfc_simplify_expr(start, 1))
691 	        gfc_internal_error("Simplification error");
692 	      mpz_set (section_index[i], start->value.integer);
693 	      gfc_free_expr(start);
694 	    }
695 	  else
696 	    mpz_set (section_index[i], ar->as->lower[i]->value.integer);
697 	}
698       else
699 	break;
700     }
701 
702   mpz_set_si (*offset_ret, 0);
703   mpz_init_set_si (delta, 1);
704   mpz_init (tmp);
705   for (i = 0; i < ar->dimen; i++)
706     {
707       mpz_sub (tmp, section_index[i], ar->as->lower[i]->value.integer);
708       mpz_mul (tmp, tmp, delta);
709       mpz_add (*offset_ret, tmp, *offset_ret);
710 
711       mpz_sub (tmp, ar->as->upper[i]->value.integer,
712 	       ar->as->lower[i]->value.integer);
713       mpz_add_ui (tmp, tmp, 1);
714       mpz_mul (delta, tmp, delta);
715     }
716   mpz_clear (tmp);
717   mpz_clear (delta);
718 }
719 
720 
721 /* Rearrange a structure constructor so the elements are in the specified
722    order.  Also insert NULL entries if necessary.  */
723 
724 static void
formalize_structure_cons(gfc_expr * expr)725 formalize_structure_cons (gfc_expr *expr)
726 {
727   gfc_constructor_base base = NULL;
728   gfc_constructor *cur;
729   gfc_component *order;
730 
731   /* Constructor is already formalized.  */
732   cur = gfc_constructor_first (expr->value.constructor);
733   if (!cur || cur->n.component == NULL)
734     return;
735 
736   for (order = expr->ts.u.derived->components; order; order = order->next)
737     {
738       cur = find_con_by_component (order, expr->value.constructor);
739       if (cur)
740 	gfc_constructor_append_expr (&base, cur->expr, &cur->expr->where);
741       else
742 	gfc_constructor_append_expr (&base, NULL, NULL);
743     }
744 
745   /* For all what it's worth, one would expect
746        gfc_constructor_free (expr->value.constructor);
747      here. However, if the constructor is actually free'd,
748      hell breaks loose in the testsuite?!  */
749 
750   expr->value.constructor = base;
751 }
752 
753 
754 /* Make sure an initialization expression is in normalized form, i.e., all
755    elements of the constructors are in the correct order.  */
756 
757 static void
formalize_init_expr(gfc_expr * expr)758 formalize_init_expr (gfc_expr *expr)
759 {
760   expr_t type;
761   gfc_constructor *c;
762 
763   if (expr == NULL)
764     return;
765 
766   type = expr->expr_type;
767   switch (type)
768     {
769     case EXPR_ARRAY:
770       for (c = gfc_constructor_first (expr->value.constructor);
771 	   c; c = gfc_constructor_next (c))
772 	formalize_init_expr (c->expr);
773 
774     break;
775 
776     case EXPR_STRUCTURE:
777       formalize_structure_cons (expr);
778       break;
779 
780     default:
781       break;
782     }
783 }
784 
785 
786 /* Resolve symbol's initial value after all data statement.  */
787 
788 void
gfc_formalize_init_value(gfc_symbol * sym)789 gfc_formalize_init_value (gfc_symbol *sym)
790 {
791   formalize_init_expr (sym->value);
792 }
793 
794 
795 /* Get the integer value into RET_AS and SECTION from AS and AR, and return
796    offset.  */
797 
798 void
gfc_get_section_index(gfc_array_ref * ar,mpz_t * section_index,mpz_t * offset)799 gfc_get_section_index (gfc_array_ref *ar, mpz_t *section_index, mpz_t *offset)
800 {
801   int i;
802   mpz_t delta;
803   mpz_t tmp;
804   gfc_expr *start;
805 
806   mpz_set_si (*offset, 0);
807   mpz_init (tmp);
808   mpz_init_set_si (delta, 1);
809   for (i = 0; i < ar->dimen; i++)
810     {
811       mpz_init (section_index[i]);
812       switch (ar->dimen_type[i])
813 	{
814 	case DIMEN_ELEMENT:
815 	case DIMEN_RANGE:
816 	  if (ar->start[i])
817 	    {
818 	      start = gfc_copy_expr(ar->start[i]);
819 	      if(!gfc_simplify_expr(start, 1))
820 	        gfc_internal_error("Simplification error");
821 	      mpz_sub (tmp, start->value.integer,
822 		       ar->as->lower[i]->value.integer);
823 	      mpz_mul (tmp, tmp, delta);
824 	      mpz_add (*offset, tmp, *offset);
825 	      mpz_set (section_index[i], start->value.integer);
826 	      gfc_free_expr(start);
827 	    }
828 	  else
829 	      mpz_set (section_index[i], ar->as->lower[i]->value.integer);
830 	  break;
831 
832 	case DIMEN_VECTOR:
833 	  gfc_internal_error ("TODO: Vector sections in data statements");
834 
835 	default:
836 	  gcc_unreachable ();
837 	}
838 
839       mpz_sub (tmp, ar->as->upper[i]->value.integer,
840 	       ar->as->lower[i]->value.integer);
841       mpz_add_ui (tmp, tmp, 1);
842       mpz_mul (delta, tmp, delta);
843     }
844 
845   mpz_clear (tmp);
846   mpz_clear (delta);
847 }
848 
849