xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/fortran/array.c (revision 4ac76180e904e771b9d522c7e57296d371f06499)
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 (&current_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, &current_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