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>
6 This file is part of GCC.
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
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
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/>. */
23 /* Notes for DATA statement implementation:
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.
29 The complexity exists in the handling of array section, implied do
30 and array of struct appeared in DATA statement.
32 We call gfc_conv_structure, gfc_con_array_array_initializer,
33 etc., to convert the initial value. Refer to trans-expr.c and
40 #include "constructor.h"
42 static void formalize_init_expr (gfc_expr
*);
44 /* Calculate the array element offset. */
47 get_array_index (gfc_array_ref
*ar
, mpz_t
*offset
)
55 mpz_set_si (*offset
, 0);
56 mpz_init_set_si (delta
, 1);
57 for (i
= 0; i
< ar
->dimen
; i
++)
59 e
= gfc_copy_expr (ar
->start
[i
]);
60 gfc_simplify_expr (e
, 1);
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
);
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
);
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
);
81 /* Find if there is a constructor which component is equal to COM.
82 TODO: remove this, use symbol.c(gfc_find_component) instead. */
84 static gfc_constructor
*
85 find_con_by_component (gfc_component
*com
, gfc_constructor_base base
)
89 for (c
= gfc_constructor_first (base
); c
; c
= gfc_constructor_next (c
))
90 if (com
== c
->n
.component
)
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. */
103 create_character_initializer (gfc_expr
*init
, gfc_typespec
*ts
,
104 gfc_ref
*ref
, gfc_expr
*rvalue
)
109 gfc_extract_int (ts
->u
.cl
->length
, &len
);
113 /* Create a new initializer. */
114 init
= gfc_get_character_expr (ts
->kind
, NULL
, NULL
, len
);
118 dest
= init
->value
.character
.string
;
122 gfc_expr
*start_expr
, *end_expr
;
124 gcc_assert (ref
->type
== REF_SUBSTRING
);
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
);
131 if ((gfc_simplify_expr (start_expr
, 1) == FAILURE
)
132 || (gfc_simplify_expr (end_expr
, 1)) == FAILURE
)
134 gfc_error ("failure to simplify substring reference in DATA "
135 "statement at %L", &ref
->u
.ss
.start
->where
);
139 gfc_extract_int (start_expr
, &start
);
141 gfc_extract_int (end_expr
, &end
);
145 /* Set the whole string. */
150 /* Copy the initial value. */
151 if (rvalue
->ts
.type
== BT_HOLLERITH
)
152 len
= rvalue
->representation
.length
- rvalue
->ts
.u
.pad
;
154 len
= rvalue
->value
.character
.length
;
156 if (len
> end
- start
)
158 gfc_warning_now ("Initialization string starting at %L was "
159 "truncated to fit the variable (%d/%d)",
160 &rvalue
->where
, end
- start
, len
);
164 if (rvalue
->ts
.type
== BT_HOLLERITH
)
167 for (i
= 0; i
< len
; i
++)
168 dest
[start
+i
] = rvalue
->representation
.string
[i
];
171 memcpy (&dest
[start
], rvalue
->value
.character
.string
,
172 len
* sizeof (gfc_char_t
));
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
));
178 if (rvalue
->ts
.type
== BT_HOLLERITH
)
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
);
190 /* Assign the initial value RVALUE to LVALUE's symbol->value. If the
191 LVALUE already has an initialization, we extend this, otherwise we
195 gfc_assign_data_value (gfc_expr
*lvalue
, gfc_expr
*rvalue
, mpz_t index
)
200 gfc_constructor
*con
;
201 gfc_constructor
*last_con
;
203 gfc_typespec
*last_ts
;
206 symbol
= lvalue
->symtree
->n
.sym
;
207 init
= symbol
->value
;
208 last_ts
= &symbol
->ts
;
210 mpz_init_set_si (offset
, 0);
212 /* Find/create the parent expressions for subobject references. */
213 for (ref
= lvalue
->ref
; ref
; ref
= ref
->next
)
215 /* Break out of the loop if we find a substring. */
216 if (ref
->type
== REF_SUBSTRING
)
218 /* A substring should always be the last subobject reference. */
219 gcc_assert (ref
->next
== NULL
);
223 /* Use the existing initializer expression if it exists. Otherwise
226 expr
= gfc_get_expr ();
230 /* Find or create this element. */
234 if (ref
->u
.ar
.as
->rank
== 0)
236 gcc_assert (ref
->u
.ar
.as
->corank
> 0);
242 if (init
&& expr
->expr_type
!= EXPR_ARRAY
)
244 gfc_error ("'%s' at %L already is initialized at %L",
245 lvalue
->symtree
->n
.sym
->name
, &lvalue
->where
,
252 /* The element typespec will be the same as the array
255 /* Setup the expression to hold the constructor. */
256 expr
->expr_type
= EXPR_ARRAY
;
257 expr
->rank
= ref
->u
.ar
.as
->rank
;
260 if (ref
->u
.ar
.type
== AR_ELEMENT
)
261 get_array_index (&ref
->u
.ar
, &offset
);
263 mpz_set (offset
, index
);
265 /* Check the bounds. */
266 if (mpz_cmp_si (offset
, 0) < 0)
268 gfc_error ("Data element below array lower bound at %L",
275 if (spec_size (ref
->u
.ar
.as
, &size
) == SUCCESS
)
277 if (mpz_cmp (offset
, size
) >= 0)
280 gfc_error ("Data element above array upper bound at %L",
288 con
= gfc_constructor_lookup (expr
->value
.constructor
,
289 mpz_get_si (offset
));
292 con
= gfc_constructor_insert_expr (&expr
->value
.constructor
,
293 NULL
, &rvalue
->where
,
294 mpz_get_si (offset
));
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
;
307 gcc_assert (expr
->expr_type
== EXPR_STRUCTURE
);
308 last_ts
= &ref
->u
.c
.component
->ts
;
310 /* Find the same element in the existing constructor. */
311 con
= find_con_by_component (ref
->u
.c
.component
,
312 expr
->value
.constructor
);
316 /* Create a new constructor. */
317 con
= gfc_constructor_append_expr (&expr
->value
.constructor
,
319 con
->n
.component
= ref
->u
.c
.component
;
329 /* Point the container at the new expression. */
330 if (last_con
== NULL
)
331 symbol
->value
= expr
;
333 last_con
->expr
= expr
;
341 if (ref
|| last_ts
->type
== BT_CHARACTER
)
343 if (lvalue
->ts
.u
.cl
->length
== NULL
&& !(ref
&& ref
->u
.ss
.length
!= NULL
))
345 expr
= create_character_initializer (init
, last_ts
, ref
, rvalue
);
349 /* Overwriting an existing initializer is non-standard but usually only
350 provokes a warning from other compilers. */
353 /* Order in which the expressions arrive here depends on whether
354 they are from data statements or F95 style declarations.
355 Therefore, check which is the most recent. */
356 expr
= (LOCATION_LINE (init
->where
.lb
->location
)
357 > LOCATION_LINE (rvalue
->where
.lb
->location
))
359 if (gfc_notify_std (GFC_STD_GNU
,"Extension: "
360 "re-initialization of '%s' at %L",
361 symbol
->name
, &expr
->where
) == FAILURE
)
365 expr
= gfc_copy_expr (rvalue
);
366 if (!gfc_compare_types (&lvalue
->ts
, &expr
->ts
))
367 gfc_convert_type (expr
, &lvalue
->ts
, 0);
370 if (last_con
== NULL
)
371 symbol
->value
= expr
;
373 last_con
->expr
= expr
;
383 /* Similarly, but initialize REPEAT consecutive values in LVALUE the same
387 gfc_assign_data_value_range (gfc_expr
*lvalue
, gfc_expr
*rvalue
,
388 mpz_t index
, mpz_t repeat
)
390 mpz_t offset
, last_offset
;
394 mpz_init (last_offset
);
395 mpz_add (last_offset
, index
, repeat
);
398 for (mpz_set(offset
, index
) ; mpz_cmp(offset
, last_offset
) < 0;
399 mpz_add_ui (offset
, offset
, 1))
400 if (gfc_assign_data_value (lvalue
, rvalue
, offset
) == FAILURE
)
407 mpz_clear (last_offset
);
413 /* Modify the index of array section and re-calculate the array offset. */
416 gfc_advance_section (mpz_t
*section_index
, gfc_array_ref
*ar
,
425 for (i
= 0; i
< ar
->dimen
; i
++)
427 if (ar
->dimen_type
[i
] != DIMEN_RANGE
)
432 mpz_add (section_index
[i
], section_index
[i
],
433 ar
->stride
[i
]->value
.integer
);
434 if (mpz_cmp_si (ar
->stride
[i
]->value
.integer
, 0) >= 0)
441 mpz_add_ui (section_index
[i
], section_index
[i
], 1);
446 cmp
= mpz_cmp (section_index
[i
], ar
->end
[i
]->value
.integer
);
448 cmp
= mpz_cmp (section_index
[i
], ar
->as
->upper
[i
]->value
.integer
);
450 if ((cmp
> 0 && forwards
) || (cmp
< 0 && !forwards
))
452 /* Reset index to start, then loop to advance the next index. */
454 mpz_set (section_index
[i
], ar
->start
[i
]->value
.integer
);
456 mpz_set (section_index
[i
], ar
->as
->lower
[i
]->value
.integer
);
462 mpz_set_si (*offset_ret
, 0);
463 mpz_init_set_si (delta
, 1);
465 for (i
= 0; i
< ar
->dimen
; i
++)
467 mpz_sub (tmp
, section_index
[i
], ar
->as
->lower
[i
]->value
.integer
);
468 mpz_mul (tmp
, tmp
, delta
);
469 mpz_add (*offset_ret
, tmp
, *offset_ret
);
471 mpz_sub (tmp
, ar
->as
->upper
[i
]->value
.integer
,
472 ar
->as
->lower
[i
]->value
.integer
);
473 mpz_add_ui (tmp
, tmp
, 1);
474 mpz_mul (delta
, tmp
, delta
);
481 /* Rearrange a structure constructor so the elements are in the specified
482 order. Also insert NULL entries if necessary. */
485 formalize_structure_cons (gfc_expr
*expr
)
487 gfc_constructor_base base
= NULL
;
488 gfc_constructor
*cur
;
489 gfc_component
*order
;
491 /* Constructor is already formalized. */
492 cur
= gfc_constructor_first (expr
->value
.constructor
);
493 if (!cur
|| cur
->n
.component
== NULL
)
496 for (order
= expr
->ts
.u
.derived
->components
; order
; order
= order
->next
)
498 cur
= find_con_by_component (order
, expr
->value
.constructor
);
500 gfc_constructor_append_expr (&base
, cur
->expr
, &cur
->expr
->where
);
502 gfc_constructor_append_expr (&base
, NULL
, NULL
);
505 /* For all what it's worth, one would expect
506 gfc_constructor_free (expr->value.constructor);
507 here. However, if the constructor is actually free'd,
508 hell breaks loose in the testsuite?! */
510 expr
->value
.constructor
= base
;
514 /* Make sure an initialization expression is in normalized form, i.e., all
515 elements of the constructors are in the correct order. */
518 formalize_init_expr (gfc_expr
*expr
)
526 type
= expr
->expr_type
;
530 for (c
= gfc_constructor_first (expr
->value
.constructor
);
531 c
; c
= gfc_constructor_next (c
))
532 formalize_init_expr (c
->expr
);
537 formalize_structure_cons (expr
);
546 /* Resolve symbol's initial value after all data statement. */
549 gfc_formalize_init_value (gfc_symbol
*sym
)
551 formalize_init_expr (sym
->value
);
555 /* Get the integer value into RET_AS and SECTION from AS and AR, and return
559 gfc_get_section_index (gfc_array_ref
*ar
, mpz_t
*section_index
, mpz_t
*offset
)
565 mpz_set_si (*offset
, 0);
567 mpz_init_set_si (delta
, 1);
568 for (i
= 0; i
< ar
->dimen
; i
++)
570 mpz_init (section_index
[i
]);
571 switch (ar
->dimen_type
[i
])
577 mpz_sub (tmp
, ar
->start
[i
]->value
.integer
,
578 ar
->as
->lower
[i
]->value
.integer
);
579 mpz_mul (tmp
, tmp
, delta
);
580 mpz_add (*offset
, tmp
, *offset
);
581 mpz_set (section_index
[i
], ar
->start
[i
]->value
.integer
);
584 mpz_set (section_index
[i
], ar
->as
->lower
[i
]->value
.integer
);
588 gfc_internal_error ("TODO: Vector sections in data statements");
594 mpz_sub (tmp
, ar
->as
->upper
[i
]->value
.integer
,
595 ar
->as
->lower
[i
]->value
.integer
);
596 mpz_add_ui (tmp
, tmp
, 1);
597 mpz_mul (delta
, tmp
, delta
);