annotate gcc/fortran/array.c @ 111:04ced10e8804

gcc 7
author kono
date Fri, 27 Oct 2017 22:46:09 +0900
parents
children 84e7813d76e9
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* Array things
kono
parents:
diff changeset
2 Copyright (C) 2000-2017 Free Software Foundation, Inc.
kono
parents:
diff changeset
3 Contributed by Andy Vaught
kono
parents:
diff changeset
4
kono
parents:
diff changeset
5 This file is part of GCC.
kono
parents:
diff changeset
6
kono
parents:
diff changeset
7 GCC is free software; you can redistribute it and/or modify it under
kono
parents:
diff changeset
8 the terms of the GNU General Public License as published by the Free
kono
parents:
diff changeset
9 Software Foundation; either version 3, or (at your option) any later
kono
parents:
diff changeset
10 version.
kono
parents:
diff changeset
11
kono
parents:
diff changeset
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
kono
parents:
diff changeset
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
kono
parents:
diff changeset
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
kono
parents:
diff changeset
15 for more details.
kono
parents:
diff changeset
16
kono
parents:
diff changeset
17 You should have received a copy of the GNU General Public License
kono
parents:
diff changeset
18 along with GCC; see the file COPYING3. If not see
kono
parents:
diff changeset
19 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
20
kono
parents:
diff changeset
21 #include "config.h"
kono
parents:
diff changeset
22 #include "system.h"
kono
parents:
diff changeset
23 #include "coretypes.h"
kono
parents:
diff changeset
24 #include "options.h"
kono
parents:
diff changeset
25 #include "gfortran.h"
kono
parents:
diff changeset
26 #include "match.h"
kono
parents:
diff changeset
27 #include "constructor.h"
kono
parents:
diff changeset
28
kono
parents:
diff changeset
29 /**************** Array reference matching subroutines *****************/
kono
parents:
diff changeset
30
kono
parents:
diff changeset
31 /* Copy an array reference structure. */
kono
parents:
diff changeset
32
kono
parents:
diff changeset
33 gfc_array_ref *
kono
parents:
diff changeset
34 gfc_copy_array_ref (gfc_array_ref *src)
kono
parents:
diff changeset
35 {
kono
parents:
diff changeset
36 gfc_array_ref *dest;
kono
parents:
diff changeset
37 int i;
kono
parents:
diff changeset
38
kono
parents:
diff changeset
39 if (src == NULL)
kono
parents:
diff changeset
40 return NULL;
kono
parents:
diff changeset
41
kono
parents:
diff changeset
42 dest = gfc_get_array_ref ();
kono
parents:
diff changeset
43
kono
parents:
diff changeset
44 *dest = *src;
kono
parents:
diff changeset
45
kono
parents:
diff changeset
46 for (i = 0; i < GFC_MAX_DIMENSIONS; i++)
kono
parents:
diff changeset
47 {
kono
parents:
diff changeset
48 dest->start[i] = gfc_copy_expr (src->start[i]);
kono
parents:
diff changeset
49 dest->end[i] = gfc_copy_expr (src->end[i]);
kono
parents:
diff changeset
50 dest->stride[i] = gfc_copy_expr (src->stride[i]);
kono
parents:
diff changeset
51 }
kono
parents:
diff changeset
52
kono
parents:
diff changeset
53 return dest;
kono
parents:
diff changeset
54 }
kono
parents:
diff changeset
55
kono
parents:
diff changeset
56
kono
parents:
diff changeset
57 /* Match a single dimension of an array reference. This can be a
kono
parents:
diff changeset
58 single element or an array section. Any modifications we've made
kono
parents:
diff changeset
59 to the ar structure are cleaned up by the caller. If the init
kono
parents:
diff changeset
60 is set, we require the subscript to be a valid initialization
kono
parents:
diff changeset
61 expression. */
kono
parents:
diff changeset
62
kono
parents:
diff changeset
63 static match
kono
parents:
diff changeset
64 match_subscript (gfc_array_ref *ar, int init, bool match_star)
kono
parents:
diff changeset
65 {
kono
parents:
diff changeset
66 match m = MATCH_ERROR;
kono
parents:
diff changeset
67 bool star = false;
kono
parents:
diff changeset
68 int i;
kono
parents:
diff changeset
69
kono
parents:
diff changeset
70 i = ar->dimen + ar->codimen;
kono
parents:
diff changeset
71
kono
parents:
diff changeset
72 gfc_gobble_whitespace ();
kono
parents:
diff changeset
73 ar->c_where[i] = gfc_current_locus;
kono
parents:
diff changeset
74 ar->start[i] = ar->end[i] = ar->stride[i] = NULL;
kono
parents:
diff changeset
75
kono
parents:
diff changeset
76 /* We can't be sure of the difference between DIMEN_ELEMENT and
kono
parents:
diff changeset
77 DIMEN_VECTOR until we know the type of the element itself at
kono
parents:
diff changeset
78 resolution time. */
kono
parents:
diff changeset
79
kono
parents:
diff changeset
80 ar->dimen_type[i] = DIMEN_UNKNOWN;
kono
parents:
diff changeset
81
kono
parents:
diff changeset
82 if (gfc_match_char (':') == MATCH_YES)
kono
parents:
diff changeset
83 goto end_element;
kono
parents:
diff changeset
84
kono
parents:
diff changeset
85 /* Get start element. */
kono
parents:
diff changeset
86 if (match_star && (m = gfc_match_char ('*')) == MATCH_YES)
kono
parents:
diff changeset
87 star = true;
kono
parents:
diff changeset
88
kono
parents:
diff changeset
89 if (!star && init)
kono
parents:
diff changeset
90 m = gfc_match_init_expr (&ar->start[i]);
kono
parents:
diff changeset
91 else if (!star)
kono
parents:
diff changeset
92 m = gfc_match_expr (&ar->start[i]);
kono
parents:
diff changeset
93
kono
parents:
diff changeset
94 if (m == MATCH_NO)
kono
parents:
diff changeset
95 gfc_error ("Expected array subscript at %C");
kono
parents:
diff changeset
96 if (m != MATCH_YES)
kono
parents:
diff changeset
97 return MATCH_ERROR;
kono
parents:
diff changeset
98
kono
parents:
diff changeset
99 if (gfc_match_char (':') == MATCH_NO)
kono
parents:
diff changeset
100 goto matched;
kono
parents:
diff changeset
101
kono
parents:
diff changeset
102 if (star)
kono
parents:
diff changeset
103 {
kono
parents:
diff changeset
104 gfc_error ("Unexpected %<*%> in coarray subscript at %C");
kono
parents:
diff changeset
105 return MATCH_ERROR;
kono
parents:
diff changeset
106 }
kono
parents:
diff changeset
107
kono
parents:
diff changeset
108 /* Get an optional end element. Because we've seen the colon, we
kono
parents:
diff changeset
109 definitely have a range along this dimension. */
kono
parents:
diff changeset
110 end_element:
kono
parents:
diff changeset
111 ar->dimen_type[i] = DIMEN_RANGE;
kono
parents:
diff changeset
112
kono
parents:
diff changeset
113 if (match_star && (m = gfc_match_char ('*')) == MATCH_YES)
kono
parents:
diff changeset
114 star = true;
kono
parents:
diff changeset
115 else if (init)
kono
parents:
diff changeset
116 m = gfc_match_init_expr (&ar->end[i]);
kono
parents:
diff changeset
117 else
kono
parents:
diff changeset
118 m = gfc_match_expr (&ar->end[i]);
kono
parents:
diff changeset
119
kono
parents:
diff changeset
120 if (m == MATCH_ERROR)
kono
parents:
diff changeset
121 return MATCH_ERROR;
kono
parents:
diff changeset
122
kono
parents:
diff changeset
123 /* See if we have an optional stride. */
kono
parents:
diff changeset
124 if (gfc_match_char (':') == MATCH_YES)
kono
parents:
diff changeset
125 {
kono
parents:
diff changeset
126 if (star)
kono
parents:
diff changeset
127 {
kono
parents:
diff changeset
128 gfc_error ("Strides not allowed in coarray subscript at %C");
kono
parents:
diff changeset
129 return MATCH_ERROR;
kono
parents:
diff changeset
130 }
kono
parents:
diff changeset
131
kono
parents:
diff changeset
132 m = init ? gfc_match_init_expr (&ar->stride[i])
kono
parents:
diff changeset
133 : gfc_match_expr (&ar->stride[i]);
kono
parents:
diff changeset
134
kono
parents:
diff changeset
135 if (m == MATCH_NO)
kono
parents:
diff changeset
136 gfc_error ("Expected array subscript stride at %C");
kono
parents:
diff changeset
137 if (m != MATCH_YES)
kono
parents:
diff changeset
138 return MATCH_ERROR;
kono
parents:
diff changeset
139 }
kono
parents:
diff changeset
140
kono
parents:
diff changeset
141 matched:
kono
parents:
diff changeset
142 if (star)
kono
parents:
diff changeset
143 ar->dimen_type[i] = DIMEN_STAR;
kono
parents:
diff changeset
144
kono
parents:
diff changeset
145 return MATCH_YES;
kono
parents:
diff changeset
146 }
kono
parents:
diff changeset
147
kono
parents:
diff changeset
148
kono
parents:
diff changeset
149 /* Match an array reference, whether it is the whole array or particular
kono
parents:
diff changeset
150 elements or a section. If init is set, the reference has to consist
kono
parents:
diff changeset
151 of init expressions. */
kono
parents:
diff changeset
152
kono
parents:
diff changeset
153 match
kono
parents:
diff changeset
154 gfc_match_array_ref (gfc_array_ref *ar, gfc_array_spec *as, int init,
kono
parents:
diff changeset
155 int corank)
kono
parents:
diff changeset
156 {
kono
parents:
diff changeset
157 match m;
kono
parents:
diff changeset
158 bool matched_bracket = false;
kono
parents:
diff changeset
159 gfc_expr *tmp;
kono
parents:
diff changeset
160 bool stat_just_seen = false;
kono
parents:
diff changeset
161
kono
parents:
diff changeset
162 memset (ar, '\0', sizeof (*ar));
kono
parents:
diff changeset
163
kono
parents:
diff changeset
164 ar->where = gfc_current_locus;
kono
parents:
diff changeset
165 ar->as = as;
kono
parents:
diff changeset
166 ar->type = AR_UNKNOWN;
kono
parents:
diff changeset
167
kono
parents:
diff changeset
168 if (gfc_match_char ('[') == MATCH_YES)
kono
parents:
diff changeset
169 {
kono
parents:
diff changeset
170 matched_bracket = true;
kono
parents:
diff changeset
171 goto coarray;
kono
parents:
diff changeset
172 }
kono
parents:
diff changeset
173
kono
parents:
diff changeset
174 if (gfc_match_char ('(') != MATCH_YES)
kono
parents:
diff changeset
175 {
kono
parents:
diff changeset
176 ar->type = AR_FULL;
kono
parents:
diff changeset
177 ar->dimen = 0;
kono
parents:
diff changeset
178 return MATCH_YES;
kono
parents:
diff changeset
179 }
kono
parents:
diff changeset
180
kono
parents:
diff changeset
181 for (ar->dimen = 0; ar->dimen < GFC_MAX_DIMENSIONS; ar->dimen++)
kono
parents:
diff changeset
182 {
kono
parents:
diff changeset
183 m = match_subscript (ar, init, false);
kono
parents:
diff changeset
184 if (m == MATCH_ERROR)
kono
parents:
diff changeset
185 return MATCH_ERROR;
kono
parents:
diff changeset
186
kono
parents:
diff changeset
187 if (gfc_match_char (')') == MATCH_YES)
kono
parents:
diff changeset
188 {
kono
parents:
diff changeset
189 ar->dimen++;
kono
parents:
diff changeset
190 goto coarray;
kono
parents:
diff changeset
191 }
kono
parents:
diff changeset
192
kono
parents:
diff changeset
193 if (gfc_match_char (',') != MATCH_YES)
kono
parents:
diff changeset
194 {
kono
parents:
diff changeset
195 gfc_error ("Invalid form of array reference at %C");
kono
parents:
diff changeset
196 return MATCH_ERROR;
kono
parents:
diff changeset
197 }
kono
parents:
diff changeset
198 }
kono
parents:
diff changeset
199
kono
parents:
diff changeset
200 gfc_error ("Array reference at %C cannot have more than %d dimensions",
kono
parents:
diff changeset
201 GFC_MAX_DIMENSIONS);
kono
parents:
diff changeset
202 return MATCH_ERROR;
kono
parents:
diff changeset
203
kono
parents:
diff changeset
204 coarray:
kono
parents:
diff changeset
205 if (!matched_bracket && gfc_match_char ('[') != MATCH_YES)
kono
parents:
diff changeset
206 {
kono
parents:
diff changeset
207 if (ar->dimen > 0)
kono
parents:
diff changeset
208 return MATCH_YES;
kono
parents:
diff changeset
209 else
kono
parents:
diff changeset
210 return MATCH_ERROR;
kono
parents:
diff changeset
211 }
kono
parents:
diff changeset
212
kono
parents:
diff changeset
213 if (flag_coarray == GFC_FCOARRAY_NONE)
kono
parents:
diff changeset
214 {
kono
parents:
diff changeset
215 gfc_fatal_error ("Coarrays disabled at %C, use %<-fcoarray=%> to enable");
kono
parents:
diff changeset
216 return MATCH_ERROR;
kono
parents:
diff changeset
217 }
kono
parents:
diff changeset
218
kono
parents:
diff changeset
219 if (corank == 0)
kono
parents:
diff changeset
220 {
kono
parents:
diff changeset
221 gfc_error ("Unexpected coarray designator at %C");
kono
parents:
diff changeset
222 return MATCH_ERROR;
kono
parents:
diff changeset
223 }
kono
parents:
diff changeset
224
kono
parents:
diff changeset
225 ar->stat = NULL;
kono
parents:
diff changeset
226
kono
parents:
diff changeset
227 for (ar->codimen = 0; ar->codimen + ar->dimen < GFC_MAX_DIMENSIONS; ar->codimen++)
kono
parents:
diff changeset
228 {
kono
parents:
diff changeset
229 m = match_subscript (ar, init, true);
kono
parents:
diff changeset
230 if (m == MATCH_ERROR)
kono
parents:
diff changeset
231 return MATCH_ERROR;
kono
parents:
diff changeset
232
kono
parents:
diff changeset
233 stat_just_seen = false;
kono
parents:
diff changeset
234 if (gfc_match(" , stat = %e",&tmp) == MATCH_YES && ar->stat == NULL)
kono
parents:
diff changeset
235 {
kono
parents:
diff changeset
236 ar->stat = tmp;
kono
parents:
diff changeset
237 stat_just_seen = true;
kono
parents:
diff changeset
238 }
kono
parents:
diff changeset
239
kono
parents:
diff changeset
240 if (ar->stat && !stat_just_seen)
kono
parents:
diff changeset
241 {
kono
parents:
diff changeset
242 gfc_error ("STAT= attribute in %C misplaced");
kono
parents:
diff changeset
243 return MATCH_ERROR;
kono
parents:
diff changeset
244 }
kono
parents:
diff changeset
245
kono
parents:
diff changeset
246 if (gfc_match_char (']') == MATCH_YES)
kono
parents:
diff changeset
247 {
kono
parents:
diff changeset
248 ar->codimen++;
kono
parents:
diff changeset
249 if (ar->codimen < corank)
kono
parents:
diff changeset
250 {
kono
parents:
diff changeset
251 gfc_error ("Too few codimensions at %C, expected %d not %d",
kono
parents:
diff changeset
252 corank, ar->codimen);
kono
parents:
diff changeset
253 return MATCH_ERROR;
kono
parents:
diff changeset
254 }
kono
parents:
diff changeset
255 if (ar->codimen > corank)
kono
parents:
diff changeset
256 {
kono
parents:
diff changeset
257 gfc_error ("Too many codimensions at %C, expected %d not %d",
kono
parents:
diff changeset
258 corank, ar->codimen);
kono
parents:
diff changeset
259 return MATCH_ERROR;
kono
parents:
diff changeset
260 }
kono
parents:
diff changeset
261 return MATCH_YES;
kono
parents:
diff changeset
262 }
kono
parents:
diff changeset
263
kono
parents:
diff changeset
264 if (gfc_match_char (',') != MATCH_YES)
kono
parents:
diff changeset
265 {
kono
parents:
diff changeset
266 if (gfc_match_char ('*') == MATCH_YES)
kono
parents:
diff changeset
267 gfc_error ("Unexpected %<*%> for codimension %d of %d at %C",
kono
parents:
diff changeset
268 ar->codimen + 1, corank);
kono
parents:
diff changeset
269 else
kono
parents:
diff changeset
270 gfc_error ("Invalid form of coarray reference at %C");
kono
parents:
diff changeset
271 return MATCH_ERROR;
kono
parents:
diff changeset
272 }
kono
parents:
diff changeset
273 else if (ar->dimen_type[ar->codimen + ar->dimen] == DIMEN_STAR)
kono
parents:
diff changeset
274 {
kono
parents:
diff changeset
275 gfc_error ("Unexpected %<*%> for codimension %d of %d at %C",
kono
parents:
diff changeset
276 ar->codimen + 1, corank);
kono
parents:
diff changeset
277 return MATCH_ERROR;
kono
parents:
diff changeset
278 }
kono
parents:
diff changeset
279
kono
parents:
diff changeset
280 if (ar->codimen >= corank)
kono
parents:
diff changeset
281 {
kono
parents:
diff changeset
282 gfc_error ("Invalid codimension %d at %C, only %d codimensions exist",
kono
parents:
diff changeset
283 ar->codimen + 1, corank);
kono
parents:
diff changeset
284 return MATCH_ERROR;
kono
parents:
diff changeset
285 }
kono
parents:
diff changeset
286 }
kono
parents:
diff changeset
287
kono
parents:
diff changeset
288 gfc_error ("Array reference at %C cannot have more than %d dimensions",
kono
parents:
diff changeset
289 GFC_MAX_DIMENSIONS);
kono
parents:
diff changeset
290 return MATCH_ERROR;
kono
parents:
diff changeset
291
kono
parents:
diff changeset
292 }
kono
parents:
diff changeset
293
kono
parents:
diff changeset
294
kono
parents:
diff changeset
295 /************** Array specification matching subroutines ***************/
kono
parents:
diff changeset
296
kono
parents:
diff changeset
297 /* Free all of the expressions associated with array bounds
kono
parents:
diff changeset
298 specifications. */
kono
parents:
diff changeset
299
kono
parents:
diff changeset
300 void
kono
parents:
diff changeset
301 gfc_free_array_spec (gfc_array_spec *as)
kono
parents:
diff changeset
302 {
kono
parents:
diff changeset
303 int i;
kono
parents:
diff changeset
304
kono
parents:
diff changeset
305 if (as == NULL)
kono
parents:
diff changeset
306 return;
kono
parents:
diff changeset
307
kono
parents:
diff changeset
308 for (i = 0; i < as->rank + as->corank; i++)
kono
parents:
diff changeset
309 {
kono
parents:
diff changeset
310 gfc_free_expr (as->lower[i]);
kono
parents:
diff changeset
311 gfc_free_expr (as->upper[i]);
kono
parents:
diff changeset
312 }
kono
parents:
diff changeset
313
kono
parents:
diff changeset
314 free (as);
kono
parents:
diff changeset
315 }
kono
parents:
diff changeset
316
kono
parents:
diff changeset
317
kono
parents:
diff changeset
318 /* Take an array bound, resolves the expression, that make up the
kono
parents:
diff changeset
319 shape and check associated constraints. */
kono
parents:
diff changeset
320
kono
parents:
diff changeset
321 static bool
kono
parents:
diff changeset
322 resolve_array_bound (gfc_expr *e, int check_constant)
kono
parents:
diff changeset
323 {
kono
parents:
diff changeset
324 if (e == NULL)
kono
parents:
diff changeset
325 return true;
kono
parents:
diff changeset
326
kono
parents:
diff changeset
327 if (!gfc_resolve_expr (e)
kono
parents:
diff changeset
328 || !gfc_specification_expr (e))
kono
parents:
diff changeset
329 return false;
kono
parents:
diff changeset
330
kono
parents:
diff changeset
331 if (check_constant && !gfc_is_constant_expr (e))
kono
parents:
diff changeset
332 {
kono
parents:
diff changeset
333 if (e->expr_type == EXPR_VARIABLE)
kono
parents:
diff changeset
334 gfc_error ("Variable %qs at %L in this context must be constant",
kono
parents:
diff changeset
335 e->symtree->n.sym->name, &e->where);
kono
parents:
diff changeset
336 else
kono
parents:
diff changeset
337 gfc_error ("Expression at %L in this context must be constant",
kono
parents:
diff changeset
338 &e->where);
kono
parents:
diff changeset
339 return false;
kono
parents:
diff changeset
340 }
kono
parents:
diff changeset
341
kono
parents:
diff changeset
342 return true;
kono
parents:
diff changeset
343 }
kono
parents:
diff changeset
344
kono
parents:
diff changeset
345
kono
parents:
diff changeset
346 /* Takes an array specification, resolves the expressions that make up
kono
parents:
diff changeset
347 the shape and make sure everything is integral. */
kono
parents:
diff changeset
348
kono
parents:
diff changeset
349 bool
kono
parents:
diff changeset
350 gfc_resolve_array_spec (gfc_array_spec *as, int check_constant)
kono
parents:
diff changeset
351 {
kono
parents:
diff changeset
352 gfc_expr *e;
kono
parents:
diff changeset
353 int i;
kono
parents:
diff changeset
354
kono
parents:
diff changeset
355 if (as == NULL)
kono
parents:
diff changeset
356 return true;
kono
parents:
diff changeset
357
kono
parents:
diff changeset
358 if (as->resolved)
kono
parents:
diff changeset
359 return true;
kono
parents:
diff changeset
360
kono
parents:
diff changeset
361 for (i = 0; i < as->rank + as->corank; i++)
kono
parents:
diff changeset
362 {
kono
parents:
diff changeset
363 e = as->lower[i];
kono
parents:
diff changeset
364 if (!resolve_array_bound (e, check_constant))
kono
parents:
diff changeset
365 return false;
kono
parents:
diff changeset
366
kono
parents:
diff changeset
367 e = as->upper[i];
kono
parents:
diff changeset
368 if (!resolve_array_bound (e, check_constant))
kono
parents:
diff changeset
369 return false;
kono
parents:
diff changeset
370
kono
parents:
diff changeset
371 if ((as->lower[i] == NULL) || (as->upper[i] == NULL))
kono
parents:
diff changeset
372 continue;
kono
parents:
diff changeset
373
kono
parents:
diff changeset
374 /* If the size is negative in this dimension, set it to zero. */
kono
parents:
diff changeset
375 if (as->lower[i]->expr_type == EXPR_CONSTANT
kono
parents:
diff changeset
376 && as->upper[i]->expr_type == EXPR_CONSTANT
kono
parents:
diff changeset
377 && mpz_cmp (as->upper[i]->value.integer,
kono
parents:
diff changeset
378 as->lower[i]->value.integer) < 0)
kono
parents:
diff changeset
379 {
kono
parents:
diff changeset
380 gfc_free_expr (as->upper[i]);
kono
parents:
diff changeset
381 as->upper[i] = gfc_copy_expr (as->lower[i]);
kono
parents:
diff changeset
382 mpz_sub_ui (as->upper[i]->value.integer,
kono
parents:
diff changeset
383 as->upper[i]->value.integer, 1);
kono
parents:
diff changeset
384 }
kono
parents:
diff changeset
385 }
kono
parents:
diff changeset
386
kono
parents:
diff changeset
387 as->resolved = true;
kono
parents:
diff changeset
388
kono
parents:
diff changeset
389 return true;
kono
parents:
diff changeset
390 }
kono
parents:
diff changeset
391
kono
parents:
diff changeset
392
kono
parents:
diff changeset
393 /* Match a single array element specification. The return values as
kono
parents:
diff changeset
394 well as the upper and lower bounds of the array spec are filled
kono
parents:
diff changeset
395 in according to what we see on the input. The caller makes sure
kono
parents:
diff changeset
396 individual specifications make sense as a whole.
kono
parents:
diff changeset
397
kono
parents:
diff changeset
398
kono
parents:
diff changeset
399 Parsed Lower Upper Returned
kono
parents:
diff changeset
400 ------------------------------------
kono
parents:
diff changeset
401 : NULL NULL AS_DEFERRED (*)
kono
parents:
diff changeset
402 x 1 x AS_EXPLICIT
kono
parents:
diff changeset
403 x: x NULL AS_ASSUMED_SHAPE
kono
parents:
diff changeset
404 x:y x y AS_EXPLICIT
kono
parents:
diff changeset
405 x:* x NULL AS_ASSUMED_SIZE
kono
parents:
diff changeset
406 * 1 NULL AS_ASSUMED_SIZE
kono
parents:
diff changeset
407
kono
parents:
diff changeset
408 (*) For non-pointer dummy arrays this is AS_ASSUMED_SHAPE. This
kono
parents:
diff changeset
409 is fixed during the resolution of formal interfaces.
kono
parents:
diff changeset
410
kono
parents:
diff changeset
411 Anything else AS_UNKNOWN. */
kono
parents:
diff changeset
412
kono
parents:
diff changeset
413 static array_type
kono
parents:
diff changeset
414 match_array_element_spec (gfc_array_spec *as)
kono
parents:
diff changeset
415 {
kono
parents:
diff changeset
416 gfc_expr **upper, **lower;
kono
parents:
diff changeset
417 match m;
kono
parents:
diff changeset
418 int rank;
kono
parents:
diff changeset
419
kono
parents:
diff changeset
420 rank = as->rank == -1 ? 0 : as->rank;
kono
parents:
diff changeset
421 lower = &as->lower[rank + as->corank - 1];
kono
parents:
diff changeset
422 upper = &as->upper[rank + as->corank - 1];
kono
parents:
diff changeset
423
kono
parents:
diff changeset
424 if (gfc_match_char ('*') == MATCH_YES)
kono
parents:
diff changeset
425 {
kono
parents:
diff changeset
426 *lower = gfc_get_int_expr (gfc_default_integer_kind, NULL, 1);
kono
parents:
diff changeset
427 return AS_ASSUMED_SIZE;
kono
parents:
diff changeset
428 }
kono
parents:
diff changeset
429
kono
parents:
diff changeset
430 if (gfc_match_char (':') == MATCH_YES)
kono
parents:
diff changeset
431 return AS_DEFERRED;
kono
parents:
diff changeset
432
kono
parents:
diff changeset
433 m = gfc_match_expr (upper);
kono
parents:
diff changeset
434 if (m == MATCH_NO)
kono
parents:
diff changeset
435 gfc_error ("Expected expression in array specification at %C");
kono
parents:
diff changeset
436 if (m != MATCH_YES)
kono
parents:
diff changeset
437 return AS_UNKNOWN;
kono
parents:
diff changeset
438 if (!gfc_expr_check_typed (*upper, gfc_current_ns, false))
kono
parents:
diff changeset
439 return AS_UNKNOWN;
kono
parents:
diff changeset
440
kono
parents:
diff changeset
441 if (((*upper)->expr_type == EXPR_CONSTANT
kono
parents:
diff changeset
442 && (*upper)->ts.type != BT_INTEGER) ||
kono
parents:
diff changeset
443 ((*upper)->expr_type == EXPR_FUNCTION
kono
parents:
diff changeset
444 && (*upper)->ts.type == BT_UNKNOWN
kono
parents:
diff changeset
445 && (*upper)->symtree
kono
parents:
diff changeset
446 && strcmp ((*upper)->symtree->name, "null") == 0))
kono
parents:
diff changeset
447 {
kono
parents:
diff changeset
448 gfc_error ("Expecting a scalar INTEGER expression at %C, found %s",
kono
parents:
diff changeset
449 gfc_basic_typename ((*upper)->ts.type));
kono
parents:
diff changeset
450 return AS_UNKNOWN;
kono
parents:
diff changeset
451 }
kono
parents:
diff changeset
452
kono
parents:
diff changeset
453 if (gfc_match_char (':') == MATCH_NO)
kono
parents:
diff changeset
454 {
kono
parents:
diff changeset
455 *lower = gfc_get_int_expr (gfc_default_integer_kind, NULL, 1);
kono
parents:
diff changeset
456 return AS_EXPLICIT;
kono
parents:
diff changeset
457 }
kono
parents:
diff changeset
458
kono
parents:
diff changeset
459 *lower = *upper;
kono
parents:
diff changeset
460 *upper = NULL;
kono
parents:
diff changeset
461
kono
parents:
diff changeset
462 if (gfc_match_char ('*') == MATCH_YES)
kono
parents:
diff changeset
463 return AS_ASSUMED_SIZE;
kono
parents:
diff changeset
464
kono
parents:
diff changeset
465 m = gfc_match_expr (upper);
kono
parents:
diff changeset
466 if (m == MATCH_ERROR)
kono
parents:
diff changeset
467 return AS_UNKNOWN;
kono
parents:
diff changeset
468 if (m == MATCH_NO)
kono
parents:
diff changeset
469 return AS_ASSUMED_SHAPE;
kono
parents:
diff changeset
470 if (!gfc_expr_check_typed (*upper, gfc_current_ns, false))
kono
parents:
diff changeset
471 return AS_UNKNOWN;
kono
parents:
diff changeset
472
kono
parents:
diff changeset
473 if (((*upper)->expr_type == EXPR_CONSTANT
kono
parents:
diff changeset
474 && (*upper)->ts.type != BT_INTEGER) ||
kono
parents:
diff changeset
475 ((*upper)->expr_type == EXPR_FUNCTION
kono
parents:
diff changeset
476 && (*upper)->ts.type == BT_UNKNOWN
kono
parents:
diff changeset
477 && (*upper)->symtree
kono
parents:
diff changeset
478 && strcmp ((*upper)->symtree->name, "null") == 0))
kono
parents:
diff changeset
479 {
kono
parents:
diff changeset
480 gfc_error ("Expecting a scalar INTEGER expression at %C, found %s",
kono
parents:
diff changeset
481 gfc_basic_typename ((*upper)->ts.type));
kono
parents:
diff changeset
482 return AS_UNKNOWN;
kono
parents:
diff changeset
483 }
kono
parents:
diff changeset
484
kono
parents:
diff changeset
485 return AS_EXPLICIT;
kono
parents:
diff changeset
486 }
kono
parents:
diff changeset
487
kono
parents:
diff changeset
488
kono
parents:
diff changeset
489 /* Matches an array specification, incidentally figuring out what sort
kono
parents:
diff changeset
490 it is. Match either a normal array specification, or a coarray spec
kono
parents:
diff changeset
491 or both. Optionally allow [:] for coarrays. */
kono
parents:
diff changeset
492
kono
parents:
diff changeset
493 match
kono
parents:
diff changeset
494 gfc_match_array_spec (gfc_array_spec **asp, bool match_dim, bool match_codim)
kono
parents:
diff changeset
495 {
kono
parents:
diff changeset
496 array_type current_type;
kono
parents:
diff changeset
497 gfc_array_spec *as;
kono
parents:
diff changeset
498 int i;
kono
parents:
diff changeset
499
kono
parents:
diff changeset
500 as = gfc_get_array_spec ();
kono
parents:
diff changeset
501
kono
parents:
diff changeset
502 if (!match_dim)
kono
parents:
diff changeset
503 goto coarray;
kono
parents:
diff changeset
504
kono
parents:
diff changeset
505 if (gfc_match_char ('(') != MATCH_YES)
kono
parents:
diff changeset
506 {
kono
parents:
diff changeset
507 if (!match_codim)
kono
parents:
diff changeset
508 goto done;
kono
parents:
diff changeset
509 goto coarray;
kono
parents:
diff changeset
510 }
kono
parents:
diff changeset
511
kono
parents:
diff changeset
512 if (gfc_match (" .. )") == MATCH_YES)
kono
parents:
diff changeset
513 {
kono
parents:
diff changeset
514 as->type = AS_ASSUMED_RANK;
kono
parents:
diff changeset
515 as->rank = -1;
kono
parents:
diff changeset
516
kono
parents:
diff changeset
517 if (!gfc_notify_std (GFC_STD_F2008_TS, "Assumed-rank array at %C"))
kono
parents:
diff changeset
518 goto cleanup;
kono
parents:
diff changeset
519
kono
parents:
diff changeset
520 if (!match_codim)
kono
parents:
diff changeset
521 goto done;
kono
parents:
diff changeset
522 goto coarray;
kono
parents:
diff changeset
523 }
kono
parents:
diff changeset
524
kono
parents:
diff changeset
525 for (;;)
kono
parents:
diff changeset
526 {
kono
parents:
diff changeset
527 as->rank++;
kono
parents:
diff changeset
528 current_type = match_array_element_spec (as);
kono
parents:
diff changeset
529
kono
parents:
diff changeset
530 /* Note that current_type == AS_ASSUMED_SIZE for both assumed-size
kono
parents:
diff changeset
531 and implied-shape specifications. If the rank is at least 2, we can
kono
parents:
diff changeset
532 distinguish between them. But for rank 1, we currently return
kono
parents:
diff changeset
533 ASSUMED_SIZE; this gets adjusted later when we know for sure
kono
parents:
diff changeset
534 whether the symbol parsed is a PARAMETER or not. */
kono
parents:
diff changeset
535
kono
parents:
diff changeset
536 if (as->rank == 1)
kono
parents:
diff changeset
537 {
kono
parents:
diff changeset
538 if (current_type == AS_UNKNOWN)
kono
parents:
diff changeset
539 goto cleanup;
kono
parents:
diff changeset
540 as->type = current_type;
kono
parents:
diff changeset
541 }
kono
parents:
diff changeset
542 else
kono
parents:
diff changeset
543 switch (as->type)
kono
parents:
diff changeset
544 { /* See how current spec meshes with the existing. */
kono
parents:
diff changeset
545 case AS_UNKNOWN:
kono
parents:
diff changeset
546 goto cleanup;
kono
parents:
diff changeset
547
kono
parents:
diff changeset
548 case AS_IMPLIED_SHAPE:
kono
parents:
diff changeset
549 if (current_type != AS_ASSUMED_SHAPE)
kono
parents:
diff changeset
550 {
kono
parents:
diff changeset
551 gfc_error ("Bad array specification for implied-shape"
kono
parents:
diff changeset
552 " array at %C");
kono
parents:
diff changeset
553 goto cleanup;
kono
parents:
diff changeset
554 }
kono
parents:
diff changeset
555 break;
kono
parents:
diff changeset
556
kono
parents:
diff changeset
557 case AS_EXPLICIT:
kono
parents:
diff changeset
558 if (current_type == AS_ASSUMED_SIZE)
kono
parents:
diff changeset
559 {
kono
parents:
diff changeset
560 as->type = AS_ASSUMED_SIZE;
kono
parents:
diff changeset
561 break;
kono
parents:
diff changeset
562 }
kono
parents:
diff changeset
563
kono
parents:
diff changeset
564 if (current_type == AS_EXPLICIT)
kono
parents:
diff changeset
565 break;
kono
parents:
diff changeset
566
kono
parents:
diff changeset
567 gfc_error ("Bad array specification for an explicitly shaped "
kono
parents:
diff changeset
568 "array at %C");
kono
parents:
diff changeset
569
kono
parents:
diff changeset
570 goto cleanup;
kono
parents:
diff changeset
571
kono
parents:
diff changeset
572 case AS_ASSUMED_SHAPE:
kono
parents:
diff changeset
573 if ((current_type == AS_ASSUMED_SHAPE)
kono
parents:
diff changeset
574 || (current_type == AS_DEFERRED))
kono
parents:
diff changeset
575 break;
kono
parents:
diff changeset
576
kono
parents:
diff changeset
577 gfc_error ("Bad array specification for assumed shape "
kono
parents:
diff changeset
578 "array at %C");
kono
parents:
diff changeset
579 goto cleanup;
kono
parents:
diff changeset
580
kono
parents:
diff changeset
581 case AS_DEFERRED:
kono
parents:
diff changeset
582 if (current_type == AS_DEFERRED)
kono
parents:
diff changeset
583 break;
kono
parents:
diff changeset
584
kono
parents:
diff changeset
585 if (current_type == AS_ASSUMED_SHAPE)
kono
parents:
diff changeset
586 {
kono
parents:
diff changeset
587 as->type = AS_ASSUMED_SHAPE;
kono
parents:
diff changeset
588 break;
kono
parents:
diff changeset
589 }
kono
parents:
diff changeset
590
kono
parents:
diff changeset
591 gfc_error ("Bad specification for deferred shape array at %C");
kono
parents:
diff changeset
592 goto cleanup;
kono
parents:
diff changeset
593
kono
parents:
diff changeset
594 case AS_ASSUMED_SIZE:
kono
parents:
diff changeset
595 if (as->rank == 2 && current_type == AS_ASSUMED_SIZE)
kono
parents:
diff changeset
596 {
kono
parents:
diff changeset
597 as->type = AS_IMPLIED_SHAPE;
kono
parents:
diff changeset
598 break;
kono
parents:
diff changeset
599 }
kono
parents:
diff changeset
600
kono
parents:
diff changeset
601 gfc_error ("Bad specification for assumed size array at %C");
kono
parents:
diff changeset
602 goto cleanup;
kono
parents:
diff changeset
603
kono
parents:
diff changeset
604 case AS_ASSUMED_RANK:
kono
parents:
diff changeset
605 gcc_unreachable ();
kono
parents:
diff changeset
606 }
kono
parents:
diff changeset
607
kono
parents:
diff changeset
608 if (gfc_match_char (')') == MATCH_YES)
kono
parents:
diff changeset
609 break;
kono
parents:
diff changeset
610
kono
parents:
diff changeset
611 if (gfc_match_char (',') != MATCH_YES)
kono
parents:
diff changeset
612 {
kono
parents:
diff changeset
613 gfc_error ("Expected another dimension in array declaration at %C");
kono
parents:
diff changeset
614 goto cleanup;
kono
parents:
diff changeset
615 }
kono
parents:
diff changeset
616
kono
parents:
diff changeset
617 if (as->rank + as->corank >= GFC_MAX_DIMENSIONS)
kono
parents:
diff changeset
618 {
kono
parents:
diff changeset
619 gfc_error ("Array specification at %C has more than %d dimensions",
kono
parents:
diff changeset
620 GFC_MAX_DIMENSIONS);
kono
parents:
diff changeset
621 goto cleanup;
kono
parents:
diff changeset
622 }
kono
parents:
diff changeset
623
kono
parents:
diff changeset
624 if (as->corank + as->rank >= 7
kono
parents:
diff changeset
625 && !gfc_notify_std (GFC_STD_F2008, "Array specification at %C "
kono
parents:
diff changeset
626 "with more than 7 dimensions"))
kono
parents:
diff changeset
627 goto cleanup;
kono
parents:
diff changeset
628 }
kono
parents:
diff changeset
629
kono
parents:
diff changeset
630 if (!match_codim)
kono
parents:
diff changeset
631 goto done;
kono
parents:
diff changeset
632
kono
parents:
diff changeset
633 coarray:
kono
parents:
diff changeset
634 if (gfc_match_char ('[') != MATCH_YES)
kono
parents:
diff changeset
635 goto done;
kono
parents:
diff changeset
636
kono
parents:
diff changeset
637 if (!gfc_notify_std (GFC_STD_F2008, "Coarray declaration at %C"))
kono
parents:
diff changeset
638 goto cleanup;
kono
parents:
diff changeset
639
kono
parents:
diff changeset
640 if (flag_coarray == GFC_FCOARRAY_NONE)
kono
parents:
diff changeset
641 {
kono
parents:
diff changeset
642 gfc_fatal_error ("Coarrays disabled at %C, use %<-fcoarray=%> to enable");
kono
parents:
diff changeset
643 goto cleanup;
kono
parents:
diff changeset
644 }
kono
parents:
diff changeset
645
kono
parents:
diff changeset
646 if (as->rank >= GFC_MAX_DIMENSIONS)
kono
parents:
diff changeset
647 {
kono
parents:
diff changeset
648 gfc_error ("Array specification at %C has more than %d "
kono
parents:
diff changeset
649 "dimensions", GFC_MAX_DIMENSIONS);
kono
parents:
diff changeset
650 goto cleanup;
kono
parents:
diff changeset
651 }
kono
parents:
diff changeset
652
kono
parents:
diff changeset
653 for (;;)
kono
parents:
diff changeset
654 {
kono
parents:
diff changeset
655 as->corank++;
kono
parents:
diff changeset
656 current_type = match_array_element_spec (as);
kono
parents:
diff changeset
657
kono
parents:
diff changeset
658 if (current_type == AS_UNKNOWN)
kono
parents:
diff changeset
659 goto cleanup;
kono
parents:
diff changeset
660
kono
parents:
diff changeset
661 if (as->corank == 1)
kono
parents:
diff changeset
662 as->cotype = current_type;
kono
parents:
diff changeset
663 else
kono
parents:
diff changeset
664 switch (as->cotype)
kono
parents:
diff changeset
665 { /* See how current spec meshes with the existing. */
kono
parents:
diff changeset
666 case AS_IMPLIED_SHAPE:
kono
parents:
diff changeset
667 case AS_UNKNOWN:
kono
parents:
diff changeset
668 goto cleanup;
kono
parents:
diff changeset
669
kono
parents:
diff changeset
670 case AS_EXPLICIT:
kono
parents:
diff changeset
671 if (current_type == AS_ASSUMED_SIZE)
kono
parents:
diff changeset
672 {
kono
parents:
diff changeset
673 as->cotype = AS_ASSUMED_SIZE;
kono
parents:
diff changeset
674 break;
kono
parents:
diff changeset
675 }
kono
parents:
diff changeset
676
kono
parents:
diff changeset
677 if (current_type == AS_EXPLICIT)
kono
parents:
diff changeset
678 break;
kono
parents:
diff changeset
679
kono
parents:
diff changeset
680 gfc_error ("Bad array specification for an explicitly "
kono
parents:
diff changeset
681 "shaped array at %C");
kono
parents:
diff changeset
682
kono
parents:
diff changeset
683 goto cleanup;
kono
parents:
diff changeset
684
kono
parents:
diff changeset
685 case AS_ASSUMED_SHAPE:
kono
parents:
diff changeset
686 if ((current_type == AS_ASSUMED_SHAPE)
kono
parents:
diff changeset
687 || (current_type == AS_DEFERRED))
kono
parents:
diff changeset
688 break;
kono
parents:
diff changeset
689
kono
parents:
diff changeset
690 gfc_error ("Bad array specification for assumed shape "
kono
parents:
diff changeset
691 "array at %C");
kono
parents:
diff changeset
692 goto cleanup;
kono
parents:
diff changeset
693
kono
parents:
diff changeset
694 case AS_DEFERRED:
kono
parents:
diff changeset
695 if (current_type == AS_DEFERRED)
kono
parents:
diff changeset
696 break;
kono
parents:
diff changeset
697
kono
parents:
diff changeset
698 if (current_type == AS_ASSUMED_SHAPE)
kono
parents:
diff changeset
699 {
kono
parents:
diff changeset
700 as->cotype = AS_ASSUMED_SHAPE;
kono
parents:
diff changeset
701 break;
kono
parents:
diff changeset
702 }
kono
parents:
diff changeset
703
kono
parents:
diff changeset
704 gfc_error ("Bad specification for deferred shape array at %C");
kono
parents:
diff changeset
705 goto cleanup;
kono
parents:
diff changeset
706
kono
parents:
diff changeset
707 case AS_ASSUMED_SIZE:
kono
parents:
diff changeset
708 gfc_error ("Bad specification for assumed size array at %C");
kono
parents:
diff changeset
709 goto cleanup;
kono
parents:
diff changeset
710
kono
parents:
diff changeset
711 case AS_ASSUMED_RANK:
kono
parents:
diff changeset
712 gcc_unreachable ();
kono
parents:
diff changeset
713 }
kono
parents:
diff changeset
714
kono
parents:
diff changeset
715 if (gfc_match_char (']') == MATCH_YES)
kono
parents:
diff changeset
716 break;
kono
parents:
diff changeset
717
kono
parents:
diff changeset
718 if (gfc_match_char (',') != MATCH_YES)
kono
parents:
diff changeset
719 {
kono
parents:
diff changeset
720 gfc_error ("Expected another dimension in array declaration at %C");
kono
parents:
diff changeset
721 goto cleanup;
kono
parents:
diff changeset
722 }
kono
parents:
diff changeset
723
kono
parents:
diff changeset
724 if (as->rank + as->corank >= GFC_MAX_DIMENSIONS)
kono
parents:
diff changeset
725 {
kono
parents:
diff changeset
726 gfc_error ("Array specification at %C has more than %d "
kono
parents:
diff changeset
727 "dimensions", GFC_MAX_DIMENSIONS);
kono
parents:
diff changeset
728 goto cleanup;
kono
parents:
diff changeset
729 }
kono
parents:
diff changeset
730 }
kono
parents:
diff changeset
731
kono
parents:
diff changeset
732 if (current_type == AS_EXPLICIT)
kono
parents:
diff changeset
733 {
kono
parents:
diff changeset
734 gfc_error ("Upper bound of last coarray dimension must be %<*%> at %C");
kono
parents:
diff changeset
735 goto cleanup;
kono
parents:
diff changeset
736 }
kono
parents:
diff changeset
737
kono
parents:
diff changeset
738 if (as->cotype == AS_ASSUMED_SIZE)
kono
parents:
diff changeset
739 as->cotype = AS_EXPLICIT;
kono
parents:
diff changeset
740
kono
parents:
diff changeset
741 if (as->rank == 0)
kono
parents:
diff changeset
742 as->type = as->cotype;
kono
parents:
diff changeset
743
kono
parents:
diff changeset
744 done:
kono
parents:
diff changeset
745 if (as->rank == 0 && as->corank == 0)
kono
parents:
diff changeset
746 {
kono
parents:
diff changeset
747 *asp = NULL;
kono
parents:
diff changeset
748 gfc_free_array_spec (as);
kono
parents:
diff changeset
749 return MATCH_NO;
kono
parents:
diff changeset
750 }
kono
parents:
diff changeset
751
kono
parents:
diff changeset
752 /* If a lower bounds of an assumed shape array is blank, put in one. */
kono
parents:
diff changeset
753 if (as->type == AS_ASSUMED_SHAPE)
kono
parents:
diff changeset
754 {
kono
parents:
diff changeset
755 for (i = 0; i < as->rank + as->corank; i++)
kono
parents:
diff changeset
756 {
kono
parents:
diff changeset
757 if (as->lower[i] == NULL)
kono
parents:
diff changeset
758 as->lower[i] = gfc_get_int_expr (gfc_default_integer_kind, NULL, 1);
kono
parents:
diff changeset
759 }
kono
parents:
diff changeset
760 }
kono
parents:
diff changeset
761
kono
parents:
diff changeset
762 *asp = as;
kono
parents:
diff changeset
763
kono
parents:
diff changeset
764 return MATCH_YES;
kono
parents:
diff changeset
765
kono
parents:
diff changeset
766 cleanup:
kono
parents:
diff changeset
767 /* Something went wrong. */
kono
parents:
diff changeset
768 gfc_free_array_spec (as);
kono
parents:
diff changeset
769 return MATCH_ERROR;
kono
parents:
diff changeset
770 }
kono
parents:
diff changeset
771
kono
parents:
diff changeset
772
kono
parents:
diff changeset
773 /* Given a symbol and an array specification, modify the symbol to
kono
parents:
diff changeset
774 have that array specification. The error locus is needed in case
kono
parents:
diff changeset
775 something goes wrong. On failure, the caller must free the spec. */
kono
parents:
diff changeset
776
kono
parents:
diff changeset
777 bool
kono
parents:
diff changeset
778 gfc_set_array_spec (gfc_symbol *sym, gfc_array_spec *as, locus *error_loc)
kono
parents:
diff changeset
779 {
kono
parents:
diff changeset
780 int i;
kono
parents:
diff changeset
781
kono
parents:
diff changeset
782 if (as == NULL)
kono
parents:
diff changeset
783 return true;
kono
parents:
diff changeset
784
kono
parents:
diff changeset
785 if (as->rank
kono
parents:
diff changeset
786 && !gfc_add_dimension (&sym->attr, sym->name, error_loc))
kono
parents:
diff changeset
787 return false;
kono
parents:
diff changeset
788
kono
parents:
diff changeset
789 if (as->corank
kono
parents:
diff changeset
790 && !gfc_add_codimension (&sym->attr, sym->name, error_loc))
kono
parents:
diff changeset
791 return false;
kono
parents:
diff changeset
792
kono
parents:
diff changeset
793 if (sym->as == NULL)
kono
parents:
diff changeset
794 {
kono
parents:
diff changeset
795 sym->as = as;
kono
parents:
diff changeset
796 return true;
kono
parents:
diff changeset
797 }
kono
parents:
diff changeset
798
kono
parents:
diff changeset
799 if ((sym->as->type == AS_ASSUMED_RANK && as->corank)
kono
parents:
diff changeset
800 || (as->type == AS_ASSUMED_RANK && sym->as->corank))
kono
parents:
diff changeset
801 {
kono
parents:
diff changeset
802 gfc_error ("The assumed-rank array %qs at %L shall not have a "
kono
parents:
diff changeset
803 "codimension", sym->name, error_loc);
kono
parents:
diff changeset
804 return false;
kono
parents:
diff changeset
805 }
kono
parents:
diff changeset
806
kono
parents:
diff changeset
807 if (as->corank)
kono
parents:
diff changeset
808 {
kono
parents:
diff changeset
809 /* The "sym" has no corank (checked via gfc_add_codimension). Thus
kono
parents:
diff changeset
810 the codimension is simply added. */
kono
parents:
diff changeset
811 gcc_assert (as->rank == 0 && sym->as->corank == 0);
kono
parents:
diff changeset
812
kono
parents:
diff changeset
813 sym->as->cotype = as->cotype;
kono
parents:
diff changeset
814 sym->as->corank = as->corank;
kono
parents:
diff changeset
815 for (i = 0; i < as->corank; i++)
kono
parents:
diff changeset
816 {
kono
parents:
diff changeset
817 sym->as->lower[sym->as->rank + i] = as->lower[i];
kono
parents:
diff changeset
818 sym->as->upper[sym->as->rank + i] = as->upper[i];
kono
parents:
diff changeset
819 }
kono
parents:
diff changeset
820 }
kono
parents:
diff changeset
821 else
kono
parents:
diff changeset
822 {
kono
parents:
diff changeset
823 /* The "sym" has no rank (checked via gfc_add_dimension). Thus
kono
parents:
diff changeset
824 the dimension is added - but first the codimensions (if existing
kono
parents:
diff changeset
825 need to be shifted to make space for the dimension. */
kono
parents:
diff changeset
826 gcc_assert (as->corank == 0 && sym->as->rank == 0);
kono
parents:
diff changeset
827
kono
parents:
diff changeset
828 sym->as->rank = as->rank;
kono
parents:
diff changeset
829 sym->as->type = as->type;
kono
parents:
diff changeset
830 sym->as->cray_pointee = as->cray_pointee;
kono
parents:
diff changeset
831 sym->as->cp_was_assumed = as->cp_was_assumed;
kono
parents:
diff changeset
832
kono
parents:
diff changeset
833 for (i = 0; i < sym->as->corank; i++)
kono
parents:
diff changeset
834 {
kono
parents:
diff changeset
835 sym->as->lower[as->rank + i] = sym->as->lower[i];
kono
parents:
diff changeset
836 sym->as->upper[as->rank + i] = sym->as->upper[i];
kono
parents:
diff changeset
837 }
kono
parents:
diff changeset
838 for (i = 0; i < as->rank; i++)
kono
parents:
diff changeset
839 {
kono
parents:
diff changeset
840 sym->as->lower[i] = as->lower[i];
kono
parents:
diff changeset
841 sym->as->upper[i] = as->upper[i];
kono
parents:
diff changeset
842 }
kono
parents:
diff changeset
843 }
kono
parents:
diff changeset
844
kono
parents:
diff changeset
845 free (as);
kono
parents:
diff changeset
846 return true;
kono
parents:
diff changeset
847 }
kono
parents:
diff changeset
848
kono
parents:
diff changeset
849
kono
parents:
diff changeset
850 /* Copy an array specification. */
kono
parents:
diff changeset
851
kono
parents:
diff changeset
852 gfc_array_spec *
kono
parents:
diff changeset
853 gfc_copy_array_spec (gfc_array_spec *src)
kono
parents:
diff changeset
854 {
kono
parents:
diff changeset
855 gfc_array_spec *dest;
kono
parents:
diff changeset
856 int i;
kono
parents:
diff changeset
857
kono
parents:
diff changeset
858 if (src == NULL)
kono
parents:
diff changeset
859 return NULL;
kono
parents:
diff changeset
860
kono
parents:
diff changeset
861 dest = gfc_get_array_spec ();
kono
parents:
diff changeset
862
kono
parents:
diff changeset
863 *dest = *src;
kono
parents:
diff changeset
864
kono
parents:
diff changeset
865 for (i = 0; i < dest->rank + dest->corank; i++)
kono
parents:
diff changeset
866 {
kono
parents:
diff changeset
867 dest->lower[i] = gfc_copy_expr (dest->lower[i]);
kono
parents:
diff changeset
868 dest->upper[i] = gfc_copy_expr (dest->upper[i]);
kono
parents:
diff changeset
869 }
kono
parents:
diff changeset
870
kono
parents:
diff changeset
871 return dest;
kono
parents:
diff changeset
872 }
kono
parents:
diff changeset
873
kono
parents:
diff changeset
874
kono
parents:
diff changeset
875 /* Returns nonzero if the two expressions are equal. Only handles integer
kono
parents:
diff changeset
876 constants. */
kono
parents:
diff changeset
877
kono
parents:
diff changeset
878 static int
kono
parents:
diff changeset
879 compare_bounds (gfc_expr *bound1, gfc_expr *bound2)
kono
parents:
diff changeset
880 {
kono
parents:
diff changeset
881 if (bound1 == NULL || bound2 == NULL
kono
parents:
diff changeset
882 || bound1->expr_type != EXPR_CONSTANT
kono
parents:
diff changeset
883 || bound2->expr_type != EXPR_CONSTANT
kono
parents:
diff changeset
884 || bound1->ts.type != BT_INTEGER
kono
parents:
diff changeset
885 || bound2->ts.type != BT_INTEGER)
kono
parents:
diff changeset
886 gfc_internal_error ("gfc_compare_array_spec(): Array spec clobbered");
kono
parents:
diff changeset
887
kono
parents:
diff changeset
888 if (mpz_cmp (bound1->value.integer, bound2->value.integer) == 0)
kono
parents:
diff changeset
889 return 1;
kono
parents:
diff changeset
890 else
kono
parents:
diff changeset
891 return 0;
kono
parents:
diff changeset
892 }
kono
parents:
diff changeset
893
kono
parents:
diff changeset
894
kono
parents:
diff changeset
895 /* Compares two array specifications. They must be constant or deferred
kono
parents:
diff changeset
896 shape. */
kono
parents:
diff changeset
897
kono
parents:
diff changeset
898 int
kono
parents:
diff changeset
899 gfc_compare_array_spec (gfc_array_spec *as1, gfc_array_spec *as2)
kono
parents:
diff changeset
900 {
kono
parents:
diff changeset
901 int i;
kono
parents:
diff changeset
902
kono
parents:
diff changeset
903 if (as1 == NULL && as2 == NULL)
kono
parents:
diff changeset
904 return 1;
kono
parents:
diff changeset
905
kono
parents:
diff changeset
906 if (as1 == NULL || as2 == NULL)
kono
parents:
diff changeset
907 return 0;
kono
parents:
diff changeset
908
kono
parents:
diff changeset
909 if (as1->rank != as2->rank)
kono
parents:
diff changeset
910 return 0;
kono
parents:
diff changeset
911
kono
parents:
diff changeset
912 if (as1->corank != as2->corank)
kono
parents:
diff changeset
913 return 0;
kono
parents:
diff changeset
914
kono
parents:
diff changeset
915 if (as1->rank == 0)
kono
parents:
diff changeset
916 return 1;
kono
parents:
diff changeset
917
kono
parents:
diff changeset
918 if (as1->type != as2->type)
kono
parents:
diff changeset
919 return 0;
kono
parents:
diff changeset
920
kono
parents:
diff changeset
921 if (as1->type == AS_EXPLICIT)
kono
parents:
diff changeset
922 for (i = 0; i < as1->rank + as1->corank; i++)
kono
parents:
diff changeset
923 {
kono
parents:
diff changeset
924 if (compare_bounds (as1->lower[i], as2->lower[i]) == 0)
kono
parents:
diff changeset
925 return 0;
kono
parents:
diff changeset
926
kono
parents:
diff changeset
927 if (compare_bounds (as1->upper[i], as2->upper[i]) == 0)
kono
parents:
diff changeset
928 return 0;
kono
parents:
diff changeset
929 }
kono
parents:
diff changeset
930
kono
parents:
diff changeset
931 return 1;
kono
parents:
diff changeset
932 }
kono
parents:
diff changeset
933
kono
parents:
diff changeset
934
kono
parents:
diff changeset
935 /****************** Array constructor functions ******************/
kono
parents:
diff changeset
936
kono
parents:
diff changeset
937
kono
parents:
diff changeset
938 /* Given an expression node that might be an array constructor and a
kono
parents:
diff changeset
939 symbol, make sure that no iterators in this or child constructors
kono
parents:
diff changeset
940 use the symbol as an implied-DO iterator. Returns nonzero if a
kono
parents:
diff changeset
941 duplicate was found. */
kono
parents:
diff changeset
942
kono
parents:
diff changeset
943 static int
kono
parents:
diff changeset
944 check_duplicate_iterator (gfc_constructor_base base, gfc_symbol *master)
kono
parents:
diff changeset
945 {
kono
parents:
diff changeset
946 gfc_constructor *c;
kono
parents:
diff changeset
947 gfc_expr *e;
kono
parents:
diff changeset
948
kono
parents:
diff changeset
949 for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
kono
parents:
diff changeset
950 {
kono
parents:
diff changeset
951 e = c->expr;
kono
parents:
diff changeset
952
kono
parents:
diff changeset
953 if (e->expr_type == EXPR_ARRAY
kono
parents:
diff changeset
954 && check_duplicate_iterator (e->value.constructor, master))
kono
parents:
diff changeset
955 return 1;
kono
parents:
diff changeset
956
kono
parents:
diff changeset
957 if (c->iterator == NULL)
kono
parents:
diff changeset
958 continue;
kono
parents:
diff changeset
959
kono
parents:
diff changeset
960 if (c->iterator->var->symtree->n.sym == master)
kono
parents:
diff changeset
961 {
kono
parents:
diff changeset
962 gfc_error ("DO-iterator %qs at %L is inside iterator of the "
kono
parents:
diff changeset
963 "same name", master->name, &c->where);
kono
parents:
diff changeset
964
kono
parents:
diff changeset
965 return 1;
kono
parents:
diff changeset
966 }
kono
parents:
diff changeset
967 }
kono
parents:
diff changeset
968
kono
parents:
diff changeset
969 return 0;
kono
parents:
diff changeset
970 }
kono
parents:
diff changeset
971
kono
parents:
diff changeset
972
kono
parents:
diff changeset
973 /* Forward declaration because these functions are mutually recursive. */
kono
parents:
diff changeset
974 static match match_array_cons_element (gfc_constructor_base *);
kono
parents:
diff changeset
975
kono
parents:
diff changeset
976 /* Match a list of array elements. */
kono
parents:
diff changeset
977
kono
parents:
diff changeset
978 static match
kono
parents:
diff changeset
979 match_array_list (gfc_constructor_base *result)
kono
parents:
diff changeset
980 {
kono
parents:
diff changeset
981 gfc_constructor_base head;
kono
parents:
diff changeset
982 gfc_constructor *p;
kono
parents:
diff changeset
983 gfc_iterator iter;
kono
parents:
diff changeset
984 locus old_loc;
kono
parents:
diff changeset
985 gfc_expr *e;
kono
parents:
diff changeset
986 match m;
kono
parents:
diff changeset
987 int n;
kono
parents:
diff changeset
988
kono
parents:
diff changeset
989 old_loc = gfc_current_locus;
kono
parents:
diff changeset
990
kono
parents:
diff changeset
991 if (gfc_match_char ('(') == MATCH_NO)
kono
parents:
diff changeset
992 return MATCH_NO;
kono
parents:
diff changeset
993
kono
parents:
diff changeset
994 memset (&iter, '\0', sizeof (gfc_iterator));
kono
parents:
diff changeset
995 head = NULL;
kono
parents:
diff changeset
996
kono
parents:
diff changeset
997 m = match_array_cons_element (&head);
kono
parents:
diff changeset
998 if (m != MATCH_YES)
kono
parents:
diff changeset
999 goto cleanup;
kono
parents:
diff changeset
1000
kono
parents:
diff changeset
1001 if (gfc_match_char (',') != MATCH_YES)
kono
parents:
diff changeset
1002 {
kono
parents:
diff changeset
1003 m = MATCH_NO;
kono
parents:
diff changeset
1004 goto cleanup;
kono
parents:
diff changeset
1005 }
kono
parents:
diff changeset
1006
kono
parents:
diff changeset
1007 for (n = 1;; n++)
kono
parents:
diff changeset
1008 {
kono
parents:
diff changeset
1009 m = gfc_match_iterator (&iter, 0);
kono
parents:
diff changeset
1010 if (m == MATCH_YES)
kono
parents:
diff changeset
1011 break;
kono
parents:
diff changeset
1012 if (m == MATCH_ERROR)
kono
parents:
diff changeset
1013 goto cleanup;
kono
parents:
diff changeset
1014
kono
parents:
diff changeset
1015 m = match_array_cons_element (&head);
kono
parents:
diff changeset
1016 if (m == MATCH_ERROR)
kono
parents:
diff changeset
1017 goto cleanup;
kono
parents:
diff changeset
1018 if (m == MATCH_NO)
kono
parents:
diff changeset
1019 {
kono
parents:
diff changeset
1020 if (n > 2)
kono
parents:
diff changeset
1021 goto syntax;
kono
parents:
diff changeset
1022 m = MATCH_NO;
kono
parents:
diff changeset
1023 goto cleanup; /* Could be a complex constant */
kono
parents:
diff changeset
1024 }
kono
parents:
diff changeset
1025
kono
parents:
diff changeset
1026 if (gfc_match_char (',') != MATCH_YES)
kono
parents:
diff changeset
1027 {
kono
parents:
diff changeset
1028 if (n > 2)
kono
parents:
diff changeset
1029 goto syntax;
kono
parents:
diff changeset
1030 m = MATCH_NO;
kono
parents:
diff changeset
1031 goto cleanup;
kono
parents:
diff changeset
1032 }
kono
parents:
diff changeset
1033 }
kono
parents:
diff changeset
1034
kono
parents:
diff changeset
1035 if (gfc_match_char (')') != MATCH_YES)
kono
parents:
diff changeset
1036 goto syntax;
kono
parents:
diff changeset
1037
kono
parents:
diff changeset
1038 if (check_duplicate_iterator (head, iter.var->symtree->n.sym))
kono
parents:
diff changeset
1039 {
kono
parents:
diff changeset
1040 m = MATCH_ERROR;
kono
parents:
diff changeset
1041 goto cleanup;
kono
parents:
diff changeset
1042 }
kono
parents:
diff changeset
1043
kono
parents:
diff changeset
1044 e = gfc_get_array_expr (BT_UNKNOWN, 0, &old_loc);
kono
parents:
diff changeset
1045 e->value.constructor = head;
kono
parents:
diff changeset
1046
kono
parents:
diff changeset
1047 p = gfc_constructor_append_expr (result, e, &gfc_current_locus);
kono
parents:
diff changeset
1048 p->iterator = gfc_get_iterator ();
kono
parents:
diff changeset
1049 *p->iterator = iter;
kono
parents:
diff changeset
1050
kono
parents:
diff changeset
1051 return MATCH_YES;
kono
parents:
diff changeset
1052
kono
parents:
diff changeset
1053 syntax:
kono
parents:
diff changeset
1054 gfc_error ("Syntax error in array constructor at %C");
kono
parents:
diff changeset
1055 m = MATCH_ERROR;
kono
parents:
diff changeset
1056
kono
parents:
diff changeset
1057 cleanup:
kono
parents:
diff changeset
1058 gfc_constructor_free (head);
kono
parents:
diff changeset
1059 gfc_free_iterator (&iter, 0);
kono
parents:
diff changeset
1060 gfc_current_locus = old_loc;
kono
parents:
diff changeset
1061 return m;
kono
parents:
diff changeset
1062 }
kono
parents:
diff changeset
1063
kono
parents:
diff changeset
1064
kono
parents:
diff changeset
1065 /* Match a single element of an array constructor, which can be a
kono
parents:
diff changeset
1066 single expression or a list of elements. */
kono
parents:
diff changeset
1067
kono
parents:
diff changeset
1068 static match
kono
parents:
diff changeset
1069 match_array_cons_element (gfc_constructor_base *result)
kono
parents:
diff changeset
1070 {
kono
parents:
diff changeset
1071 gfc_expr *expr;
kono
parents:
diff changeset
1072 match m;
kono
parents:
diff changeset
1073
kono
parents:
diff changeset
1074 m = match_array_list (result);
kono
parents:
diff changeset
1075 if (m != MATCH_NO)
kono
parents:
diff changeset
1076 return m;
kono
parents:
diff changeset
1077
kono
parents:
diff changeset
1078 m = gfc_match_expr (&expr);
kono
parents:
diff changeset
1079 if (m != MATCH_YES)
kono
parents:
diff changeset
1080 return m;
kono
parents:
diff changeset
1081
kono
parents:
diff changeset
1082 gfc_constructor_append_expr (result, expr, &gfc_current_locus);
kono
parents:
diff changeset
1083 return MATCH_YES;
kono
parents:
diff changeset
1084 }
kono
parents:
diff changeset
1085
kono
parents:
diff changeset
1086
kono
parents:
diff changeset
1087 /* Match an array constructor. */
kono
parents:
diff changeset
1088
kono
parents:
diff changeset
1089 match
kono
parents:
diff changeset
1090 gfc_match_array_constructor (gfc_expr **result)
kono
parents:
diff changeset
1091 {
kono
parents:
diff changeset
1092 gfc_constructor *c;
kono
parents:
diff changeset
1093 gfc_constructor_base head;
kono
parents:
diff changeset
1094 gfc_expr *expr;
kono
parents:
diff changeset
1095 gfc_typespec ts;
kono
parents:
diff changeset
1096 locus where;
kono
parents:
diff changeset
1097 match m;
kono
parents:
diff changeset
1098 const char *end_delim;
kono
parents:
diff changeset
1099 bool seen_ts;
kono
parents:
diff changeset
1100
kono
parents:
diff changeset
1101 head = NULL;
kono
parents:
diff changeset
1102 seen_ts = false;
kono
parents:
diff changeset
1103
kono
parents:
diff changeset
1104 if (gfc_match (" (/") == MATCH_NO)
kono
parents:
diff changeset
1105 {
kono
parents:
diff changeset
1106 if (gfc_match (" [") == MATCH_NO)
kono
parents:
diff changeset
1107 return MATCH_NO;
kono
parents:
diff changeset
1108 else
kono
parents:
diff changeset
1109 {
kono
parents:
diff changeset
1110 if (!gfc_notify_std (GFC_STD_F2003, "[...] "
kono
parents:
diff changeset
1111 "style array constructors at %C"))
kono
parents:
diff changeset
1112 return MATCH_ERROR;
kono
parents:
diff changeset
1113 end_delim = " ]";
kono
parents:
diff changeset
1114 }
kono
parents:
diff changeset
1115 }
kono
parents:
diff changeset
1116 else
kono
parents:
diff changeset
1117 end_delim = " /)";
kono
parents:
diff changeset
1118
kono
parents:
diff changeset
1119 where = gfc_current_locus;
kono
parents:
diff changeset
1120
kono
parents:
diff changeset
1121 /* Try to match an optional "type-spec ::" */
kono
parents:
diff changeset
1122 gfc_clear_ts (&ts);
kono
parents:
diff changeset
1123 m = gfc_match_type_spec (&ts);
kono
parents:
diff changeset
1124 if (m == MATCH_YES)
kono
parents:
diff changeset
1125 {
kono
parents:
diff changeset
1126 seen_ts = (gfc_match (" ::") == MATCH_YES);
kono
parents:
diff changeset
1127
kono
parents:
diff changeset
1128 if (seen_ts)
kono
parents:
diff changeset
1129 {
kono
parents:
diff changeset
1130 if (!gfc_notify_std (GFC_STD_F2003, "Array constructor "
kono
parents:
diff changeset
1131 "including type specification at %C"))
kono
parents:
diff changeset
1132 goto cleanup;
kono
parents:
diff changeset
1133
kono
parents:
diff changeset
1134 if (ts.deferred)
kono
parents:
diff changeset
1135 {
kono
parents:
diff changeset
1136 gfc_error ("Type-spec at %L cannot contain a deferred "
kono
parents:
diff changeset
1137 "type parameter", &where);
kono
parents:
diff changeset
1138 goto cleanup;
kono
parents:
diff changeset
1139 }
kono
parents:
diff changeset
1140
kono
parents:
diff changeset
1141 if (ts.type == BT_CHARACTER
kono
parents:
diff changeset
1142 && ts.u.cl && !ts.u.cl->length && !ts.u.cl->length_from_typespec)
kono
parents:
diff changeset
1143 {
kono
parents:
diff changeset
1144 gfc_error ("Type-spec at %L cannot contain an asterisk for a "
kono
parents:
diff changeset
1145 "type parameter", &where);
kono
parents:
diff changeset
1146 goto cleanup;
kono
parents:
diff changeset
1147 }
kono
parents:
diff changeset
1148 }
kono
parents:
diff changeset
1149 }
kono
parents:
diff changeset
1150 else if (m == MATCH_ERROR)
kono
parents:
diff changeset
1151 goto cleanup;
kono
parents:
diff changeset
1152
kono
parents:
diff changeset
1153 if (!seen_ts)
kono
parents:
diff changeset
1154 gfc_current_locus = where;
kono
parents:
diff changeset
1155
kono
parents:
diff changeset
1156 if (gfc_match (end_delim) == MATCH_YES)
kono
parents:
diff changeset
1157 {
kono
parents:
diff changeset
1158 if (seen_ts)
kono
parents:
diff changeset
1159 goto done;
kono
parents:
diff changeset
1160 else
kono
parents:
diff changeset
1161 {
kono
parents:
diff changeset
1162 gfc_error ("Empty array constructor at %C is not allowed");
kono
parents:
diff changeset
1163 goto cleanup;
kono
parents:
diff changeset
1164 }
kono
parents:
diff changeset
1165 }
kono
parents:
diff changeset
1166
kono
parents:
diff changeset
1167 for (;;)
kono
parents:
diff changeset
1168 {
kono
parents:
diff changeset
1169 m = match_array_cons_element (&head);
kono
parents:
diff changeset
1170 if (m == MATCH_ERROR)
kono
parents:
diff changeset
1171 goto cleanup;
kono
parents:
diff changeset
1172 if (m == MATCH_NO)
kono
parents:
diff changeset
1173 goto syntax;
kono
parents:
diff changeset
1174
kono
parents:
diff changeset
1175 if (gfc_match_char (',') == MATCH_NO)
kono
parents:
diff changeset
1176 break;
kono
parents:
diff changeset
1177 }
kono
parents:
diff changeset
1178
kono
parents:
diff changeset
1179 if (gfc_match (end_delim) == MATCH_NO)
kono
parents:
diff changeset
1180 goto syntax;
kono
parents:
diff changeset
1181
kono
parents:
diff changeset
1182 done:
kono
parents:
diff changeset
1183 /* Size must be calculated at resolution time. */
kono
parents:
diff changeset
1184 if (seen_ts)
kono
parents:
diff changeset
1185 {
kono
parents:
diff changeset
1186 expr = gfc_get_array_expr (ts.type, ts.kind, &where);
kono
parents:
diff changeset
1187 expr->ts = ts;
kono
parents:
diff changeset
1188
kono
parents:
diff changeset
1189 /* If the typespec is CHARACTER, check that array elements can
kono
parents:
diff changeset
1190 be converted. See PR fortran/67803. */
kono
parents:
diff changeset
1191 if (ts.type == BT_CHARACTER)
kono
parents:
diff changeset
1192 {
kono
parents:
diff changeset
1193 c = gfc_constructor_first (head);
kono
parents:
diff changeset
1194 for (; c; c = gfc_constructor_next (c))
kono
parents:
diff changeset
1195 {
kono
parents:
diff changeset
1196 if (gfc_numeric_ts (&c->expr->ts)
kono
parents:
diff changeset
1197 || c->expr->ts.type == BT_LOGICAL)
kono
parents:
diff changeset
1198 {
kono
parents:
diff changeset
1199 gfc_error ("Incompatible typespec for array element at %L",
kono
parents:
diff changeset
1200 &c->expr->where);
kono
parents:
diff changeset
1201 return MATCH_ERROR;
kono
parents:
diff changeset
1202 }
kono
parents:
diff changeset
1203
kono
parents:
diff changeset
1204 /* Special case null(). */
kono
parents:
diff changeset
1205 if (c->expr->expr_type == EXPR_FUNCTION
kono
parents:
diff changeset
1206 && c->expr->ts.type == BT_UNKNOWN
kono
parents:
diff changeset
1207 && strcmp (c->expr->symtree->name, "null") == 0)
kono
parents:
diff changeset
1208 {
kono
parents:
diff changeset
1209 gfc_error ("Incompatible typespec for array element at %L",
kono
parents:
diff changeset
1210 &c->expr->where);
kono
parents:
diff changeset
1211 return MATCH_ERROR;
kono
parents:
diff changeset
1212 }
kono
parents:
diff changeset
1213 }
kono
parents:
diff changeset
1214 }
kono
parents:
diff changeset
1215
kono
parents:
diff changeset
1216 /* Walk the constructor and ensure type conversion for numeric types. */
kono
parents:
diff changeset
1217 if (gfc_numeric_ts (&ts))
kono
parents:
diff changeset
1218 {
kono
parents:
diff changeset
1219 c = gfc_constructor_first (head);
kono
parents:
diff changeset
1220 for (; c; c = gfc_constructor_next (c))
kono
parents:
diff changeset
1221 gfc_convert_type (c->expr, &ts, 1);
kono
parents:
diff changeset
1222 }
kono
parents:
diff changeset
1223 }
kono
parents:
diff changeset
1224 else
kono
parents:
diff changeset
1225 expr = gfc_get_array_expr (BT_UNKNOWN, 0, &where);
kono
parents:
diff changeset
1226
kono
parents:
diff changeset
1227 expr->value.constructor = head;
kono
parents:
diff changeset
1228 if (expr->ts.u.cl)
kono
parents:
diff changeset
1229 expr->ts.u.cl->length_from_typespec = seen_ts;
kono
parents:
diff changeset
1230
kono
parents:
diff changeset
1231 *result = expr;
kono
parents:
diff changeset
1232
kono
parents:
diff changeset
1233 return MATCH_YES;
kono
parents:
diff changeset
1234
kono
parents:
diff changeset
1235 syntax:
kono
parents:
diff changeset
1236 gfc_error ("Syntax error in array constructor at %C");
kono
parents:
diff changeset
1237
kono
parents:
diff changeset
1238 cleanup:
kono
parents:
diff changeset
1239 gfc_constructor_free (head);
kono
parents:
diff changeset
1240 return MATCH_ERROR;
kono
parents:
diff changeset
1241 }
kono
parents:
diff changeset
1242
kono
parents:
diff changeset
1243
kono
parents:
diff changeset
1244
kono
parents:
diff changeset
1245 /************** Check array constructors for correctness **************/
kono
parents:
diff changeset
1246
kono
parents:
diff changeset
1247 /* Given an expression, compare it's type with the type of the current
kono
parents:
diff changeset
1248 constructor. Returns nonzero if an error was issued. The
kono
parents:
diff changeset
1249 cons_state variable keeps track of whether the type of the
kono
parents:
diff changeset
1250 constructor being read or resolved is known to be good, bad or just
kono
parents:
diff changeset
1251 starting out. */
kono
parents:
diff changeset
1252
kono
parents:
diff changeset
1253 static gfc_typespec constructor_ts;
kono
parents:
diff changeset
1254 static enum
kono
parents:
diff changeset
1255 { CONS_START, CONS_GOOD, CONS_BAD }
kono
parents:
diff changeset
1256 cons_state;
kono
parents:
diff changeset
1257
kono
parents:
diff changeset
1258 static int
kono
parents:
diff changeset
1259 check_element_type (gfc_expr *expr, bool convert)
kono
parents:
diff changeset
1260 {
kono
parents:
diff changeset
1261 if (cons_state == CONS_BAD)
kono
parents:
diff changeset
1262 return 0; /* Suppress further errors */
kono
parents:
diff changeset
1263
kono
parents:
diff changeset
1264 if (cons_state == CONS_START)
kono
parents:
diff changeset
1265 {
kono
parents:
diff changeset
1266 if (expr->ts.type == BT_UNKNOWN)
kono
parents:
diff changeset
1267 cons_state = CONS_BAD;
kono
parents:
diff changeset
1268 else
kono
parents:
diff changeset
1269 {
kono
parents:
diff changeset
1270 cons_state = CONS_GOOD;
kono
parents:
diff changeset
1271 constructor_ts = expr->ts;
kono
parents:
diff changeset
1272 }
kono
parents:
diff changeset
1273
kono
parents:
diff changeset
1274 return 0;
kono
parents:
diff changeset
1275 }
kono
parents:
diff changeset
1276
kono
parents:
diff changeset
1277 if (gfc_compare_types (&constructor_ts, &expr->ts))
kono
parents:
diff changeset
1278 return 0;
kono
parents:
diff changeset
1279
kono
parents:
diff changeset
1280 if (convert)
kono
parents:
diff changeset
1281 return gfc_convert_type(expr, &constructor_ts, 1) ? 0 : 1;
kono
parents:
diff changeset
1282
kono
parents:
diff changeset
1283 gfc_error ("Element in %s array constructor at %L is %s",
kono
parents:
diff changeset
1284 gfc_typename (&constructor_ts), &expr->where,
kono
parents:
diff changeset
1285 gfc_typename (&expr->ts));
kono
parents:
diff changeset
1286
kono
parents:
diff changeset
1287 cons_state = CONS_BAD;
kono
parents:
diff changeset
1288 return 1;
kono
parents:
diff changeset
1289 }
kono
parents:
diff changeset
1290
kono
parents:
diff changeset
1291
kono
parents:
diff changeset
1292 /* Recursive work function for gfc_check_constructor_type(). */
kono
parents:
diff changeset
1293
kono
parents:
diff changeset
1294 static bool
kono
parents:
diff changeset
1295 check_constructor_type (gfc_constructor_base base, bool convert)
kono
parents:
diff changeset
1296 {
kono
parents:
diff changeset
1297 gfc_constructor *c;
kono
parents:
diff changeset
1298 gfc_expr *e;
kono
parents:
diff changeset
1299
kono
parents:
diff changeset
1300 for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
kono
parents:
diff changeset
1301 {
kono
parents:
diff changeset
1302 e = c->expr;
kono
parents:
diff changeset
1303
kono
parents:
diff changeset
1304 if (e->expr_type == EXPR_ARRAY)
kono
parents:
diff changeset
1305 {
kono
parents:
diff changeset
1306 if (!check_constructor_type (e->value.constructor, convert))
kono
parents:
diff changeset
1307 return false;
kono
parents:
diff changeset
1308
kono
parents:
diff changeset
1309 continue;
kono
parents:
diff changeset
1310 }
kono
parents:
diff changeset
1311
kono
parents:
diff changeset
1312 if (check_element_type (e, convert))
kono
parents:
diff changeset
1313 return false;
kono
parents:
diff changeset
1314 }
kono
parents:
diff changeset
1315
kono
parents:
diff changeset
1316 return true;
kono
parents:
diff changeset
1317 }
kono
parents:
diff changeset
1318
kono
parents:
diff changeset
1319
kono
parents:
diff changeset
1320 /* Check that all elements of an array constructor are the same type.
kono
parents:
diff changeset
1321 On false, an error has been generated. */
kono
parents:
diff changeset
1322
kono
parents:
diff changeset
1323 bool
kono
parents:
diff changeset
1324 gfc_check_constructor_type (gfc_expr *e)
kono
parents:
diff changeset
1325 {
kono
parents:
diff changeset
1326 bool t;
kono
parents:
diff changeset
1327
kono
parents:
diff changeset
1328 if (e->ts.type != BT_UNKNOWN)
kono
parents:
diff changeset
1329 {
kono
parents:
diff changeset
1330 cons_state = CONS_GOOD;
kono
parents:
diff changeset
1331 constructor_ts = e->ts;
kono
parents:
diff changeset
1332 }
kono
parents:
diff changeset
1333 else
kono
parents:
diff changeset
1334 {
kono
parents:
diff changeset
1335 cons_state = CONS_START;
kono
parents:
diff changeset
1336 gfc_clear_ts (&constructor_ts);
kono
parents:
diff changeset
1337 }
kono
parents:
diff changeset
1338
kono
parents:
diff changeset
1339 /* If e->ts.type != BT_UNKNOWN, the array constructor included a
kono
parents:
diff changeset
1340 typespec, and we will now convert the values on the fly. */
kono
parents:
diff changeset
1341 t = check_constructor_type (e->value.constructor, e->ts.type != BT_UNKNOWN);
kono
parents:
diff changeset
1342 if (t && e->ts.type == BT_UNKNOWN)
kono
parents:
diff changeset
1343 e->ts = constructor_ts;
kono
parents:
diff changeset
1344
kono
parents:
diff changeset
1345 return t;
kono
parents:
diff changeset
1346 }
kono
parents:
diff changeset
1347
kono
parents:
diff changeset
1348
kono
parents:
diff changeset
1349
kono
parents:
diff changeset
1350 typedef struct cons_stack
kono
parents:
diff changeset
1351 {
kono
parents:
diff changeset
1352 gfc_iterator *iterator;
kono
parents:
diff changeset
1353 struct cons_stack *previous;
kono
parents:
diff changeset
1354 }
kono
parents:
diff changeset
1355 cons_stack;
kono
parents:
diff changeset
1356
kono
parents:
diff changeset
1357 static cons_stack *base;
kono
parents:
diff changeset
1358
kono
parents:
diff changeset
1359 static bool check_constructor (gfc_constructor_base, bool (*) (gfc_expr *));
kono
parents:
diff changeset
1360
kono
parents:
diff changeset
1361 /* Check an EXPR_VARIABLE expression in a constructor to make sure
kono
parents:
diff changeset
1362 that that variable is an iteration variables. */
kono
parents:
diff changeset
1363
kono
parents:
diff changeset
1364 bool
kono
parents:
diff changeset
1365 gfc_check_iter_variable (gfc_expr *expr)
kono
parents:
diff changeset
1366 {
kono
parents:
diff changeset
1367 gfc_symbol *sym;
kono
parents:
diff changeset
1368 cons_stack *c;
kono
parents:
diff changeset
1369
kono
parents:
diff changeset
1370 sym = expr->symtree->n.sym;
kono
parents:
diff changeset
1371
kono
parents:
diff changeset
1372 for (c = base; c && c->iterator; c = c->previous)
kono
parents:
diff changeset
1373 if (sym == c->iterator->var->symtree->n.sym)
kono
parents:
diff changeset
1374 return true;
kono
parents:
diff changeset
1375
kono
parents:
diff changeset
1376 return false;
kono
parents:
diff changeset
1377 }
kono
parents:
diff changeset
1378
kono
parents:
diff changeset
1379
kono
parents:
diff changeset
1380 /* Recursive work function for gfc_check_constructor(). This amounts
kono
parents:
diff changeset
1381 to calling the check function for each expression in the
kono
parents:
diff changeset
1382 constructor, giving variables with the names of iterators a pass. */
kono
parents:
diff changeset
1383
kono
parents:
diff changeset
1384 static bool
kono
parents:
diff changeset
1385 check_constructor (gfc_constructor_base ctor, bool (*check_function) (gfc_expr *))
kono
parents:
diff changeset
1386 {
kono
parents:
diff changeset
1387 cons_stack element;
kono
parents:
diff changeset
1388 gfc_expr *e;
kono
parents:
diff changeset
1389 bool t;
kono
parents:
diff changeset
1390 gfc_constructor *c;
kono
parents:
diff changeset
1391
kono
parents:
diff changeset
1392 for (c = gfc_constructor_first (ctor); c; c = gfc_constructor_next (c))
kono
parents:
diff changeset
1393 {
kono
parents:
diff changeset
1394 e = c->expr;
kono
parents:
diff changeset
1395
kono
parents:
diff changeset
1396 if (!e)
kono
parents:
diff changeset
1397 continue;
kono
parents:
diff changeset
1398
kono
parents:
diff changeset
1399 if (e->expr_type != EXPR_ARRAY)
kono
parents:
diff changeset
1400 {
kono
parents:
diff changeset
1401 if (!(*check_function)(e))
kono
parents:
diff changeset
1402 return false;
kono
parents:
diff changeset
1403 continue;
kono
parents:
diff changeset
1404 }
kono
parents:
diff changeset
1405
kono
parents:
diff changeset
1406 element.previous = base;
kono
parents:
diff changeset
1407 element.iterator = c->iterator;
kono
parents:
diff changeset
1408
kono
parents:
diff changeset
1409 base = &element;
kono
parents:
diff changeset
1410 t = check_constructor (e->value.constructor, check_function);
kono
parents:
diff changeset
1411 base = element.previous;
kono
parents:
diff changeset
1412
kono
parents:
diff changeset
1413 if (!t)
kono
parents:
diff changeset
1414 return false;
kono
parents:
diff changeset
1415 }
kono
parents:
diff changeset
1416
kono
parents:
diff changeset
1417 /* Nothing went wrong, so all OK. */
kono
parents:
diff changeset
1418 return true;
kono
parents:
diff changeset
1419 }
kono
parents:
diff changeset
1420
kono
parents:
diff changeset
1421
kono
parents:
diff changeset
1422 /* Checks a constructor to see if it is a particular kind of
kono
parents:
diff changeset
1423 expression -- specification, restricted, or initialization as
kono
parents:
diff changeset
1424 determined by the check_function. */
kono
parents:
diff changeset
1425
kono
parents:
diff changeset
1426 bool
kono
parents:
diff changeset
1427 gfc_check_constructor (gfc_expr *expr, bool (*check_function) (gfc_expr *))
kono
parents:
diff changeset
1428 {
kono
parents:
diff changeset
1429 cons_stack *base_save;
kono
parents:
diff changeset
1430 bool t;
kono
parents:
diff changeset
1431
kono
parents:
diff changeset
1432 base_save = base;
kono
parents:
diff changeset
1433 base = NULL;
kono
parents:
diff changeset
1434
kono
parents:
diff changeset
1435 t = check_constructor (expr->value.constructor, check_function);
kono
parents:
diff changeset
1436 base = base_save;
kono
parents:
diff changeset
1437
kono
parents:
diff changeset
1438 return t;
kono
parents:
diff changeset
1439 }
kono
parents:
diff changeset
1440
kono
parents:
diff changeset
1441
kono
parents:
diff changeset
1442
kono
parents:
diff changeset
1443 /**************** Simplification of array constructors ****************/
kono
parents:
diff changeset
1444
kono
parents:
diff changeset
1445 iterator_stack *iter_stack;
kono
parents:
diff changeset
1446
kono
parents:
diff changeset
1447 typedef struct
kono
parents:
diff changeset
1448 {
kono
parents:
diff changeset
1449 gfc_constructor_base base;
kono
parents:
diff changeset
1450 int extract_count, extract_n;
kono
parents:
diff changeset
1451 gfc_expr *extracted;
kono
parents:
diff changeset
1452 mpz_t *count;
kono
parents:
diff changeset
1453
kono
parents:
diff changeset
1454 mpz_t *offset;
kono
parents:
diff changeset
1455 gfc_component *component;
kono
parents:
diff changeset
1456 mpz_t *repeat;
kono
parents:
diff changeset
1457
kono
parents:
diff changeset
1458 bool (*expand_work_function) (gfc_expr *);
kono
parents:
diff changeset
1459 }
kono
parents:
diff changeset
1460 expand_info;
kono
parents:
diff changeset
1461
kono
parents:
diff changeset
1462 static expand_info current_expand;
kono
parents:
diff changeset
1463
kono
parents:
diff changeset
1464 static bool expand_constructor (gfc_constructor_base);
kono
parents:
diff changeset
1465
kono
parents:
diff changeset
1466
kono
parents:
diff changeset
1467 /* Work function that counts the number of elements present in a
kono
parents:
diff changeset
1468 constructor. */
kono
parents:
diff changeset
1469
kono
parents:
diff changeset
1470 static bool
kono
parents:
diff changeset
1471 count_elements (gfc_expr *e)
kono
parents:
diff changeset
1472 {
kono
parents:
diff changeset
1473 mpz_t result;
kono
parents:
diff changeset
1474
kono
parents:
diff changeset
1475 if (e->rank == 0)
kono
parents:
diff changeset
1476 mpz_add_ui (*current_expand.count, *current_expand.count, 1);
kono
parents:
diff changeset
1477 else
kono
parents:
diff changeset
1478 {
kono
parents:
diff changeset
1479 if (!gfc_array_size (e, &result))
kono
parents:
diff changeset
1480 {
kono
parents:
diff changeset
1481 gfc_free_expr (e);
kono
parents:
diff changeset
1482 return false;
kono
parents:
diff changeset
1483 }
kono
parents:
diff changeset
1484
kono
parents:
diff changeset
1485 mpz_add (*current_expand.count, *current_expand.count, result);
kono
parents:
diff changeset
1486 mpz_clear (result);
kono
parents:
diff changeset
1487 }
kono
parents:
diff changeset
1488
kono
parents:
diff changeset
1489 gfc_free_expr (e);
kono
parents:
diff changeset
1490 return true;
kono
parents:
diff changeset
1491 }
kono
parents:
diff changeset
1492
kono
parents:
diff changeset
1493
kono
parents:
diff changeset
1494 /* Work function that extracts a particular element from an array
kono
parents:
diff changeset
1495 constructor, freeing the rest. */
kono
parents:
diff changeset
1496
kono
parents:
diff changeset
1497 static bool
kono
parents:
diff changeset
1498 extract_element (gfc_expr *e)
kono
parents:
diff changeset
1499 {
kono
parents:
diff changeset
1500 if (e->rank != 0)
kono
parents:
diff changeset
1501 { /* Something unextractable */
kono
parents:
diff changeset
1502 gfc_free_expr (e);
kono
parents:
diff changeset
1503 return false;
kono
parents:
diff changeset
1504 }
kono
parents:
diff changeset
1505
kono
parents:
diff changeset
1506 if (current_expand.extract_count == current_expand.extract_n)
kono
parents:
diff changeset
1507 current_expand.extracted = e;
kono
parents:
diff changeset
1508 else
kono
parents:
diff changeset
1509 gfc_free_expr (e);
kono
parents:
diff changeset
1510
kono
parents:
diff changeset
1511 current_expand.extract_count++;
kono
parents:
diff changeset
1512
kono
parents:
diff changeset
1513 return true;
kono
parents:
diff changeset
1514 }
kono
parents:
diff changeset
1515
kono
parents:
diff changeset
1516
kono
parents:
diff changeset
1517 /* Work function that constructs a new constructor out of the old one,
kono
parents:
diff changeset
1518 stringing new elements together. */
kono
parents:
diff changeset
1519
kono
parents:
diff changeset
1520 static bool
kono
parents:
diff changeset
1521 expand (gfc_expr *e)
kono
parents:
diff changeset
1522 {
kono
parents:
diff changeset
1523 gfc_constructor *c = gfc_constructor_append_expr (&current_expand.base,
kono
parents:
diff changeset
1524 e, &e->where);
kono
parents:
diff changeset
1525
kono
parents:
diff changeset
1526 c->n.component = current_expand.component;
kono
parents:
diff changeset
1527 return true;
kono
parents:
diff changeset
1528 }
kono
parents:
diff changeset
1529
kono
parents:
diff changeset
1530
kono
parents:
diff changeset
1531 /* Given an initialization expression that is a variable reference,
kono
parents:
diff changeset
1532 substitute the current value of the iteration variable. */
kono
parents:
diff changeset
1533
kono
parents:
diff changeset
1534 void
kono
parents:
diff changeset
1535 gfc_simplify_iterator_var (gfc_expr *e)
kono
parents:
diff changeset
1536 {
kono
parents:
diff changeset
1537 iterator_stack *p;
kono
parents:
diff changeset
1538
kono
parents:
diff changeset
1539 for (p = iter_stack; p; p = p->prev)
kono
parents:
diff changeset
1540 if (e->symtree == p->variable)
kono
parents:
diff changeset
1541 break;
kono
parents:
diff changeset
1542
kono
parents:
diff changeset
1543 if (p == NULL)
kono
parents:
diff changeset
1544 return; /* Variable not found */
kono
parents:
diff changeset
1545
kono
parents:
diff changeset
1546 gfc_replace_expr (e, gfc_get_int_expr (gfc_default_integer_kind, NULL, 0));
kono
parents:
diff changeset
1547
kono
parents:
diff changeset
1548 mpz_set (e->value.integer, p->value);
kono
parents:
diff changeset
1549
kono
parents:
diff changeset
1550 return;
kono
parents:
diff changeset
1551 }
kono
parents:
diff changeset
1552
kono
parents:
diff changeset
1553
kono
parents:
diff changeset
1554 /* Expand an expression with that is inside of a constructor,
kono
parents:
diff changeset
1555 recursing into other constructors if present. */
kono
parents:
diff changeset
1556
kono
parents:
diff changeset
1557 static bool
kono
parents:
diff changeset
1558 expand_expr (gfc_expr *e)
kono
parents:
diff changeset
1559 {
kono
parents:
diff changeset
1560 if (e->expr_type == EXPR_ARRAY)
kono
parents:
diff changeset
1561 return expand_constructor (e->value.constructor);
kono
parents:
diff changeset
1562
kono
parents:
diff changeset
1563 e = gfc_copy_expr (e);
kono
parents:
diff changeset
1564
kono
parents:
diff changeset
1565 if (!gfc_simplify_expr (e, 1))
kono
parents:
diff changeset
1566 {
kono
parents:
diff changeset
1567 gfc_free_expr (e);
kono
parents:
diff changeset
1568 return false;
kono
parents:
diff changeset
1569 }
kono
parents:
diff changeset
1570
kono
parents:
diff changeset
1571 return current_expand.expand_work_function (e);
kono
parents:
diff changeset
1572 }
kono
parents:
diff changeset
1573
kono
parents:
diff changeset
1574
kono
parents:
diff changeset
1575 static bool
kono
parents:
diff changeset
1576 expand_iterator (gfc_constructor *c)
kono
parents:
diff changeset
1577 {
kono
parents:
diff changeset
1578 gfc_expr *start, *end, *step;
kono
parents:
diff changeset
1579 iterator_stack frame;
kono
parents:
diff changeset
1580 mpz_t trip;
kono
parents:
diff changeset
1581 bool t;
kono
parents:
diff changeset
1582
kono
parents:
diff changeset
1583 end = step = NULL;
kono
parents:
diff changeset
1584
kono
parents:
diff changeset
1585 t = false;
kono
parents:
diff changeset
1586
kono
parents:
diff changeset
1587 mpz_init (trip);
kono
parents:
diff changeset
1588 mpz_init (frame.value);
kono
parents:
diff changeset
1589 frame.prev = NULL;
kono
parents:
diff changeset
1590
kono
parents:
diff changeset
1591 start = gfc_copy_expr (c->iterator->start);
kono
parents:
diff changeset
1592 if (!gfc_simplify_expr (start, 1))
kono
parents:
diff changeset
1593 goto cleanup;
kono
parents:
diff changeset
1594
kono
parents:
diff changeset
1595 if (start->expr_type != EXPR_CONSTANT || start->ts.type != BT_INTEGER)
kono
parents:
diff changeset
1596 goto cleanup;
kono
parents:
diff changeset
1597
kono
parents:
diff changeset
1598 end = gfc_copy_expr (c->iterator->end);
kono
parents:
diff changeset
1599 if (!gfc_simplify_expr (end, 1))
kono
parents:
diff changeset
1600 goto cleanup;
kono
parents:
diff changeset
1601
kono
parents:
diff changeset
1602 if (end->expr_type != EXPR_CONSTANT || end->ts.type != BT_INTEGER)
kono
parents:
diff changeset
1603 goto cleanup;
kono
parents:
diff changeset
1604
kono
parents:
diff changeset
1605 step = gfc_copy_expr (c->iterator->step);
kono
parents:
diff changeset
1606 if (!gfc_simplify_expr (step, 1))
kono
parents:
diff changeset
1607 goto cleanup;
kono
parents:
diff changeset
1608
kono
parents:
diff changeset
1609 if (step->expr_type != EXPR_CONSTANT || step->ts.type != BT_INTEGER)
kono
parents:
diff changeset
1610 goto cleanup;
kono
parents:
diff changeset
1611
kono
parents:
diff changeset
1612 if (mpz_sgn (step->value.integer) == 0)
kono
parents:
diff changeset
1613 {
kono
parents:
diff changeset
1614 gfc_error ("Iterator step at %L cannot be zero", &step->where);
kono
parents:
diff changeset
1615 goto cleanup;
kono
parents:
diff changeset
1616 }
kono
parents:
diff changeset
1617
kono
parents:
diff changeset
1618 /* Calculate the trip count of the loop. */
kono
parents:
diff changeset
1619 mpz_sub (trip, end->value.integer, start->value.integer);
kono
parents:
diff changeset
1620 mpz_add (trip, trip, step->value.integer);
kono
parents:
diff changeset
1621 mpz_tdiv_q (trip, trip, step->value.integer);
kono
parents:
diff changeset
1622
kono
parents:
diff changeset
1623 mpz_set (frame.value, start->value.integer);
kono
parents:
diff changeset
1624
kono
parents:
diff changeset
1625 frame.prev = iter_stack;
kono
parents:
diff changeset
1626 frame.variable = c->iterator->var->symtree;
kono
parents:
diff changeset
1627 iter_stack = &frame;
kono
parents:
diff changeset
1628
kono
parents:
diff changeset
1629 while (mpz_sgn (trip) > 0)
kono
parents:
diff changeset
1630 {
kono
parents:
diff changeset
1631 if (!expand_expr (c->expr))
kono
parents:
diff changeset
1632 goto cleanup;
kono
parents:
diff changeset
1633
kono
parents:
diff changeset
1634 mpz_add (frame.value, frame.value, step->value.integer);
kono
parents:
diff changeset
1635 mpz_sub_ui (trip, trip, 1);
kono
parents:
diff changeset
1636 }
kono
parents:
diff changeset
1637
kono
parents:
diff changeset
1638 t = true;
kono
parents:
diff changeset
1639
kono
parents:
diff changeset
1640 cleanup:
kono
parents:
diff changeset
1641 gfc_free_expr (start);
kono
parents:
diff changeset
1642 gfc_free_expr (end);
kono
parents:
diff changeset
1643 gfc_free_expr (step);
kono
parents:
diff changeset
1644
kono
parents:
diff changeset
1645 mpz_clear (trip);
kono
parents:
diff changeset
1646 mpz_clear (frame.value);
kono
parents:
diff changeset
1647
kono
parents:
diff changeset
1648 iter_stack = frame.prev;
kono
parents:
diff changeset
1649
kono
parents:
diff changeset
1650 return t;
kono
parents:
diff changeset
1651 }
kono
parents:
diff changeset
1652
kono
parents:
diff changeset
1653
kono
parents:
diff changeset
1654 /* Expand a constructor into constant constructors without any
kono
parents:
diff changeset
1655 iterators, calling the work function for each of the expanded
kono
parents:
diff changeset
1656 expressions. The work function needs to either save or free the
kono
parents:
diff changeset
1657 passed expression. */
kono
parents:
diff changeset
1658
kono
parents:
diff changeset
1659 static bool
kono
parents:
diff changeset
1660 expand_constructor (gfc_constructor_base base)
kono
parents:
diff changeset
1661 {
kono
parents:
diff changeset
1662 gfc_constructor *c;
kono
parents:
diff changeset
1663 gfc_expr *e;
kono
parents:
diff changeset
1664
kono
parents:
diff changeset
1665 for (c = gfc_constructor_first (base); c; c = gfc_constructor_next(c))
kono
parents:
diff changeset
1666 {
kono
parents:
diff changeset
1667 if (c->iterator != NULL)
kono
parents:
diff changeset
1668 {
kono
parents:
diff changeset
1669 if (!expand_iterator (c))
kono
parents:
diff changeset
1670 return false;
kono
parents:
diff changeset
1671 continue;
kono
parents:
diff changeset
1672 }
kono
parents:
diff changeset
1673
kono
parents:
diff changeset
1674 e = c->expr;
kono
parents:
diff changeset
1675
kono
parents:
diff changeset
1676 if (e->expr_type == EXPR_ARRAY)
kono
parents:
diff changeset
1677 {
kono
parents:
diff changeset
1678 if (!expand_constructor (e->value.constructor))
kono
parents:
diff changeset
1679 return false;
kono
parents:
diff changeset
1680
kono
parents:
diff changeset
1681 continue;
kono
parents:
diff changeset
1682 }
kono
parents:
diff changeset
1683
kono
parents:
diff changeset
1684 e = gfc_copy_expr (e);
kono
parents:
diff changeset
1685 if (!gfc_simplify_expr (e, 1))
kono
parents:
diff changeset
1686 {
kono
parents:
diff changeset
1687 gfc_free_expr (e);
kono
parents:
diff changeset
1688 return false;
kono
parents:
diff changeset
1689 }
kono
parents:
diff changeset
1690 current_expand.offset = &c->offset;
kono
parents:
diff changeset
1691 current_expand.repeat = &c->repeat;
kono
parents:
diff changeset
1692 current_expand.component = c->n.component;
kono
parents:
diff changeset
1693 if (!current_expand.expand_work_function(e))
kono
parents:
diff changeset
1694 return false;
kono
parents:
diff changeset
1695 }
kono
parents:
diff changeset
1696 return true;
kono
parents:
diff changeset
1697 }
kono
parents:
diff changeset
1698
kono
parents:
diff changeset
1699
kono
parents:
diff changeset
1700 /* Given an array expression and an element number (starting at zero),
kono
parents:
diff changeset
1701 return a pointer to the array element. NULL is returned if the
kono
parents:
diff changeset
1702 size of the array has been exceeded. The expression node returned
kono
parents:
diff changeset
1703 remains a part of the array and should not be freed. Access is not
kono
parents:
diff changeset
1704 efficient at all, but this is another place where things do not
kono
parents:
diff changeset
1705 have to be particularly fast. */
kono
parents:
diff changeset
1706
kono
parents:
diff changeset
1707 static gfc_expr *
kono
parents:
diff changeset
1708 gfc_get_array_element (gfc_expr *array, int element)
kono
parents:
diff changeset
1709 {
kono
parents:
diff changeset
1710 expand_info expand_save;
kono
parents:
diff changeset
1711 gfc_expr *e;
kono
parents:
diff changeset
1712 bool rc;
kono
parents:
diff changeset
1713
kono
parents:
diff changeset
1714 expand_save = current_expand;
kono
parents:
diff changeset
1715 current_expand.extract_n = element;
kono
parents:
diff changeset
1716 current_expand.expand_work_function = extract_element;
kono
parents:
diff changeset
1717 current_expand.extracted = NULL;
kono
parents:
diff changeset
1718 current_expand.extract_count = 0;
kono
parents:
diff changeset
1719
kono
parents:
diff changeset
1720 iter_stack = NULL;
kono
parents:
diff changeset
1721
kono
parents:
diff changeset
1722 rc = expand_constructor (array->value.constructor);
kono
parents:
diff changeset
1723 e = current_expand.extracted;
kono
parents:
diff changeset
1724 current_expand = expand_save;
kono
parents:
diff changeset
1725
kono
parents:
diff changeset
1726 if (!rc)
kono
parents:
diff changeset
1727 return NULL;
kono
parents:
diff changeset
1728
kono
parents:
diff changeset
1729 return e;
kono
parents:
diff changeset
1730 }
kono
parents:
diff changeset
1731
kono
parents:
diff changeset
1732
kono
parents:
diff changeset
1733 /* Top level subroutine for expanding constructors. We only expand
kono
parents:
diff changeset
1734 constructor if they are small enough. */
kono
parents:
diff changeset
1735
kono
parents:
diff changeset
1736 bool
kono
parents:
diff changeset
1737 gfc_expand_constructor (gfc_expr *e, bool fatal)
kono
parents:
diff changeset
1738 {
kono
parents:
diff changeset
1739 expand_info expand_save;
kono
parents:
diff changeset
1740 gfc_expr *f;
kono
parents:
diff changeset
1741 bool rc;
kono
parents:
diff changeset
1742
kono
parents:
diff changeset
1743 /* If we can successfully get an array element at the max array size then
kono
parents:
diff changeset
1744 the array is too big to expand, so we just return. */
kono
parents:
diff changeset
1745 f = gfc_get_array_element (e, flag_max_array_constructor);
kono
parents:
diff changeset
1746 if (f != NULL)
kono
parents:
diff changeset
1747 {
kono
parents:
diff changeset
1748 gfc_free_expr (f);
kono
parents:
diff changeset
1749 if (fatal)
kono
parents:
diff changeset
1750 {
kono
parents:
diff changeset
1751 gfc_error ("The number of elements in the array constructor "
kono
parents:
diff changeset
1752 "at %L requires an increase of the allowed %d "
kono
parents:
diff changeset
1753 "upper limit. See %<-fmax-array-constructor%> "
kono
parents:
diff changeset
1754 "option", &e->where, flag_max_array_constructor);
kono
parents:
diff changeset
1755 return false;
kono
parents:
diff changeset
1756 }
kono
parents:
diff changeset
1757 return true;
kono
parents:
diff changeset
1758 }
kono
parents:
diff changeset
1759
kono
parents:
diff changeset
1760 /* We now know the array is not too big so go ahead and try to expand it. */
kono
parents:
diff changeset
1761 expand_save = current_expand;
kono
parents:
diff changeset
1762 current_expand.base = NULL;
kono
parents:
diff changeset
1763
kono
parents:
diff changeset
1764 iter_stack = NULL;
kono
parents:
diff changeset
1765
kono
parents:
diff changeset
1766 current_expand.expand_work_function = expand;
kono
parents:
diff changeset
1767
kono
parents:
diff changeset
1768 if (!expand_constructor (e->value.constructor))
kono
parents:
diff changeset
1769 {
kono
parents:
diff changeset
1770 gfc_constructor_free (current_expand.base);
kono
parents:
diff changeset
1771 rc = false;
kono
parents:
diff changeset
1772 goto done;
kono
parents:
diff changeset
1773 }
kono
parents:
diff changeset
1774
kono
parents:
diff changeset
1775 gfc_constructor_free (e->value.constructor);
kono
parents:
diff changeset
1776 e->value.constructor = current_expand.base;
kono
parents:
diff changeset
1777
kono
parents:
diff changeset
1778 rc = true;
kono
parents:
diff changeset
1779
kono
parents:
diff changeset
1780 done:
kono
parents:
diff changeset
1781 current_expand = expand_save;
kono
parents:
diff changeset
1782
kono
parents:
diff changeset
1783 return rc;
kono
parents:
diff changeset
1784 }
kono
parents:
diff changeset
1785
kono
parents:
diff changeset
1786
kono
parents:
diff changeset
1787 /* Work function for checking that an element of a constructor is a
kono
parents:
diff changeset
1788 constant, after removal of any iteration variables. We return
kono
parents:
diff changeset
1789 false if not so. */
kono
parents:
diff changeset
1790
kono
parents:
diff changeset
1791 static bool
kono
parents:
diff changeset
1792 is_constant_element (gfc_expr *e)
kono
parents:
diff changeset
1793 {
kono
parents:
diff changeset
1794 int rv;
kono
parents:
diff changeset
1795
kono
parents:
diff changeset
1796 rv = gfc_is_constant_expr (e);
kono
parents:
diff changeset
1797 gfc_free_expr (e);
kono
parents:
diff changeset
1798
kono
parents:
diff changeset
1799 return rv ? true : false;
kono
parents:
diff changeset
1800 }
kono
parents:
diff changeset
1801
kono
parents:
diff changeset
1802
kono
parents:
diff changeset
1803 /* Given an array constructor, determine if the constructor is
kono
parents:
diff changeset
1804 constant or not by expanding it and making sure that all elements
kono
parents:
diff changeset
1805 are constants. This is a bit of a hack since something like (/ (i,
kono
parents:
diff changeset
1806 i=1,100000000) /) will take a while as* opposed to a more clever
kono
parents:
diff changeset
1807 function that traverses the expression tree. FIXME. */
kono
parents:
diff changeset
1808
kono
parents:
diff changeset
1809 int
kono
parents:
diff changeset
1810 gfc_constant_ac (gfc_expr *e)
kono
parents:
diff changeset
1811 {
kono
parents:
diff changeset
1812 expand_info expand_save;
kono
parents:
diff changeset
1813 bool rc;
kono
parents:
diff changeset
1814
kono
parents:
diff changeset
1815 iter_stack = NULL;
kono
parents:
diff changeset
1816 expand_save = current_expand;
kono
parents:
diff changeset
1817 current_expand.expand_work_function = is_constant_element;
kono
parents:
diff changeset
1818
kono
parents:
diff changeset
1819 rc = expand_constructor (e->value.constructor);
kono
parents:
diff changeset
1820
kono
parents:
diff changeset
1821 current_expand = expand_save;
kono
parents:
diff changeset
1822 if (!rc)
kono
parents:
diff changeset
1823 return 0;
kono
parents:
diff changeset
1824
kono
parents:
diff changeset
1825 return 1;
kono
parents:
diff changeset
1826 }
kono
parents:
diff changeset
1827
kono
parents:
diff changeset
1828
kono
parents:
diff changeset
1829 /* Returns nonzero if an array constructor has been completely
kono
parents:
diff changeset
1830 expanded (no iterators) and zero if iterators are present. */
kono
parents:
diff changeset
1831
kono
parents:
diff changeset
1832 int
kono
parents:
diff changeset
1833 gfc_expanded_ac (gfc_expr *e)
kono
parents:
diff changeset
1834 {
kono
parents:
diff changeset
1835 gfc_constructor *c;
kono
parents:
diff changeset
1836
kono
parents:
diff changeset
1837 if (e->expr_type == EXPR_ARRAY)
kono
parents:
diff changeset
1838 for (c = gfc_constructor_first (e->value.constructor);
kono
parents:
diff changeset
1839 c; c = gfc_constructor_next (c))
kono
parents:
diff changeset
1840 if (c->iterator != NULL || !gfc_expanded_ac (c->expr))
kono
parents:
diff changeset
1841 return 0;
kono
parents:
diff changeset
1842
kono
parents:
diff changeset
1843 return 1;
kono
parents:
diff changeset
1844 }
kono
parents:
diff changeset
1845
kono
parents:
diff changeset
1846
kono
parents:
diff changeset
1847 /*************** Type resolution of array constructors ***************/
kono
parents:
diff changeset
1848
kono
parents:
diff changeset
1849
kono
parents:
diff changeset
1850 /* The symbol expr_is_sought_symbol_ref will try to find. */
kono
parents:
diff changeset
1851 static const gfc_symbol *sought_symbol = NULL;
kono
parents:
diff changeset
1852
kono
parents:
diff changeset
1853
kono
parents:
diff changeset
1854 /* Tells whether the expression E is a variable reference to the symbol
kono
parents:
diff changeset
1855 in the static variable SOUGHT_SYMBOL, and sets the locus pointer WHERE
kono
parents:
diff changeset
1856 accordingly.
kono
parents:
diff changeset
1857 To be used with gfc_expr_walker: if a reference is found we don't need
kono
parents:
diff changeset
1858 to look further so we return 1 to skip any further walk. */
kono
parents:
diff changeset
1859
kono
parents:
diff changeset
1860 static int
kono
parents:
diff changeset
1861 expr_is_sought_symbol_ref (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
kono
parents:
diff changeset
1862 void *where)
kono
parents:
diff changeset
1863 {
kono
parents:
diff changeset
1864 gfc_expr *expr = *e;
kono
parents:
diff changeset
1865 locus *sym_loc = (locus *)where;
kono
parents:
diff changeset
1866
kono
parents:
diff changeset
1867 if (expr->expr_type == EXPR_VARIABLE
kono
parents:
diff changeset
1868 && expr->symtree->n.sym == sought_symbol)
kono
parents:
diff changeset
1869 {
kono
parents:
diff changeset
1870 *sym_loc = expr->where;
kono
parents:
diff changeset
1871 return 1;
kono
parents:
diff changeset
1872 }
kono
parents:
diff changeset
1873
kono
parents:
diff changeset
1874 return 0;
kono
parents:
diff changeset
1875 }
kono
parents:
diff changeset
1876
kono
parents:
diff changeset
1877
kono
parents:
diff changeset
1878 /* Tells whether the expression EXPR contains a reference to the symbol
kono
parents:
diff changeset
1879 SYM and in that case sets the position SYM_LOC where the reference is. */
kono
parents:
diff changeset
1880
kono
parents:
diff changeset
1881 static bool
kono
parents:
diff changeset
1882 find_symbol_in_expr (gfc_symbol *sym, gfc_expr *expr, locus *sym_loc)
kono
parents:
diff changeset
1883 {
kono
parents:
diff changeset
1884 int ret;
kono
parents:
diff changeset
1885
kono
parents:
diff changeset
1886 sought_symbol = sym;
kono
parents:
diff changeset
1887 ret = gfc_expr_walker (&expr, &expr_is_sought_symbol_ref, sym_loc);
kono
parents:
diff changeset
1888 sought_symbol = NULL;
kono
parents:
diff changeset
1889 return ret;
kono
parents:
diff changeset
1890 }
kono
parents:
diff changeset
1891
kono
parents:
diff changeset
1892
kono
parents:
diff changeset
1893 /* Recursive array list resolution function. All of the elements must
kono
parents:
diff changeset
1894 be of the same type. */
kono
parents:
diff changeset
1895
kono
parents:
diff changeset
1896 static bool
kono
parents:
diff changeset
1897 resolve_array_list (gfc_constructor_base base)
kono
parents:
diff changeset
1898 {
kono
parents:
diff changeset
1899 bool t;
kono
parents:
diff changeset
1900 gfc_constructor *c;
kono
parents:
diff changeset
1901 gfc_iterator *iter;
kono
parents:
diff changeset
1902
kono
parents:
diff changeset
1903 t = true;
kono
parents:
diff changeset
1904
kono
parents:
diff changeset
1905 for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
kono
parents:
diff changeset
1906 {
kono
parents:
diff changeset
1907 iter = c->iterator;
kono
parents:
diff changeset
1908 if (iter != NULL)
kono
parents:
diff changeset
1909 {
kono
parents:
diff changeset
1910 gfc_symbol *iter_var;
kono
parents:
diff changeset
1911 locus iter_var_loc;
kono
parents:
diff changeset
1912
kono
parents:
diff changeset
1913 if (!gfc_resolve_iterator (iter, false, true))
kono
parents:
diff changeset
1914 t = false;
kono
parents:
diff changeset
1915
kono
parents:
diff changeset
1916 /* Check for bounds referencing the iterator variable. */
kono
parents:
diff changeset
1917 gcc_assert (iter->var->expr_type == EXPR_VARIABLE);
kono
parents:
diff changeset
1918 iter_var = iter->var->symtree->n.sym;
kono
parents:
diff changeset
1919 if (find_symbol_in_expr (iter_var, iter->start, &iter_var_loc))
kono
parents:
diff changeset
1920 {
kono
parents:
diff changeset
1921 if (!gfc_notify_std (GFC_STD_LEGACY, "AC-IMPLIED-DO initial "
kono
parents:
diff changeset
1922 "expression references control variable "
kono
parents:
diff changeset
1923 "at %L", &iter_var_loc))
kono
parents:
diff changeset
1924 t = false;
kono
parents:
diff changeset
1925 }
kono
parents:
diff changeset
1926 if (find_symbol_in_expr (iter_var, iter->end, &iter_var_loc))
kono
parents:
diff changeset
1927 {
kono
parents:
diff changeset
1928 if (!gfc_notify_std (GFC_STD_LEGACY, "AC-IMPLIED-DO final "
kono
parents:
diff changeset
1929 "expression references control variable "
kono
parents:
diff changeset
1930 "at %L", &iter_var_loc))
kono
parents:
diff changeset
1931 t = false;
kono
parents:
diff changeset
1932 }
kono
parents:
diff changeset
1933 if (find_symbol_in_expr (iter_var, iter->step, &iter_var_loc))
kono
parents:
diff changeset
1934 {
kono
parents:
diff changeset
1935 if (!gfc_notify_std (GFC_STD_LEGACY, "AC-IMPLIED-DO step "
kono
parents:
diff changeset
1936 "expression references control variable "
kono
parents:
diff changeset
1937 "at %L", &iter_var_loc))
kono
parents:
diff changeset
1938 t = false;
kono
parents:
diff changeset
1939 }
kono
parents:
diff changeset
1940 }
kono
parents:
diff changeset
1941
kono
parents:
diff changeset
1942 if (!gfc_resolve_expr (c->expr))
kono
parents:
diff changeset
1943 t = false;
kono
parents:
diff changeset
1944
kono
parents:
diff changeset
1945 if (UNLIMITED_POLY (c->expr))
kono
parents:
diff changeset
1946 {
kono
parents:
diff changeset
1947 gfc_error ("Array constructor value at %L shall not be unlimited "
kono
parents:
diff changeset
1948 "polymorphic [F2008: C4106]", &c->expr->where);
kono
parents:
diff changeset
1949 t = false;
kono
parents:
diff changeset
1950 }
kono
parents:
diff changeset
1951 }
kono
parents:
diff changeset
1952
kono
parents:
diff changeset
1953 return t;
kono
parents:
diff changeset
1954 }
kono
parents:
diff changeset
1955
kono
parents:
diff changeset
1956 /* Resolve character array constructor. If it has a specified constant character
kono
parents:
diff changeset
1957 length, pad/truncate the elements here; if the length is not specified and
kono
parents:
diff changeset
1958 all elements are of compile-time known length, emit an error as this is
kono
parents:
diff changeset
1959 invalid. */
kono
parents:
diff changeset
1960
kono
parents:
diff changeset
1961 bool
kono
parents:
diff changeset
1962 gfc_resolve_character_array_constructor (gfc_expr *expr)
kono
parents:
diff changeset
1963 {
kono
parents:
diff changeset
1964 gfc_constructor *p;
kono
parents:
diff changeset
1965 int found_length;
kono
parents:
diff changeset
1966
kono
parents:
diff changeset
1967 gcc_assert (expr->expr_type == EXPR_ARRAY);
kono
parents:
diff changeset
1968 gcc_assert (expr->ts.type == BT_CHARACTER);
kono
parents:
diff changeset
1969
kono
parents:
diff changeset
1970 if (expr->ts.u.cl == NULL)
kono
parents:
diff changeset
1971 {
kono
parents:
diff changeset
1972 for (p = gfc_constructor_first (expr->value.constructor);
kono
parents:
diff changeset
1973 p; p = gfc_constructor_next (p))
kono
parents:
diff changeset
1974 if (p->expr->ts.u.cl != NULL)
kono
parents:
diff changeset
1975 {
kono
parents:
diff changeset
1976 /* Ensure that if there is a char_len around that it is
kono
parents:
diff changeset
1977 used; otherwise the middle-end confuses them! */
kono
parents:
diff changeset
1978 expr->ts.u.cl = p->expr->ts.u.cl;
kono
parents:
diff changeset
1979 goto got_charlen;
kono
parents:
diff changeset
1980 }
kono
parents:
diff changeset
1981
kono
parents:
diff changeset
1982 expr->ts.u.cl = gfc_new_charlen (gfc_current_ns, NULL);
kono
parents:
diff changeset
1983 }
kono
parents:
diff changeset
1984
kono
parents:
diff changeset
1985 got_charlen:
kono
parents:
diff changeset
1986
kono
parents:
diff changeset
1987 found_length = -1;
kono
parents:
diff changeset
1988
kono
parents:
diff changeset
1989 if (expr->ts.u.cl->length == NULL)
kono
parents:
diff changeset
1990 {
kono
parents:
diff changeset
1991 /* Check that all constant string elements have the same length until
kono
parents:
diff changeset
1992 we reach the end or find a variable-length one. */
kono
parents:
diff changeset
1993
kono
parents:
diff changeset
1994 for (p = gfc_constructor_first (expr->value.constructor);
kono
parents:
diff changeset
1995 p; p = gfc_constructor_next (p))
kono
parents:
diff changeset
1996 {
kono
parents:
diff changeset
1997 int current_length = -1;
kono
parents:
diff changeset
1998 gfc_ref *ref;
kono
parents:
diff changeset
1999 for (ref = p->expr->ref; ref; ref = ref->next)
kono
parents:
diff changeset
2000 if (ref->type == REF_SUBSTRING
kono
parents:
diff changeset
2001 && ref->u.ss.start->expr_type == EXPR_CONSTANT
kono
parents:
diff changeset
2002 && ref->u.ss.end->expr_type == EXPR_CONSTANT)
kono
parents:
diff changeset
2003 break;
kono
parents:
diff changeset
2004
kono
parents:
diff changeset
2005 if (p->expr->expr_type == EXPR_CONSTANT)
kono
parents:
diff changeset
2006 current_length = p->expr->value.character.length;
kono
parents:
diff changeset
2007 else if (ref)
kono
parents:
diff changeset
2008 {
kono
parents:
diff changeset
2009 long j;
kono
parents:
diff changeset
2010 j = mpz_get_ui (ref->u.ss.end->value.integer)
kono
parents:
diff changeset
2011 - mpz_get_ui (ref->u.ss.start->value.integer) + 1;
kono
parents:
diff changeset
2012 current_length = (int) j;
kono
parents:
diff changeset
2013 }
kono
parents:
diff changeset
2014 else if (p->expr->ts.u.cl && p->expr->ts.u.cl->length
kono
parents:
diff changeset
2015 && p->expr->ts.u.cl->length->expr_type == EXPR_CONSTANT)
kono
parents:
diff changeset
2016 {
kono
parents:
diff changeset
2017 long j;
kono
parents:
diff changeset
2018 j = mpz_get_si (p->expr->ts.u.cl->length->value.integer);
kono
parents:
diff changeset
2019 current_length = (int) j;
kono
parents:
diff changeset
2020 }
kono
parents:
diff changeset
2021 else
kono
parents:
diff changeset
2022 return true;
kono
parents:
diff changeset
2023
kono
parents:
diff changeset
2024 gcc_assert (current_length != -1);
kono
parents:
diff changeset
2025
kono
parents:
diff changeset
2026 if (found_length == -1)
kono
parents:
diff changeset
2027 found_length = current_length;
kono
parents:
diff changeset
2028 else if (found_length != current_length)
kono
parents:
diff changeset
2029 {
kono
parents:
diff changeset
2030 gfc_error ("Different CHARACTER lengths (%d/%d) in array"
kono
parents:
diff changeset
2031 " constructor at %L", found_length, current_length,
kono
parents:
diff changeset
2032 &p->expr->where);
kono
parents:
diff changeset
2033 return false;
kono
parents:
diff changeset
2034 }
kono
parents:
diff changeset
2035
kono
parents:
diff changeset
2036 gcc_assert (found_length == current_length);
kono
parents:
diff changeset
2037 }
kono
parents:
diff changeset
2038
kono
parents:
diff changeset
2039 gcc_assert (found_length != -1);
kono
parents:
diff changeset
2040
kono
parents:
diff changeset
2041 /* Update the character length of the array constructor. */
kono
parents:
diff changeset
2042 expr->ts.u.cl->length = gfc_get_int_expr (gfc_default_integer_kind,
kono
parents:
diff changeset
2043 NULL, found_length);
kono
parents:
diff changeset
2044 }
kono
parents:
diff changeset
2045 else
kono
parents:
diff changeset
2046 {
kono
parents:
diff changeset
2047 /* We've got a character length specified. It should be an integer,
kono
parents:
diff changeset
2048 otherwise an error is signalled elsewhere. */
kono
parents:
diff changeset
2049 gcc_assert (expr->ts.u.cl->length);
kono
parents:
diff changeset
2050
kono
parents:
diff changeset
2051 /* If we've got a constant character length, pad according to this.
kono
parents:
diff changeset
2052 gfc_extract_int does check for BT_INTEGER and EXPR_CONSTANT and sets
kono
parents:
diff changeset
2053 max_length only if they pass. */
kono
parents:
diff changeset
2054 gfc_extract_int (expr->ts.u.cl->length, &found_length);
kono
parents:
diff changeset
2055
kono
parents:
diff changeset
2056 /* Now pad/truncate the elements accordingly to the specified character
kono
parents:
diff changeset
2057 length. This is ok inside this conditional, as in the case above
kono
parents:
diff changeset
2058 (without typespec) all elements are verified to have the same length
kono
parents:
diff changeset
2059 anyway. */
kono
parents:
diff changeset
2060 if (found_length != -1)
kono
parents:
diff changeset
2061 for (p = gfc_constructor_first (expr->value.constructor);
kono
parents:
diff changeset
2062 p; p = gfc_constructor_next (p))
kono
parents:
diff changeset
2063 if (p->expr->expr_type == EXPR_CONSTANT)
kono
parents:
diff changeset
2064 {
kono
parents:
diff changeset
2065 gfc_expr *cl = NULL;
kono
parents:
diff changeset
2066 int current_length = -1;
kono
parents:
diff changeset
2067 bool has_ts;
kono
parents:
diff changeset
2068
kono
parents:
diff changeset
2069 if (p->expr->ts.u.cl && p->expr->ts.u.cl->length)
kono
parents:
diff changeset
2070 {
kono
parents:
diff changeset
2071 cl = p->expr->ts.u.cl->length;
kono
parents:
diff changeset
2072 gfc_extract_int (cl, &current_length);
kono
parents:
diff changeset
2073 }
kono
parents:
diff changeset
2074
kono
parents:
diff changeset
2075 /* If gfc_extract_int above set current_length, we implicitly
kono
parents:
diff changeset
2076 know the type is BT_INTEGER and it's EXPR_CONSTANT. */
kono
parents:
diff changeset
2077
kono
parents:
diff changeset
2078 has_ts = expr->ts.u.cl->length_from_typespec;
kono
parents:
diff changeset
2079
kono
parents:
diff changeset
2080 if (! cl
kono
parents:
diff changeset
2081 || (current_length != -1 && current_length != found_length))
kono
parents:
diff changeset
2082 gfc_set_constant_character_len (found_length, p->expr,
kono
parents:
diff changeset
2083 has_ts ? -1 : found_length);
kono
parents:
diff changeset
2084 }
kono
parents:
diff changeset
2085 }
kono
parents:
diff changeset
2086
kono
parents:
diff changeset
2087 return true;
kono
parents:
diff changeset
2088 }
kono
parents:
diff changeset
2089
kono
parents:
diff changeset
2090
kono
parents:
diff changeset
2091 /* Resolve all of the expressions in an array list. */
kono
parents:
diff changeset
2092
kono
parents:
diff changeset
2093 bool
kono
parents:
diff changeset
2094 gfc_resolve_array_constructor (gfc_expr *expr)
kono
parents:
diff changeset
2095 {
kono
parents:
diff changeset
2096 bool t;
kono
parents:
diff changeset
2097
kono
parents:
diff changeset
2098 t = resolve_array_list (expr->value.constructor);
kono
parents:
diff changeset
2099 if (t)
kono
parents:
diff changeset
2100 t = gfc_check_constructor_type (expr);
kono
parents:
diff changeset
2101
kono
parents:
diff changeset
2102 /* gfc_resolve_character_array_constructor is called in gfc_resolve_expr after
kono
parents:
diff changeset
2103 the call to this function, so we don't need to call it here; if it was
kono
parents:
diff changeset
2104 called twice, an error message there would be duplicated. */
kono
parents:
diff changeset
2105
kono
parents:
diff changeset
2106 return t;
kono
parents:
diff changeset
2107 }
kono
parents:
diff changeset
2108
kono
parents:
diff changeset
2109
kono
parents:
diff changeset
2110 /* Copy an iterator structure. */
kono
parents:
diff changeset
2111
kono
parents:
diff changeset
2112 gfc_iterator *
kono
parents:
diff changeset
2113 gfc_copy_iterator (gfc_iterator *src)
kono
parents:
diff changeset
2114 {
kono
parents:
diff changeset
2115 gfc_iterator *dest;
kono
parents:
diff changeset
2116
kono
parents:
diff changeset
2117 if (src == NULL)
kono
parents:
diff changeset
2118 return NULL;
kono
parents:
diff changeset
2119
kono
parents:
diff changeset
2120 dest = gfc_get_iterator ();
kono
parents:
diff changeset
2121
kono
parents:
diff changeset
2122 dest->var = gfc_copy_expr (src->var);
kono
parents:
diff changeset
2123 dest->start = gfc_copy_expr (src->start);
kono
parents:
diff changeset
2124 dest->end = gfc_copy_expr (src->end);
kono
parents:
diff changeset
2125 dest->step = gfc_copy_expr (src->step);
kono
parents:
diff changeset
2126
kono
parents:
diff changeset
2127 return dest;
kono
parents:
diff changeset
2128 }
kono
parents:
diff changeset
2129
kono
parents:
diff changeset
2130
kono
parents:
diff changeset
2131 /********* Subroutines for determining the size of an array *********/
kono
parents:
diff changeset
2132
kono
parents:
diff changeset
2133 /* These are needed just to accommodate RESHAPE(). There are no
kono
parents:
diff changeset
2134 diagnostics here, we just return a negative number if something
kono
parents:
diff changeset
2135 goes wrong. */
kono
parents:
diff changeset
2136
kono
parents:
diff changeset
2137
kono
parents:
diff changeset
2138 /* Get the size of single dimension of an array specification. The
kono
parents:
diff changeset
2139 array is guaranteed to be one dimensional. */
kono
parents:
diff changeset
2140
kono
parents:
diff changeset
2141 bool
kono
parents:
diff changeset
2142 spec_dimen_size (gfc_array_spec *as, int dimen, mpz_t *result)
kono
parents:
diff changeset
2143 {
kono
parents:
diff changeset
2144 if (as == NULL)
kono
parents:
diff changeset
2145 return false;
kono
parents:
diff changeset
2146
kono
parents:
diff changeset
2147 if (dimen < 0 || dimen > as->rank - 1)
kono
parents:
diff changeset
2148 gfc_internal_error ("spec_dimen_size(): Bad dimension");
kono
parents:
diff changeset
2149
kono
parents:
diff changeset
2150 if (as->type != AS_EXPLICIT
kono
parents:
diff changeset
2151 || as->lower[dimen]->expr_type != EXPR_CONSTANT
kono
parents:
diff changeset
2152 || as->upper[dimen]->expr_type != EXPR_CONSTANT
kono
parents:
diff changeset
2153 || as->lower[dimen]->ts.type != BT_INTEGER
kono
parents:
diff changeset
2154 || as->upper[dimen]->ts.type != BT_INTEGER)
kono
parents:
diff changeset
2155 return false;
kono
parents:
diff changeset
2156
kono
parents:
diff changeset
2157 mpz_init (*result);
kono
parents:
diff changeset
2158
kono
parents:
diff changeset
2159 mpz_sub (*result, as->upper[dimen]->value.integer,
kono
parents:
diff changeset
2160 as->lower[dimen]->value.integer);
kono
parents:
diff changeset
2161
kono
parents:
diff changeset
2162 mpz_add_ui (*result, *result, 1);
kono
parents:
diff changeset
2163
kono
parents:
diff changeset
2164 return true;
kono
parents:
diff changeset
2165 }
kono
parents:
diff changeset
2166
kono
parents:
diff changeset
2167
kono
parents:
diff changeset
2168 bool
kono
parents:
diff changeset
2169 spec_size (gfc_array_spec *as, mpz_t *result)
kono
parents:
diff changeset
2170 {
kono
parents:
diff changeset
2171 mpz_t size;
kono
parents:
diff changeset
2172 int d;
kono
parents:
diff changeset
2173
kono
parents:
diff changeset
2174 if (!as || as->type == AS_ASSUMED_RANK)
kono
parents:
diff changeset
2175 return false;
kono
parents:
diff changeset
2176
kono
parents:
diff changeset
2177 mpz_init_set_ui (*result, 1);
kono
parents:
diff changeset
2178
kono
parents:
diff changeset
2179 for (d = 0; d < as->rank; d++)
kono
parents:
diff changeset
2180 {
kono
parents:
diff changeset
2181 if (!spec_dimen_size (as, d, &size))
kono
parents:
diff changeset
2182 {
kono
parents:
diff changeset
2183 mpz_clear (*result);
kono
parents:
diff changeset
2184 return false;
kono
parents:
diff changeset
2185 }
kono
parents:
diff changeset
2186
kono
parents:
diff changeset
2187 mpz_mul (*result, *result, size);
kono
parents:
diff changeset
2188 mpz_clear (size);
kono
parents:
diff changeset
2189 }
kono
parents:
diff changeset
2190
kono
parents:
diff changeset
2191 return true;
kono
parents:
diff changeset
2192 }
kono
parents:
diff changeset
2193
kono
parents:
diff changeset
2194
kono
parents:
diff changeset
2195 /* Get the number of elements in an array section. Optionally, also supply
kono
parents:
diff changeset
2196 the end value. */
kono
parents:
diff changeset
2197
kono
parents:
diff changeset
2198 bool
kono
parents:
diff changeset
2199 gfc_ref_dimen_size (gfc_array_ref *ar, int dimen, mpz_t *result, mpz_t *end)
kono
parents:
diff changeset
2200 {
kono
parents:
diff changeset
2201 mpz_t upper, lower, stride;
kono
parents:
diff changeset
2202 mpz_t diff;
kono
parents:
diff changeset
2203 bool t;
kono
parents:
diff changeset
2204 gfc_expr *stride_expr = NULL;
kono
parents:
diff changeset
2205
kono
parents:
diff changeset
2206 if (dimen < 0 || ar == NULL)
kono
parents:
diff changeset
2207 gfc_internal_error ("gfc_ref_dimen_size(): Bad dimension");
kono
parents:
diff changeset
2208
kono
parents:
diff changeset
2209 if (dimen > ar->dimen - 1)
kono
parents:
diff changeset
2210 {
kono
parents:
diff changeset
2211 gfc_error ("Bad array dimension at %L", &ar->c_where[dimen]);
kono
parents:
diff changeset
2212 return false;
kono
parents:
diff changeset
2213 }
kono
parents:
diff changeset
2214
kono
parents:
diff changeset
2215 switch (ar->dimen_type[dimen])
kono
parents:
diff changeset
2216 {
kono
parents:
diff changeset
2217 case DIMEN_ELEMENT:
kono
parents:
diff changeset
2218 mpz_init (*result);
kono
parents:
diff changeset
2219 mpz_set_ui (*result, 1);
kono
parents:
diff changeset
2220 t = true;
kono
parents:
diff changeset
2221 break;
kono
parents:
diff changeset
2222
kono
parents:
diff changeset
2223 case DIMEN_VECTOR:
kono
parents:
diff changeset
2224 t = gfc_array_size (ar->start[dimen], result); /* Recurse! */
kono
parents:
diff changeset
2225 break;
kono
parents:
diff changeset
2226
kono
parents:
diff changeset
2227 case DIMEN_RANGE:
kono
parents:
diff changeset
2228
kono
parents:
diff changeset
2229 mpz_init (stride);
kono
parents:
diff changeset
2230
kono
parents:
diff changeset
2231 if (ar->stride[dimen] == NULL)
kono
parents:
diff changeset
2232 mpz_set_ui (stride, 1);
kono
parents:
diff changeset
2233 else
kono
parents:
diff changeset
2234 {
kono
parents:
diff changeset
2235 stride_expr = gfc_copy_expr(ar->stride[dimen]);
kono
parents:
diff changeset
2236 if(!gfc_simplify_expr(stride_expr, 1))
kono
parents:
diff changeset
2237 gfc_internal_error("Simplification error");
kono
parents:
diff changeset
2238 if (stride_expr->expr_type != EXPR_CONSTANT)
kono
parents:
diff changeset
2239 {
kono
parents:
diff changeset
2240 mpz_clear (stride);
kono
parents:
diff changeset
2241 return false;
kono
parents:
diff changeset
2242 }
kono
parents:
diff changeset
2243 mpz_set (stride, stride_expr->value.integer);
kono
parents:
diff changeset
2244 gfc_free_expr(stride_expr);
kono
parents:
diff changeset
2245 }
kono
parents:
diff changeset
2246
kono
parents:
diff changeset
2247 /* Calculate the number of elements via gfc_dep_differce, but only if
kono
parents:
diff changeset
2248 start and end are both supplied in the reference or the array spec.
kono
parents:
diff changeset
2249 This is to guard against strange but valid code like
kono
parents:
diff changeset
2250
kono
parents:
diff changeset
2251 subroutine foo(a,n)
kono
parents:
diff changeset
2252 real a(1:n)
kono
parents:
diff changeset
2253 n = 3
kono
parents:
diff changeset
2254 print *,size(a(n-1:))
kono
parents:
diff changeset
2255
kono
parents:
diff changeset
2256 where the user changes the value of a variable. If we have to
kono
parents:
diff changeset
2257 determine end as well, we cannot do this using gfc_dep_difference.
kono
parents:
diff changeset
2258 Fall back to the constants-only code then. */
kono
parents:
diff changeset
2259
kono
parents:
diff changeset
2260 if (end == NULL)
kono
parents:
diff changeset
2261 {
kono
parents:
diff changeset
2262 bool use_dep;
kono
parents:
diff changeset
2263
kono
parents:
diff changeset
2264 use_dep = gfc_dep_difference (ar->end[dimen], ar->start[dimen],
kono
parents:
diff changeset
2265 &diff);
kono
parents:
diff changeset
2266 if (!use_dep && ar->end[dimen] == NULL && ar->start[dimen] == NULL)
kono
parents:
diff changeset
2267 use_dep = gfc_dep_difference (ar->as->upper[dimen],
kono
parents:
diff changeset
2268 ar->as->lower[dimen], &diff);
kono
parents:
diff changeset
2269
kono
parents:
diff changeset
2270 if (use_dep)
kono
parents:
diff changeset
2271 {
kono
parents:
diff changeset
2272 mpz_init (*result);
kono
parents:
diff changeset
2273 mpz_add (*result, diff, stride);
kono
parents:
diff changeset
2274 mpz_div (*result, *result, stride);
kono
parents:
diff changeset
2275 if (mpz_cmp_ui (*result, 0) < 0)
kono
parents:
diff changeset
2276 mpz_set_ui (*result, 0);
kono
parents:
diff changeset
2277
kono
parents:
diff changeset
2278 mpz_clear (stride);
kono
parents:
diff changeset
2279 mpz_clear (diff);
kono
parents:
diff changeset
2280 return true;
kono
parents:
diff changeset
2281 }
kono
parents:
diff changeset
2282
kono
parents:
diff changeset
2283 }
kono
parents:
diff changeset
2284
kono
parents:
diff changeset
2285 /* Constant-only code here, which covers more cases
kono
parents:
diff changeset
2286 like a(:4) etc. */
kono
parents:
diff changeset
2287 mpz_init (upper);
kono
parents:
diff changeset
2288 mpz_init (lower);
kono
parents:
diff changeset
2289 t = false;
kono
parents:
diff changeset
2290
kono
parents:
diff changeset
2291 if (ar->start[dimen] == NULL)
kono
parents:
diff changeset
2292 {
kono
parents:
diff changeset
2293 if (ar->as->lower[dimen] == NULL
kono
parents:
diff changeset
2294 || ar->as->lower[dimen]->expr_type != EXPR_CONSTANT
kono
parents:
diff changeset
2295 || ar->as->lower[dimen]->ts.type != BT_INTEGER)
kono
parents:
diff changeset
2296 goto cleanup;
kono
parents:
diff changeset
2297 mpz_set (lower, ar->as->lower[dimen]->value.integer);
kono
parents:
diff changeset
2298 }
kono
parents:
diff changeset
2299 else
kono
parents:
diff changeset
2300 {
kono
parents:
diff changeset
2301 if (ar->start[dimen]->expr_type != EXPR_CONSTANT)
kono
parents:
diff changeset
2302 goto cleanup;
kono
parents:
diff changeset
2303 mpz_set (lower, ar->start[dimen]->value.integer);
kono
parents:
diff changeset
2304 }
kono
parents:
diff changeset
2305
kono
parents:
diff changeset
2306 if (ar->end[dimen] == NULL)
kono
parents:
diff changeset
2307 {
kono
parents:
diff changeset
2308 if (ar->as->upper[dimen] == NULL
kono
parents:
diff changeset
2309 || ar->as->upper[dimen]->expr_type != EXPR_CONSTANT
kono
parents:
diff changeset
2310 || ar->as->upper[dimen]->ts.type != BT_INTEGER)
kono
parents:
diff changeset
2311 goto cleanup;
kono
parents:
diff changeset
2312 mpz_set (upper, ar->as->upper[dimen]->value.integer);
kono
parents:
diff changeset
2313 }
kono
parents:
diff changeset
2314 else
kono
parents:
diff changeset
2315 {
kono
parents:
diff changeset
2316 if (ar->end[dimen]->expr_type != EXPR_CONSTANT)
kono
parents:
diff changeset
2317 goto cleanup;
kono
parents:
diff changeset
2318 mpz_set (upper, ar->end[dimen]->value.integer);
kono
parents:
diff changeset
2319 }
kono
parents:
diff changeset
2320
kono
parents:
diff changeset
2321 mpz_init (*result);
kono
parents:
diff changeset
2322 mpz_sub (*result, upper, lower);
kono
parents:
diff changeset
2323 mpz_add (*result, *result, stride);
kono
parents:
diff changeset
2324 mpz_div (*result, *result, stride);
kono
parents:
diff changeset
2325
kono
parents:
diff changeset
2326 /* Zero stride caught earlier. */
kono
parents:
diff changeset
2327 if (mpz_cmp_ui (*result, 0) < 0)
kono
parents:
diff changeset
2328 mpz_set_ui (*result, 0);
kono
parents:
diff changeset
2329 t = true;
kono
parents:
diff changeset
2330
kono
parents:
diff changeset
2331 if (end)
kono
parents:
diff changeset
2332 {
kono
parents:
diff changeset
2333 mpz_init (*end);
kono
parents:
diff changeset
2334
kono
parents:
diff changeset
2335 mpz_sub_ui (*end, *result, 1UL);
kono
parents:
diff changeset
2336 mpz_mul (*end, *end, stride);
kono
parents:
diff changeset
2337 mpz_add (*end, *end, lower);
kono
parents:
diff changeset
2338 }
kono
parents:
diff changeset
2339
kono
parents:
diff changeset
2340 cleanup:
kono
parents:
diff changeset
2341 mpz_clear (upper);
kono
parents:
diff changeset
2342 mpz_clear (lower);
kono
parents:
diff changeset
2343 mpz_clear (stride);
kono
parents:
diff changeset
2344 return t;
kono
parents:
diff changeset
2345
kono
parents:
diff changeset
2346 default:
kono
parents:
diff changeset
2347 gfc_internal_error ("gfc_ref_dimen_size(): Bad dimen_type");
kono
parents:
diff changeset
2348 }
kono
parents:
diff changeset
2349
kono
parents:
diff changeset
2350 return t;
kono
parents:
diff changeset
2351 }
kono
parents:
diff changeset
2352
kono
parents:
diff changeset
2353
kono
parents:
diff changeset
2354 static bool
kono
parents:
diff changeset
2355 ref_size (gfc_array_ref *ar, mpz_t *result)
kono
parents:
diff changeset
2356 {
kono
parents:
diff changeset
2357 mpz_t size;
kono
parents:
diff changeset
2358 int d;
kono
parents:
diff changeset
2359
kono
parents:
diff changeset
2360 mpz_init_set_ui (*result, 1);
kono
parents:
diff changeset
2361
kono
parents:
diff changeset
2362 for (d = 0; d < ar->dimen; d++)
kono
parents:
diff changeset
2363 {
kono
parents:
diff changeset
2364 if (!gfc_ref_dimen_size (ar, d, &size, NULL))
kono
parents:
diff changeset
2365 {
kono
parents:
diff changeset
2366 mpz_clear (*result);
kono
parents:
diff changeset
2367 return false;
kono
parents:
diff changeset
2368 }
kono
parents:
diff changeset
2369
kono
parents:
diff changeset
2370 mpz_mul (*result, *result, size);
kono
parents:
diff changeset
2371 mpz_clear (size);
kono
parents:
diff changeset
2372 }
kono
parents:
diff changeset
2373
kono
parents:
diff changeset
2374 return true;
kono
parents:
diff changeset
2375 }
kono
parents:
diff changeset
2376
kono
parents:
diff changeset
2377
kono
parents:
diff changeset
2378 /* Given an array expression and a dimension, figure out how many
kono
parents:
diff changeset
2379 elements it has along that dimension. Returns true if we were
kono
parents:
diff changeset
2380 able to return a result in the 'result' variable, false
kono
parents:
diff changeset
2381 otherwise. */
kono
parents:
diff changeset
2382
kono
parents:
diff changeset
2383 bool
kono
parents:
diff changeset
2384 gfc_array_dimen_size (gfc_expr *array, int dimen, mpz_t *result)
kono
parents:
diff changeset
2385 {
kono
parents:
diff changeset
2386 gfc_ref *ref;
kono
parents:
diff changeset
2387 int i;
kono
parents:
diff changeset
2388
kono
parents:
diff changeset
2389 gcc_assert (array != NULL);
kono
parents:
diff changeset
2390
kono
parents:
diff changeset
2391 if (array->ts.type == BT_CLASS)
kono
parents:
diff changeset
2392 return false;
kono
parents:
diff changeset
2393
kono
parents:
diff changeset
2394 if (array->rank == -1)
kono
parents:
diff changeset
2395 return false;
kono
parents:
diff changeset
2396
kono
parents:
diff changeset
2397 if (dimen < 0 || dimen > array->rank - 1)
kono
parents:
diff changeset
2398 gfc_internal_error ("gfc_array_dimen_size(): Bad dimension");
kono
parents:
diff changeset
2399
kono
parents:
diff changeset
2400 switch (array->expr_type)
kono
parents:
diff changeset
2401 {
kono
parents:
diff changeset
2402 case EXPR_VARIABLE:
kono
parents:
diff changeset
2403 case EXPR_FUNCTION:
kono
parents:
diff changeset
2404 for (ref = array->ref; ref; ref = ref->next)
kono
parents:
diff changeset
2405 {
kono
parents:
diff changeset
2406 if (ref->type != REF_ARRAY)
kono
parents:
diff changeset
2407 continue;
kono
parents:
diff changeset
2408
kono
parents:
diff changeset
2409 if (ref->u.ar.type == AR_FULL)
kono
parents:
diff changeset
2410 return spec_dimen_size (ref->u.ar.as, dimen, result);
kono
parents:
diff changeset
2411
kono
parents:
diff changeset
2412 if (ref->u.ar.type == AR_SECTION)
kono
parents:
diff changeset
2413 {
kono
parents:
diff changeset
2414 for (i = 0; dimen >= 0; i++)
kono
parents:
diff changeset
2415 if (ref->u.ar.dimen_type[i] != DIMEN_ELEMENT)
kono
parents:
diff changeset
2416 dimen--;
kono
parents:
diff changeset
2417
kono
parents:
diff changeset
2418 return gfc_ref_dimen_size (&ref->u.ar, i - 1, result, NULL);
kono
parents:
diff changeset
2419 }
kono
parents:
diff changeset
2420 }
kono
parents:
diff changeset
2421
kono
parents:
diff changeset
2422 if (array->shape && array->shape[dimen])
kono
parents:
diff changeset
2423 {
kono
parents:
diff changeset
2424 mpz_init_set (*result, array->shape[dimen]);
kono
parents:
diff changeset
2425 return true;
kono
parents:
diff changeset
2426 }
kono
parents:
diff changeset
2427
kono
parents:
diff changeset
2428 if (array->symtree->n.sym->attr.generic
kono
parents:
diff changeset
2429 && array->value.function.esym != NULL)
kono
parents:
diff changeset
2430 {
kono
parents:
diff changeset
2431 if (!spec_dimen_size (array->value.function.esym->as, dimen, result))
kono
parents:
diff changeset
2432 return false;
kono
parents:
diff changeset
2433 }
kono
parents:
diff changeset
2434 else if (!spec_dimen_size (array->symtree->n.sym->as, dimen, result))
kono
parents:
diff changeset
2435 return false;
kono
parents:
diff changeset
2436
kono
parents:
diff changeset
2437 break;
kono
parents:
diff changeset
2438
kono
parents:
diff changeset
2439 case EXPR_ARRAY:
kono
parents:
diff changeset
2440 if (array->shape == NULL) {
kono
parents:
diff changeset
2441 /* Expressions with rank > 1 should have "shape" properly set */
kono
parents:
diff changeset
2442 if ( array->rank != 1 )
kono
parents:
diff changeset
2443 gfc_internal_error ("gfc_array_dimen_size(): Bad EXPR_ARRAY expr");
kono
parents:
diff changeset
2444 return gfc_array_size(array, result);
kono
parents:
diff changeset
2445 }
kono
parents:
diff changeset
2446
kono
parents:
diff changeset
2447 /* Fall through */
kono
parents:
diff changeset
2448 default:
kono
parents:
diff changeset
2449 if (array->shape == NULL)
kono
parents:
diff changeset
2450 return false;
kono
parents:
diff changeset
2451
kono
parents:
diff changeset
2452 mpz_init_set (*result, array->shape[dimen]);
kono
parents:
diff changeset
2453
kono
parents:
diff changeset
2454 break;
kono
parents:
diff changeset
2455 }
kono
parents:
diff changeset
2456
kono
parents:
diff changeset
2457 return true;
kono
parents:
diff changeset
2458 }
kono
parents:
diff changeset
2459
kono
parents:
diff changeset
2460
kono
parents:
diff changeset
2461 /* Given an array expression, figure out how many elements are in the
kono
parents:
diff changeset
2462 array. Returns true if this is possible, and sets the 'result'
kono
parents:
diff changeset
2463 variable. Otherwise returns false. */
kono
parents:
diff changeset
2464
kono
parents:
diff changeset
2465 bool
kono
parents:
diff changeset
2466 gfc_array_size (gfc_expr *array, mpz_t *result)
kono
parents:
diff changeset
2467 {
kono
parents:
diff changeset
2468 expand_info expand_save;
kono
parents:
diff changeset
2469 gfc_ref *ref;
kono
parents:
diff changeset
2470 int i;
kono
parents:
diff changeset
2471 bool t;
kono
parents:
diff changeset
2472
kono
parents:
diff changeset
2473 if (array->ts.type == BT_CLASS)
kono
parents:
diff changeset
2474 return false;
kono
parents:
diff changeset
2475
kono
parents:
diff changeset
2476 switch (array->expr_type)
kono
parents:
diff changeset
2477 {
kono
parents:
diff changeset
2478 case EXPR_ARRAY:
kono
parents:
diff changeset
2479 gfc_push_suppress_errors ();
kono
parents:
diff changeset
2480
kono
parents:
diff changeset
2481 expand_save = current_expand;
kono
parents:
diff changeset
2482
kono
parents:
diff changeset
2483 current_expand.count = result;
kono
parents:
diff changeset
2484 mpz_init_set_ui (*result, 0);
kono
parents:
diff changeset
2485
kono
parents:
diff changeset
2486 current_expand.expand_work_function = count_elements;
kono
parents:
diff changeset
2487 iter_stack = NULL;
kono
parents:
diff changeset
2488
kono
parents:
diff changeset
2489 t = expand_constructor (array->value.constructor);
kono
parents:
diff changeset
2490
kono
parents:
diff changeset
2491 gfc_pop_suppress_errors ();
kono
parents:
diff changeset
2492
kono
parents:
diff changeset
2493 if (!t)
kono
parents:
diff changeset
2494 mpz_clear (*result);
kono
parents:
diff changeset
2495 current_expand = expand_save;
kono
parents:
diff changeset
2496 return t;
kono
parents:
diff changeset
2497
kono
parents:
diff changeset
2498 case EXPR_VARIABLE:
kono
parents:
diff changeset
2499 for (ref = array->ref; ref; ref = ref->next)
kono
parents:
diff changeset
2500 {
kono
parents:
diff changeset
2501 if (ref->type != REF_ARRAY)
kono
parents:
diff changeset
2502 continue;
kono
parents:
diff changeset
2503
kono
parents:
diff changeset
2504 if (ref->u.ar.type == AR_FULL)
kono
parents:
diff changeset
2505 return spec_size (ref->u.ar.as, result);
kono
parents:
diff changeset
2506
kono
parents:
diff changeset
2507 if (ref->u.ar.type == AR_SECTION)
kono
parents:
diff changeset
2508 return ref_size (&ref->u.ar, result);
kono
parents:
diff changeset
2509 }
kono
parents:
diff changeset
2510
kono
parents:
diff changeset
2511 return spec_size (array->symtree->n.sym->as, result);
kono
parents:
diff changeset
2512
kono
parents:
diff changeset
2513
kono
parents:
diff changeset
2514 default:
kono
parents:
diff changeset
2515 if (array->rank == 0 || array->shape == NULL)
kono
parents:
diff changeset
2516 return false;
kono
parents:
diff changeset
2517
kono
parents:
diff changeset
2518 mpz_init_set_ui (*result, 1);
kono
parents:
diff changeset
2519
kono
parents:
diff changeset
2520 for (i = 0; i < array->rank; i++)
kono
parents:
diff changeset
2521 mpz_mul (*result, *result, array->shape[i]);
kono
parents:
diff changeset
2522
kono
parents:
diff changeset
2523 break;
kono
parents:
diff changeset
2524 }
kono
parents:
diff changeset
2525
kono
parents:
diff changeset
2526 return true;
kono
parents:
diff changeset
2527 }
kono
parents:
diff changeset
2528
kono
parents:
diff changeset
2529
kono
parents:
diff changeset
2530 /* Given an array reference, return the shape of the reference in an
kono
parents:
diff changeset
2531 array of mpz_t integers. */
kono
parents:
diff changeset
2532
kono
parents:
diff changeset
2533 bool
kono
parents:
diff changeset
2534 gfc_array_ref_shape (gfc_array_ref *ar, mpz_t *shape)
kono
parents:
diff changeset
2535 {
kono
parents:
diff changeset
2536 int d;
kono
parents:
diff changeset
2537 int i;
kono
parents:
diff changeset
2538
kono
parents:
diff changeset
2539 d = 0;
kono
parents:
diff changeset
2540
kono
parents:
diff changeset
2541 switch (ar->type)
kono
parents:
diff changeset
2542 {
kono
parents:
diff changeset
2543 case AR_FULL:
kono
parents:
diff changeset
2544 for (; d < ar->as->rank; d++)
kono
parents:
diff changeset
2545 if (!spec_dimen_size (ar->as, d, &shape[d]))
kono
parents:
diff changeset
2546 goto cleanup;
kono
parents:
diff changeset
2547
kono
parents:
diff changeset
2548 return true;
kono
parents:
diff changeset
2549
kono
parents:
diff changeset
2550 case AR_SECTION:
kono
parents:
diff changeset
2551 for (i = 0; i < ar->dimen; i++)
kono
parents:
diff changeset
2552 {
kono
parents:
diff changeset
2553 if (ar->dimen_type[i] != DIMEN_ELEMENT)
kono
parents:
diff changeset
2554 {
kono
parents:
diff changeset
2555 if (!gfc_ref_dimen_size (ar, i, &shape[d], NULL))
kono
parents:
diff changeset
2556 goto cleanup;
kono
parents:
diff changeset
2557 d++;
kono
parents:
diff changeset
2558 }
kono
parents:
diff changeset
2559 }
kono
parents:
diff changeset
2560
kono
parents:
diff changeset
2561 return true;
kono
parents:
diff changeset
2562
kono
parents:
diff changeset
2563 default:
kono
parents:
diff changeset
2564 break;
kono
parents:
diff changeset
2565 }
kono
parents:
diff changeset
2566
kono
parents:
diff changeset
2567 cleanup:
kono
parents:
diff changeset
2568 gfc_clear_shape (shape, d);
kono
parents:
diff changeset
2569 return false;
kono
parents:
diff changeset
2570 }
kono
parents:
diff changeset
2571
kono
parents:
diff changeset
2572
kono
parents:
diff changeset
2573 /* Given an array expression, find the array reference structure that
kono
parents:
diff changeset
2574 characterizes the reference. */
kono
parents:
diff changeset
2575
kono
parents:
diff changeset
2576 gfc_array_ref *
kono
parents:
diff changeset
2577 gfc_find_array_ref (gfc_expr *e, bool allow_null)
kono
parents:
diff changeset
2578 {
kono
parents:
diff changeset
2579 gfc_ref *ref;
kono
parents:
diff changeset
2580
kono
parents:
diff changeset
2581 for (ref = e->ref; ref; ref = ref->next)
kono
parents:
diff changeset
2582 if (ref->type == REF_ARRAY
kono
parents:
diff changeset
2583 && (ref->u.ar.type == AR_FULL || ref->u.ar.type == AR_SECTION))
kono
parents:
diff changeset
2584 break;
kono
parents:
diff changeset
2585
kono
parents:
diff changeset
2586 if (ref == NULL)
kono
parents:
diff changeset
2587 {
kono
parents:
diff changeset
2588 if (allow_null)
kono
parents:
diff changeset
2589 return NULL;
kono
parents:
diff changeset
2590 else
kono
parents:
diff changeset
2591 gfc_internal_error ("gfc_find_array_ref(): No ref found");
kono
parents:
diff changeset
2592 }
kono
parents:
diff changeset
2593
kono
parents:
diff changeset
2594 return &ref->u.ar;
kono
parents:
diff changeset
2595 }
kono
parents:
diff changeset
2596
kono
parents:
diff changeset
2597
kono
parents:
diff changeset
2598 /* Find out if an array shape is known at compile time. */
kono
parents:
diff changeset
2599
kono
parents:
diff changeset
2600 bool
kono
parents:
diff changeset
2601 gfc_is_compile_time_shape (gfc_array_spec *as)
kono
parents:
diff changeset
2602 {
kono
parents:
diff changeset
2603 if (as->type != AS_EXPLICIT)
kono
parents:
diff changeset
2604 return false;
kono
parents:
diff changeset
2605
kono
parents:
diff changeset
2606 for (int i = 0; i < as->rank; i++)
kono
parents:
diff changeset
2607 if (!gfc_is_constant_expr (as->lower[i])
kono
parents:
diff changeset
2608 || !gfc_is_constant_expr (as->upper[i]))
kono
parents:
diff changeset
2609 return false;
kono
parents:
diff changeset
2610
kono
parents:
diff changeset
2611 return true;
kono
parents:
diff changeset
2612 }