OSDN Git Service

2010-05-28 Tobias Burnus <burnus@net-b.de>
[pf3gnuchains/gcc-fork.git] / gcc / fortran / data.c
1 /* Supporting functions for resolving DATA statement.
2    Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
3    Free Software Foundation, Inc.
4    Contributed by Lifang Zeng <zlf605@hotmail.com>
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
12
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3.  If not see
20 <http://www.gnu.org/licenses/>.  */
21
22
23 /* Notes for DATA statement implementation:
24                                                                                
25    We first assign initial value to each symbol by gfc_assign_data_value
26    during resolving DATA statement. Refer to check_data_variable and
27    traverse_data_list in resolve.c.
28                                                                                
29    The complexity exists in the handling of array section, implied do
30    and array of struct appeared in DATA statement.
31                                                                                
32    We call gfc_conv_structure, gfc_con_array_array_initializer,
33    etc., to convert the initial value. Refer to trans-expr.c and
34    trans-array.c.  */
35
36 #include "config.h"
37 #include "system.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
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       mpz_sub (tmp, tmp, ar->as->lower[i]->value.integer);
69       mpz_mul (tmp, tmp, delta);
70       mpz_add (*offset, tmp, *offset);
71
72       mpz_sub (tmp, ar->as->upper[i]->value.integer,
73                ar->as->lower[i]->value.integer);
74       mpz_add_ui (tmp, tmp, 1);
75       mpz_mul (delta, tmp, delta);
76     }
77   mpz_clear (delta);
78   mpz_clear (tmp);
79 }
80
81 /* Find if there is a constructor which component is equal to COM.
82    TODO: remove this, use symbol.c(gfc_find_component) instead.  */
83
84 static gfc_constructor *
85 find_con_by_component (gfc_component *com, gfc_constructor_base base)
86 {
87   gfc_constructor *c;
88
89   for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
90     if (com == c->n.component)
91       return c;
92
93   return NULL;
94 }
95
96
97 /* Create a character type initialization expression from RVALUE.
98    TS [and REF] describe [the substring of] the variable being initialized.
99    INIT is the existing initializer, not NULL.  Initialization is performed
100    according to normal assignment rules.  */
101
102 static gfc_expr *
103 create_character_intializer (gfc_expr *init, gfc_typespec *ts,
104                              gfc_ref *ref, gfc_expr *rvalue)
105 {
106   int len, start, end;
107   gfc_char_t *dest;
108             
109   gfc_extract_int (ts->u.cl->length, &len);
110
111   if (init == NULL)
112     {
113       /* Create a new initializer.  */
114       init = gfc_get_character_expr (ts->kind, NULL, NULL, len);
115       init->ts = *ts;
116     }
117
118   dest = init->value.character.string;
119
120   if (ref)
121     {
122       gfc_expr *start_expr, *end_expr;
123
124       gcc_assert (ref->type == REF_SUBSTRING);
125
126       /* Only set a substring of the destination.  Fortran substring bounds
127          are one-based [start, end], we want zero based [start, end).  */
128       start_expr = gfc_copy_expr (ref->u.ss.start);
129       end_expr = gfc_copy_expr (ref->u.ss.end);
130
131       if ((gfc_simplify_expr (start_expr, 1) == FAILURE)
132           || (gfc_simplify_expr (end_expr, 1)) == FAILURE)
133         {
134           gfc_error ("failure to simplify substring reference in DATA "
135                      "statement at %L", &ref->u.ss.start->where);
136           return NULL;
137         }
138
139       gfc_extract_int (start_expr, &start);
140       start--;
141       gfc_extract_int (end_expr, &end);
142     }
143   else
144     {
145       /* Set the whole string.  */
146       start = 0;
147       end = len;
148     }
149
150   /* Copy the initial value.  */
151   if (rvalue->ts.type == BT_HOLLERITH)
152     len = rvalue->representation.length;
153   else
154     len = rvalue->value.character.length;
155
156   if (len > end - start)
157     {
158       gfc_warning_now ("Initialization string starting at %L was "
159                        "truncated to fit the variable (%d/%d)",
160                        &rvalue->where, end - start, len);
161       len = end - start;
162     }
163
164   if (rvalue->ts.type == BT_HOLLERITH)
165     {
166       int i;
167       for (i = 0; i < len; i++)
168         dest[start+i] = rvalue->representation.string[i];
169     }
170   else
171     memcpy (&dest[start], rvalue->value.character.string,
172             len * sizeof (gfc_char_t));
173
174   /* Pad with spaces.  Substrings will already be blanked.  */
175   if (len < end - start && ref == NULL)
176     gfc_wide_memset (&dest[start + len], ' ', end - (start + len));
177
178   if (rvalue->ts.type == BT_HOLLERITH)
179     {
180       init->representation.length = init->value.character.length;
181       init->representation.string
182         = gfc_widechar_to_char (init->value.character.string,
183                                 init->value.character.length);
184     }
185
186   return init;
187 }
188
189
190 /* Assign the initial value RVALUE to  LVALUE's symbol->value. If the
191    LVALUE already has an initialization, we extend this, otherwise we
192    create a new one.  */
193
194 gfc_try
195 gfc_assign_data_value (gfc_expr *lvalue, gfc_expr *rvalue, mpz_t index)
196 {
197   gfc_ref *ref;
198   gfc_expr *init;
199   gfc_expr *expr;
200   gfc_constructor *con;
201   gfc_constructor *last_con;
202   gfc_symbol *symbol;
203   gfc_typespec *last_ts;
204   mpz_t offset;
205
206   symbol = lvalue->symtree->n.sym;
207   init = symbol->value;
208   last_ts = &symbol->ts;
209   last_con = NULL;
210   mpz_init_set_si (offset, 0);
211
212   /* Find/create the parent expressions for subobject references.  */
213   for (ref = lvalue->ref; ref; ref = ref->next)
214     {
215       /* Break out of the loop if we find a substring.  */
216       if (ref->type == REF_SUBSTRING)
217         {
218           /* A substring should always be the last subobject reference.  */
219           gcc_assert (ref->next == NULL);
220           break;
221         }
222
223       /* Use the existing initializer expression if it exists.  Otherwise
224          create a new one.  */
225       if (init == NULL)
226         expr = gfc_get_expr ();
227       else
228         expr = init;
229
230       /* Find or create this element.  */
231       switch (ref->type)
232         {
233         case REF_ARRAY:
234           if (ref->u.ar.as->rank == 0)
235             {
236               gcc_assert (ref->u.ar.as->corank > 0);
237               if (init == NULL)
238                 gfc_free (expr);
239               continue;
240             }
241
242           if (init && expr->expr_type != EXPR_ARRAY)
243             {
244               gfc_error ("'%s' at %L already is initialized at %L",
245                          lvalue->symtree->n.sym->name, &lvalue->where,
246                          &init->where);
247               return FAILURE;
248             }
249
250           if (init == NULL)
251             {
252               /* The element typespec will be the same as the array
253                  typespec.  */
254               expr->ts = *last_ts;
255               /* Setup the expression to hold the constructor.  */
256               expr->expr_type = EXPR_ARRAY;
257               expr->rank = ref->u.ar.as->rank;
258             }
259
260           if (ref->u.ar.type == AR_ELEMENT)
261             get_array_index (&ref->u.ar, &offset);
262           else
263             mpz_set (offset, index);
264
265           /* Check the bounds.  */
266           if (mpz_cmp_si (offset, 0) < 0)
267             {
268               gfc_error ("Data element below array lower bound at %L",
269                          &lvalue->where);
270               return FAILURE;
271             }
272           else
273             {
274               mpz_t size;
275               if (spec_size (ref->u.ar.as, &size) == SUCCESS)
276                 {
277                   if (mpz_cmp (offset, size) >= 0)
278                   {
279                     mpz_clear (size);
280                     gfc_error ("Data element above array upper bound at %L",
281                                &lvalue->where);
282                     return FAILURE;
283                   }
284                   mpz_clear (size);
285                 }
286             }
287
288           con = gfc_constructor_lookup (expr->value.constructor,
289                                         mpz_get_si (offset));
290           if (!con)
291             {
292               con = gfc_constructor_insert_expr (&expr->value.constructor,
293                                                  NULL, &rvalue->where,
294                                                  mpz_get_si (offset));
295             }
296           break;
297
298         case REF_COMPONENT:
299           if (init == NULL)
300             {
301               /* Setup the expression to hold the constructor.  */
302               expr->expr_type = EXPR_STRUCTURE;
303               expr->ts.type = BT_DERIVED;
304               expr->ts.u.derived = ref->u.c.sym;
305             }
306           else
307             gcc_assert (expr->expr_type == EXPR_STRUCTURE);
308           last_ts = &ref->u.c.component->ts;
309
310           /* Find the same element in the existing constructor.  */
311           con = find_con_by_component (ref->u.c.component,
312                                        expr->value.constructor);
313
314           if (con == NULL)
315             {
316               /* Create a new constructor.  */
317               con = gfc_constructor_append_expr (&expr->value.constructor,
318                                                  NULL, NULL);
319               con->n.component = ref->u.c.component;
320             }
321           break;
322
323         default:
324           gcc_unreachable ();
325         }
326
327       if (init == NULL)
328         {
329           /* Point the container at the new expression.  */
330           if (last_con == NULL)
331             symbol->value = expr;
332           else
333             last_con->expr = expr;
334         }
335       init = con->expr;
336       last_con = con;
337     }
338
339   if (ref || last_ts->type == BT_CHARACTER)
340     {
341       if (lvalue->ts.u.cl->length == NULL && !(ref && ref->u.ss.length != NULL))
342         return FAILURE;
343       expr = create_character_intializer (init, last_ts, ref, rvalue);
344     }
345   else
346     {
347       /* Overwriting an existing initializer is non-standard but usually only
348          provokes a warning from other compilers.  */
349       if (init != NULL)
350         {
351           /* Order in which the expressions arrive here depends on whether
352              they are from data statements or F95 style declarations.
353              Therefore, check which is the most recent.  */
354           expr = (LOCATION_LINE (init->where.lb->location)
355                   > LOCATION_LINE (rvalue->where.lb->location))
356                ? init : rvalue;
357           if (gfc_notify_std (GFC_STD_GNU,"Extension: "
358                               "re-initialization of '%s' at %L",
359                               symbol->name, &expr->where) == FAILURE)
360             return FAILURE;
361         }
362
363       expr = gfc_copy_expr (rvalue);
364       if (!gfc_compare_types (&lvalue->ts, &expr->ts))
365         gfc_convert_type (expr, &lvalue->ts, 0);
366     }
367
368   if (last_con == NULL)
369     symbol->value = expr;
370   else
371     last_con->expr = expr;
372
373   return SUCCESS;
374 }
375
376
377 /* Similarly, but initialize REPEAT consecutive values in LVALUE the same
378    value in RVALUE.  */
379
380 gfc_try
381 gfc_assign_data_value_range (gfc_expr *lvalue, gfc_expr *rvalue,
382                              mpz_t index, mpz_t repeat)
383 {
384   mpz_t offset, last_offset;
385   gfc_try t;
386
387   mpz_init (offset);
388   mpz_init (last_offset);
389   mpz_add (last_offset, index, repeat);
390
391   t = SUCCESS;
392   for (mpz_set(offset, index) ; mpz_cmp(offset, last_offset) < 0;
393                    mpz_add_ui (offset, offset, 1))
394     if (gfc_assign_data_value (lvalue, rvalue, offset) == FAILURE)
395       {
396         t = FAILURE;
397         break;
398       }
399
400   mpz_clear (offset);
401   mpz_clear (last_offset);
402
403   return t;
404 }
405
406
407 /* Modify the index of array section and re-calculate the array offset.  */
408
409 void 
410 gfc_advance_section (mpz_t *section_index, gfc_array_ref *ar,
411                      mpz_t *offset_ret)
412 {
413   int i;
414   mpz_t delta;
415   mpz_t tmp; 
416   bool forwards;
417   int cmp;
418
419   for (i = 0; i < ar->dimen; i++)
420     {
421       if (ar->dimen_type[i] != DIMEN_RANGE)
422         continue;
423
424       if (ar->stride[i])
425         {
426           mpz_add (section_index[i], section_index[i],
427                    ar->stride[i]->value.integer);
428         if (mpz_cmp_si (ar->stride[i]->value.integer, 0) >= 0)
429           forwards = true;
430         else
431           forwards = false;
432         }
433       else
434         {
435           mpz_add_ui (section_index[i], section_index[i], 1);
436           forwards = true;
437         }
438       
439       if (ar->end[i])
440         cmp = mpz_cmp (section_index[i], ar->end[i]->value.integer);
441       else
442         cmp = mpz_cmp (section_index[i], ar->as->upper[i]->value.integer);
443
444       if ((cmp > 0 && forwards) || (cmp < 0 && !forwards))
445         {
446           /* Reset index to start, then loop to advance the next index.  */
447           if (ar->start[i])
448             mpz_set (section_index[i], ar->start[i]->value.integer);
449           else
450             mpz_set (section_index[i], ar->as->lower[i]->value.integer);
451         }
452       else
453         break;
454     }
455
456   mpz_set_si (*offset_ret, 0);
457   mpz_init_set_si (delta, 1);
458   mpz_init (tmp);
459   for (i = 0; i < ar->dimen; i++)
460     {
461       mpz_sub (tmp, section_index[i], ar->as->lower[i]->value.integer);
462       mpz_mul (tmp, tmp, delta);
463       mpz_add (*offset_ret, tmp, *offset_ret);
464
465       mpz_sub (tmp, ar->as->upper[i]->value.integer, 
466                ar->as->lower[i]->value.integer);
467       mpz_add_ui (tmp, tmp, 1);
468       mpz_mul (delta, tmp, delta);
469     }
470   mpz_clear (tmp);
471   mpz_clear (delta);
472 }
473
474
475 /* Rearrange a structure constructor so the elements are in the specified
476    order.  Also insert NULL entries if necessary.  */
477
478 static void
479 formalize_structure_cons (gfc_expr *expr)
480 {
481   gfc_constructor_base base = NULL;
482   gfc_constructor *cur;
483   gfc_component *order;
484
485   /* Constructor is already formalized.  */
486   cur = gfc_constructor_first (expr->value.constructor);
487   if (!cur || cur->n.component == NULL)
488     return;
489
490   for (order = expr->ts.u.derived->components; order; order = order->next)
491     {
492       cur = find_con_by_component (order, expr->value.constructor);
493       if (cur)
494         gfc_constructor_append_expr (&base, cur->expr, &cur->expr->where);
495       else
496         gfc_constructor_append_expr (&base, NULL, NULL);
497     }
498
499   /* For all what it's worth, one would expect
500        gfc_constructor_free (expr->value.constructor);
501      here. However, if the constructor is actually free'd,
502      hell breaks loose in the testsuite?!  */
503
504   expr->value.constructor = base;
505 }
506
507
508 /* Make sure an initialization expression is in normalized form, i.e., all
509    elements of the constructors are in the correct order.  */
510
511 static void
512 formalize_init_expr (gfc_expr *expr)
513 {
514   expr_t type;
515   gfc_constructor *c;
516
517   if (expr == NULL)
518     return;
519
520   type = expr->expr_type;
521   switch (type)
522     {
523     case EXPR_ARRAY:
524       for (c = gfc_constructor_first (expr->value.constructor);
525            c; c = gfc_constructor_next (c))
526         formalize_init_expr (c->expr);
527
528     break;
529
530     case EXPR_STRUCTURE:
531       formalize_structure_cons (expr);
532       break;
533
534     default:
535       break;
536     }
537 }
538
539
540 /* Resolve symbol's initial value after all data statement.  */
541
542 void
543 gfc_formalize_init_value (gfc_symbol *sym)
544 {
545   formalize_init_expr (sym->value);
546 }
547
548
549 /* Get the integer value into RET_AS and SECTION from AS and AR, and return
550    offset.  */
551  
552 void
553 gfc_get_section_index (gfc_array_ref *ar, mpz_t *section_index, mpz_t *offset)
554 {
555   int i;
556   mpz_t delta;
557   mpz_t tmp;
558
559   mpz_set_si (*offset, 0);
560   mpz_init (tmp);
561   mpz_init_set_si (delta, 1);
562   for (i = 0; i < ar->dimen; i++)
563     {
564       mpz_init (section_index[i]);
565       switch (ar->dimen_type[i])
566         {
567         case DIMEN_ELEMENT:
568         case DIMEN_RANGE:
569           if (ar->start[i])
570             {
571               mpz_sub (tmp, ar->start[i]->value.integer,
572                        ar->as->lower[i]->value.integer);
573               mpz_mul (tmp, tmp, delta);
574               mpz_add (*offset, tmp, *offset);
575               mpz_set (section_index[i], ar->start[i]->value.integer);
576             }
577           else
578               mpz_set (section_index[i], ar->as->lower[i]->value.integer);
579           break;
580
581         case DIMEN_VECTOR:
582           gfc_internal_error ("TODO: Vector sections in data statements");
583
584         default:
585           gcc_unreachable ();
586         }
587
588       mpz_sub (tmp, ar->as->upper[i]->value.integer, 
589                ar->as->lower[i]->value.integer);
590       mpz_add_ui (tmp, tmp, 1);
591       mpz_mul (delta, tmp, delta);
592     }
593
594   mpz_clear (tmp);
595   mpz_clear (delta);
596 }
597