1627f7eb2Smrg /* Array things
2*4c3eb207Smrg Copyright (C) 2000-2020 Free Software Foundation, Inc.
3627f7eb2Smrg Contributed by Andy Vaught
4627f7eb2Smrg
5627f7eb2Smrg This file is part of GCC.
6627f7eb2Smrg
7627f7eb2Smrg GCC is free software; you can redistribute it and/or modify it under
8627f7eb2Smrg the terms of the GNU General Public License as published by the Free
9627f7eb2Smrg Software Foundation; either version 3, or (at your option) any later
10627f7eb2Smrg version.
11627f7eb2Smrg
12627f7eb2Smrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13627f7eb2Smrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
14627f7eb2Smrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15627f7eb2Smrg for more details.
16627f7eb2Smrg
17627f7eb2Smrg You should have received a copy of the GNU General Public License
18627f7eb2Smrg along with GCC; see the file COPYING3. If not see
19627f7eb2Smrg <http://www.gnu.org/licenses/>. */
20627f7eb2Smrg
21627f7eb2Smrg #include "config.h"
22627f7eb2Smrg #include "system.h"
23627f7eb2Smrg #include "coretypes.h"
24627f7eb2Smrg #include "options.h"
25627f7eb2Smrg #include "gfortran.h"
26*4c3eb207Smrg #include "parse.h"
27627f7eb2Smrg #include "match.h"
28627f7eb2Smrg #include "constructor.h"
29627f7eb2Smrg
30627f7eb2Smrg /**************** Array reference matching subroutines *****************/
31627f7eb2Smrg
32627f7eb2Smrg /* Copy an array reference structure. */
33627f7eb2Smrg
34627f7eb2Smrg gfc_array_ref *
gfc_copy_array_ref(gfc_array_ref * src)35627f7eb2Smrg gfc_copy_array_ref (gfc_array_ref *src)
36627f7eb2Smrg {
37627f7eb2Smrg gfc_array_ref *dest;
38627f7eb2Smrg int i;
39627f7eb2Smrg
40627f7eb2Smrg if (src == NULL)
41627f7eb2Smrg return NULL;
42627f7eb2Smrg
43627f7eb2Smrg dest = gfc_get_array_ref ();
44627f7eb2Smrg
45627f7eb2Smrg *dest = *src;
46627f7eb2Smrg
47627f7eb2Smrg for (i = 0; i < GFC_MAX_DIMENSIONS; i++)
48627f7eb2Smrg {
49627f7eb2Smrg dest->start[i] = gfc_copy_expr (src->start[i]);
50627f7eb2Smrg dest->end[i] = gfc_copy_expr (src->end[i]);
51627f7eb2Smrg dest->stride[i] = gfc_copy_expr (src->stride[i]);
52627f7eb2Smrg }
53627f7eb2Smrg
54627f7eb2Smrg return dest;
55627f7eb2Smrg }
56627f7eb2Smrg
57627f7eb2Smrg
58627f7eb2Smrg /* Match a single dimension of an array reference. This can be a
59627f7eb2Smrg single element or an array section. Any modifications we've made
60627f7eb2Smrg to the ar structure are cleaned up by the caller. If the init
61627f7eb2Smrg is set, we require the subscript to be a valid initialization
62627f7eb2Smrg expression. */
63627f7eb2Smrg
64627f7eb2Smrg static match
match_subscript(gfc_array_ref * ar,int init,bool match_star)65627f7eb2Smrg match_subscript (gfc_array_ref *ar, int init, bool match_star)
66627f7eb2Smrg {
67627f7eb2Smrg match m = MATCH_ERROR;
68627f7eb2Smrg bool star = false;
69627f7eb2Smrg int i;
70*4c3eb207Smrg bool saw_boz = false;
71627f7eb2Smrg
72627f7eb2Smrg i = ar->dimen + ar->codimen;
73627f7eb2Smrg
74627f7eb2Smrg gfc_gobble_whitespace ();
75627f7eb2Smrg ar->c_where[i] = gfc_current_locus;
76627f7eb2Smrg ar->start[i] = ar->end[i] = ar->stride[i] = NULL;
77627f7eb2Smrg
78627f7eb2Smrg /* We can't be sure of the difference between DIMEN_ELEMENT and
79627f7eb2Smrg DIMEN_VECTOR until we know the type of the element itself at
80627f7eb2Smrg resolution time. */
81627f7eb2Smrg
82627f7eb2Smrg ar->dimen_type[i] = DIMEN_UNKNOWN;
83627f7eb2Smrg
84627f7eb2Smrg if (gfc_match_char (':') == MATCH_YES)
85627f7eb2Smrg goto end_element;
86627f7eb2Smrg
87627f7eb2Smrg /* Get start element. */
88627f7eb2Smrg if (match_star && (m = gfc_match_char ('*')) == MATCH_YES)
89627f7eb2Smrg star = true;
90627f7eb2Smrg
91627f7eb2Smrg if (!star && init)
92627f7eb2Smrg m = gfc_match_init_expr (&ar->start[i]);
93627f7eb2Smrg else if (!star)
94627f7eb2Smrg m = gfc_match_expr (&ar->start[i]);
95627f7eb2Smrg
96*4c3eb207Smrg if (ar->start[i] && ar->start[i]->ts.type == BT_BOZ)
97*4c3eb207Smrg {
98*4c3eb207Smrg gfc_error ("Invalid BOZ literal constant used in subscript at %C");
99*4c3eb207Smrg saw_boz = true;
100*4c3eb207Smrg }
101*4c3eb207Smrg
102627f7eb2Smrg if (m == MATCH_NO)
103627f7eb2Smrg gfc_error ("Expected array subscript at %C");
104627f7eb2Smrg if (m != MATCH_YES)
105627f7eb2Smrg return MATCH_ERROR;
106627f7eb2Smrg
107627f7eb2Smrg if (gfc_match_char (':') == MATCH_NO)
108627f7eb2Smrg goto matched;
109627f7eb2Smrg
110627f7eb2Smrg if (star)
111627f7eb2Smrg {
112627f7eb2Smrg gfc_error ("Unexpected %<*%> in coarray subscript at %C");
113627f7eb2Smrg return MATCH_ERROR;
114627f7eb2Smrg }
115627f7eb2Smrg
116627f7eb2Smrg /* Get an optional end element. Because we've seen the colon, we
117627f7eb2Smrg definitely have a range along this dimension. */
118627f7eb2Smrg end_element:
119627f7eb2Smrg ar->dimen_type[i] = DIMEN_RANGE;
120627f7eb2Smrg
121627f7eb2Smrg if (match_star && (m = gfc_match_char ('*')) == MATCH_YES)
122627f7eb2Smrg star = true;
123627f7eb2Smrg else if (init)
124627f7eb2Smrg m = gfc_match_init_expr (&ar->end[i]);
125627f7eb2Smrg else
126627f7eb2Smrg m = gfc_match_expr (&ar->end[i]);
127627f7eb2Smrg
128*4c3eb207Smrg if (ar->end[i] && ar->end[i]->ts.type == BT_BOZ)
129*4c3eb207Smrg {
130*4c3eb207Smrg gfc_error ("Invalid BOZ literal constant used in subscript at %C");
131*4c3eb207Smrg saw_boz = true;
132*4c3eb207Smrg }
133*4c3eb207Smrg
134627f7eb2Smrg if (m == MATCH_ERROR)
135627f7eb2Smrg return MATCH_ERROR;
136627f7eb2Smrg
137627f7eb2Smrg /* See if we have an optional stride. */
138627f7eb2Smrg if (gfc_match_char (':') == MATCH_YES)
139627f7eb2Smrg {
140627f7eb2Smrg if (star)
141627f7eb2Smrg {
142627f7eb2Smrg gfc_error ("Strides not allowed in coarray subscript at %C");
143627f7eb2Smrg return MATCH_ERROR;
144627f7eb2Smrg }
145627f7eb2Smrg
146627f7eb2Smrg m = init ? gfc_match_init_expr (&ar->stride[i])
147627f7eb2Smrg : gfc_match_expr (&ar->stride[i]);
148627f7eb2Smrg
149*4c3eb207Smrg if (ar->stride[i] && ar->stride[i]->ts.type == BT_BOZ)
150*4c3eb207Smrg {
151*4c3eb207Smrg gfc_error ("Invalid BOZ literal constant used in subscript at %C");
152*4c3eb207Smrg saw_boz = true;
153*4c3eb207Smrg }
154*4c3eb207Smrg
155627f7eb2Smrg if (m == MATCH_NO)
156627f7eb2Smrg gfc_error ("Expected array subscript stride at %C");
157627f7eb2Smrg if (m != MATCH_YES)
158627f7eb2Smrg return MATCH_ERROR;
159627f7eb2Smrg }
160627f7eb2Smrg
161627f7eb2Smrg matched:
162627f7eb2Smrg if (star)
163627f7eb2Smrg ar->dimen_type[i] = DIMEN_STAR;
164627f7eb2Smrg
165*4c3eb207Smrg return (saw_boz ? MATCH_ERROR : MATCH_YES);
166627f7eb2Smrg }
167627f7eb2Smrg
168627f7eb2Smrg
169627f7eb2Smrg /* Match an array reference, whether it is the whole array or particular
170627f7eb2Smrg elements or a section. If init is set, the reference has to consist
171627f7eb2Smrg of init expressions. */
172627f7eb2Smrg
173627f7eb2Smrg match
gfc_match_array_ref(gfc_array_ref * ar,gfc_array_spec * as,int init,int corank)174627f7eb2Smrg gfc_match_array_ref (gfc_array_ref *ar, gfc_array_spec *as, int init,
175627f7eb2Smrg int corank)
176627f7eb2Smrg {
177627f7eb2Smrg match m;
178627f7eb2Smrg bool matched_bracket = false;
179627f7eb2Smrg gfc_expr *tmp;
180627f7eb2Smrg bool stat_just_seen = false;
181627f7eb2Smrg bool team_just_seen = false;
182627f7eb2Smrg
183627f7eb2Smrg memset (ar, '\0', sizeof (*ar));
184627f7eb2Smrg
185627f7eb2Smrg ar->where = gfc_current_locus;
186627f7eb2Smrg ar->as = as;
187627f7eb2Smrg ar->type = AR_UNKNOWN;
188627f7eb2Smrg
189627f7eb2Smrg if (gfc_match_char ('[') == MATCH_YES)
190627f7eb2Smrg {
191627f7eb2Smrg matched_bracket = true;
192627f7eb2Smrg goto coarray;
193627f7eb2Smrg }
194627f7eb2Smrg
195627f7eb2Smrg if (gfc_match_char ('(') != MATCH_YES)
196627f7eb2Smrg {
197627f7eb2Smrg ar->type = AR_FULL;
198627f7eb2Smrg ar->dimen = 0;
199627f7eb2Smrg return MATCH_YES;
200627f7eb2Smrg }
201627f7eb2Smrg
202627f7eb2Smrg for (ar->dimen = 0; ar->dimen < GFC_MAX_DIMENSIONS; ar->dimen++)
203627f7eb2Smrg {
204627f7eb2Smrg m = match_subscript (ar, init, false);
205627f7eb2Smrg if (m == MATCH_ERROR)
206627f7eb2Smrg return MATCH_ERROR;
207627f7eb2Smrg
208627f7eb2Smrg if (gfc_match_char (')') == MATCH_YES)
209627f7eb2Smrg {
210627f7eb2Smrg ar->dimen++;
211627f7eb2Smrg goto coarray;
212627f7eb2Smrg }
213627f7eb2Smrg
214627f7eb2Smrg if (gfc_match_char (',') != MATCH_YES)
215627f7eb2Smrg {
216627f7eb2Smrg gfc_error ("Invalid form of array reference at %C");
217627f7eb2Smrg return MATCH_ERROR;
218627f7eb2Smrg }
219627f7eb2Smrg }
220627f7eb2Smrg
221627f7eb2Smrg if (ar->dimen >= 7
222627f7eb2Smrg && !gfc_notify_std (GFC_STD_F2008,
223627f7eb2Smrg "Array reference at %C has more than 7 dimensions"))
224627f7eb2Smrg return MATCH_ERROR;
225627f7eb2Smrg
226627f7eb2Smrg gfc_error ("Array reference at %C cannot have more than %d dimensions",
227627f7eb2Smrg GFC_MAX_DIMENSIONS);
228627f7eb2Smrg return MATCH_ERROR;
229627f7eb2Smrg
230627f7eb2Smrg coarray:
231627f7eb2Smrg if (!matched_bracket && gfc_match_char ('[') != MATCH_YES)
232627f7eb2Smrg {
233627f7eb2Smrg if (ar->dimen > 0)
234627f7eb2Smrg return MATCH_YES;
235627f7eb2Smrg else
236627f7eb2Smrg return MATCH_ERROR;
237627f7eb2Smrg }
238627f7eb2Smrg
239627f7eb2Smrg if (flag_coarray == GFC_FCOARRAY_NONE)
240627f7eb2Smrg {
241627f7eb2Smrg gfc_fatal_error ("Coarrays disabled at %C, use %<-fcoarray=%> to enable");
242627f7eb2Smrg return MATCH_ERROR;
243627f7eb2Smrg }
244627f7eb2Smrg
245627f7eb2Smrg if (corank == 0)
246627f7eb2Smrg {
247627f7eb2Smrg gfc_error ("Unexpected coarray designator at %C");
248627f7eb2Smrg return MATCH_ERROR;
249627f7eb2Smrg }
250627f7eb2Smrg
251627f7eb2Smrg ar->stat = NULL;
252627f7eb2Smrg
253627f7eb2Smrg for (ar->codimen = 0; ar->codimen + ar->dimen < GFC_MAX_DIMENSIONS; ar->codimen++)
254627f7eb2Smrg {
255627f7eb2Smrg m = match_subscript (ar, init, true);
256627f7eb2Smrg if (m == MATCH_ERROR)
257627f7eb2Smrg return MATCH_ERROR;
258627f7eb2Smrg
259627f7eb2Smrg team_just_seen = false;
260627f7eb2Smrg stat_just_seen = false;
261627f7eb2Smrg if (gfc_match (" , team = %e", &tmp) == MATCH_YES && ar->team == NULL)
262627f7eb2Smrg {
263627f7eb2Smrg ar->team = tmp;
264627f7eb2Smrg team_just_seen = true;
265627f7eb2Smrg }
266627f7eb2Smrg
267627f7eb2Smrg if (ar->team && !team_just_seen)
268627f7eb2Smrg {
269627f7eb2Smrg gfc_error ("TEAM= attribute in %C misplaced");
270627f7eb2Smrg return MATCH_ERROR;
271627f7eb2Smrg }
272627f7eb2Smrg
273627f7eb2Smrg if (gfc_match (" , stat = %e",&tmp) == MATCH_YES && ar->stat == NULL)
274627f7eb2Smrg {
275627f7eb2Smrg ar->stat = tmp;
276627f7eb2Smrg stat_just_seen = true;
277627f7eb2Smrg }
278627f7eb2Smrg
279627f7eb2Smrg if (ar->stat && !stat_just_seen)
280627f7eb2Smrg {
281627f7eb2Smrg gfc_error ("STAT= attribute in %C misplaced");
282627f7eb2Smrg return MATCH_ERROR;
283627f7eb2Smrg }
284627f7eb2Smrg
285627f7eb2Smrg if (gfc_match_char (']') == MATCH_YES)
286627f7eb2Smrg {
287627f7eb2Smrg ar->codimen++;
288627f7eb2Smrg if (ar->codimen < corank)
289627f7eb2Smrg {
290627f7eb2Smrg gfc_error ("Too few codimensions at %C, expected %d not %d",
291627f7eb2Smrg corank, ar->codimen);
292627f7eb2Smrg return MATCH_ERROR;
293627f7eb2Smrg }
294627f7eb2Smrg if (ar->codimen > corank)
295627f7eb2Smrg {
296627f7eb2Smrg gfc_error ("Too many codimensions at %C, expected %d not %d",
297627f7eb2Smrg corank, ar->codimen);
298627f7eb2Smrg return MATCH_ERROR;
299627f7eb2Smrg }
300627f7eb2Smrg return MATCH_YES;
301627f7eb2Smrg }
302627f7eb2Smrg
303627f7eb2Smrg if (gfc_match_char (',') != MATCH_YES)
304627f7eb2Smrg {
305627f7eb2Smrg if (gfc_match_char ('*') == MATCH_YES)
306627f7eb2Smrg gfc_error ("Unexpected %<*%> for codimension %d of %d at %C",
307627f7eb2Smrg ar->codimen + 1, corank);
308627f7eb2Smrg else
309627f7eb2Smrg gfc_error ("Invalid form of coarray reference at %C");
310627f7eb2Smrg return MATCH_ERROR;
311627f7eb2Smrg }
312627f7eb2Smrg else if (ar->dimen_type[ar->codimen + ar->dimen] == DIMEN_STAR)
313627f7eb2Smrg {
314627f7eb2Smrg gfc_error ("Unexpected %<*%> for codimension %d of %d at %C",
315627f7eb2Smrg ar->codimen + 1, corank);
316627f7eb2Smrg return MATCH_ERROR;
317627f7eb2Smrg }
318627f7eb2Smrg
319627f7eb2Smrg if (ar->codimen >= corank)
320627f7eb2Smrg {
321627f7eb2Smrg gfc_error ("Invalid codimension %d at %C, only %d codimensions exist",
322627f7eb2Smrg ar->codimen + 1, corank);
323627f7eb2Smrg return MATCH_ERROR;
324627f7eb2Smrg }
325627f7eb2Smrg }
326627f7eb2Smrg
327627f7eb2Smrg gfc_error ("Array reference at %C cannot have more than %d dimensions",
328627f7eb2Smrg GFC_MAX_DIMENSIONS);
329627f7eb2Smrg return MATCH_ERROR;
330627f7eb2Smrg
331627f7eb2Smrg }
332627f7eb2Smrg
333627f7eb2Smrg
334627f7eb2Smrg /************** Array specification matching subroutines ***************/
335627f7eb2Smrg
336627f7eb2Smrg /* Free all of the expressions associated with array bounds
337627f7eb2Smrg specifications. */
338627f7eb2Smrg
339627f7eb2Smrg void
gfc_free_array_spec(gfc_array_spec * as)340627f7eb2Smrg gfc_free_array_spec (gfc_array_spec *as)
341627f7eb2Smrg {
342627f7eb2Smrg int i;
343627f7eb2Smrg
344627f7eb2Smrg if (as == NULL)
345627f7eb2Smrg return;
346627f7eb2Smrg
347627f7eb2Smrg if (as->corank == 0)
348627f7eb2Smrg {
349627f7eb2Smrg for (i = 0; i < as->rank; i++)
350627f7eb2Smrg {
351627f7eb2Smrg gfc_free_expr (as->lower[i]);
352627f7eb2Smrg gfc_free_expr (as->upper[i]);
353627f7eb2Smrg }
354627f7eb2Smrg }
355627f7eb2Smrg else
356627f7eb2Smrg {
357627f7eb2Smrg int n = as->rank + as->corank - (as->cotype == AS_EXPLICIT ? 1 : 0);
358627f7eb2Smrg for (i = 0; i < n; i++)
359627f7eb2Smrg {
360627f7eb2Smrg gfc_free_expr (as->lower[i]);
361627f7eb2Smrg gfc_free_expr (as->upper[i]);
362627f7eb2Smrg }
363627f7eb2Smrg }
364627f7eb2Smrg
365627f7eb2Smrg free (as);
366627f7eb2Smrg }
367627f7eb2Smrg
368627f7eb2Smrg
369627f7eb2Smrg /* Take an array bound, resolves the expression, that make up the
370627f7eb2Smrg shape and check associated constraints. */
371627f7eb2Smrg
372627f7eb2Smrg static bool
resolve_array_bound(gfc_expr * e,int check_constant)373627f7eb2Smrg resolve_array_bound (gfc_expr *e, int check_constant)
374627f7eb2Smrg {
375627f7eb2Smrg if (e == NULL)
376627f7eb2Smrg return true;
377627f7eb2Smrg
378627f7eb2Smrg if (!gfc_resolve_expr (e)
379627f7eb2Smrg || !gfc_specification_expr (e))
380627f7eb2Smrg return false;
381627f7eb2Smrg
382627f7eb2Smrg if (check_constant && !gfc_is_constant_expr (e))
383627f7eb2Smrg {
384627f7eb2Smrg if (e->expr_type == EXPR_VARIABLE)
385627f7eb2Smrg gfc_error ("Variable %qs at %L in this context must be constant",
386627f7eb2Smrg e->symtree->n.sym->name, &e->where);
387627f7eb2Smrg else
388627f7eb2Smrg gfc_error ("Expression at %L in this context must be constant",
389627f7eb2Smrg &e->where);
390627f7eb2Smrg return false;
391627f7eb2Smrg }
392627f7eb2Smrg
393627f7eb2Smrg return true;
394627f7eb2Smrg }
395627f7eb2Smrg
396627f7eb2Smrg
397627f7eb2Smrg /* Takes an array specification, resolves the expressions that make up
398627f7eb2Smrg the shape and make sure everything is integral. */
399627f7eb2Smrg
400627f7eb2Smrg bool
gfc_resolve_array_spec(gfc_array_spec * as,int check_constant)401627f7eb2Smrg gfc_resolve_array_spec (gfc_array_spec *as, int check_constant)
402627f7eb2Smrg {
403627f7eb2Smrg gfc_expr *e;
404627f7eb2Smrg int i;
405627f7eb2Smrg
406627f7eb2Smrg if (as == NULL)
407627f7eb2Smrg return true;
408627f7eb2Smrg
409627f7eb2Smrg if (as->resolved)
410627f7eb2Smrg return true;
411627f7eb2Smrg
412627f7eb2Smrg for (i = 0; i < as->rank + as->corank; i++)
413627f7eb2Smrg {
414*4c3eb207Smrg if (i == GFC_MAX_DIMENSIONS)
415*4c3eb207Smrg return false;
416*4c3eb207Smrg
417627f7eb2Smrg e = as->lower[i];
418627f7eb2Smrg if (!resolve_array_bound (e, check_constant))
419627f7eb2Smrg return false;
420627f7eb2Smrg
421627f7eb2Smrg e = as->upper[i];
422627f7eb2Smrg if (!resolve_array_bound (e, check_constant))
423627f7eb2Smrg return false;
424627f7eb2Smrg
425627f7eb2Smrg if ((as->lower[i] == NULL) || (as->upper[i] == NULL))
426627f7eb2Smrg continue;
427627f7eb2Smrg
428627f7eb2Smrg /* If the size is negative in this dimension, set it to zero. */
429627f7eb2Smrg if (as->lower[i]->expr_type == EXPR_CONSTANT
430627f7eb2Smrg && as->upper[i]->expr_type == EXPR_CONSTANT
431627f7eb2Smrg && mpz_cmp (as->upper[i]->value.integer,
432627f7eb2Smrg as->lower[i]->value.integer) < 0)
433627f7eb2Smrg {
434627f7eb2Smrg gfc_free_expr (as->upper[i]);
435627f7eb2Smrg as->upper[i] = gfc_copy_expr (as->lower[i]);
436627f7eb2Smrg mpz_sub_ui (as->upper[i]->value.integer,
437627f7eb2Smrg as->upper[i]->value.integer, 1);
438627f7eb2Smrg }
439627f7eb2Smrg }
440627f7eb2Smrg
441627f7eb2Smrg as->resolved = true;
442627f7eb2Smrg
443627f7eb2Smrg return true;
444627f7eb2Smrg }
445627f7eb2Smrg
446627f7eb2Smrg
447627f7eb2Smrg /* Match a single array element specification. The return values as
448627f7eb2Smrg well as the upper and lower bounds of the array spec are filled
449627f7eb2Smrg in according to what we see on the input. The caller makes sure
450627f7eb2Smrg individual specifications make sense as a whole.
451627f7eb2Smrg
452627f7eb2Smrg
453627f7eb2Smrg Parsed Lower Upper Returned
454627f7eb2Smrg ------------------------------------
455627f7eb2Smrg : NULL NULL AS_DEFERRED (*)
456627f7eb2Smrg x 1 x AS_EXPLICIT
457627f7eb2Smrg x: x NULL AS_ASSUMED_SHAPE
458627f7eb2Smrg x:y x y AS_EXPLICIT
459627f7eb2Smrg x:* x NULL AS_ASSUMED_SIZE
460627f7eb2Smrg * 1 NULL AS_ASSUMED_SIZE
461627f7eb2Smrg
462627f7eb2Smrg (*) For non-pointer dummy arrays this is AS_ASSUMED_SHAPE. This
463627f7eb2Smrg is fixed during the resolution of formal interfaces.
464627f7eb2Smrg
465627f7eb2Smrg Anything else AS_UNKNOWN. */
466627f7eb2Smrg
467627f7eb2Smrg static array_type
match_array_element_spec(gfc_array_spec * as)468627f7eb2Smrg match_array_element_spec (gfc_array_spec *as)
469627f7eb2Smrg {
470627f7eb2Smrg gfc_expr **upper, **lower;
471627f7eb2Smrg match m;
472627f7eb2Smrg int rank;
473627f7eb2Smrg
474627f7eb2Smrg rank = as->rank == -1 ? 0 : as->rank;
475627f7eb2Smrg lower = &as->lower[rank + as->corank - 1];
476627f7eb2Smrg upper = &as->upper[rank + as->corank - 1];
477627f7eb2Smrg
478627f7eb2Smrg if (gfc_match_char ('*') == MATCH_YES)
479627f7eb2Smrg {
480627f7eb2Smrg *lower = gfc_get_int_expr (gfc_default_integer_kind, NULL, 1);
481627f7eb2Smrg return AS_ASSUMED_SIZE;
482627f7eb2Smrg }
483627f7eb2Smrg
484627f7eb2Smrg if (gfc_match_char (':') == MATCH_YES)
485627f7eb2Smrg return AS_DEFERRED;
486627f7eb2Smrg
487627f7eb2Smrg m = gfc_match_expr (upper);
488627f7eb2Smrg if (m == MATCH_NO)
489627f7eb2Smrg gfc_error ("Expected expression in array specification at %C");
490627f7eb2Smrg if (m != MATCH_YES)
491627f7eb2Smrg return AS_UNKNOWN;
492627f7eb2Smrg if (!gfc_expr_check_typed (*upper, gfc_current_ns, false))
493627f7eb2Smrg return AS_UNKNOWN;
494627f7eb2Smrg
495627f7eb2Smrg if (((*upper)->expr_type == EXPR_CONSTANT
496627f7eb2Smrg && (*upper)->ts.type != BT_INTEGER) ||
497627f7eb2Smrg ((*upper)->expr_type == EXPR_FUNCTION
498627f7eb2Smrg && (*upper)->ts.type == BT_UNKNOWN
499627f7eb2Smrg && (*upper)->symtree
500627f7eb2Smrg && strcmp ((*upper)->symtree->name, "null") == 0))
501627f7eb2Smrg {
502627f7eb2Smrg gfc_error ("Expecting a scalar INTEGER expression at %C, found %s",
503627f7eb2Smrg gfc_basic_typename ((*upper)->ts.type));
504627f7eb2Smrg return AS_UNKNOWN;
505627f7eb2Smrg }
506627f7eb2Smrg
507627f7eb2Smrg if (gfc_match_char (':') == MATCH_NO)
508627f7eb2Smrg {
509627f7eb2Smrg *lower = gfc_get_int_expr (gfc_default_integer_kind, NULL, 1);
510627f7eb2Smrg return AS_EXPLICIT;
511627f7eb2Smrg }
512627f7eb2Smrg
513627f7eb2Smrg *lower = *upper;
514627f7eb2Smrg *upper = NULL;
515627f7eb2Smrg
516627f7eb2Smrg if (gfc_match_char ('*') == MATCH_YES)
517627f7eb2Smrg return AS_ASSUMED_SIZE;
518627f7eb2Smrg
519627f7eb2Smrg m = gfc_match_expr (upper);
520627f7eb2Smrg if (m == MATCH_ERROR)
521627f7eb2Smrg return AS_UNKNOWN;
522627f7eb2Smrg if (m == MATCH_NO)
523627f7eb2Smrg return AS_ASSUMED_SHAPE;
524627f7eb2Smrg if (!gfc_expr_check_typed (*upper, gfc_current_ns, false))
525627f7eb2Smrg return AS_UNKNOWN;
526627f7eb2Smrg
527627f7eb2Smrg if (((*upper)->expr_type == EXPR_CONSTANT
528627f7eb2Smrg && (*upper)->ts.type != BT_INTEGER) ||
529627f7eb2Smrg ((*upper)->expr_type == EXPR_FUNCTION
530627f7eb2Smrg && (*upper)->ts.type == BT_UNKNOWN
531627f7eb2Smrg && (*upper)->symtree
532627f7eb2Smrg && strcmp ((*upper)->symtree->name, "null") == 0))
533627f7eb2Smrg {
534627f7eb2Smrg gfc_error ("Expecting a scalar INTEGER expression at %C, found %s",
535627f7eb2Smrg gfc_basic_typename ((*upper)->ts.type));
536627f7eb2Smrg return AS_UNKNOWN;
537627f7eb2Smrg }
538627f7eb2Smrg
539627f7eb2Smrg return AS_EXPLICIT;
540627f7eb2Smrg }
541627f7eb2Smrg
542627f7eb2Smrg
543627f7eb2Smrg /* Matches an array specification, incidentally figuring out what sort
544627f7eb2Smrg it is. Match either a normal array specification, or a coarray spec
545627f7eb2Smrg or both. Optionally allow [:] for coarrays. */
546627f7eb2Smrg
547627f7eb2Smrg match
gfc_match_array_spec(gfc_array_spec ** asp,bool match_dim,bool match_codim)548627f7eb2Smrg gfc_match_array_spec (gfc_array_spec **asp, bool match_dim, bool match_codim)
549627f7eb2Smrg {
550627f7eb2Smrg array_type current_type;
551627f7eb2Smrg gfc_array_spec *as;
552627f7eb2Smrg int i;
553627f7eb2Smrg
554627f7eb2Smrg as = gfc_get_array_spec ();
555627f7eb2Smrg
556627f7eb2Smrg if (!match_dim)
557627f7eb2Smrg goto coarray;
558627f7eb2Smrg
559627f7eb2Smrg if (gfc_match_char ('(') != MATCH_YES)
560627f7eb2Smrg {
561627f7eb2Smrg if (!match_codim)
562627f7eb2Smrg goto done;
563627f7eb2Smrg goto coarray;
564627f7eb2Smrg }
565627f7eb2Smrg
566627f7eb2Smrg if (gfc_match (" .. )") == MATCH_YES)
567627f7eb2Smrg {
568627f7eb2Smrg as->type = AS_ASSUMED_RANK;
569627f7eb2Smrg as->rank = -1;
570627f7eb2Smrg
571627f7eb2Smrg if (!gfc_notify_std (GFC_STD_F2018, "Assumed-rank array at %C"))
572627f7eb2Smrg goto cleanup;
573627f7eb2Smrg
574627f7eb2Smrg if (!match_codim)
575627f7eb2Smrg goto done;
576627f7eb2Smrg goto coarray;
577627f7eb2Smrg }
578627f7eb2Smrg
579627f7eb2Smrg for (;;)
580627f7eb2Smrg {
581627f7eb2Smrg as->rank++;
582627f7eb2Smrg current_type = match_array_element_spec (as);
583627f7eb2Smrg
584627f7eb2Smrg /* Note that current_type == AS_ASSUMED_SIZE for both assumed-size
585627f7eb2Smrg and implied-shape specifications. If the rank is at least 2, we can
586627f7eb2Smrg distinguish between them. But for rank 1, we currently return
587627f7eb2Smrg ASSUMED_SIZE; this gets adjusted later when we know for sure
588627f7eb2Smrg whether the symbol parsed is a PARAMETER or not. */
589627f7eb2Smrg
590627f7eb2Smrg if (as->rank == 1)
591627f7eb2Smrg {
592627f7eb2Smrg if (current_type == AS_UNKNOWN)
593627f7eb2Smrg goto cleanup;
594627f7eb2Smrg as->type = current_type;
595627f7eb2Smrg }
596627f7eb2Smrg else
597627f7eb2Smrg switch (as->type)
598627f7eb2Smrg { /* See how current spec meshes with the existing. */
599627f7eb2Smrg case AS_UNKNOWN:
600627f7eb2Smrg goto cleanup;
601627f7eb2Smrg
602627f7eb2Smrg case AS_IMPLIED_SHAPE:
603*4c3eb207Smrg if (current_type != AS_ASSUMED_SIZE)
604627f7eb2Smrg {
605627f7eb2Smrg gfc_error ("Bad array specification for implied-shape"
606627f7eb2Smrg " array at %C");
607627f7eb2Smrg goto cleanup;
608627f7eb2Smrg }
609627f7eb2Smrg break;
610627f7eb2Smrg
611627f7eb2Smrg case AS_EXPLICIT:
612627f7eb2Smrg if (current_type == AS_ASSUMED_SIZE)
613627f7eb2Smrg {
614627f7eb2Smrg as->type = AS_ASSUMED_SIZE;
615627f7eb2Smrg break;
616627f7eb2Smrg }
617627f7eb2Smrg
618627f7eb2Smrg if (current_type == AS_EXPLICIT)
619627f7eb2Smrg break;
620627f7eb2Smrg
621627f7eb2Smrg gfc_error ("Bad array specification for an explicitly shaped "
622627f7eb2Smrg "array at %C");
623627f7eb2Smrg
624627f7eb2Smrg goto cleanup;
625627f7eb2Smrg
626627f7eb2Smrg case AS_ASSUMED_SHAPE:
627627f7eb2Smrg if ((current_type == AS_ASSUMED_SHAPE)
628627f7eb2Smrg || (current_type == AS_DEFERRED))
629627f7eb2Smrg break;
630627f7eb2Smrg
631627f7eb2Smrg gfc_error ("Bad array specification for assumed shape "
632627f7eb2Smrg "array at %C");
633627f7eb2Smrg goto cleanup;
634627f7eb2Smrg
635627f7eb2Smrg case AS_DEFERRED:
636627f7eb2Smrg if (current_type == AS_DEFERRED)
637627f7eb2Smrg break;
638627f7eb2Smrg
639627f7eb2Smrg if (current_type == AS_ASSUMED_SHAPE)
640627f7eb2Smrg {
641627f7eb2Smrg as->type = AS_ASSUMED_SHAPE;
642627f7eb2Smrg break;
643627f7eb2Smrg }
644627f7eb2Smrg
645627f7eb2Smrg gfc_error ("Bad specification for deferred shape array at %C");
646627f7eb2Smrg goto cleanup;
647627f7eb2Smrg
648627f7eb2Smrg case AS_ASSUMED_SIZE:
649627f7eb2Smrg if (as->rank == 2 && current_type == AS_ASSUMED_SIZE)
650627f7eb2Smrg {
651627f7eb2Smrg as->type = AS_IMPLIED_SHAPE;
652627f7eb2Smrg break;
653627f7eb2Smrg }
654627f7eb2Smrg
655627f7eb2Smrg gfc_error ("Bad specification for assumed size array at %C");
656627f7eb2Smrg goto cleanup;
657627f7eb2Smrg
658627f7eb2Smrg case AS_ASSUMED_RANK:
659627f7eb2Smrg gcc_unreachable ();
660627f7eb2Smrg }
661627f7eb2Smrg
662627f7eb2Smrg if (gfc_match_char (')') == MATCH_YES)
663627f7eb2Smrg break;
664627f7eb2Smrg
665627f7eb2Smrg if (gfc_match_char (',') != MATCH_YES)
666627f7eb2Smrg {
667627f7eb2Smrg gfc_error ("Expected another dimension in array declaration at %C");
668627f7eb2Smrg goto cleanup;
669627f7eb2Smrg }
670627f7eb2Smrg
671627f7eb2Smrg if (as->rank + as->corank >= GFC_MAX_DIMENSIONS)
672627f7eb2Smrg {
673627f7eb2Smrg gfc_error ("Array specification at %C has more than %d dimensions",
674627f7eb2Smrg GFC_MAX_DIMENSIONS);
675627f7eb2Smrg goto cleanup;
676627f7eb2Smrg }
677627f7eb2Smrg
678627f7eb2Smrg if (as->corank + as->rank >= 7
679627f7eb2Smrg && !gfc_notify_std (GFC_STD_F2008, "Array specification at %C "
680627f7eb2Smrg "with more than 7 dimensions"))
681627f7eb2Smrg goto cleanup;
682627f7eb2Smrg }
683627f7eb2Smrg
684627f7eb2Smrg if (!match_codim)
685627f7eb2Smrg goto done;
686627f7eb2Smrg
687627f7eb2Smrg coarray:
688627f7eb2Smrg if (gfc_match_char ('[') != MATCH_YES)
689627f7eb2Smrg goto done;
690627f7eb2Smrg
691627f7eb2Smrg if (!gfc_notify_std (GFC_STD_F2008, "Coarray declaration at %C"))
692627f7eb2Smrg goto cleanup;
693627f7eb2Smrg
694627f7eb2Smrg if (flag_coarray == GFC_FCOARRAY_NONE)
695627f7eb2Smrg {
696627f7eb2Smrg gfc_fatal_error ("Coarrays disabled at %C, use %<-fcoarray=%> to enable");
697627f7eb2Smrg goto cleanup;
698627f7eb2Smrg }
699627f7eb2Smrg
700627f7eb2Smrg if (as->rank >= GFC_MAX_DIMENSIONS)
701627f7eb2Smrg {
702627f7eb2Smrg gfc_error ("Array specification at %C has more than %d "
703627f7eb2Smrg "dimensions", GFC_MAX_DIMENSIONS);
704627f7eb2Smrg goto cleanup;
705627f7eb2Smrg }
706627f7eb2Smrg
707627f7eb2Smrg for (;;)
708627f7eb2Smrg {
709627f7eb2Smrg as->corank++;
710627f7eb2Smrg current_type = match_array_element_spec (as);
711627f7eb2Smrg
712627f7eb2Smrg if (current_type == AS_UNKNOWN)
713627f7eb2Smrg goto cleanup;
714627f7eb2Smrg
715627f7eb2Smrg if (as->corank == 1)
716627f7eb2Smrg as->cotype = current_type;
717627f7eb2Smrg else
718627f7eb2Smrg switch (as->cotype)
719627f7eb2Smrg { /* See how current spec meshes with the existing. */
720627f7eb2Smrg case AS_IMPLIED_SHAPE:
721627f7eb2Smrg case AS_UNKNOWN:
722627f7eb2Smrg goto cleanup;
723627f7eb2Smrg
724627f7eb2Smrg case AS_EXPLICIT:
725627f7eb2Smrg if (current_type == AS_ASSUMED_SIZE)
726627f7eb2Smrg {
727627f7eb2Smrg as->cotype = AS_ASSUMED_SIZE;
728627f7eb2Smrg break;
729627f7eb2Smrg }
730627f7eb2Smrg
731627f7eb2Smrg if (current_type == AS_EXPLICIT)
732627f7eb2Smrg break;
733627f7eb2Smrg
734627f7eb2Smrg gfc_error ("Bad array specification for an explicitly "
735627f7eb2Smrg "shaped array at %C");
736627f7eb2Smrg
737627f7eb2Smrg goto cleanup;
738627f7eb2Smrg
739627f7eb2Smrg case AS_ASSUMED_SHAPE:
740627f7eb2Smrg if ((current_type == AS_ASSUMED_SHAPE)
741627f7eb2Smrg || (current_type == AS_DEFERRED))
742627f7eb2Smrg break;
743627f7eb2Smrg
744627f7eb2Smrg gfc_error ("Bad array specification for assumed shape "
745627f7eb2Smrg "array at %C");
746627f7eb2Smrg goto cleanup;
747627f7eb2Smrg
748627f7eb2Smrg case AS_DEFERRED:
749627f7eb2Smrg if (current_type == AS_DEFERRED)
750627f7eb2Smrg break;
751627f7eb2Smrg
752627f7eb2Smrg if (current_type == AS_ASSUMED_SHAPE)
753627f7eb2Smrg {
754627f7eb2Smrg as->cotype = AS_ASSUMED_SHAPE;
755627f7eb2Smrg break;
756627f7eb2Smrg }
757627f7eb2Smrg
758627f7eb2Smrg gfc_error ("Bad specification for deferred shape array at %C");
759627f7eb2Smrg goto cleanup;
760627f7eb2Smrg
761627f7eb2Smrg case AS_ASSUMED_SIZE:
762627f7eb2Smrg gfc_error ("Bad specification for assumed size array at %C");
763627f7eb2Smrg goto cleanup;
764627f7eb2Smrg
765627f7eb2Smrg case AS_ASSUMED_RANK:
766627f7eb2Smrg gcc_unreachable ();
767627f7eb2Smrg }
768627f7eb2Smrg
769627f7eb2Smrg if (gfc_match_char (']') == MATCH_YES)
770627f7eb2Smrg break;
771627f7eb2Smrg
772627f7eb2Smrg if (gfc_match_char (',') != MATCH_YES)
773627f7eb2Smrg {
774627f7eb2Smrg gfc_error ("Expected another dimension in array declaration at %C");
775627f7eb2Smrg goto cleanup;
776627f7eb2Smrg }
777627f7eb2Smrg
778627f7eb2Smrg if (as->rank + as->corank >= GFC_MAX_DIMENSIONS)
779627f7eb2Smrg {
780627f7eb2Smrg gfc_error ("Array specification at %C has more than %d "
781627f7eb2Smrg "dimensions", GFC_MAX_DIMENSIONS);
782627f7eb2Smrg goto cleanup;
783627f7eb2Smrg }
784627f7eb2Smrg }
785627f7eb2Smrg
786627f7eb2Smrg if (current_type == AS_EXPLICIT)
787627f7eb2Smrg {
788627f7eb2Smrg gfc_error ("Upper bound of last coarray dimension must be %<*%> at %C");
789627f7eb2Smrg goto cleanup;
790627f7eb2Smrg }
791627f7eb2Smrg
792627f7eb2Smrg if (as->cotype == AS_ASSUMED_SIZE)
793627f7eb2Smrg as->cotype = AS_EXPLICIT;
794627f7eb2Smrg
795627f7eb2Smrg if (as->rank == 0)
796627f7eb2Smrg as->type = as->cotype;
797627f7eb2Smrg
798627f7eb2Smrg done:
799627f7eb2Smrg if (as->rank == 0 && as->corank == 0)
800627f7eb2Smrg {
801627f7eb2Smrg *asp = NULL;
802627f7eb2Smrg gfc_free_array_spec (as);
803627f7eb2Smrg return MATCH_NO;
804627f7eb2Smrg }
805627f7eb2Smrg
806627f7eb2Smrg /* If a lower bounds of an assumed shape array is blank, put in one. */
807627f7eb2Smrg if (as->type == AS_ASSUMED_SHAPE)
808627f7eb2Smrg {
809627f7eb2Smrg for (i = 0; i < as->rank + as->corank; i++)
810627f7eb2Smrg {
811627f7eb2Smrg if (as->lower[i] == NULL)
812627f7eb2Smrg as->lower[i] = gfc_get_int_expr (gfc_default_integer_kind, NULL, 1);
813627f7eb2Smrg }
814627f7eb2Smrg }
815627f7eb2Smrg
816627f7eb2Smrg *asp = as;
817627f7eb2Smrg
818627f7eb2Smrg return MATCH_YES;
819627f7eb2Smrg
820627f7eb2Smrg cleanup:
821627f7eb2Smrg /* Something went wrong. */
822627f7eb2Smrg gfc_free_array_spec (as);
823627f7eb2Smrg return MATCH_ERROR;
824627f7eb2Smrg }
825627f7eb2Smrg
826627f7eb2Smrg /* Given a symbol and an array specification, modify the symbol to
827627f7eb2Smrg have that array specification. The error locus is needed in case
828627f7eb2Smrg something goes wrong. On failure, the caller must free the spec. */
829627f7eb2Smrg
830627f7eb2Smrg bool
gfc_set_array_spec(gfc_symbol * sym,gfc_array_spec * as,locus * error_loc)831627f7eb2Smrg gfc_set_array_spec (gfc_symbol *sym, gfc_array_spec *as, locus *error_loc)
832627f7eb2Smrg {
833627f7eb2Smrg int i;
834*4c3eb207Smrg symbol_attribute *attr;
835627f7eb2Smrg
836627f7eb2Smrg if (as == NULL)
837627f7eb2Smrg return true;
838627f7eb2Smrg
839*4c3eb207Smrg /* If the symbol corresponds to a submodule module procedure the array spec is
840*4c3eb207Smrg already set, so do not attempt to set it again here. */
841*4c3eb207Smrg attr = &sym->attr;
842*4c3eb207Smrg if (gfc_submodule_procedure(attr))
843*4c3eb207Smrg return true;
844*4c3eb207Smrg
845627f7eb2Smrg if (as->rank
846627f7eb2Smrg && !gfc_add_dimension (&sym->attr, sym->name, error_loc))
847627f7eb2Smrg return false;
848627f7eb2Smrg
849627f7eb2Smrg if (as->corank
850627f7eb2Smrg && !gfc_add_codimension (&sym->attr, sym->name, error_loc))
851627f7eb2Smrg return false;
852627f7eb2Smrg
853627f7eb2Smrg if (sym->as == NULL)
854627f7eb2Smrg {
855627f7eb2Smrg sym->as = as;
856627f7eb2Smrg return true;
857627f7eb2Smrg }
858627f7eb2Smrg
859627f7eb2Smrg if ((sym->as->type == AS_ASSUMED_RANK && as->corank)
860627f7eb2Smrg || (as->type == AS_ASSUMED_RANK && sym->as->corank))
861627f7eb2Smrg {
862627f7eb2Smrg gfc_error ("The assumed-rank array %qs at %L shall not have a "
863627f7eb2Smrg "codimension", sym->name, error_loc);
864627f7eb2Smrg return false;
865627f7eb2Smrg }
866627f7eb2Smrg
867*4c3eb207Smrg /* Check F2018:C822. */
868*4c3eb207Smrg if (sym->as->rank + sym->as->corank > GFC_MAX_DIMENSIONS)
869*4c3eb207Smrg goto too_many;
870*4c3eb207Smrg
871627f7eb2Smrg if (as->corank)
872627f7eb2Smrg {
873627f7eb2Smrg sym->as->cotype = as->cotype;
874627f7eb2Smrg sym->as->corank = as->corank;
875627f7eb2Smrg /* Check F2018:C822. */
876627f7eb2Smrg if (sym->as->rank + sym->as->corank > GFC_MAX_DIMENSIONS)
877627f7eb2Smrg goto too_many;
878627f7eb2Smrg
879627f7eb2Smrg for (i = 0; i < as->corank; i++)
880627f7eb2Smrg {
881627f7eb2Smrg sym->as->lower[sym->as->rank + i] = as->lower[i];
882627f7eb2Smrg sym->as->upper[sym->as->rank + i] = as->upper[i];
883627f7eb2Smrg }
884627f7eb2Smrg }
885627f7eb2Smrg else
886627f7eb2Smrg {
887627f7eb2Smrg /* The "sym" has no rank (checked via gfc_add_dimension). Thus
888627f7eb2Smrg the dimension is added - but first the codimensions (if existing
889627f7eb2Smrg need to be shifted to make space for the dimension. */
890627f7eb2Smrg gcc_assert (as->corank == 0 && sym->as->rank == 0);
891627f7eb2Smrg
892627f7eb2Smrg sym->as->rank = as->rank;
893627f7eb2Smrg sym->as->type = as->type;
894627f7eb2Smrg sym->as->cray_pointee = as->cray_pointee;
895627f7eb2Smrg sym->as->cp_was_assumed = as->cp_was_assumed;
896627f7eb2Smrg
897627f7eb2Smrg /* Check F2018:C822. */
898627f7eb2Smrg if (sym->as->rank + sym->as->corank > GFC_MAX_DIMENSIONS)
899627f7eb2Smrg goto too_many;
900627f7eb2Smrg
901627f7eb2Smrg for (i = sym->as->corank - 1; i >= 0; i--)
902627f7eb2Smrg {
903627f7eb2Smrg sym->as->lower[as->rank + i] = sym->as->lower[i];
904627f7eb2Smrg sym->as->upper[as->rank + i] = sym->as->upper[i];
905627f7eb2Smrg }
906627f7eb2Smrg for (i = 0; i < as->rank; i++)
907627f7eb2Smrg {
908627f7eb2Smrg sym->as->lower[i] = as->lower[i];
909627f7eb2Smrg sym->as->upper[i] = as->upper[i];
910627f7eb2Smrg }
911627f7eb2Smrg }
912627f7eb2Smrg
913627f7eb2Smrg free (as);
914627f7eb2Smrg return true;
915627f7eb2Smrg
916627f7eb2Smrg too_many:
917627f7eb2Smrg
918627f7eb2Smrg gfc_error ("rank + corank of %qs exceeds %d at %C", sym->name,
919627f7eb2Smrg GFC_MAX_DIMENSIONS);
920627f7eb2Smrg return false;
921627f7eb2Smrg }
922627f7eb2Smrg
923627f7eb2Smrg
924627f7eb2Smrg /* Copy an array specification. */
925627f7eb2Smrg
926627f7eb2Smrg gfc_array_spec *
gfc_copy_array_spec(gfc_array_spec * src)927627f7eb2Smrg gfc_copy_array_spec (gfc_array_spec *src)
928627f7eb2Smrg {
929627f7eb2Smrg gfc_array_spec *dest;
930627f7eb2Smrg int i;
931627f7eb2Smrg
932627f7eb2Smrg if (src == NULL)
933627f7eb2Smrg return NULL;
934627f7eb2Smrg
935627f7eb2Smrg dest = gfc_get_array_spec ();
936627f7eb2Smrg
937627f7eb2Smrg *dest = *src;
938627f7eb2Smrg
939627f7eb2Smrg for (i = 0; i < dest->rank + dest->corank; i++)
940627f7eb2Smrg {
941627f7eb2Smrg dest->lower[i] = gfc_copy_expr (dest->lower[i]);
942627f7eb2Smrg dest->upper[i] = gfc_copy_expr (dest->upper[i]);
943627f7eb2Smrg }
944627f7eb2Smrg
945627f7eb2Smrg return dest;
946627f7eb2Smrg }
947627f7eb2Smrg
948627f7eb2Smrg
949627f7eb2Smrg /* Returns nonzero if the two expressions are equal. Only handles integer
950627f7eb2Smrg constants. */
951627f7eb2Smrg
952627f7eb2Smrg static int
compare_bounds(gfc_expr * bound1,gfc_expr * bound2)953627f7eb2Smrg compare_bounds (gfc_expr *bound1, gfc_expr *bound2)
954627f7eb2Smrg {
955627f7eb2Smrg if (bound1 == NULL || bound2 == NULL
956627f7eb2Smrg || bound1->expr_type != EXPR_CONSTANT
957627f7eb2Smrg || bound2->expr_type != EXPR_CONSTANT
958627f7eb2Smrg || bound1->ts.type != BT_INTEGER
959627f7eb2Smrg || bound2->ts.type != BT_INTEGER)
960627f7eb2Smrg gfc_internal_error ("gfc_compare_array_spec(): Array spec clobbered");
961627f7eb2Smrg
962627f7eb2Smrg if (mpz_cmp (bound1->value.integer, bound2->value.integer) == 0)
963627f7eb2Smrg return 1;
964627f7eb2Smrg else
965627f7eb2Smrg return 0;
966627f7eb2Smrg }
967627f7eb2Smrg
968627f7eb2Smrg
969627f7eb2Smrg /* Compares two array specifications. They must be constant or deferred
970627f7eb2Smrg shape. */
971627f7eb2Smrg
972627f7eb2Smrg int
gfc_compare_array_spec(gfc_array_spec * as1,gfc_array_spec * as2)973627f7eb2Smrg gfc_compare_array_spec (gfc_array_spec *as1, gfc_array_spec *as2)
974627f7eb2Smrg {
975627f7eb2Smrg int i;
976627f7eb2Smrg
977627f7eb2Smrg if (as1 == NULL && as2 == NULL)
978627f7eb2Smrg return 1;
979627f7eb2Smrg
980627f7eb2Smrg if (as1 == NULL || as2 == NULL)
981627f7eb2Smrg return 0;
982627f7eb2Smrg
983627f7eb2Smrg if (as1->rank != as2->rank)
984627f7eb2Smrg return 0;
985627f7eb2Smrg
986627f7eb2Smrg if (as1->corank != as2->corank)
987627f7eb2Smrg return 0;
988627f7eb2Smrg
989627f7eb2Smrg if (as1->rank == 0)
990627f7eb2Smrg return 1;
991627f7eb2Smrg
992627f7eb2Smrg if (as1->type != as2->type)
993627f7eb2Smrg return 0;
994627f7eb2Smrg
995627f7eb2Smrg if (as1->type == AS_EXPLICIT)
996627f7eb2Smrg for (i = 0; i < as1->rank + as1->corank; i++)
997627f7eb2Smrg {
998627f7eb2Smrg if (compare_bounds (as1->lower[i], as2->lower[i]) == 0)
999627f7eb2Smrg return 0;
1000627f7eb2Smrg
1001627f7eb2Smrg if (compare_bounds (as1->upper[i], as2->upper[i]) == 0)
1002627f7eb2Smrg return 0;
1003627f7eb2Smrg }
1004627f7eb2Smrg
1005627f7eb2Smrg return 1;
1006627f7eb2Smrg }
1007627f7eb2Smrg
1008627f7eb2Smrg
1009627f7eb2Smrg /****************** Array constructor functions ******************/
1010627f7eb2Smrg
1011627f7eb2Smrg
1012627f7eb2Smrg /* Given an expression node that might be an array constructor and a
1013627f7eb2Smrg symbol, make sure that no iterators in this or child constructors
1014627f7eb2Smrg use the symbol as an implied-DO iterator. Returns nonzero if a
1015627f7eb2Smrg duplicate was found. */
1016627f7eb2Smrg
1017627f7eb2Smrg static int
check_duplicate_iterator(gfc_constructor_base base,gfc_symbol * master)1018627f7eb2Smrg check_duplicate_iterator (gfc_constructor_base base, gfc_symbol *master)
1019627f7eb2Smrg {
1020627f7eb2Smrg gfc_constructor *c;
1021627f7eb2Smrg gfc_expr *e;
1022627f7eb2Smrg
1023627f7eb2Smrg for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
1024627f7eb2Smrg {
1025627f7eb2Smrg e = c->expr;
1026627f7eb2Smrg
1027627f7eb2Smrg if (e->expr_type == EXPR_ARRAY
1028627f7eb2Smrg && check_duplicate_iterator (e->value.constructor, master))
1029627f7eb2Smrg return 1;
1030627f7eb2Smrg
1031627f7eb2Smrg if (c->iterator == NULL)
1032627f7eb2Smrg continue;
1033627f7eb2Smrg
1034627f7eb2Smrg if (c->iterator->var->symtree->n.sym == master)
1035627f7eb2Smrg {
1036627f7eb2Smrg gfc_error ("DO-iterator %qs at %L is inside iterator of the "
1037627f7eb2Smrg "same name", master->name, &c->where);
1038627f7eb2Smrg
1039627f7eb2Smrg return 1;
1040627f7eb2Smrg }
1041627f7eb2Smrg }
1042627f7eb2Smrg
1043627f7eb2Smrg return 0;
1044627f7eb2Smrg }
1045627f7eb2Smrg
1046627f7eb2Smrg
1047627f7eb2Smrg /* Forward declaration because these functions are mutually recursive. */
1048627f7eb2Smrg static match match_array_cons_element (gfc_constructor_base *);
1049627f7eb2Smrg
1050627f7eb2Smrg /* Match a list of array elements. */
1051627f7eb2Smrg
1052627f7eb2Smrg static match
match_array_list(gfc_constructor_base * result)1053627f7eb2Smrg match_array_list (gfc_constructor_base *result)
1054627f7eb2Smrg {
1055627f7eb2Smrg gfc_constructor_base head;
1056627f7eb2Smrg gfc_constructor *p;
1057627f7eb2Smrg gfc_iterator iter;
1058627f7eb2Smrg locus old_loc;
1059627f7eb2Smrg gfc_expr *e;
1060627f7eb2Smrg match m;
1061627f7eb2Smrg int n;
1062627f7eb2Smrg
1063627f7eb2Smrg old_loc = gfc_current_locus;
1064627f7eb2Smrg
1065627f7eb2Smrg if (gfc_match_char ('(') == MATCH_NO)
1066627f7eb2Smrg return MATCH_NO;
1067627f7eb2Smrg
1068627f7eb2Smrg memset (&iter, '\0', sizeof (gfc_iterator));
1069627f7eb2Smrg head = NULL;
1070627f7eb2Smrg
1071627f7eb2Smrg m = match_array_cons_element (&head);
1072627f7eb2Smrg if (m != MATCH_YES)
1073627f7eb2Smrg goto cleanup;
1074627f7eb2Smrg
1075627f7eb2Smrg if (gfc_match_char (',') != MATCH_YES)
1076627f7eb2Smrg {
1077627f7eb2Smrg m = MATCH_NO;
1078627f7eb2Smrg goto cleanup;
1079627f7eb2Smrg }
1080627f7eb2Smrg
1081627f7eb2Smrg for (n = 1;; n++)
1082627f7eb2Smrg {
1083627f7eb2Smrg m = gfc_match_iterator (&iter, 0);
1084627f7eb2Smrg if (m == MATCH_YES)
1085627f7eb2Smrg break;
1086627f7eb2Smrg if (m == MATCH_ERROR)
1087627f7eb2Smrg goto cleanup;
1088627f7eb2Smrg
1089627f7eb2Smrg m = match_array_cons_element (&head);
1090627f7eb2Smrg if (m == MATCH_ERROR)
1091627f7eb2Smrg goto cleanup;
1092627f7eb2Smrg if (m == MATCH_NO)
1093627f7eb2Smrg {
1094627f7eb2Smrg if (n > 2)
1095627f7eb2Smrg goto syntax;
1096627f7eb2Smrg m = MATCH_NO;
1097627f7eb2Smrg goto cleanup; /* Could be a complex constant */
1098627f7eb2Smrg }
1099627f7eb2Smrg
1100627f7eb2Smrg if (gfc_match_char (',') != MATCH_YES)
1101627f7eb2Smrg {
1102627f7eb2Smrg if (n > 2)
1103627f7eb2Smrg goto syntax;
1104627f7eb2Smrg m = MATCH_NO;
1105627f7eb2Smrg goto cleanup;
1106627f7eb2Smrg }
1107627f7eb2Smrg }
1108627f7eb2Smrg
1109627f7eb2Smrg if (gfc_match_char (')') != MATCH_YES)
1110627f7eb2Smrg goto syntax;
1111627f7eb2Smrg
1112627f7eb2Smrg if (check_duplicate_iterator (head, iter.var->symtree->n.sym))
1113627f7eb2Smrg {
1114627f7eb2Smrg m = MATCH_ERROR;
1115627f7eb2Smrg goto cleanup;
1116627f7eb2Smrg }
1117627f7eb2Smrg
1118627f7eb2Smrg e = gfc_get_array_expr (BT_UNKNOWN, 0, &old_loc);
1119627f7eb2Smrg e->value.constructor = head;
1120627f7eb2Smrg
1121627f7eb2Smrg p = gfc_constructor_append_expr (result, e, &gfc_current_locus);
1122627f7eb2Smrg p->iterator = gfc_get_iterator ();
1123627f7eb2Smrg *p->iterator = iter;
1124627f7eb2Smrg
1125627f7eb2Smrg return MATCH_YES;
1126627f7eb2Smrg
1127627f7eb2Smrg syntax:
1128627f7eb2Smrg gfc_error ("Syntax error in array constructor at %C");
1129627f7eb2Smrg m = MATCH_ERROR;
1130627f7eb2Smrg
1131627f7eb2Smrg cleanup:
1132627f7eb2Smrg gfc_constructor_free (head);
1133627f7eb2Smrg gfc_free_iterator (&iter, 0);
1134627f7eb2Smrg gfc_current_locus = old_loc;
1135627f7eb2Smrg return m;
1136627f7eb2Smrg }
1137627f7eb2Smrg
1138627f7eb2Smrg
1139627f7eb2Smrg /* Match a single element of an array constructor, which can be a
1140627f7eb2Smrg single expression or a list of elements. */
1141627f7eb2Smrg
1142627f7eb2Smrg static match
match_array_cons_element(gfc_constructor_base * result)1143627f7eb2Smrg match_array_cons_element (gfc_constructor_base *result)
1144627f7eb2Smrg {
1145627f7eb2Smrg gfc_expr *expr;
1146627f7eb2Smrg match m;
1147627f7eb2Smrg
1148627f7eb2Smrg m = match_array_list (result);
1149627f7eb2Smrg if (m != MATCH_NO)
1150627f7eb2Smrg return m;
1151627f7eb2Smrg
1152627f7eb2Smrg m = gfc_match_expr (&expr);
1153627f7eb2Smrg if (m != MATCH_YES)
1154627f7eb2Smrg return m;
1155627f7eb2Smrg
1156*4c3eb207Smrg if (expr->ts.type == BT_BOZ)
1157*4c3eb207Smrg {
1158*4c3eb207Smrg gfc_error ("BOZ literal constant at %L cannot appear in an "
1159*4c3eb207Smrg "array constructor", &expr->where);
1160*4c3eb207Smrg goto done;
1161*4c3eb207Smrg }
1162*4c3eb207Smrg
1163627f7eb2Smrg if (expr->expr_type == EXPR_FUNCTION
1164627f7eb2Smrg && expr->ts.type == BT_UNKNOWN
1165627f7eb2Smrg && strcmp(expr->symtree->name, "null") == 0)
1166627f7eb2Smrg {
1167627f7eb2Smrg gfc_error ("NULL() at %C cannot appear in an array constructor");
1168*4c3eb207Smrg goto done;
1169627f7eb2Smrg }
1170627f7eb2Smrg
1171627f7eb2Smrg gfc_constructor_append_expr (result, expr, &gfc_current_locus);
1172627f7eb2Smrg return MATCH_YES;
1173*4c3eb207Smrg
1174*4c3eb207Smrg done:
1175*4c3eb207Smrg gfc_free_expr (expr);
1176*4c3eb207Smrg return MATCH_ERROR;
1177627f7eb2Smrg }
1178627f7eb2Smrg
1179627f7eb2Smrg
1180627f7eb2Smrg /* Convert components of an array constructor to the type in ts. */
1181627f7eb2Smrg
1182627f7eb2Smrg static match
walk_array_constructor(gfc_typespec * ts,gfc_constructor_base head)1183627f7eb2Smrg walk_array_constructor (gfc_typespec *ts, gfc_constructor_base head)
1184627f7eb2Smrg {
1185627f7eb2Smrg gfc_constructor *c;
1186627f7eb2Smrg gfc_expr *e;
1187627f7eb2Smrg match m;
1188627f7eb2Smrg
1189627f7eb2Smrg for (c = gfc_constructor_first (head); c; c = gfc_constructor_next (c))
1190627f7eb2Smrg {
1191627f7eb2Smrg e = c->expr;
1192627f7eb2Smrg if (e->expr_type == EXPR_ARRAY && e->ts.type == BT_UNKNOWN
1193627f7eb2Smrg && !e->ref && e->value.constructor)
1194627f7eb2Smrg {
1195627f7eb2Smrg m = walk_array_constructor (ts, e->value.constructor);
1196627f7eb2Smrg if (m == MATCH_ERROR)
1197627f7eb2Smrg return m;
1198627f7eb2Smrg }
1199*4c3eb207Smrg else if (!gfc_convert_type_warn (e, ts, 1, 1, true)
1200*4c3eb207Smrg && e->ts.type != BT_UNKNOWN)
1201627f7eb2Smrg return MATCH_ERROR;
1202627f7eb2Smrg }
1203627f7eb2Smrg return MATCH_YES;
1204627f7eb2Smrg }
1205627f7eb2Smrg
1206627f7eb2Smrg /* Match an array constructor. */
1207627f7eb2Smrg
1208627f7eb2Smrg match
gfc_match_array_constructor(gfc_expr ** result)1209627f7eb2Smrg gfc_match_array_constructor (gfc_expr **result)
1210627f7eb2Smrg {
1211627f7eb2Smrg gfc_constructor *c;
1212627f7eb2Smrg gfc_constructor_base head;
1213627f7eb2Smrg gfc_expr *expr;
1214627f7eb2Smrg gfc_typespec ts;
1215627f7eb2Smrg locus where;
1216627f7eb2Smrg match m;
1217627f7eb2Smrg const char *end_delim;
1218627f7eb2Smrg bool seen_ts;
1219627f7eb2Smrg
1220627f7eb2Smrg head = NULL;
1221627f7eb2Smrg seen_ts = false;
1222627f7eb2Smrg
1223627f7eb2Smrg if (gfc_match (" (/") == MATCH_NO)
1224627f7eb2Smrg {
1225627f7eb2Smrg if (gfc_match (" [") == MATCH_NO)
1226627f7eb2Smrg return MATCH_NO;
1227627f7eb2Smrg else
1228627f7eb2Smrg {
1229627f7eb2Smrg if (!gfc_notify_std (GFC_STD_F2003, "[...] "
1230627f7eb2Smrg "style array constructors at %C"))
1231627f7eb2Smrg return MATCH_ERROR;
1232627f7eb2Smrg end_delim = " ]";
1233627f7eb2Smrg }
1234627f7eb2Smrg }
1235627f7eb2Smrg else
1236627f7eb2Smrg end_delim = " /)";
1237627f7eb2Smrg
1238627f7eb2Smrg where = gfc_current_locus;
1239627f7eb2Smrg
1240627f7eb2Smrg /* Try to match an optional "type-spec ::" */
1241627f7eb2Smrg gfc_clear_ts (&ts);
1242627f7eb2Smrg m = gfc_match_type_spec (&ts);
1243627f7eb2Smrg if (m == MATCH_YES)
1244627f7eb2Smrg {
1245627f7eb2Smrg seen_ts = (gfc_match (" ::") == MATCH_YES);
1246627f7eb2Smrg
1247627f7eb2Smrg if (seen_ts)
1248627f7eb2Smrg {
1249627f7eb2Smrg if (!gfc_notify_std (GFC_STD_F2003, "Array constructor "
1250627f7eb2Smrg "including type specification at %C"))
1251627f7eb2Smrg goto cleanup;
1252627f7eb2Smrg
1253627f7eb2Smrg if (ts.deferred)
1254627f7eb2Smrg {
1255627f7eb2Smrg gfc_error ("Type-spec at %L cannot contain a deferred "
1256627f7eb2Smrg "type parameter", &where);
1257627f7eb2Smrg goto cleanup;
1258627f7eb2Smrg }
1259627f7eb2Smrg
1260627f7eb2Smrg if (ts.type == BT_CHARACTER
1261627f7eb2Smrg && ts.u.cl && !ts.u.cl->length && !ts.u.cl->length_from_typespec)
1262627f7eb2Smrg {
1263627f7eb2Smrg gfc_error ("Type-spec at %L cannot contain an asterisk for a "
1264627f7eb2Smrg "type parameter", &where);
1265627f7eb2Smrg goto cleanup;
1266627f7eb2Smrg }
1267627f7eb2Smrg }
1268627f7eb2Smrg }
1269627f7eb2Smrg else if (m == MATCH_ERROR)
1270627f7eb2Smrg goto cleanup;
1271627f7eb2Smrg
1272627f7eb2Smrg if (!seen_ts)
1273627f7eb2Smrg gfc_current_locus = where;
1274627f7eb2Smrg
1275627f7eb2Smrg if (gfc_match (end_delim) == MATCH_YES)
1276627f7eb2Smrg {
1277627f7eb2Smrg if (seen_ts)
1278627f7eb2Smrg goto done;
1279627f7eb2Smrg else
1280627f7eb2Smrg {
1281627f7eb2Smrg gfc_error ("Empty array constructor at %C is not allowed");
1282627f7eb2Smrg goto cleanup;
1283627f7eb2Smrg }
1284627f7eb2Smrg }
1285627f7eb2Smrg
1286627f7eb2Smrg for (;;)
1287627f7eb2Smrg {
1288627f7eb2Smrg m = match_array_cons_element (&head);
1289627f7eb2Smrg if (m == MATCH_ERROR)
1290627f7eb2Smrg goto cleanup;
1291627f7eb2Smrg if (m == MATCH_NO)
1292627f7eb2Smrg goto syntax;
1293627f7eb2Smrg
1294627f7eb2Smrg if (gfc_match_char (',') == MATCH_NO)
1295627f7eb2Smrg break;
1296627f7eb2Smrg }
1297627f7eb2Smrg
1298627f7eb2Smrg if (gfc_match (end_delim) == MATCH_NO)
1299627f7eb2Smrg goto syntax;
1300627f7eb2Smrg
1301627f7eb2Smrg done:
1302627f7eb2Smrg /* Size must be calculated at resolution time. */
1303627f7eb2Smrg if (seen_ts)
1304627f7eb2Smrg {
1305627f7eb2Smrg expr = gfc_get_array_expr (ts.type, ts.kind, &where);
1306627f7eb2Smrg expr->ts = ts;
1307627f7eb2Smrg
1308627f7eb2Smrg /* If the typespec is CHARACTER, check that array elements can
1309627f7eb2Smrg be converted. See PR fortran/67803. */
1310627f7eb2Smrg if (ts.type == BT_CHARACTER)
1311627f7eb2Smrg {
1312627f7eb2Smrg c = gfc_constructor_first (head);
1313627f7eb2Smrg for (; c; c = gfc_constructor_next (c))
1314627f7eb2Smrg {
1315627f7eb2Smrg if (gfc_numeric_ts (&c->expr->ts)
1316627f7eb2Smrg || c->expr->ts.type == BT_LOGICAL)
1317627f7eb2Smrg {
1318627f7eb2Smrg gfc_error ("Incompatible typespec for array element at %L",
1319627f7eb2Smrg &c->expr->where);
1320627f7eb2Smrg return MATCH_ERROR;
1321627f7eb2Smrg }
1322627f7eb2Smrg
1323627f7eb2Smrg /* Special case null(). */
1324627f7eb2Smrg if (c->expr->expr_type == EXPR_FUNCTION
1325627f7eb2Smrg && c->expr->ts.type == BT_UNKNOWN
1326627f7eb2Smrg && strcmp (c->expr->symtree->name, "null") == 0)
1327627f7eb2Smrg {
1328627f7eb2Smrg gfc_error ("Incompatible typespec for array element at %L",
1329627f7eb2Smrg &c->expr->where);
1330627f7eb2Smrg return MATCH_ERROR;
1331627f7eb2Smrg }
1332627f7eb2Smrg }
1333627f7eb2Smrg }
1334627f7eb2Smrg
1335627f7eb2Smrg /* Walk the constructor, and if possible, do type conversion for
1336627f7eb2Smrg numeric types. */
1337627f7eb2Smrg if (gfc_numeric_ts (&ts))
1338627f7eb2Smrg {
1339627f7eb2Smrg m = walk_array_constructor (&ts, head);
1340627f7eb2Smrg if (m == MATCH_ERROR)
1341627f7eb2Smrg return m;
1342627f7eb2Smrg }
1343627f7eb2Smrg }
1344627f7eb2Smrg else
1345627f7eb2Smrg expr = gfc_get_array_expr (BT_UNKNOWN, 0, &where);
1346627f7eb2Smrg
1347627f7eb2Smrg expr->value.constructor = head;
1348627f7eb2Smrg if (expr->ts.u.cl)
1349627f7eb2Smrg expr->ts.u.cl->length_from_typespec = seen_ts;
1350627f7eb2Smrg
1351627f7eb2Smrg *result = expr;
1352627f7eb2Smrg
1353627f7eb2Smrg return MATCH_YES;
1354627f7eb2Smrg
1355627f7eb2Smrg syntax:
1356627f7eb2Smrg gfc_error ("Syntax error in array constructor at %C");
1357627f7eb2Smrg
1358627f7eb2Smrg cleanup:
1359627f7eb2Smrg gfc_constructor_free (head);
1360627f7eb2Smrg return MATCH_ERROR;
1361627f7eb2Smrg }
1362627f7eb2Smrg
1363627f7eb2Smrg
1364627f7eb2Smrg
1365627f7eb2Smrg /************** Check array constructors for correctness **************/
1366627f7eb2Smrg
1367627f7eb2Smrg /* Given an expression, compare it's type with the type of the current
1368627f7eb2Smrg constructor. Returns nonzero if an error was issued. The
1369627f7eb2Smrg cons_state variable keeps track of whether the type of the
1370627f7eb2Smrg constructor being read or resolved is known to be good, bad or just
1371627f7eb2Smrg starting out. */
1372627f7eb2Smrg
1373627f7eb2Smrg static gfc_typespec constructor_ts;
1374627f7eb2Smrg static enum
1375627f7eb2Smrg { CONS_START, CONS_GOOD, CONS_BAD }
1376627f7eb2Smrg cons_state;
1377627f7eb2Smrg
1378627f7eb2Smrg static int
check_element_type(gfc_expr * expr,bool convert)1379627f7eb2Smrg check_element_type (gfc_expr *expr, bool convert)
1380627f7eb2Smrg {
1381627f7eb2Smrg if (cons_state == CONS_BAD)
1382627f7eb2Smrg return 0; /* Suppress further errors */
1383627f7eb2Smrg
1384627f7eb2Smrg if (cons_state == CONS_START)
1385627f7eb2Smrg {
1386627f7eb2Smrg if (expr->ts.type == BT_UNKNOWN)
1387627f7eb2Smrg cons_state = CONS_BAD;
1388627f7eb2Smrg else
1389627f7eb2Smrg {
1390627f7eb2Smrg cons_state = CONS_GOOD;
1391627f7eb2Smrg constructor_ts = expr->ts;
1392627f7eb2Smrg }
1393627f7eb2Smrg
1394627f7eb2Smrg return 0;
1395627f7eb2Smrg }
1396627f7eb2Smrg
1397627f7eb2Smrg if (gfc_compare_types (&constructor_ts, &expr->ts))
1398627f7eb2Smrg return 0;
1399627f7eb2Smrg
1400627f7eb2Smrg if (convert)
1401*4c3eb207Smrg return gfc_convert_type_warn (expr, &constructor_ts, 1, 1, true) ? 0 : 1;
1402627f7eb2Smrg
1403627f7eb2Smrg gfc_error ("Element in %s array constructor at %L is %s",
1404627f7eb2Smrg gfc_typename (&constructor_ts), &expr->where,
1405*4c3eb207Smrg gfc_typename (expr));
1406627f7eb2Smrg
1407627f7eb2Smrg cons_state = CONS_BAD;
1408627f7eb2Smrg return 1;
1409627f7eb2Smrg }
1410627f7eb2Smrg
1411627f7eb2Smrg
1412627f7eb2Smrg /* Recursive work function for gfc_check_constructor_type(). */
1413627f7eb2Smrg
1414627f7eb2Smrg static bool
check_constructor_type(gfc_constructor_base base,bool convert)1415627f7eb2Smrg check_constructor_type (gfc_constructor_base base, bool convert)
1416627f7eb2Smrg {
1417627f7eb2Smrg gfc_constructor *c;
1418627f7eb2Smrg gfc_expr *e;
1419627f7eb2Smrg
1420627f7eb2Smrg for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
1421627f7eb2Smrg {
1422627f7eb2Smrg e = c->expr;
1423627f7eb2Smrg
1424627f7eb2Smrg if (e->expr_type == EXPR_ARRAY)
1425627f7eb2Smrg {
1426627f7eb2Smrg if (!check_constructor_type (e->value.constructor, convert))
1427627f7eb2Smrg return false;
1428627f7eb2Smrg
1429627f7eb2Smrg continue;
1430627f7eb2Smrg }
1431627f7eb2Smrg
1432627f7eb2Smrg if (check_element_type (e, convert))
1433627f7eb2Smrg return false;
1434627f7eb2Smrg }
1435627f7eb2Smrg
1436627f7eb2Smrg return true;
1437627f7eb2Smrg }
1438627f7eb2Smrg
1439627f7eb2Smrg
1440627f7eb2Smrg /* Check that all elements of an array constructor are the same type.
1441627f7eb2Smrg On false, an error has been generated. */
1442627f7eb2Smrg
1443627f7eb2Smrg bool
gfc_check_constructor_type(gfc_expr * e)1444627f7eb2Smrg gfc_check_constructor_type (gfc_expr *e)
1445627f7eb2Smrg {
1446627f7eb2Smrg bool t;
1447627f7eb2Smrg
1448627f7eb2Smrg if (e->ts.type != BT_UNKNOWN)
1449627f7eb2Smrg {
1450627f7eb2Smrg cons_state = CONS_GOOD;
1451627f7eb2Smrg constructor_ts = e->ts;
1452627f7eb2Smrg }
1453627f7eb2Smrg else
1454627f7eb2Smrg {
1455627f7eb2Smrg cons_state = CONS_START;
1456627f7eb2Smrg gfc_clear_ts (&constructor_ts);
1457627f7eb2Smrg }
1458627f7eb2Smrg
1459627f7eb2Smrg /* If e->ts.type != BT_UNKNOWN, the array constructor included a
1460627f7eb2Smrg typespec, and we will now convert the values on the fly. */
1461627f7eb2Smrg t = check_constructor_type (e->value.constructor, e->ts.type != BT_UNKNOWN);
1462627f7eb2Smrg if (t && e->ts.type == BT_UNKNOWN)
1463627f7eb2Smrg e->ts = constructor_ts;
1464627f7eb2Smrg
1465627f7eb2Smrg return t;
1466627f7eb2Smrg }
1467627f7eb2Smrg
1468627f7eb2Smrg
1469627f7eb2Smrg
1470627f7eb2Smrg typedef struct cons_stack
1471627f7eb2Smrg {
1472627f7eb2Smrg gfc_iterator *iterator;
1473627f7eb2Smrg struct cons_stack *previous;
1474627f7eb2Smrg }
1475627f7eb2Smrg cons_stack;
1476627f7eb2Smrg
1477627f7eb2Smrg static cons_stack *base;
1478627f7eb2Smrg
1479627f7eb2Smrg static bool check_constructor (gfc_constructor_base, bool (*) (gfc_expr *));
1480627f7eb2Smrg
1481627f7eb2Smrg /* Check an EXPR_VARIABLE expression in a constructor to make sure
1482*4c3eb207Smrg that that variable is an iteration variable. */
1483627f7eb2Smrg
1484627f7eb2Smrg bool
gfc_check_iter_variable(gfc_expr * expr)1485627f7eb2Smrg gfc_check_iter_variable (gfc_expr *expr)
1486627f7eb2Smrg {
1487627f7eb2Smrg gfc_symbol *sym;
1488627f7eb2Smrg cons_stack *c;
1489627f7eb2Smrg
1490627f7eb2Smrg sym = expr->symtree->n.sym;
1491627f7eb2Smrg
1492627f7eb2Smrg for (c = base; c && c->iterator; c = c->previous)
1493627f7eb2Smrg if (sym == c->iterator->var->symtree->n.sym)
1494627f7eb2Smrg return true;
1495627f7eb2Smrg
1496627f7eb2Smrg return false;
1497627f7eb2Smrg }
1498627f7eb2Smrg
1499627f7eb2Smrg
1500627f7eb2Smrg /* Recursive work function for gfc_check_constructor(). This amounts
1501627f7eb2Smrg to calling the check function for each expression in the
1502627f7eb2Smrg constructor, giving variables with the names of iterators a pass. */
1503627f7eb2Smrg
1504627f7eb2Smrg static bool
check_constructor(gfc_constructor_base ctor,bool (* check_function)(gfc_expr *))1505627f7eb2Smrg check_constructor (gfc_constructor_base ctor, bool (*check_function) (gfc_expr *))
1506627f7eb2Smrg {
1507627f7eb2Smrg cons_stack element;
1508627f7eb2Smrg gfc_expr *e;
1509627f7eb2Smrg bool t;
1510627f7eb2Smrg gfc_constructor *c;
1511627f7eb2Smrg
1512627f7eb2Smrg for (c = gfc_constructor_first (ctor); c; c = gfc_constructor_next (c))
1513627f7eb2Smrg {
1514627f7eb2Smrg e = c->expr;
1515627f7eb2Smrg
1516627f7eb2Smrg if (!e)
1517627f7eb2Smrg continue;
1518627f7eb2Smrg
1519627f7eb2Smrg if (e->expr_type != EXPR_ARRAY)
1520627f7eb2Smrg {
1521627f7eb2Smrg if (!(*check_function)(e))
1522627f7eb2Smrg return false;
1523627f7eb2Smrg continue;
1524627f7eb2Smrg }
1525627f7eb2Smrg
1526627f7eb2Smrg element.previous = base;
1527627f7eb2Smrg element.iterator = c->iterator;
1528627f7eb2Smrg
1529627f7eb2Smrg base = &element;
1530627f7eb2Smrg t = check_constructor (e->value.constructor, check_function);
1531627f7eb2Smrg base = element.previous;
1532627f7eb2Smrg
1533627f7eb2Smrg if (!t)
1534627f7eb2Smrg return false;
1535627f7eb2Smrg }
1536627f7eb2Smrg
1537627f7eb2Smrg /* Nothing went wrong, so all OK. */
1538627f7eb2Smrg return true;
1539627f7eb2Smrg }
1540627f7eb2Smrg
1541627f7eb2Smrg
1542627f7eb2Smrg /* Checks a constructor to see if it is a particular kind of
1543627f7eb2Smrg expression -- specification, restricted, or initialization as
1544627f7eb2Smrg determined by the check_function. */
1545627f7eb2Smrg
1546627f7eb2Smrg bool
gfc_check_constructor(gfc_expr * expr,bool (* check_function)(gfc_expr *))1547627f7eb2Smrg gfc_check_constructor (gfc_expr *expr, bool (*check_function) (gfc_expr *))
1548627f7eb2Smrg {
1549627f7eb2Smrg cons_stack *base_save;
1550627f7eb2Smrg bool t;
1551627f7eb2Smrg
1552627f7eb2Smrg base_save = base;
1553627f7eb2Smrg base = NULL;
1554627f7eb2Smrg
1555627f7eb2Smrg t = check_constructor (expr->value.constructor, check_function);
1556627f7eb2Smrg base = base_save;
1557627f7eb2Smrg
1558627f7eb2Smrg return t;
1559627f7eb2Smrg }
1560627f7eb2Smrg
1561627f7eb2Smrg
1562627f7eb2Smrg
1563627f7eb2Smrg /**************** Simplification of array constructors ****************/
1564627f7eb2Smrg
1565627f7eb2Smrg iterator_stack *iter_stack;
1566627f7eb2Smrg
1567627f7eb2Smrg typedef struct
1568627f7eb2Smrg {
1569627f7eb2Smrg gfc_constructor_base base;
1570627f7eb2Smrg int extract_count, extract_n;
1571627f7eb2Smrg gfc_expr *extracted;
1572627f7eb2Smrg mpz_t *count;
1573627f7eb2Smrg
1574627f7eb2Smrg mpz_t *offset;
1575627f7eb2Smrg gfc_component *component;
1576627f7eb2Smrg mpz_t *repeat;
1577627f7eb2Smrg
1578627f7eb2Smrg bool (*expand_work_function) (gfc_expr *);
1579627f7eb2Smrg }
1580627f7eb2Smrg expand_info;
1581627f7eb2Smrg
1582627f7eb2Smrg static expand_info current_expand;
1583627f7eb2Smrg
1584627f7eb2Smrg static bool expand_constructor (gfc_constructor_base);
1585627f7eb2Smrg
1586627f7eb2Smrg
1587627f7eb2Smrg /* Work function that counts the number of elements present in a
1588627f7eb2Smrg constructor. */
1589627f7eb2Smrg
1590627f7eb2Smrg static bool
count_elements(gfc_expr * e)1591627f7eb2Smrg count_elements (gfc_expr *e)
1592627f7eb2Smrg {
1593627f7eb2Smrg mpz_t result;
1594627f7eb2Smrg
1595627f7eb2Smrg if (e->rank == 0)
1596627f7eb2Smrg mpz_add_ui (*current_expand.count, *current_expand.count, 1);
1597627f7eb2Smrg else
1598627f7eb2Smrg {
1599627f7eb2Smrg if (!gfc_array_size (e, &result))
1600627f7eb2Smrg {
1601627f7eb2Smrg gfc_free_expr (e);
1602627f7eb2Smrg return false;
1603627f7eb2Smrg }
1604627f7eb2Smrg
1605627f7eb2Smrg mpz_add (*current_expand.count, *current_expand.count, result);
1606627f7eb2Smrg mpz_clear (result);
1607627f7eb2Smrg }
1608627f7eb2Smrg
1609627f7eb2Smrg gfc_free_expr (e);
1610627f7eb2Smrg return true;
1611627f7eb2Smrg }
1612627f7eb2Smrg
1613627f7eb2Smrg
1614627f7eb2Smrg /* Work function that extracts a particular element from an array
1615627f7eb2Smrg constructor, freeing the rest. */
1616627f7eb2Smrg
1617627f7eb2Smrg static bool
extract_element(gfc_expr * e)1618627f7eb2Smrg extract_element (gfc_expr *e)
1619627f7eb2Smrg {
1620627f7eb2Smrg if (e->rank != 0)
1621627f7eb2Smrg { /* Something unextractable */
1622627f7eb2Smrg gfc_free_expr (e);
1623627f7eb2Smrg return false;
1624627f7eb2Smrg }
1625627f7eb2Smrg
1626627f7eb2Smrg if (current_expand.extract_count == current_expand.extract_n)
1627627f7eb2Smrg current_expand.extracted = e;
1628627f7eb2Smrg else
1629627f7eb2Smrg gfc_free_expr (e);
1630627f7eb2Smrg
1631627f7eb2Smrg current_expand.extract_count++;
1632627f7eb2Smrg
1633627f7eb2Smrg return true;
1634627f7eb2Smrg }
1635627f7eb2Smrg
1636627f7eb2Smrg
1637627f7eb2Smrg /* Work function that constructs a new constructor out of the old one,
1638627f7eb2Smrg stringing new elements together. */
1639627f7eb2Smrg
1640627f7eb2Smrg static bool
expand(gfc_expr * e)1641627f7eb2Smrg expand (gfc_expr *e)
1642627f7eb2Smrg {
1643627f7eb2Smrg gfc_constructor *c = gfc_constructor_append_expr (¤t_expand.base,
1644627f7eb2Smrg e, &e->where);
1645627f7eb2Smrg
1646627f7eb2Smrg c->n.component = current_expand.component;
1647627f7eb2Smrg return true;
1648627f7eb2Smrg }
1649627f7eb2Smrg
1650627f7eb2Smrg
1651627f7eb2Smrg /* Given an initialization expression that is a variable reference,
1652627f7eb2Smrg substitute the current value of the iteration variable. */
1653627f7eb2Smrg
1654627f7eb2Smrg void
gfc_simplify_iterator_var(gfc_expr * e)1655627f7eb2Smrg gfc_simplify_iterator_var (gfc_expr *e)
1656627f7eb2Smrg {
1657627f7eb2Smrg iterator_stack *p;
1658627f7eb2Smrg
1659627f7eb2Smrg for (p = iter_stack; p; p = p->prev)
1660627f7eb2Smrg if (e->symtree == p->variable)
1661627f7eb2Smrg break;
1662627f7eb2Smrg
1663627f7eb2Smrg if (p == NULL)
1664627f7eb2Smrg return; /* Variable not found */
1665627f7eb2Smrg
1666627f7eb2Smrg gfc_replace_expr (e, gfc_get_int_expr (gfc_default_integer_kind, NULL, 0));
1667627f7eb2Smrg
1668627f7eb2Smrg mpz_set (e->value.integer, p->value);
1669627f7eb2Smrg
1670627f7eb2Smrg return;
1671627f7eb2Smrg }
1672627f7eb2Smrg
1673627f7eb2Smrg
1674627f7eb2Smrg /* Expand an expression with that is inside of a constructor,
1675627f7eb2Smrg recursing into other constructors if present. */
1676627f7eb2Smrg
1677627f7eb2Smrg static bool
expand_expr(gfc_expr * e)1678627f7eb2Smrg expand_expr (gfc_expr *e)
1679627f7eb2Smrg {
1680627f7eb2Smrg if (e->expr_type == EXPR_ARRAY)
1681627f7eb2Smrg return expand_constructor (e->value.constructor);
1682627f7eb2Smrg
1683627f7eb2Smrg e = gfc_copy_expr (e);
1684627f7eb2Smrg
1685627f7eb2Smrg if (!gfc_simplify_expr (e, 1))
1686627f7eb2Smrg {
1687627f7eb2Smrg gfc_free_expr (e);
1688627f7eb2Smrg return false;
1689627f7eb2Smrg }
1690627f7eb2Smrg
1691627f7eb2Smrg return current_expand.expand_work_function (e);
1692627f7eb2Smrg }
1693627f7eb2Smrg
1694627f7eb2Smrg
1695627f7eb2Smrg static bool
expand_iterator(gfc_constructor * c)1696627f7eb2Smrg expand_iterator (gfc_constructor *c)
1697627f7eb2Smrg {
1698627f7eb2Smrg gfc_expr *start, *end, *step;
1699627f7eb2Smrg iterator_stack frame;
1700627f7eb2Smrg mpz_t trip;
1701627f7eb2Smrg bool t;
1702627f7eb2Smrg
1703627f7eb2Smrg end = step = NULL;
1704627f7eb2Smrg
1705627f7eb2Smrg t = false;
1706627f7eb2Smrg
1707627f7eb2Smrg mpz_init (trip);
1708627f7eb2Smrg mpz_init (frame.value);
1709627f7eb2Smrg frame.prev = NULL;
1710627f7eb2Smrg
1711627f7eb2Smrg start = gfc_copy_expr (c->iterator->start);
1712627f7eb2Smrg if (!gfc_simplify_expr (start, 1))
1713627f7eb2Smrg goto cleanup;
1714627f7eb2Smrg
1715627f7eb2Smrg if (start->expr_type != EXPR_CONSTANT || start->ts.type != BT_INTEGER)
1716627f7eb2Smrg goto cleanup;
1717627f7eb2Smrg
1718627f7eb2Smrg end = gfc_copy_expr (c->iterator->end);
1719627f7eb2Smrg if (!gfc_simplify_expr (end, 1))
1720627f7eb2Smrg goto cleanup;
1721627f7eb2Smrg
1722627f7eb2Smrg if (end->expr_type != EXPR_CONSTANT || end->ts.type != BT_INTEGER)
1723627f7eb2Smrg goto cleanup;
1724627f7eb2Smrg
1725627f7eb2Smrg step = gfc_copy_expr (c->iterator->step);
1726627f7eb2Smrg if (!gfc_simplify_expr (step, 1))
1727627f7eb2Smrg goto cleanup;
1728627f7eb2Smrg
1729627f7eb2Smrg if (step->expr_type != EXPR_CONSTANT || step->ts.type != BT_INTEGER)
1730627f7eb2Smrg goto cleanup;
1731627f7eb2Smrg
1732627f7eb2Smrg if (mpz_sgn (step->value.integer) == 0)
1733627f7eb2Smrg {
1734627f7eb2Smrg gfc_error ("Iterator step at %L cannot be zero", &step->where);
1735627f7eb2Smrg goto cleanup;
1736627f7eb2Smrg }
1737627f7eb2Smrg
1738627f7eb2Smrg /* Calculate the trip count of the loop. */
1739627f7eb2Smrg mpz_sub (trip, end->value.integer, start->value.integer);
1740627f7eb2Smrg mpz_add (trip, trip, step->value.integer);
1741627f7eb2Smrg mpz_tdiv_q (trip, trip, step->value.integer);
1742627f7eb2Smrg
1743627f7eb2Smrg mpz_set (frame.value, start->value.integer);
1744627f7eb2Smrg
1745627f7eb2Smrg frame.prev = iter_stack;
1746627f7eb2Smrg frame.variable = c->iterator->var->symtree;
1747627f7eb2Smrg iter_stack = &frame;
1748627f7eb2Smrg
1749627f7eb2Smrg while (mpz_sgn (trip) > 0)
1750627f7eb2Smrg {
1751627f7eb2Smrg if (!expand_expr (c->expr))
1752627f7eb2Smrg goto cleanup;
1753627f7eb2Smrg
1754627f7eb2Smrg mpz_add (frame.value, frame.value, step->value.integer);
1755627f7eb2Smrg mpz_sub_ui (trip, trip, 1);
1756627f7eb2Smrg }
1757627f7eb2Smrg
1758627f7eb2Smrg t = true;
1759627f7eb2Smrg
1760627f7eb2Smrg cleanup:
1761627f7eb2Smrg gfc_free_expr (start);
1762627f7eb2Smrg gfc_free_expr (end);
1763627f7eb2Smrg gfc_free_expr (step);
1764627f7eb2Smrg
1765627f7eb2Smrg mpz_clear (trip);
1766627f7eb2Smrg mpz_clear (frame.value);
1767627f7eb2Smrg
1768627f7eb2Smrg iter_stack = frame.prev;
1769627f7eb2Smrg
1770627f7eb2Smrg return t;
1771627f7eb2Smrg }
1772627f7eb2Smrg
1773*4c3eb207Smrg /* Variables for noticing if all constructors are empty, and
1774*4c3eb207Smrg if any of them had a type. */
1775*4c3eb207Smrg
1776*4c3eb207Smrg static bool empty_constructor;
1777*4c3eb207Smrg static gfc_typespec empty_ts;
1778627f7eb2Smrg
1779627f7eb2Smrg /* Expand a constructor into constant constructors without any
1780627f7eb2Smrg iterators, calling the work function for each of the expanded
1781627f7eb2Smrg expressions. The work function needs to either save or free the
1782627f7eb2Smrg passed expression. */
1783627f7eb2Smrg
1784627f7eb2Smrg static bool
expand_constructor(gfc_constructor_base base)1785627f7eb2Smrg expand_constructor (gfc_constructor_base base)
1786627f7eb2Smrg {
1787627f7eb2Smrg gfc_constructor *c;
1788627f7eb2Smrg gfc_expr *e;
1789627f7eb2Smrg
1790627f7eb2Smrg for (c = gfc_constructor_first (base); c; c = gfc_constructor_next(c))
1791627f7eb2Smrg {
1792627f7eb2Smrg if (c->iterator != NULL)
1793627f7eb2Smrg {
1794627f7eb2Smrg if (!expand_iterator (c))
1795627f7eb2Smrg return false;
1796627f7eb2Smrg continue;
1797627f7eb2Smrg }
1798627f7eb2Smrg
1799627f7eb2Smrg e = c->expr;
1800627f7eb2Smrg
1801*4c3eb207Smrg if (e == NULL)
1802*4c3eb207Smrg return false;
1803*4c3eb207Smrg
1804*4c3eb207Smrg if (empty_constructor)
1805*4c3eb207Smrg empty_ts = e->ts;
1806*4c3eb207Smrg
1807*4c3eb207Smrg /* Simplify constant array expression/section within constructor. */
1808*4c3eb207Smrg if (e->expr_type == EXPR_VARIABLE && e->rank > 0 && e->ref
1809*4c3eb207Smrg && e->symtree && e->symtree->n.sym
1810*4c3eb207Smrg && e->symtree->n.sym->attr.flavor == FL_PARAMETER)
1811*4c3eb207Smrg gfc_simplify_expr (e, 0);
1812*4c3eb207Smrg
1813627f7eb2Smrg if (e->expr_type == EXPR_ARRAY)
1814627f7eb2Smrg {
1815627f7eb2Smrg if (!expand_constructor (e->value.constructor))
1816627f7eb2Smrg return false;
1817627f7eb2Smrg
1818627f7eb2Smrg continue;
1819627f7eb2Smrg }
1820627f7eb2Smrg
1821*4c3eb207Smrg empty_constructor = false;
1822627f7eb2Smrg e = gfc_copy_expr (e);
1823627f7eb2Smrg if (!gfc_simplify_expr (e, 1))
1824627f7eb2Smrg {
1825627f7eb2Smrg gfc_free_expr (e);
1826627f7eb2Smrg return false;
1827627f7eb2Smrg }
1828*4c3eb207Smrg e->from_constructor = 1;
1829627f7eb2Smrg current_expand.offset = &c->offset;
1830627f7eb2Smrg current_expand.repeat = &c->repeat;
1831627f7eb2Smrg current_expand.component = c->n.component;
1832627f7eb2Smrg if (!current_expand.expand_work_function(e))
1833627f7eb2Smrg return false;
1834627f7eb2Smrg }
1835627f7eb2Smrg return true;
1836627f7eb2Smrg }
1837627f7eb2Smrg
1838627f7eb2Smrg
1839627f7eb2Smrg /* Given an array expression and an element number (starting at zero),
1840627f7eb2Smrg return a pointer to the array element. NULL is returned if the
1841627f7eb2Smrg size of the array has been exceeded. The expression node returned
1842627f7eb2Smrg remains a part of the array and should not be freed. Access is not
1843627f7eb2Smrg efficient at all, but this is another place where things do not
1844627f7eb2Smrg have to be particularly fast. */
1845627f7eb2Smrg
1846627f7eb2Smrg static gfc_expr *
gfc_get_array_element(gfc_expr * array,int element)1847627f7eb2Smrg gfc_get_array_element (gfc_expr *array, int element)
1848627f7eb2Smrg {
1849627f7eb2Smrg expand_info expand_save;
1850627f7eb2Smrg gfc_expr *e;
1851627f7eb2Smrg bool rc;
1852627f7eb2Smrg
1853627f7eb2Smrg expand_save = current_expand;
1854627f7eb2Smrg current_expand.extract_n = element;
1855627f7eb2Smrg current_expand.expand_work_function = extract_element;
1856627f7eb2Smrg current_expand.extracted = NULL;
1857627f7eb2Smrg current_expand.extract_count = 0;
1858627f7eb2Smrg
1859627f7eb2Smrg iter_stack = NULL;
1860627f7eb2Smrg
1861627f7eb2Smrg rc = expand_constructor (array->value.constructor);
1862627f7eb2Smrg e = current_expand.extracted;
1863627f7eb2Smrg current_expand = expand_save;
1864627f7eb2Smrg
1865627f7eb2Smrg if (!rc)
1866627f7eb2Smrg return NULL;
1867627f7eb2Smrg
1868627f7eb2Smrg return e;
1869627f7eb2Smrg }
1870627f7eb2Smrg
1871627f7eb2Smrg
1872627f7eb2Smrg /* Top level subroutine for expanding constructors. We only expand
1873627f7eb2Smrg constructor if they are small enough. */
1874627f7eb2Smrg
1875627f7eb2Smrg bool
gfc_expand_constructor(gfc_expr * e,bool fatal)1876627f7eb2Smrg gfc_expand_constructor (gfc_expr *e, bool fatal)
1877627f7eb2Smrg {
1878627f7eb2Smrg expand_info expand_save;
1879627f7eb2Smrg gfc_expr *f;
1880627f7eb2Smrg bool rc;
1881627f7eb2Smrg
1882*4c3eb207Smrg if (gfc_is_size_zero_array (e))
1883*4c3eb207Smrg return true;
1884*4c3eb207Smrg
1885627f7eb2Smrg /* If we can successfully get an array element at the max array size then
1886627f7eb2Smrg the array is too big to expand, so we just return. */
1887627f7eb2Smrg f = gfc_get_array_element (e, flag_max_array_constructor);
1888627f7eb2Smrg if (f != NULL)
1889627f7eb2Smrg {
1890627f7eb2Smrg gfc_free_expr (f);
1891627f7eb2Smrg if (fatal)
1892627f7eb2Smrg {
1893627f7eb2Smrg gfc_error ("The number of elements in the array constructor "
1894627f7eb2Smrg "at %L requires an increase of the allowed %d "
1895627f7eb2Smrg "upper limit. See %<-fmax-array-constructor%> "
1896627f7eb2Smrg "option", &e->where, flag_max_array_constructor);
1897627f7eb2Smrg return false;
1898627f7eb2Smrg }
1899627f7eb2Smrg return true;
1900627f7eb2Smrg }
1901627f7eb2Smrg
1902627f7eb2Smrg /* We now know the array is not too big so go ahead and try to expand it. */
1903627f7eb2Smrg expand_save = current_expand;
1904627f7eb2Smrg current_expand.base = NULL;
1905627f7eb2Smrg
1906627f7eb2Smrg iter_stack = NULL;
1907627f7eb2Smrg
1908*4c3eb207Smrg empty_constructor = true;
1909*4c3eb207Smrg gfc_clear_ts (&empty_ts);
1910627f7eb2Smrg current_expand.expand_work_function = expand;
1911627f7eb2Smrg
1912627f7eb2Smrg if (!expand_constructor (e->value.constructor))
1913627f7eb2Smrg {
1914627f7eb2Smrg gfc_constructor_free (current_expand.base);
1915627f7eb2Smrg rc = false;
1916627f7eb2Smrg goto done;
1917627f7eb2Smrg }
1918627f7eb2Smrg
1919*4c3eb207Smrg /* If we don't have an explicit constructor type, and there
1920*4c3eb207Smrg were only empty constructors, then take the type from
1921*4c3eb207Smrg them. */
1922*4c3eb207Smrg
1923*4c3eb207Smrg if (constructor_ts.type == BT_UNKNOWN && empty_constructor)
1924*4c3eb207Smrg e->ts = empty_ts;
1925*4c3eb207Smrg
1926627f7eb2Smrg gfc_constructor_free (e->value.constructor);
1927627f7eb2Smrg e->value.constructor = current_expand.base;
1928627f7eb2Smrg
1929627f7eb2Smrg rc = true;
1930627f7eb2Smrg
1931627f7eb2Smrg done:
1932627f7eb2Smrg current_expand = expand_save;
1933627f7eb2Smrg
1934627f7eb2Smrg return rc;
1935627f7eb2Smrg }
1936627f7eb2Smrg
1937627f7eb2Smrg
1938627f7eb2Smrg /* Work function for checking that an element of a constructor is a
1939627f7eb2Smrg constant, after removal of any iteration variables. We return
1940627f7eb2Smrg false if not so. */
1941627f7eb2Smrg
1942627f7eb2Smrg static bool
is_constant_element(gfc_expr * e)1943627f7eb2Smrg is_constant_element (gfc_expr *e)
1944627f7eb2Smrg {
1945627f7eb2Smrg int rv;
1946627f7eb2Smrg
1947627f7eb2Smrg rv = gfc_is_constant_expr (e);
1948627f7eb2Smrg gfc_free_expr (e);
1949627f7eb2Smrg
1950627f7eb2Smrg return rv ? true : false;
1951627f7eb2Smrg }
1952627f7eb2Smrg
1953627f7eb2Smrg
1954627f7eb2Smrg /* Given an array constructor, determine if the constructor is
1955627f7eb2Smrg constant or not by expanding it and making sure that all elements
1956627f7eb2Smrg are constants. This is a bit of a hack since something like (/ (i,
1957627f7eb2Smrg i=1,100000000) /) will take a while as* opposed to a more clever
1958627f7eb2Smrg function that traverses the expression tree. FIXME. */
1959627f7eb2Smrg
1960627f7eb2Smrg int
gfc_constant_ac(gfc_expr * e)1961627f7eb2Smrg gfc_constant_ac (gfc_expr *e)
1962627f7eb2Smrg {
1963627f7eb2Smrg expand_info expand_save;
1964627f7eb2Smrg bool rc;
1965627f7eb2Smrg
1966627f7eb2Smrg iter_stack = NULL;
1967627f7eb2Smrg expand_save = current_expand;
1968627f7eb2Smrg current_expand.expand_work_function = is_constant_element;
1969627f7eb2Smrg
1970627f7eb2Smrg rc = expand_constructor (e->value.constructor);
1971627f7eb2Smrg
1972627f7eb2Smrg current_expand = expand_save;
1973627f7eb2Smrg if (!rc)
1974627f7eb2Smrg return 0;
1975627f7eb2Smrg
1976627f7eb2Smrg return 1;
1977627f7eb2Smrg }
1978627f7eb2Smrg
1979627f7eb2Smrg
1980627f7eb2Smrg /* Returns nonzero if an array constructor has been completely
1981627f7eb2Smrg expanded (no iterators) and zero if iterators are present. */
1982627f7eb2Smrg
1983627f7eb2Smrg int
gfc_expanded_ac(gfc_expr * e)1984627f7eb2Smrg gfc_expanded_ac (gfc_expr *e)
1985627f7eb2Smrg {
1986627f7eb2Smrg gfc_constructor *c;
1987627f7eb2Smrg
1988627f7eb2Smrg if (e->expr_type == EXPR_ARRAY)
1989627f7eb2Smrg for (c = gfc_constructor_first (e->value.constructor);
1990627f7eb2Smrg c; c = gfc_constructor_next (c))
1991627f7eb2Smrg if (c->iterator != NULL || !gfc_expanded_ac (c->expr))
1992627f7eb2Smrg return 0;
1993627f7eb2Smrg
1994627f7eb2Smrg return 1;
1995627f7eb2Smrg }
1996627f7eb2Smrg
1997627f7eb2Smrg
1998627f7eb2Smrg /*************** Type resolution of array constructors ***************/
1999627f7eb2Smrg
2000627f7eb2Smrg
2001627f7eb2Smrg /* The symbol expr_is_sought_symbol_ref will try to find. */
2002627f7eb2Smrg static const gfc_symbol *sought_symbol = NULL;
2003627f7eb2Smrg
2004627f7eb2Smrg
2005627f7eb2Smrg /* Tells whether the expression E is a variable reference to the symbol
2006627f7eb2Smrg in the static variable SOUGHT_SYMBOL, and sets the locus pointer WHERE
2007627f7eb2Smrg accordingly.
2008627f7eb2Smrg To be used with gfc_expr_walker: if a reference is found we don't need
2009627f7eb2Smrg to look further so we return 1 to skip any further walk. */
2010627f7eb2Smrg
2011627f7eb2Smrg static int
expr_is_sought_symbol_ref(gfc_expr ** e,int * walk_subtrees ATTRIBUTE_UNUSED,void * where)2012627f7eb2Smrg expr_is_sought_symbol_ref (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
2013627f7eb2Smrg void *where)
2014627f7eb2Smrg {
2015627f7eb2Smrg gfc_expr *expr = *e;
2016627f7eb2Smrg locus *sym_loc = (locus *)where;
2017627f7eb2Smrg
2018627f7eb2Smrg if (expr->expr_type == EXPR_VARIABLE
2019627f7eb2Smrg && expr->symtree->n.sym == sought_symbol)
2020627f7eb2Smrg {
2021627f7eb2Smrg *sym_loc = expr->where;
2022627f7eb2Smrg return 1;
2023627f7eb2Smrg }
2024627f7eb2Smrg
2025627f7eb2Smrg return 0;
2026627f7eb2Smrg }
2027627f7eb2Smrg
2028627f7eb2Smrg
2029627f7eb2Smrg /* Tells whether the expression EXPR contains a reference to the symbol
2030627f7eb2Smrg SYM and in that case sets the position SYM_LOC where the reference is. */
2031627f7eb2Smrg
2032627f7eb2Smrg static bool
find_symbol_in_expr(gfc_symbol * sym,gfc_expr * expr,locus * sym_loc)2033627f7eb2Smrg find_symbol_in_expr (gfc_symbol *sym, gfc_expr *expr, locus *sym_loc)
2034627f7eb2Smrg {
2035627f7eb2Smrg int ret;
2036627f7eb2Smrg
2037627f7eb2Smrg sought_symbol = sym;
2038627f7eb2Smrg ret = gfc_expr_walker (&expr, &expr_is_sought_symbol_ref, sym_loc);
2039627f7eb2Smrg sought_symbol = NULL;
2040627f7eb2Smrg return ret;
2041627f7eb2Smrg }
2042627f7eb2Smrg
2043627f7eb2Smrg
2044627f7eb2Smrg /* Recursive array list resolution function. All of the elements must
2045627f7eb2Smrg be of the same type. */
2046627f7eb2Smrg
2047627f7eb2Smrg static bool
resolve_array_list(gfc_constructor_base base)2048627f7eb2Smrg resolve_array_list (gfc_constructor_base base)
2049627f7eb2Smrg {
2050627f7eb2Smrg bool t;
2051627f7eb2Smrg gfc_constructor *c;
2052627f7eb2Smrg gfc_iterator *iter;
2053627f7eb2Smrg
2054627f7eb2Smrg t = true;
2055627f7eb2Smrg
2056627f7eb2Smrg for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
2057627f7eb2Smrg {
2058627f7eb2Smrg iter = c->iterator;
2059627f7eb2Smrg if (iter != NULL)
2060627f7eb2Smrg {
2061627f7eb2Smrg gfc_symbol *iter_var;
2062627f7eb2Smrg locus iter_var_loc;
2063627f7eb2Smrg
2064627f7eb2Smrg if (!gfc_resolve_iterator (iter, false, true))
2065627f7eb2Smrg t = false;
2066627f7eb2Smrg
2067627f7eb2Smrg /* Check for bounds referencing the iterator variable. */
2068627f7eb2Smrg gcc_assert (iter->var->expr_type == EXPR_VARIABLE);
2069627f7eb2Smrg iter_var = iter->var->symtree->n.sym;
2070627f7eb2Smrg if (find_symbol_in_expr (iter_var, iter->start, &iter_var_loc))
2071627f7eb2Smrg {
2072627f7eb2Smrg if (!gfc_notify_std (GFC_STD_LEGACY, "AC-IMPLIED-DO initial "
2073627f7eb2Smrg "expression references control variable "
2074627f7eb2Smrg "at %L", &iter_var_loc))
2075627f7eb2Smrg t = false;
2076627f7eb2Smrg }
2077627f7eb2Smrg if (find_symbol_in_expr (iter_var, iter->end, &iter_var_loc))
2078627f7eb2Smrg {
2079627f7eb2Smrg if (!gfc_notify_std (GFC_STD_LEGACY, "AC-IMPLIED-DO final "
2080627f7eb2Smrg "expression references control variable "
2081627f7eb2Smrg "at %L", &iter_var_loc))
2082627f7eb2Smrg t = false;
2083627f7eb2Smrg }
2084627f7eb2Smrg if (find_symbol_in_expr (iter_var, iter->step, &iter_var_loc))
2085627f7eb2Smrg {
2086627f7eb2Smrg if (!gfc_notify_std (GFC_STD_LEGACY, "AC-IMPLIED-DO step "
2087627f7eb2Smrg "expression references control variable "
2088627f7eb2Smrg "at %L", &iter_var_loc))
2089627f7eb2Smrg t = false;
2090627f7eb2Smrg }
2091627f7eb2Smrg }
2092627f7eb2Smrg
2093627f7eb2Smrg if (!gfc_resolve_expr (c->expr))
2094627f7eb2Smrg t = false;
2095627f7eb2Smrg
2096627f7eb2Smrg if (UNLIMITED_POLY (c->expr))
2097627f7eb2Smrg {
2098627f7eb2Smrg gfc_error ("Array constructor value at %L shall not be unlimited "
2099627f7eb2Smrg "polymorphic [F2008: C4106]", &c->expr->where);
2100627f7eb2Smrg t = false;
2101627f7eb2Smrg }
2102627f7eb2Smrg }
2103627f7eb2Smrg
2104627f7eb2Smrg return t;
2105627f7eb2Smrg }
2106627f7eb2Smrg
2107627f7eb2Smrg /* Resolve character array constructor. If it has a specified constant character
2108627f7eb2Smrg length, pad/truncate the elements here; if the length is not specified and
2109627f7eb2Smrg all elements are of compile-time known length, emit an error as this is
2110627f7eb2Smrg invalid. */
2111627f7eb2Smrg
2112627f7eb2Smrg bool
gfc_resolve_character_array_constructor(gfc_expr * expr)2113627f7eb2Smrg gfc_resolve_character_array_constructor (gfc_expr *expr)
2114627f7eb2Smrg {
2115627f7eb2Smrg gfc_constructor *p;
2116627f7eb2Smrg HOST_WIDE_INT found_length;
2117627f7eb2Smrg
2118627f7eb2Smrg gcc_assert (expr->expr_type == EXPR_ARRAY);
2119627f7eb2Smrg gcc_assert (expr->ts.type == BT_CHARACTER);
2120627f7eb2Smrg
2121627f7eb2Smrg if (expr->ts.u.cl == NULL)
2122627f7eb2Smrg {
2123627f7eb2Smrg for (p = gfc_constructor_first (expr->value.constructor);
2124627f7eb2Smrg p; p = gfc_constructor_next (p))
2125627f7eb2Smrg if (p->expr->ts.u.cl != NULL)
2126627f7eb2Smrg {
2127627f7eb2Smrg /* Ensure that if there is a char_len around that it is
2128627f7eb2Smrg used; otherwise the middle-end confuses them! */
2129627f7eb2Smrg expr->ts.u.cl = p->expr->ts.u.cl;
2130627f7eb2Smrg goto got_charlen;
2131627f7eb2Smrg }
2132627f7eb2Smrg
2133627f7eb2Smrg expr->ts.u.cl = gfc_new_charlen (gfc_current_ns, NULL);
2134627f7eb2Smrg }
2135627f7eb2Smrg
2136627f7eb2Smrg got_charlen:
2137627f7eb2Smrg
2138627f7eb2Smrg /* Early exit for zero size arrays. */
2139627f7eb2Smrg if (expr->shape)
2140627f7eb2Smrg {
2141627f7eb2Smrg mpz_t size;
2142627f7eb2Smrg HOST_WIDE_INT arraysize;
2143627f7eb2Smrg
2144627f7eb2Smrg gfc_array_size (expr, &size);
2145627f7eb2Smrg arraysize = mpz_get_ui (size);
2146627f7eb2Smrg mpz_clear (size);
2147627f7eb2Smrg
2148627f7eb2Smrg if (arraysize == 0)
2149627f7eb2Smrg return true;
2150627f7eb2Smrg }
2151627f7eb2Smrg
2152627f7eb2Smrg found_length = -1;
2153627f7eb2Smrg
2154627f7eb2Smrg if (expr->ts.u.cl->length == NULL)
2155627f7eb2Smrg {
2156627f7eb2Smrg /* Check that all constant string elements have the same length until
2157627f7eb2Smrg we reach the end or find a variable-length one. */
2158627f7eb2Smrg
2159627f7eb2Smrg for (p = gfc_constructor_first (expr->value.constructor);
2160627f7eb2Smrg p; p = gfc_constructor_next (p))
2161627f7eb2Smrg {
2162627f7eb2Smrg HOST_WIDE_INT current_length = -1;
2163627f7eb2Smrg gfc_ref *ref;
2164627f7eb2Smrg for (ref = p->expr->ref; ref; ref = ref->next)
2165627f7eb2Smrg if (ref->type == REF_SUBSTRING
2166627f7eb2Smrg && ref->u.ss.start
2167627f7eb2Smrg && ref->u.ss.start->expr_type == EXPR_CONSTANT
2168627f7eb2Smrg && ref->u.ss.end
2169627f7eb2Smrg && ref->u.ss.end->expr_type == EXPR_CONSTANT)
2170627f7eb2Smrg break;
2171627f7eb2Smrg
2172627f7eb2Smrg if (p->expr->expr_type == EXPR_CONSTANT)
2173627f7eb2Smrg current_length = p->expr->value.character.length;
2174627f7eb2Smrg else if (ref)
2175627f7eb2Smrg current_length = gfc_mpz_get_hwi (ref->u.ss.end->value.integer)
2176627f7eb2Smrg - gfc_mpz_get_hwi (ref->u.ss.start->value.integer) + 1;
2177627f7eb2Smrg else if (p->expr->ts.u.cl && p->expr->ts.u.cl->length
2178627f7eb2Smrg && p->expr->ts.u.cl->length->expr_type == EXPR_CONSTANT)
2179627f7eb2Smrg current_length = gfc_mpz_get_hwi (p->expr->ts.u.cl->length->value.integer);
2180627f7eb2Smrg else
2181627f7eb2Smrg return true;
2182627f7eb2Smrg
2183627f7eb2Smrg if (current_length < 0)
2184627f7eb2Smrg current_length = 0;
2185627f7eb2Smrg
2186627f7eb2Smrg if (found_length == -1)
2187627f7eb2Smrg found_length = current_length;
2188627f7eb2Smrg else if (found_length != current_length)
2189627f7eb2Smrg {
2190627f7eb2Smrg gfc_error ("Different CHARACTER lengths (%ld/%ld) in array"
2191627f7eb2Smrg " constructor at %L", (long) found_length,
2192627f7eb2Smrg (long) current_length, &p->expr->where);
2193627f7eb2Smrg return false;
2194627f7eb2Smrg }
2195627f7eb2Smrg
2196627f7eb2Smrg gcc_assert (found_length == current_length);
2197627f7eb2Smrg }
2198627f7eb2Smrg
2199627f7eb2Smrg gcc_assert (found_length != -1);
2200627f7eb2Smrg
2201627f7eb2Smrg /* Update the character length of the array constructor. */
2202627f7eb2Smrg expr->ts.u.cl->length = gfc_get_int_expr (gfc_charlen_int_kind,
2203627f7eb2Smrg NULL, found_length);
2204627f7eb2Smrg }
2205627f7eb2Smrg else
2206627f7eb2Smrg {
2207627f7eb2Smrg /* We've got a character length specified. It should be an integer,
2208627f7eb2Smrg otherwise an error is signalled elsewhere. */
2209627f7eb2Smrg gcc_assert (expr->ts.u.cl->length);
2210627f7eb2Smrg
2211627f7eb2Smrg /* If we've got a constant character length, pad according to this.
2212627f7eb2Smrg gfc_extract_int does check for BT_INTEGER and EXPR_CONSTANT and sets
2213627f7eb2Smrg max_length only if they pass. */
2214627f7eb2Smrg gfc_extract_hwi (expr->ts.u.cl->length, &found_length);
2215627f7eb2Smrg
2216627f7eb2Smrg /* Now pad/truncate the elements accordingly to the specified character
2217627f7eb2Smrg length. This is ok inside this conditional, as in the case above
2218627f7eb2Smrg (without typespec) all elements are verified to have the same length
2219627f7eb2Smrg anyway. */
2220627f7eb2Smrg if (found_length != -1)
2221627f7eb2Smrg for (p = gfc_constructor_first (expr->value.constructor);
2222627f7eb2Smrg p; p = gfc_constructor_next (p))
2223627f7eb2Smrg if (p->expr->expr_type == EXPR_CONSTANT)
2224627f7eb2Smrg {
2225627f7eb2Smrg gfc_expr *cl = NULL;
2226627f7eb2Smrg HOST_WIDE_INT current_length = -1;
2227627f7eb2Smrg bool has_ts;
2228627f7eb2Smrg
2229627f7eb2Smrg if (p->expr->ts.u.cl && p->expr->ts.u.cl->length)
2230627f7eb2Smrg {
2231627f7eb2Smrg cl = p->expr->ts.u.cl->length;
2232627f7eb2Smrg gfc_extract_hwi (cl, ¤t_length);
2233627f7eb2Smrg }
2234627f7eb2Smrg
2235627f7eb2Smrg /* If gfc_extract_int above set current_length, we implicitly
2236627f7eb2Smrg know the type is BT_INTEGER and it's EXPR_CONSTANT. */
2237627f7eb2Smrg
2238627f7eb2Smrg has_ts = expr->ts.u.cl->length_from_typespec;
2239627f7eb2Smrg
2240627f7eb2Smrg if (! cl
2241627f7eb2Smrg || (current_length != -1 && current_length != found_length))
2242627f7eb2Smrg gfc_set_constant_character_len (found_length, p->expr,
2243627f7eb2Smrg has_ts ? -1 : found_length);
2244627f7eb2Smrg }
2245627f7eb2Smrg }
2246627f7eb2Smrg
2247627f7eb2Smrg return true;
2248627f7eb2Smrg }
2249627f7eb2Smrg
2250627f7eb2Smrg
2251627f7eb2Smrg /* Resolve all of the expressions in an array list. */
2252627f7eb2Smrg
2253627f7eb2Smrg bool
gfc_resolve_array_constructor(gfc_expr * expr)2254627f7eb2Smrg gfc_resolve_array_constructor (gfc_expr *expr)
2255627f7eb2Smrg {
2256627f7eb2Smrg bool t;
2257627f7eb2Smrg
2258627f7eb2Smrg t = resolve_array_list (expr->value.constructor);
2259627f7eb2Smrg if (t)
2260627f7eb2Smrg t = gfc_check_constructor_type (expr);
2261627f7eb2Smrg
2262627f7eb2Smrg /* gfc_resolve_character_array_constructor is called in gfc_resolve_expr after
2263627f7eb2Smrg the call to this function, so we don't need to call it here; if it was
2264627f7eb2Smrg called twice, an error message there would be duplicated. */
2265627f7eb2Smrg
2266627f7eb2Smrg return t;
2267627f7eb2Smrg }
2268627f7eb2Smrg
2269627f7eb2Smrg
2270627f7eb2Smrg /* Copy an iterator structure. */
2271627f7eb2Smrg
2272627f7eb2Smrg gfc_iterator *
gfc_copy_iterator(gfc_iterator * src)2273627f7eb2Smrg gfc_copy_iterator (gfc_iterator *src)
2274627f7eb2Smrg {
2275627f7eb2Smrg gfc_iterator *dest;
2276627f7eb2Smrg
2277627f7eb2Smrg if (src == NULL)
2278627f7eb2Smrg return NULL;
2279627f7eb2Smrg
2280627f7eb2Smrg dest = gfc_get_iterator ();
2281627f7eb2Smrg
2282627f7eb2Smrg dest->var = gfc_copy_expr (src->var);
2283627f7eb2Smrg dest->start = gfc_copy_expr (src->start);
2284627f7eb2Smrg dest->end = gfc_copy_expr (src->end);
2285627f7eb2Smrg dest->step = gfc_copy_expr (src->step);
2286627f7eb2Smrg dest->unroll = src->unroll;
2287627f7eb2Smrg dest->ivdep = src->ivdep;
2288627f7eb2Smrg dest->vector = src->vector;
2289627f7eb2Smrg dest->novector = src->novector;
2290627f7eb2Smrg
2291627f7eb2Smrg return dest;
2292627f7eb2Smrg }
2293627f7eb2Smrg
2294627f7eb2Smrg
2295627f7eb2Smrg /********* Subroutines for determining the size of an array *********/
2296627f7eb2Smrg
2297627f7eb2Smrg /* These are needed just to accommodate RESHAPE(). There are no
2298*4c3eb207Smrg diagnostics here, we just return false if something goes wrong. */
2299627f7eb2Smrg
2300627f7eb2Smrg
2301627f7eb2Smrg /* Get the size of single dimension of an array specification. The
2302627f7eb2Smrg array is guaranteed to be one dimensional. */
2303627f7eb2Smrg
2304627f7eb2Smrg bool
spec_dimen_size(gfc_array_spec * as,int dimen,mpz_t * result)2305627f7eb2Smrg spec_dimen_size (gfc_array_spec *as, int dimen, mpz_t *result)
2306627f7eb2Smrg {
2307627f7eb2Smrg if (as == NULL)
2308627f7eb2Smrg return false;
2309627f7eb2Smrg
2310627f7eb2Smrg if (dimen < 0 || dimen > as->rank - 1)
2311627f7eb2Smrg gfc_internal_error ("spec_dimen_size(): Bad dimension");
2312627f7eb2Smrg
2313627f7eb2Smrg if (as->type != AS_EXPLICIT
2314*4c3eb207Smrg || !as->lower[dimen]
2315*4c3eb207Smrg || !as->upper[dimen])
2316*4c3eb207Smrg return false;
2317*4c3eb207Smrg
2318*4c3eb207Smrg if (as->lower[dimen]->expr_type != EXPR_CONSTANT
2319627f7eb2Smrg || as->upper[dimen]->expr_type != EXPR_CONSTANT
2320627f7eb2Smrg || as->lower[dimen]->ts.type != BT_INTEGER
2321627f7eb2Smrg || as->upper[dimen]->ts.type != BT_INTEGER)
2322627f7eb2Smrg return false;
2323627f7eb2Smrg
2324627f7eb2Smrg mpz_init (*result);
2325627f7eb2Smrg
2326627f7eb2Smrg mpz_sub (*result, as->upper[dimen]->value.integer,
2327627f7eb2Smrg as->lower[dimen]->value.integer);
2328627f7eb2Smrg
2329627f7eb2Smrg mpz_add_ui (*result, *result, 1);
2330627f7eb2Smrg
2331*4c3eb207Smrg if (mpz_cmp_si (*result, 0) < 0)
2332*4c3eb207Smrg mpz_set_si (*result, 0);
2333*4c3eb207Smrg
2334627f7eb2Smrg return true;
2335627f7eb2Smrg }
2336627f7eb2Smrg
2337627f7eb2Smrg
2338627f7eb2Smrg bool
spec_size(gfc_array_spec * as,mpz_t * result)2339627f7eb2Smrg spec_size (gfc_array_spec *as, mpz_t *result)
2340627f7eb2Smrg {
2341627f7eb2Smrg mpz_t size;
2342627f7eb2Smrg int d;
2343627f7eb2Smrg
2344627f7eb2Smrg if (!as || as->type == AS_ASSUMED_RANK)
2345627f7eb2Smrg return false;
2346627f7eb2Smrg
2347627f7eb2Smrg mpz_init_set_ui (*result, 1);
2348627f7eb2Smrg
2349627f7eb2Smrg for (d = 0; d < as->rank; d++)
2350627f7eb2Smrg {
2351627f7eb2Smrg if (!spec_dimen_size (as, d, &size))
2352627f7eb2Smrg {
2353627f7eb2Smrg mpz_clear (*result);
2354627f7eb2Smrg return false;
2355627f7eb2Smrg }
2356627f7eb2Smrg
2357627f7eb2Smrg mpz_mul (*result, *result, size);
2358627f7eb2Smrg mpz_clear (size);
2359627f7eb2Smrg }
2360627f7eb2Smrg
2361627f7eb2Smrg return true;
2362627f7eb2Smrg }
2363627f7eb2Smrg
2364627f7eb2Smrg
2365627f7eb2Smrg /* Get the number of elements in an array section. Optionally, also supply
2366627f7eb2Smrg the end value. */
2367627f7eb2Smrg
2368627f7eb2Smrg bool
gfc_ref_dimen_size(gfc_array_ref * ar,int dimen,mpz_t * result,mpz_t * end)2369627f7eb2Smrg gfc_ref_dimen_size (gfc_array_ref *ar, int dimen, mpz_t *result, mpz_t *end)
2370627f7eb2Smrg {
2371627f7eb2Smrg mpz_t upper, lower, stride;
2372627f7eb2Smrg mpz_t diff;
2373627f7eb2Smrg bool t;
2374627f7eb2Smrg gfc_expr *stride_expr = NULL;
2375627f7eb2Smrg
2376627f7eb2Smrg if (dimen < 0 || ar == NULL)
2377627f7eb2Smrg gfc_internal_error ("gfc_ref_dimen_size(): Bad dimension");
2378627f7eb2Smrg
2379627f7eb2Smrg if (dimen > ar->dimen - 1)
2380627f7eb2Smrg {
2381627f7eb2Smrg gfc_error ("Bad array dimension at %L", &ar->c_where[dimen]);
2382627f7eb2Smrg return false;
2383627f7eb2Smrg }
2384627f7eb2Smrg
2385627f7eb2Smrg switch (ar->dimen_type[dimen])
2386627f7eb2Smrg {
2387627f7eb2Smrg case DIMEN_ELEMENT:
2388627f7eb2Smrg mpz_init (*result);
2389627f7eb2Smrg mpz_set_ui (*result, 1);
2390627f7eb2Smrg t = true;
2391627f7eb2Smrg break;
2392627f7eb2Smrg
2393627f7eb2Smrg case DIMEN_VECTOR:
2394627f7eb2Smrg t = gfc_array_size (ar->start[dimen], result); /* Recurse! */
2395627f7eb2Smrg break;
2396627f7eb2Smrg
2397627f7eb2Smrg case DIMEN_RANGE:
2398627f7eb2Smrg
2399627f7eb2Smrg mpz_init (stride);
2400627f7eb2Smrg
2401627f7eb2Smrg if (ar->stride[dimen] == NULL)
2402627f7eb2Smrg mpz_set_ui (stride, 1);
2403627f7eb2Smrg else
2404627f7eb2Smrg {
2405627f7eb2Smrg stride_expr = gfc_copy_expr(ar->stride[dimen]);
2406627f7eb2Smrg
2407*4c3eb207Smrg if (!gfc_simplify_expr (stride_expr, 1)
2408*4c3eb207Smrg || stride_expr->expr_type != EXPR_CONSTANT
2409627f7eb2Smrg || mpz_cmp_ui (stride_expr->value.integer, 0) == 0)
2410627f7eb2Smrg {
2411*4c3eb207Smrg gfc_free_expr (stride_expr);
2412627f7eb2Smrg mpz_clear (stride);
2413627f7eb2Smrg return false;
2414627f7eb2Smrg }
2415627f7eb2Smrg mpz_set (stride, stride_expr->value.integer);
2416627f7eb2Smrg gfc_free_expr(stride_expr);
2417627f7eb2Smrg }
2418627f7eb2Smrg
2419627f7eb2Smrg /* Calculate the number of elements via gfc_dep_differce, but only if
2420627f7eb2Smrg start and end are both supplied in the reference or the array spec.
2421627f7eb2Smrg This is to guard against strange but valid code like
2422627f7eb2Smrg
2423627f7eb2Smrg subroutine foo(a,n)
2424627f7eb2Smrg real a(1:n)
2425627f7eb2Smrg n = 3
2426627f7eb2Smrg print *,size(a(n-1:))
2427627f7eb2Smrg
2428627f7eb2Smrg where the user changes the value of a variable. If we have to
2429627f7eb2Smrg determine end as well, we cannot do this using gfc_dep_difference.
2430627f7eb2Smrg Fall back to the constants-only code then. */
2431627f7eb2Smrg
2432627f7eb2Smrg if (end == NULL)
2433627f7eb2Smrg {
2434627f7eb2Smrg bool use_dep;
2435627f7eb2Smrg
2436627f7eb2Smrg use_dep = gfc_dep_difference (ar->end[dimen], ar->start[dimen],
2437627f7eb2Smrg &diff);
2438627f7eb2Smrg if (!use_dep && ar->end[dimen] == NULL && ar->start[dimen] == NULL)
2439627f7eb2Smrg use_dep = gfc_dep_difference (ar->as->upper[dimen],
2440627f7eb2Smrg ar->as->lower[dimen], &diff);
2441627f7eb2Smrg
2442627f7eb2Smrg if (use_dep)
2443627f7eb2Smrg {
2444627f7eb2Smrg mpz_init (*result);
2445627f7eb2Smrg mpz_add (*result, diff, stride);
2446627f7eb2Smrg mpz_div (*result, *result, stride);
2447627f7eb2Smrg if (mpz_cmp_ui (*result, 0) < 0)
2448627f7eb2Smrg mpz_set_ui (*result, 0);
2449627f7eb2Smrg
2450627f7eb2Smrg mpz_clear (stride);
2451627f7eb2Smrg mpz_clear (diff);
2452627f7eb2Smrg return true;
2453627f7eb2Smrg }
2454627f7eb2Smrg
2455627f7eb2Smrg }
2456627f7eb2Smrg
2457627f7eb2Smrg /* Constant-only code here, which covers more cases
2458627f7eb2Smrg like a(:4) etc. */
2459627f7eb2Smrg mpz_init (upper);
2460627f7eb2Smrg mpz_init (lower);
2461627f7eb2Smrg t = false;
2462627f7eb2Smrg
2463627f7eb2Smrg if (ar->start[dimen] == NULL)
2464627f7eb2Smrg {
2465627f7eb2Smrg if (ar->as->lower[dimen] == NULL
2466627f7eb2Smrg || ar->as->lower[dimen]->expr_type != EXPR_CONSTANT
2467627f7eb2Smrg || ar->as->lower[dimen]->ts.type != BT_INTEGER)
2468627f7eb2Smrg goto cleanup;
2469627f7eb2Smrg mpz_set (lower, ar->as->lower[dimen]->value.integer);
2470627f7eb2Smrg }
2471627f7eb2Smrg else
2472627f7eb2Smrg {
2473627f7eb2Smrg if (ar->start[dimen]->expr_type != EXPR_CONSTANT)
2474627f7eb2Smrg goto cleanup;
2475627f7eb2Smrg mpz_set (lower, ar->start[dimen]->value.integer);
2476627f7eb2Smrg }
2477627f7eb2Smrg
2478627f7eb2Smrg if (ar->end[dimen] == NULL)
2479627f7eb2Smrg {
2480627f7eb2Smrg if (ar->as->upper[dimen] == NULL
2481627f7eb2Smrg || ar->as->upper[dimen]->expr_type != EXPR_CONSTANT
2482627f7eb2Smrg || ar->as->upper[dimen]->ts.type != BT_INTEGER)
2483627f7eb2Smrg goto cleanup;
2484627f7eb2Smrg mpz_set (upper, ar->as->upper[dimen]->value.integer);
2485627f7eb2Smrg }
2486627f7eb2Smrg else
2487627f7eb2Smrg {
2488627f7eb2Smrg if (ar->end[dimen]->expr_type != EXPR_CONSTANT)
2489627f7eb2Smrg goto cleanup;
2490627f7eb2Smrg mpz_set (upper, ar->end[dimen]->value.integer);
2491627f7eb2Smrg }
2492627f7eb2Smrg
2493627f7eb2Smrg mpz_init (*result);
2494627f7eb2Smrg mpz_sub (*result, upper, lower);
2495627f7eb2Smrg mpz_add (*result, *result, stride);
2496627f7eb2Smrg mpz_div (*result, *result, stride);
2497627f7eb2Smrg
2498627f7eb2Smrg /* Zero stride caught earlier. */
2499627f7eb2Smrg if (mpz_cmp_ui (*result, 0) < 0)
2500627f7eb2Smrg mpz_set_ui (*result, 0);
2501627f7eb2Smrg t = true;
2502627f7eb2Smrg
2503627f7eb2Smrg if (end)
2504627f7eb2Smrg {
2505627f7eb2Smrg mpz_init (*end);
2506627f7eb2Smrg
2507627f7eb2Smrg mpz_sub_ui (*end, *result, 1UL);
2508627f7eb2Smrg mpz_mul (*end, *end, stride);
2509627f7eb2Smrg mpz_add (*end, *end, lower);
2510627f7eb2Smrg }
2511627f7eb2Smrg
2512627f7eb2Smrg cleanup:
2513627f7eb2Smrg mpz_clear (upper);
2514627f7eb2Smrg mpz_clear (lower);
2515627f7eb2Smrg mpz_clear (stride);
2516627f7eb2Smrg return t;
2517627f7eb2Smrg
2518627f7eb2Smrg default:
2519627f7eb2Smrg gfc_internal_error ("gfc_ref_dimen_size(): Bad dimen_type");
2520627f7eb2Smrg }
2521627f7eb2Smrg
2522627f7eb2Smrg return t;
2523627f7eb2Smrg }
2524627f7eb2Smrg
2525627f7eb2Smrg
2526627f7eb2Smrg static bool
ref_size(gfc_array_ref * ar,mpz_t * result)2527627f7eb2Smrg ref_size (gfc_array_ref *ar, mpz_t *result)
2528627f7eb2Smrg {
2529627f7eb2Smrg mpz_t size;
2530627f7eb2Smrg int d;
2531627f7eb2Smrg
2532627f7eb2Smrg mpz_init_set_ui (*result, 1);
2533627f7eb2Smrg
2534627f7eb2Smrg for (d = 0; d < ar->dimen; d++)
2535627f7eb2Smrg {
2536627f7eb2Smrg if (!gfc_ref_dimen_size (ar, d, &size, NULL))
2537627f7eb2Smrg {
2538627f7eb2Smrg mpz_clear (*result);
2539627f7eb2Smrg return false;
2540627f7eb2Smrg }
2541627f7eb2Smrg
2542627f7eb2Smrg mpz_mul (*result, *result, size);
2543627f7eb2Smrg mpz_clear (size);
2544627f7eb2Smrg }
2545627f7eb2Smrg
2546627f7eb2Smrg return true;
2547627f7eb2Smrg }
2548627f7eb2Smrg
2549627f7eb2Smrg
2550627f7eb2Smrg /* Given an array expression and a dimension, figure out how many
2551627f7eb2Smrg elements it has along that dimension. Returns true if we were
2552627f7eb2Smrg able to return a result in the 'result' variable, false
2553627f7eb2Smrg otherwise. */
2554627f7eb2Smrg
2555627f7eb2Smrg bool
gfc_array_dimen_size(gfc_expr * array,int dimen,mpz_t * result)2556627f7eb2Smrg gfc_array_dimen_size (gfc_expr *array, int dimen, mpz_t *result)
2557627f7eb2Smrg {
2558627f7eb2Smrg gfc_ref *ref;
2559627f7eb2Smrg int i;
2560627f7eb2Smrg
2561627f7eb2Smrg gcc_assert (array != NULL);
2562627f7eb2Smrg
2563627f7eb2Smrg if (array->ts.type == BT_CLASS)
2564627f7eb2Smrg return false;
2565627f7eb2Smrg
2566627f7eb2Smrg if (array->rank == -1)
2567627f7eb2Smrg return false;
2568627f7eb2Smrg
2569627f7eb2Smrg if (dimen < 0 || dimen > array->rank - 1)
2570627f7eb2Smrg gfc_internal_error ("gfc_array_dimen_size(): Bad dimension");
2571627f7eb2Smrg
2572627f7eb2Smrg switch (array->expr_type)
2573627f7eb2Smrg {
2574627f7eb2Smrg case EXPR_VARIABLE:
2575627f7eb2Smrg case EXPR_FUNCTION:
2576627f7eb2Smrg for (ref = array->ref; ref; ref = ref->next)
2577627f7eb2Smrg {
2578627f7eb2Smrg if (ref->type != REF_ARRAY)
2579627f7eb2Smrg continue;
2580627f7eb2Smrg
2581627f7eb2Smrg if (ref->u.ar.type == AR_FULL)
2582627f7eb2Smrg return spec_dimen_size (ref->u.ar.as, dimen, result);
2583627f7eb2Smrg
2584627f7eb2Smrg if (ref->u.ar.type == AR_SECTION)
2585627f7eb2Smrg {
2586627f7eb2Smrg for (i = 0; dimen >= 0; i++)
2587627f7eb2Smrg if (ref->u.ar.dimen_type[i] != DIMEN_ELEMENT)
2588627f7eb2Smrg dimen--;
2589627f7eb2Smrg
2590627f7eb2Smrg return gfc_ref_dimen_size (&ref->u.ar, i - 1, result, NULL);
2591627f7eb2Smrg }
2592627f7eb2Smrg }
2593627f7eb2Smrg
2594627f7eb2Smrg if (array->shape && array->shape[dimen])
2595627f7eb2Smrg {
2596627f7eb2Smrg mpz_init_set (*result, array->shape[dimen]);
2597627f7eb2Smrg return true;
2598627f7eb2Smrg }
2599627f7eb2Smrg
2600627f7eb2Smrg if (array->symtree->n.sym->attr.generic
2601627f7eb2Smrg && array->value.function.esym != NULL)
2602627f7eb2Smrg {
2603627f7eb2Smrg if (!spec_dimen_size (array->value.function.esym->as, dimen, result))
2604627f7eb2Smrg return false;
2605627f7eb2Smrg }
2606627f7eb2Smrg else if (!spec_dimen_size (array->symtree->n.sym->as, dimen, result))
2607627f7eb2Smrg return false;
2608627f7eb2Smrg
2609627f7eb2Smrg break;
2610627f7eb2Smrg
2611627f7eb2Smrg case EXPR_ARRAY:
2612627f7eb2Smrg if (array->shape == NULL) {
2613627f7eb2Smrg /* Expressions with rank > 1 should have "shape" properly set */
2614627f7eb2Smrg if ( array->rank != 1 )
2615627f7eb2Smrg gfc_internal_error ("gfc_array_dimen_size(): Bad EXPR_ARRAY expr");
2616627f7eb2Smrg return gfc_array_size(array, result);
2617627f7eb2Smrg }
2618627f7eb2Smrg
2619627f7eb2Smrg /* Fall through */
2620627f7eb2Smrg default:
2621627f7eb2Smrg if (array->shape == NULL)
2622627f7eb2Smrg return false;
2623627f7eb2Smrg
2624627f7eb2Smrg mpz_init_set (*result, array->shape[dimen]);
2625627f7eb2Smrg
2626627f7eb2Smrg break;
2627627f7eb2Smrg }
2628627f7eb2Smrg
2629627f7eb2Smrg return true;
2630627f7eb2Smrg }
2631627f7eb2Smrg
2632627f7eb2Smrg
2633627f7eb2Smrg /* Given an array expression, figure out how many elements are in the
2634627f7eb2Smrg array. Returns true if this is possible, and sets the 'result'
2635627f7eb2Smrg variable. Otherwise returns false. */
2636627f7eb2Smrg
2637627f7eb2Smrg bool
gfc_array_size(gfc_expr * array,mpz_t * result)2638627f7eb2Smrg gfc_array_size (gfc_expr *array, mpz_t *result)
2639627f7eb2Smrg {
2640627f7eb2Smrg expand_info expand_save;
2641627f7eb2Smrg gfc_ref *ref;
2642627f7eb2Smrg int i;
2643627f7eb2Smrg bool t;
2644627f7eb2Smrg
2645627f7eb2Smrg if (array->ts.type == BT_CLASS)
2646627f7eb2Smrg return false;
2647627f7eb2Smrg
2648627f7eb2Smrg switch (array->expr_type)
2649627f7eb2Smrg {
2650627f7eb2Smrg case EXPR_ARRAY:
2651627f7eb2Smrg gfc_push_suppress_errors ();
2652627f7eb2Smrg
2653627f7eb2Smrg expand_save = current_expand;
2654627f7eb2Smrg
2655627f7eb2Smrg current_expand.count = result;
2656627f7eb2Smrg mpz_init_set_ui (*result, 0);
2657627f7eb2Smrg
2658627f7eb2Smrg current_expand.expand_work_function = count_elements;
2659627f7eb2Smrg iter_stack = NULL;
2660627f7eb2Smrg
2661627f7eb2Smrg t = expand_constructor (array->value.constructor);
2662627f7eb2Smrg
2663627f7eb2Smrg gfc_pop_suppress_errors ();
2664627f7eb2Smrg
2665627f7eb2Smrg if (!t)
2666627f7eb2Smrg mpz_clear (*result);
2667627f7eb2Smrg current_expand = expand_save;
2668627f7eb2Smrg return t;
2669627f7eb2Smrg
2670627f7eb2Smrg case EXPR_VARIABLE:
2671627f7eb2Smrg for (ref = array->ref; ref; ref = ref->next)
2672627f7eb2Smrg {
2673627f7eb2Smrg if (ref->type != REF_ARRAY)
2674627f7eb2Smrg continue;
2675627f7eb2Smrg
2676627f7eb2Smrg if (ref->u.ar.type == AR_FULL)
2677627f7eb2Smrg return spec_size (ref->u.ar.as, result);
2678627f7eb2Smrg
2679627f7eb2Smrg if (ref->u.ar.type == AR_SECTION)
2680627f7eb2Smrg return ref_size (&ref->u.ar, result);
2681627f7eb2Smrg }
2682627f7eb2Smrg
2683627f7eb2Smrg return spec_size (array->symtree->n.sym->as, result);
2684627f7eb2Smrg
2685627f7eb2Smrg
2686627f7eb2Smrg default:
2687627f7eb2Smrg if (array->rank == 0 || array->shape == NULL)
2688627f7eb2Smrg return false;
2689627f7eb2Smrg
2690627f7eb2Smrg mpz_init_set_ui (*result, 1);
2691627f7eb2Smrg
2692627f7eb2Smrg for (i = 0; i < array->rank; i++)
2693627f7eb2Smrg mpz_mul (*result, *result, array->shape[i]);
2694627f7eb2Smrg
2695627f7eb2Smrg break;
2696627f7eb2Smrg }
2697627f7eb2Smrg
2698627f7eb2Smrg return true;
2699627f7eb2Smrg }
2700627f7eb2Smrg
2701627f7eb2Smrg
2702627f7eb2Smrg /* Given an array reference, return the shape of the reference in an
2703627f7eb2Smrg array of mpz_t integers. */
2704627f7eb2Smrg
2705627f7eb2Smrg bool
gfc_array_ref_shape(gfc_array_ref * ar,mpz_t * shape)2706627f7eb2Smrg gfc_array_ref_shape (gfc_array_ref *ar, mpz_t *shape)
2707627f7eb2Smrg {
2708627f7eb2Smrg int d;
2709627f7eb2Smrg int i;
2710627f7eb2Smrg
2711627f7eb2Smrg d = 0;
2712627f7eb2Smrg
2713627f7eb2Smrg switch (ar->type)
2714627f7eb2Smrg {
2715627f7eb2Smrg case AR_FULL:
2716627f7eb2Smrg for (; d < ar->as->rank; d++)
2717627f7eb2Smrg if (!spec_dimen_size (ar->as, d, &shape[d]))
2718627f7eb2Smrg goto cleanup;
2719627f7eb2Smrg
2720627f7eb2Smrg return true;
2721627f7eb2Smrg
2722627f7eb2Smrg case AR_SECTION:
2723627f7eb2Smrg for (i = 0; i < ar->dimen; i++)
2724627f7eb2Smrg {
2725627f7eb2Smrg if (ar->dimen_type[i] != DIMEN_ELEMENT)
2726627f7eb2Smrg {
2727627f7eb2Smrg if (!gfc_ref_dimen_size (ar, i, &shape[d], NULL))
2728627f7eb2Smrg goto cleanup;
2729627f7eb2Smrg d++;
2730627f7eb2Smrg }
2731627f7eb2Smrg }
2732627f7eb2Smrg
2733627f7eb2Smrg return true;
2734627f7eb2Smrg
2735627f7eb2Smrg default:
2736627f7eb2Smrg break;
2737627f7eb2Smrg }
2738627f7eb2Smrg
2739627f7eb2Smrg cleanup:
2740627f7eb2Smrg gfc_clear_shape (shape, d);
2741627f7eb2Smrg return false;
2742627f7eb2Smrg }
2743627f7eb2Smrg
2744627f7eb2Smrg
2745627f7eb2Smrg /* Given an array expression, find the array reference structure that
2746627f7eb2Smrg characterizes the reference. */
2747627f7eb2Smrg
2748627f7eb2Smrg gfc_array_ref *
gfc_find_array_ref(gfc_expr * e,bool allow_null)2749627f7eb2Smrg gfc_find_array_ref (gfc_expr *e, bool allow_null)
2750627f7eb2Smrg {
2751627f7eb2Smrg gfc_ref *ref;
2752627f7eb2Smrg
2753627f7eb2Smrg for (ref = e->ref; ref; ref = ref->next)
2754627f7eb2Smrg if (ref->type == REF_ARRAY
2755627f7eb2Smrg && (ref->u.ar.type == AR_FULL || ref->u.ar.type == AR_SECTION))
2756627f7eb2Smrg break;
2757627f7eb2Smrg
2758627f7eb2Smrg if (ref == NULL)
2759627f7eb2Smrg {
2760627f7eb2Smrg if (allow_null)
2761627f7eb2Smrg return NULL;
2762627f7eb2Smrg else
2763627f7eb2Smrg gfc_internal_error ("gfc_find_array_ref(): No ref found");
2764627f7eb2Smrg }
2765627f7eb2Smrg
2766627f7eb2Smrg return &ref->u.ar;
2767627f7eb2Smrg }
2768627f7eb2Smrg
2769627f7eb2Smrg
2770627f7eb2Smrg /* Find out if an array shape is known at compile time. */
2771627f7eb2Smrg
2772627f7eb2Smrg bool
gfc_is_compile_time_shape(gfc_array_spec * as)2773627f7eb2Smrg gfc_is_compile_time_shape (gfc_array_spec *as)
2774627f7eb2Smrg {
2775627f7eb2Smrg if (as->type != AS_EXPLICIT)
2776627f7eb2Smrg return false;
2777627f7eb2Smrg
2778627f7eb2Smrg for (int i = 0; i < as->rank; i++)
2779627f7eb2Smrg if (!gfc_is_constant_expr (as->lower[i])
2780627f7eb2Smrg || !gfc_is_constant_expr (as->upper[i]))
2781627f7eb2Smrg return false;
2782627f7eb2Smrg
2783627f7eb2Smrg return true;
2784627f7eb2Smrg }
2785