xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/fortran/primary.c (revision 4ac76180e904e771b9d522c7e57296d371f06499)
1627f7eb2Smrg /* Primary expression subroutines
24c3eb207Smrg    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"
26627f7eb2Smrg #include "arith.h"
27627f7eb2Smrg #include "match.h"
28627f7eb2Smrg #include "parse.h"
29627f7eb2Smrg #include "constructor.h"
30627f7eb2Smrg 
31627f7eb2Smrg int matching_actual_arglist = 0;
32627f7eb2Smrg 
33627f7eb2Smrg /* Matches a kind-parameter expression, which is either a named
34627f7eb2Smrg    symbolic constant or a nonnegative integer constant.  If
35627f7eb2Smrg    successful, sets the kind value to the correct integer.
36627f7eb2Smrg    The argument 'is_iso_c' signals whether the kind is an ISO_C_BINDING
37627f7eb2Smrg    symbol like e.g. 'c_int'.  */
38627f7eb2Smrg 
39627f7eb2Smrg static match
match_kind_param(int * kind,int * is_iso_c)40627f7eb2Smrg match_kind_param (int *kind, int *is_iso_c)
41627f7eb2Smrg {
42627f7eb2Smrg   char name[GFC_MAX_SYMBOL_LEN + 1];
43627f7eb2Smrg   gfc_symbol *sym;
44627f7eb2Smrg   match m;
45627f7eb2Smrg 
46627f7eb2Smrg   *is_iso_c = 0;
47627f7eb2Smrg 
48627f7eb2Smrg   m = gfc_match_small_literal_int (kind, NULL);
49627f7eb2Smrg   if (m != MATCH_NO)
50627f7eb2Smrg     return m;
51627f7eb2Smrg 
52627f7eb2Smrg   m = gfc_match_name (name);
53627f7eb2Smrg   if (m != MATCH_YES)
54627f7eb2Smrg     return m;
55627f7eb2Smrg 
56627f7eb2Smrg   if (gfc_find_symbol (name, NULL, 1, &sym))
57627f7eb2Smrg     return MATCH_ERROR;
58627f7eb2Smrg 
59627f7eb2Smrg   if (sym == NULL)
60627f7eb2Smrg     return MATCH_NO;
61627f7eb2Smrg 
62627f7eb2Smrg   *is_iso_c = sym->attr.is_iso_c;
63627f7eb2Smrg 
64627f7eb2Smrg   if (sym->attr.flavor != FL_PARAMETER)
65627f7eb2Smrg     return MATCH_NO;
66627f7eb2Smrg 
67627f7eb2Smrg   if (sym->value == NULL)
68627f7eb2Smrg     return MATCH_NO;
69627f7eb2Smrg 
70627f7eb2Smrg   if (gfc_extract_int (sym->value, kind))
71627f7eb2Smrg     return MATCH_NO;
72627f7eb2Smrg 
73627f7eb2Smrg   gfc_set_sym_referenced (sym);
74627f7eb2Smrg 
75627f7eb2Smrg   if (*kind < 0)
76627f7eb2Smrg     return MATCH_NO;
77627f7eb2Smrg 
78627f7eb2Smrg   return MATCH_YES;
79627f7eb2Smrg }
80627f7eb2Smrg 
81627f7eb2Smrg 
82627f7eb2Smrg /* Get a trailing kind-specification for non-character variables.
83627f7eb2Smrg    Returns:
84627f7eb2Smrg      * the integer kind value or
85627f7eb2Smrg      * -1 if an error was generated,
86627f7eb2Smrg      * -2 if no kind was found.
87627f7eb2Smrg    The argument 'is_iso_c' signals whether the kind is an ISO_C_BINDING
88627f7eb2Smrg    symbol like e.g. 'c_int'.  */
89627f7eb2Smrg 
90627f7eb2Smrg static int
get_kind(int * is_iso_c)91627f7eb2Smrg get_kind (int *is_iso_c)
92627f7eb2Smrg {
93627f7eb2Smrg   int kind;
94627f7eb2Smrg   match m;
95627f7eb2Smrg 
96627f7eb2Smrg   *is_iso_c = 0;
97627f7eb2Smrg 
98627f7eb2Smrg   if (gfc_match_char ('_') != MATCH_YES)
99627f7eb2Smrg     return -2;
100627f7eb2Smrg 
101627f7eb2Smrg   m = match_kind_param (&kind, is_iso_c);
102627f7eb2Smrg   if (m == MATCH_NO)
103627f7eb2Smrg     gfc_error ("Missing kind-parameter at %C");
104627f7eb2Smrg 
105627f7eb2Smrg   return (m == MATCH_YES) ? kind : -1;
106627f7eb2Smrg }
107627f7eb2Smrg 
108627f7eb2Smrg 
109627f7eb2Smrg /* Given a character and a radix, see if the character is a valid
110627f7eb2Smrg    digit in that radix.  */
111627f7eb2Smrg 
112627f7eb2Smrg int
gfc_check_digit(char c,int radix)113627f7eb2Smrg gfc_check_digit (char c, int radix)
114627f7eb2Smrg {
115627f7eb2Smrg   int r;
116627f7eb2Smrg 
117627f7eb2Smrg   switch (radix)
118627f7eb2Smrg     {
119627f7eb2Smrg     case 2:
120627f7eb2Smrg       r = ('0' <= c && c <= '1');
121627f7eb2Smrg       break;
122627f7eb2Smrg 
123627f7eb2Smrg     case 8:
124627f7eb2Smrg       r = ('0' <= c && c <= '7');
125627f7eb2Smrg       break;
126627f7eb2Smrg 
127627f7eb2Smrg     case 10:
128627f7eb2Smrg       r = ('0' <= c && c <= '9');
129627f7eb2Smrg       break;
130627f7eb2Smrg 
131627f7eb2Smrg     case 16:
132627f7eb2Smrg       r = ISXDIGIT (c);
133627f7eb2Smrg       break;
134627f7eb2Smrg 
135627f7eb2Smrg     default:
136627f7eb2Smrg       gfc_internal_error ("gfc_check_digit(): bad radix");
137627f7eb2Smrg     }
138627f7eb2Smrg 
139627f7eb2Smrg   return r;
140627f7eb2Smrg }
141627f7eb2Smrg 
142627f7eb2Smrg 
143627f7eb2Smrg /* Match the digit string part of an integer if signflag is not set,
144627f7eb2Smrg    the signed digit string part if signflag is set.  If the buffer
145627f7eb2Smrg    is NULL, we just count characters for the resolution pass.  Returns
146627f7eb2Smrg    the number of characters matched, -1 for no match.  */
147627f7eb2Smrg 
148627f7eb2Smrg static int
match_digits(int signflag,int radix,char * buffer)149627f7eb2Smrg match_digits (int signflag, int radix, char *buffer)
150627f7eb2Smrg {
151627f7eb2Smrg   locus old_loc;
152627f7eb2Smrg   int length;
153627f7eb2Smrg   char c;
154627f7eb2Smrg 
155627f7eb2Smrg   length = 0;
156627f7eb2Smrg   c = gfc_next_ascii_char ();
157627f7eb2Smrg 
158627f7eb2Smrg   if (signflag && (c == '+' || c == '-'))
159627f7eb2Smrg     {
160627f7eb2Smrg       if (buffer != NULL)
161627f7eb2Smrg 	*buffer++ = c;
162627f7eb2Smrg       gfc_gobble_whitespace ();
163627f7eb2Smrg       c = gfc_next_ascii_char ();
164627f7eb2Smrg       length++;
165627f7eb2Smrg     }
166627f7eb2Smrg 
167627f7eb2Smrg   if (!gfc_check_digit (c, radix))
168627f7eb2Smrg     return -1;
169627f7eb2Smrg 
170627f7eb2Smrg   length++;
171627f7eb2Smrg   if (buffer != NULL)
172627f7eb2Smrg     *buffer++ = c;
173627f7eb2Smrg 
174627f7eb2Smrg   for (;;)
175627f7eb2Smrg     {
176627f7eb2Smrg       old_loc = gfc_current_locus;
177627f7eb2Smrg       c = gfc_next_ascii_char ();
178627f7eb2Smrg 
179627f7eb2Smrg       if (!gfc_check_digit (c, radix))
180627f7eb2Smrg 	break;
181627f7eb2Smrg 
182627f7eb2Smrg       if (buffer != NULL)
183627f7eb2Smrg 	*buffer++ = c;
184627f7eb2Smrg       length++;
185627f7eb2Smrg     }
186627f7eb2Smrg 
187627f7eb2Smrg   gfc_current_locus = old_loc;
188627f7eb2Smrg 
189627f7eb2Smrg   return length;
190627f7eb2Smrg }
191627f7eb2Smrg 
1924c3eb207Smrg /* Convert an integer string to an expression node.  */
1934c3eb207Smrg 
1944c3eb207Smrg static gfc_expr *
convert_integer(const char * buffer,int kind,int radix,locus * where)1954c3eb207Smrg convert_integer (const char *buffer, int kind, int radix, locus *where)
1964c3eb207Smrg {
1974c3eb207Smrg   gfc_expr *e;
1984c3eb207Smrg   const char *t;
1994c3eb207Smrg 
2004c3eb207Smrg   e = gfc_get_constant_expr (BT_INTEGER, kind, where);
2014c3eb207Smrg   /* A leading plus is allowed, but not by mpz_set_str.  */
2024c3eb207Smrg   if (buffer[0] == '+')
2034c3eb207Smrg     t = buffer + 1;
2044c3eb207Smrg   else
2054c3eb207Smrg     t = buffer;
2064c3eb207Smrg   mpz_set_str (e->value.integer, t, radix);
2074c3eb207Smrg 
2084c3eb207Smrg   return e;
2094c3eb207Smrg }
2104c3eb207Smrg 
2114c3eb207Smrg 
2124c3eb207Smrg /* Convert a real string to an expression node.  */
2134c3eb207Smrg 
2144c3eb207Smrg static gfc_expr *
convert_real(const char * buffer,int kind,locus * where)2154c3eb207Smrg convert_real (const char *buffer, int kind, locus *where)
2164c3eb207Smrg {
2174c3eb207Smrg   gfc_expr *e;
2184c3eb207Smrg 
2194c3eb207Smrg   e = gfc_get_constant_expr (BT_REAL, kind, where);
2204c3eb207Smrg   mpfr_set_str (e->value.real, buffer, 10, GFC_RND_MODE);
2214c3eb207Smrg 
2224c3eb207Smrg   return e;
2234c3eb207Smrg }
2244c3eb207Smrg 
2254c3eb207Smrg 
2264c3eb207Smrg /* Convert a pair of real, constant expression nodes to a single
2274c3eb207Smrg    complex expression node.  */
2284c3eb207Smrg 
2294c3eb207Smrg static gfc_expr *
convert_complex(gfc_expr * real,gfc_expr * imag,int kind)2304c3eb207Smrg convert_complex (gfc_expr *real, gfc_expr *imag, int kind)
2314c3eb207Smrg {
2324c3eb207Smrg   gfc_expr *e;
2334c3eb207Smrg 
2344c3eb207Smrg   e = gfc_get_constant_expr (BT_COMPLEX, kind, &real->where);
2354c3eb207Smrg   mpc_set_fr_fr (e->value.complex, real->value.real, imag->value.real,
2364c3eb207Smrg 		 GFC_MPC_RND_MODE);
2374c3eb207Smrg 
2384c3eb207Smrg   return e;
2394c3eb207Smrg }
2404c3eb207Smrg 
241627f7eb2Smrg 
242627f7eb2Smrg /* Match an integer (digit string and optional kind).
243627f7eb2Smrg    A sign will be accepted if signflag is set.  */
244627f7eb2Smrg 
245627f7eb2Smrg static match
match_integer_constant(gfc_expr ** result,int signflag)246627f7eb2Smrg match_integer_constant (gfc_expr **result, int signflag)
247627f7eb2Smrg {
248627f7eb2Smrg   int length, kind, is_iso_c;
249627f7eb2Smrg   locus old_loc;
250627f7eb2Smrg   char *buffer;
251627f7eb2Smrg   gfc_expr *e;
252627f7eb2Smrg 
253627f7eb2Smrg   old_loc = gfc_current_locus;
254627f7eb2Smrg   gfc_gobble_whitespace ();
255627f7eb2Smrg 
256627f7eb2Smrg   length = match_digits (signflag, 10, NULL);
257627f7eb2Smrg   gfc_current_locus = old_loc;
258627f7eb2Smrg   if (length == -1)
259627f7eb2Smrg     return MATCH_NO;
260627f7eb2Smrg 
261627f7eb2Smrg   buffer = (char *) alloca (length + 1);
262627f7eb2Smrg   memset (buffer, '\0', length + 1);
263627f7eb2Smrg 
264627f7eb2Smrg   gfc_gobble_whitespace ();
265627f7eb2Smrg 
266627f7eb2Smrg   match_digits (signflag, 10, buffer);
267627f7eb2Smrg 
268627f7eb2Smrg   kind = get_kind (&is_iso_c);
269627f7eb2Smrg   if (kind == -2)
270627f7eb2Smrg     kind = gfc_default_integer_kind;
271627f7eb2Smrg   if (kind == -1)
272627f7eb2Smrg     return MATCH_ERROR;
273627f7eb2Smrg 
274627f7eb2Smrg   if (kind == 4 && flag_integer4_kind == 8)
275627f7eb2Smrg     kind = 8;
276627f7eb2Smrg 
277627f7eb2Smrg   if (gfc_validate_kind (BT_INTEGER, kind, true) < 0)
278627f7eb2Smrg     {
279627f7eb2Smrg       gfc_error ("Integer kind %d at %C not available", kind);
280627f7eb2Smrg       return MATCH_ERROR;
281627f7eb2Smrg     }
282627f7eb2Smrg 
2834c3eb207Smrg   e = convert_integer (buffer, kind, 10, &gfc_current_locus);
284627f7eb2Smrg   e->ts.is_c_interop = is_iso_c;
285627f7eb2Smrg 
286627f7eb2Smrg   if (gfc_range_check (e) != ARITH_OK)
287627f7eb2Smrg     {
288627f7eb2Smrg       gfc_error ("Integer too big for its kind at %C. This check can be "
289627f7eb2Smrg 		 "disabled with the option %<-fno-range-check%>");
290627f7eb2Smrg 
291627f7eb2Smrg       gfc_free_expr (e);
292627f7eb2Smrg       return MATCH_ERROR;
293627f7eb2Smrg     }
294627f7eb2Smrg 
295627f7eb2Smrg   *result = e;
296627f7eb2Smrg   return MATCH_YES;
297627f7eb2Smrg }
298627f7eb2Smrg 
299627f7eb2Smrg 
300627f7eb2Smrg /* Match a Hollerith constant.  */
301627f7eb2Smrg 
302627f7eb2Smrg static match
match_hollerith_constant(gfc_expr ** result)303627f7eb2Smrg match_hollerith_constant (gfc_expr **result)
304627f7eb2Smrg {
305627f7eb2Smrg   locus old_loc;
306627f7eb2Smrg   gfc_expr *e = NULL;
307627f7eb2Smrg   int num, pad;
308627f7eb2Smrg   int i;
309627f7eb2Smrg 
310627f7eb2Smrg   old_loc = gfc_current_locus;
311627f7eb2Smrg   gfc_gobble_whitespace ();
312627f7eb2Smrg 
313627f7eb2Smrg   if (match_integer_constant (&e, 0) == MATCH_YES
314627f7eb2Smrg       && gfc_match_char ('h') == MATCH_YES)
315627f7eb2Smrg     {
316627f7eb2Smrg       if (!gfc_notify_std (GFC_STD_LEGACY, "Hollerith constant at %C"))
317627f7eb2Smrg 	goto cleanup;
318627f7eb2Smrg 
319627f7eb2Smrg       if (gfc_extract_int (e, &num, 1))
320627f7eb2Smrg 	goto cleanup;
321627f7eb2Smrg       if (num == 0)
322627f7eb2Smrg 	{
323627f7eb2Smrg 	  gfc_error ("Invalid Hollerith constant: %L must contain at least "
324627f7eb2Smrg 		     "one character", &old_loc);
325627f7eb2Smrg 	  goto cleanup;
326627f7eb2Smrg 	}
327627f7eb2Smrg       if (e->ts.kind != gfc_default_integer_kind)
328627f7eb2Smrg 	{
329627f7eb2Smrg 	  gfc_error ("Invalid Hollerith constant: Integer kind at %L "
330627f7eb2Smrg 		     "should be default", &old_loc);
331627f7eb2Smrg 	  goto cleanup;
332627f7eb2Smrg 	}
333627f7eb2Smrg       else
334627f7eb2Smrg 	{
335627f7eb2Smrg 	  gfc_free_expr (e);
336627f7eb2Smrg 	  e = gfc_get_constant_expr (BT_HOLLERITH, gfc_default_character_kind,
337627f7eb2Smrg 				     &gfc_current_locus);
338627f7eb2Smrg 
339627f7eb2Smrg 	  /* Calculate padding needed to fit default integer memory.  */
340627f7eb2Smrg 	  pad = gfc_default_integer_kind - (num % gfc_default_integer_kind);
341627f7eb2Smrg 
342627f7eb2Smrg 	  e->representation.string = XCNEWVEC (char, num + pad + 1);
343627f7eb2Smrg 
344627f7eb2Smrg 	  for (i = 0; i < num; i++)
345627f7eb2Smrg 	    {
346627f7eb2Smrg 	      gfc_char_t c = gfc_next_char_literal (INSTRING_WARN);
347627f7eb2Smrg 	      if (! gfc_wide_fits_in_byte (c))
348627f7eb2Smrg 		{
349627f7eb2Smrg 		  gfc_error ("Invalid Hollerith constant at %L contains a "
350627f7eb2Smrg 			     "wide character", &old_loc);
351627f7eb2Smrg 		  goto cleanup;
352627f7eb2Smrg 		}
353627f7eb2Smrg 
354627f7eb2Smrg 	      e->representation.string[i] = (unsigned char) c;
355627f7eb2Smrg 	    }
356627f7eb2Smrg 
357627f7eb2Smrg 	  /* Now pad with blanks and end with a null char.  */
358627f7eb2Smrg 	  for (i = 0; i < pad; i++)
359627f7eb2Smrg 	    e->representation.string[num + i] = ' ';
360627f7eb2Smrg 
361627f7eb2Smrg 	  e->representation.string[num + i] = '\0';
362627f7eb2Smrg 	  e->representation.length = num + pad;
363627f7eb2Smrg 	  e->ts.u.pad = pad;
364627f7eb2Smrg 
365627f7eb2Smrg 	  *result = e;
366627f7eb2Smrg 	  return MATCH_YES;
367627f7eb2Smrg 	}
368627f7eb2Smrg     }
369627f7eb2Smrg 
370627f7eb2Smrg   gfc_free_expr (e);
371627f7eb2Smrg   gfc_current_locus = old_loc;
372627f7eb2Smrg   return MATCH_NO;
373627f7eb2Smrg 
374627f7eb2Smrg cleanup:
375627f7eb2Smrg   gfc_free_expr (e);
376627f7eb2Smrg   return MATCH_ERROR;
377627f7eb2Smrg }
378627f7eb2Smrg 
379627f7eb2Smrg 
380627f7eb2Smrg /* Match a binary, octal or hexadecimal constant that can be found in
381627f7eb2Smrg    a DATA statement.  The standard permits b'010...', o'73...', and
382627f7eb2Smrg    z'a1...' where b, o, and z can be capital letters.  This function
383627f7eb2Smrg    also accepts postfixed forms of the constants: '01...'b, '73...'o,
384627f7eb2Smrg    and 'a1...'z.  An additional extension is the use of x for z.  */
385627f7eb2Smrg 
386627f7eb2Smrg static match
match_boz_constant(gfc_expr ** result)387627f7eb2Smrg match_boz_constant (gfc_expr **result)
388627f7eb2Smrg {
3894c3eb207Smrg   int radix, length, x_hex;
390627f7eb2Smrg   locus old_loc, start_loc;
391627f7eb2Smrg   char *buffer, post, delim;
392627f7eb2Smrg   gfc_expr *e;
393627f7eb2Smrg 
394627f7eb2Smrg   start_loc = old_loc = gfc_current_locus;
395627f7eb2Smrg   gfc_gobble_whitespace ();
396627f7eb2Smrg 
397627f7eb2Smrg   x_hex = 0;
398627f7eb2Smrg   switch (post = gfc_next_ascii_char ())
399627f7eb2Smrg     {
400627f7eb2Smrg     case 'b':
401627f7eb2Smrg       radix = 2;
402627f7eb2Smrg       post = 0;
403627f7eb2Smrg       break;
404627f7eb2Smrg     case 'o':
405627f7eb2Smrg       radix = 8;
406627f7eb2Smrg       post = 0;
407627f7eb2Smrg       break;
408627f7eb2Smrg     case 'x':
409627f7eb2Smrg       x_hex = 1;
410627f7eb2Smrg       /* Fall through.  */
411627f7eb2Smrg     case 'z':
412627f7eb2Smrg       radix = 16;
413627f7eb2Smrg       post = 0;
414627f7eb2Smrg       break;
415627f7eb2Smrg     case '\'':
416627f7eb2Smrg       /* Fall through.  */
417627f7eb2Smrg     case '\"':
418627f7eb2Smrg       delim = post;
419627f7eb2Smrg       post = 1;
420627f7eb2Smrg       radix = 16;  /* Set to accept any valid digit string.  */
421627f7eb2Smrg       break;
422627f7eb2Smrg     default:
423627f7eb2Smrg       goto backup;
424627f7eb2Smrg     }
425627f7eb2Smrg 
426627f7eb2Smrg   /* No whitespace allowed here.  */
427627f7eb2Smrg 
428627f7eb2Smrg   if (post == 0)
429627f7eb2Smrg     delim = gfc_next_ascii_char ();
430627f7eb2Smrg 
431627f7eb2Smrg   if (delim != '\'' && delim != '\"')
432627f7eb2Smrg     goto backup;
433627f7eb2Smrg 
434627f7eb2Smrg   if (x_hex
4354c3eb207Smrg       && gfc_invalid_boz ("Hexadecimal constant at %L uses "
4364c3eb207Smrg 			  "nonstandard X instead of Z", &gfc_current_locus))
437627f7eb2Smrg     return MATCH_ERROR;
438627f7eb2Smrg 
439627f7eb2Smrg   old_loc = gfc_current_locus;
440627f7eb2Smrg 
441627f7eb2Smrg   length = match_digits (0, radix, NULL);
442627f7eb2Smrg   if (length == -1)
443627f7eb2Smrg     {
444627f7eb2Smrg       gfc_error ("Empty set of digits in BOZ constant at %C");
445627f7eb2Smrg       return MATCH_ERROR;
446627f7eb2Smrg     }
447627f7eb2Smrg 
448627f7eb2Smrg   if (gfc_next_ascii_char () != delim)
449627f7eb2Smrg     {
450627f7eb2Smrg       gfc_error ("Illegal character in BOZ constant at %C");
451627f7eb2Smrg       return MATCH_ERROR;
452627f7eb2Smrg     }
453627f7eb2Smrg 
454627f7eb2Smrg   if (post == 1)
455627f7eb2Smrg     {
456627f7eb2Smrg       switch (gfc_next_ascii_char ())
457627f7eb2Smrg 	{
458627f7eb2Smrg 	case 'b':
459627f7eb2Smrg 	  radix = 2;
460627f7eb2Smrg 	  break;
461627f7eb2Smrg 	case 'o':
462627f7eb2Smrg 	  radix = 8;
463627f7eb2Smrg 	  break;
464627f7eb2Smrg 	case 'x':
465627f7eb2Smrg 	  /* Fall through.  */
466627f7eb2Smrg 	case 'z':
467627f7eb2Smrg 	  radix = 16;
468627f7eb2Smrg 	  break;
469627f7eb2Smrg 	default:
470627f7eb2Smrg 	  goto backup;
471627f7eb2Smrg 	}
472627f7eb2Smrg 
4734c3eb207Smrg       if (gfc_invalid_boz ("BOZ constant at %C uses nonstandard postfix "
4744c3eb207Smrg 			   "syntax", &gfc_current_locus))
475627f7eb2Smrg 	return MATCH_ERROR;
476627f7eb2Smrg     }
477627f7eb2Smrg 
478627f7eb2Smrg   gfc_current_locus = old_loc;
479627f7eb2Smrg 
480627f7eb2Smrg   buffer = (char *) alloca (length + 1);
481627f7eb2Smrg   memset (buffer, '\0', length + 1);
482627f7eb2Smrg 
483627f7eb2Smrg   match_digits (0, radix, buffer);
484627f7eb2Smrg   gfc_next_ascii_char ();    /* Eat delimiter.  */
485627f7eb2Smrg   if (post == 1)
486627f7eb2Smrg     gfc_next_ascii_char ();  /* Eat postfixed b, o, z, or x.  */
487627f7eb2Smrg 
4884c3eb207Smrg   e = gfc_get_expr ();
4894c3eb207Smrg   e->expr_type = EXPR_CONSTANT;
4904c3eb207Smrg   e->ts.type = BT_BOZ;
4914c3eb207Smrg   e->where = gfc_current_locus;
4924c3eb207Smrg   e->boz.rdx = radix;
4934c3eb207Smrg   e->boz.len = length;
4944c3eb207Smrg   e->boz.str = XCNEWVEC (char, length + 1);
4954c3eb207Smrg   strncpy (e->boz.str, buffer, length);
496627f7eb2Smrg 
497627f7eb2Smrg   if (!gfc_in_match_data ()
498627f7eb2Smrg       && (!gfc_notify_std(GFC_STD_F2003, "BOZ used outside a DATA "
4994c3eb207Smrg 			  "statement at %L", &e->where)))
500627f7eb2Smrg     return MATCH_ERROR;
501627f7eb2Smrg 
502627f7eb2Smrg   *result = e;
503627f7eb2Smrg   return MATCH_YES;
504627f7eb2Smrg 
505627f7eb2Smrg backup:
506627f7eb2Smrg   gfc_current_locus = start_loc;
507627f7eb2Smrg   return MATCH_NO;
508627f7eb2Smrg }
509627f7eb2Smrg 
510627f7eb2Smrg 
511627f7eb2Smrg /* Match a real constant of some sort.  Allow a signed constant if signflag
512627f7eb2Smrg    is nonzero.  */
513627f7eb2Smrg 
514627f7eb2Smrg static match
match_real_constant(gfc_expr ** result,int signflag)515627f7eb2Smrg match_real_constant (gfc_expr **result, int signflag)
516627f7eb2Smrg {
517627f7eb2Smrg   int kind, count, seen_dp, seen_digits, is_iso_c, default_exponent;
518627f7eb2Smrg   locus old_loc, temp_loc;
519627f7eb2Smrg   char *p, *buffer, c, exp_char;
520627f7eb2Smrg   gfc_expr *e;
521627f7eb2Smrg   bool negate;
522627f7eb2Smrg 
523627f7eb2Smrg   old_loc = gfc_current_locus;
524627f7eb2Smrg   gfc_gobble_whitespace ();
525627f7eb2Smrg 
526627f7eb2Smrg   e = NULL;
527627f7eb2Smrg 
528627f7eb2Smrg   default_exponent = 0;
529627f7eb2Smrg   count = 0;
530627f7eb2Smrg   seen_dp = 0;
531627f7eb2Smrg   seen_digits = 0;
532627f7eb2Smrg   exp_char = ' ';
533627f7eb2Smrg   negate = FALSE;
534627f7eb2Smrg 
535627f7eb2Smrg   c = gfc_next_ascii_char ();
536627f7eb2Smrg   if (signflag && (c == '+' || c == '-'))
537627f7eb2Smrg     {
538627f7eb2Smrg       if (c == '-')
539627f7eb2Smrg 	negate = TRUE;
540627f7eb2Smrg 
541627f7eb2Smrg       gfc_gobble_whitespace ();
542627f7eb2Smrg       c = gfc_next_ascii_char ();
543627f7eb2Smrg     }
544627f7eb2Smrg 
545627f7eb2Smrg   /* Scan significand.  */
546627f7eb2Smrg   for (;; c = gfc_next_ascii_char (), count++)
547627f7eb2Smrg     {
548627f7eb2Smrg       if (c == '.')
549627f7eb2Smrg 	{
550627f7eb2Smrg 	  if (seen_dp)
551627f7eb2Smrg 	    goto done;
552627f7eb2Smrg 
553627f7eb2Smrg 	  /* Check to see if "." goes with a following operator like
554627f7eb2Smrg 	     ".eq.".  */
555627f7eb2Smrg 	  temp_loc = gfc_current_locus;
556627f7eb2Smrg 	  c = gfc_next_ascii_char ();
557627f7eb2Smrg 
558627f7eb2Smrg 	  if (c == 'e' || c == 'd' || c == 'q')
559627f7eb2Smrg 	    {
560627f7eb2Smrg 	      c = gfc_next_ascii_char ();
561627f7eb2Smrg 	      if (c == '.')
562627f7eb2Smrg 		goto done;	/* Operator named .e. or .d.  */
563627f7eb2Smrg 	    }
564627f7eb2Smrg 
565627f7eb2Smrg 	  if (ISALPHA (c))
566627f7eb2Smrg 	    goto done;		/* Distinguish 1.e9 from 1.eq.2 */
567627f7eb2Smrg 
568627f7eb2Smrg 	  gfc_current_locus = temp_loc;
569627f7eb2Smrg 	  seen_dp = 1;
570627f7eb2Smrg 	  continue;
571627f7eb2Smrg 	}
572627f7eb2Smrg 
573627f7eb2Smrg       if (ISDIGIT (c))
574627f7eb2Smrg 	{
575627f7eb2Smrg 	  seen_digits = 1;
576627f7eb2Smrg 	  continue;
577627f7eb2Smrg 	}
578627f7eb2Smrg 
579627f7eb2Smrg       break;
580627f7eb2Smrg     }
581627f7eb2Smrg 
582627f7eb2Smrg   if (!seen_digits || (c != 'e' && c != 'd' && c != 'q'))
583627f7eb2Smrg     goto done;
584627f7eb2Smrg   exp_char = c;
585627f7eb2Smrg 
586627f7eb2Smrg 
587627f7eb2Smrg   if (c == 'q')
588627f7eb2Smrg     {
589627f7eb2Smrg       if (!gfc_notify_std (GFC_STD_GNU, "exponent-letter 'q' in "
590627f7eb2Smrg 			   "real-literal-constant at %C"))
591627f7eb2Smrg 	return MATCH_ERROR;
592627f7eb2Smrg       else if (warn_real_q_constant)
593627f7eb2Smrg 	gfc_warning (OPT_Wreal_q_constant,
594627f7eb2Smrg 		     "Extension: exponent-letter %<q%> in real-literal-constant "
595627f7eb2Smrg 		     "at %C");
596627f7eb2Smrg     }
597627f7eb2Smrg 
598627f7eb2Smrg   /* Scan exponent.  */
599627f7eb2Smrg   c = gfc_next_ascii_char ();
600627f7eb2Smrg   count++;
601627f7eb2Smrg 
602627f7eb2Smrg   if (c == '+' || c == '-')
603627f7eb2Smrg     {				/* optional sign */
604627f7eb2Smrg       c = gfc_next_ascii_char ();
605627f7eb2Smrg       count++;
606627f7eb2Smrg     }
607627f7eb2Smrg 
608627f7eb2Smrg   if (!ISDIGIT (c))
609627f7eb2Smrg     {
610627f7eb2Smrg       /* With -fdec, default exponent to 0 instead of complaining.  */
611627f7eb2Smrg       if (flag_dec)
612627f7eb2Smrg 	default_exponent = 1;
613627f7eb2Smrg       else
614627f7eb2Smrg 	{
615627f7eb2Smrg 	  gfc_error ("Missing exponent in real number at %C");
616627f7eb2Smrg 	  return MATCH_ERROR;
617627f7eb2Smrg 	}
618627f7eb2Smrg     }
619627f7eb2Smrg 
620627f7eb2Smrg   while (ISDIGIT (c))
621627f7eb2Smrg     {
622627f7eb2Smrg       c = gfc_next_ascii_char ();
623627f7eb2Smrg       count++;
624627f7eb2Smrg     }
625627f7eb2Smrg 
626627f7eb2Smrg done:
627627f7eb2Smrg   /* Check that we have a numeric constant.  */
628627f7eb2Smrg   if (!seen_digits || (!seen_dp && exp_char == ' '))
629627f7eb2Smrg     {
630627f7eb2Smrg       gfc_current_locus = old_loc;
631627f7eb2Smrg       return MATCH_NO;
632627f7eb2Smrg     }
633627f7eb2Smrg 
634627f7eb2Smrg   /* Convert the number.  */
635627f7eb2Smrg   gfc_current_locus = old_loc;
636627f7eb2Smrg   gfc_gobble_whitespace ();
637627f7eb2Smrg 
638627f7eb2Smrg   buffer = (char *) alloca (count + default_exponent + 1);
639627f7eb2Smrg   memset (buffer, '\0', count + default_exponent + 1);
640627f7eb2Smrg 
641627f7eb2Smrg   p = buffer;
642627f7eb2Smrg   c = gfc_next_ascii_char ();
643627f7eb2Smrg   if (c == '+' || c == '-')
644627f7eb2Smrg     {
645627f7eb2Smrg       gfc_gobble_whitespace ();
646627f7eb2Smrg       c = gfc_next_ascii_char ();
647627f7eb2Smrg     }
648627f7eb2Smrg 
649627f7eb2Smrg   /* Hack for mpfr_set_str().  */
650627f7eb2Smrg   for (;;)
651627f7eb2Smrg     {
652627f7eb2Smrg       if (c == 'd' || c == 'q')
653627f7eb2Smrg 	*p = 'e';
654627f7eb2Smrg       else
655627f7eb2Smrg 	*p = c;
656627f7eb2Smrg       p++;
657627f7eb2Smrg       if (--count == 0)
658627f7eb2Smrg 	break;
659627f7eb2Smrg 
660627f7eb2Smrg       c = gfc_next_ascii_char ();
661627f7eb2Smrg     }
662627f7eb2Smrg   if (default_exponent)
663627f7eb2Smrg     *p++ = '0';
664627f7eb2Smrg 
665627f7eb2Smrg   kind = get_kind (&is_iso_c);
666627f7eb2Smrg   if (kind == -1)
667627f7eb2Smrg     goto cleanup;
668627f7eb2Smrg 
669627f7eb2Smrg   switch (exp_char)
670627f7eb2Smrg     {
671627f7eb2Smrg     case 'd':
672627f7eb2Smrg       if (kind != -2)
673627f7eb2Smrg 	{
674627f7eb2Smrg 	  gfc_error ("Real number at %C has a %<d%> exponent and an explicit "
675627f7eb2Smrg 		     "kind");
676627f7eb2Smrg 	  goto cleanup;
677627f7eb2Smrg 	}
678627f7eb2Smrg       kind = gfc_default_double_kind;
679627f7eb2Smrg 
680627f7eb2Smrg       if (kind == 4)
681627f7eb2Smrg 	{
682627f7eb2Smrg 	  if (flag_real4_kind == 8)
683627f7eb2Smrg 	    kind = 8;
684627f7eb2Smrg 	  if (flag_real4_kind == 10)
685627f7eb2Smrg 	    kind = 10;
686627f7eb2Smrg 	  if (flag_real4_kind == 16)
687627f7eb2Smrg 	    kind = 16;
688627f7eb2Smrg 	}
689627f7eb2Smrg 
690627f7eb2Smrg       if (kind == 8)
691627f7eb2Smrg 	{
692627f7eb2Smrg 	  if (flag_real8_kind == 4)
693627f7eb2Smrg 	    kind = 4;
694627f7eb2Smrg 	  if (flag_real8_kind == 10)
695627f7eb2Smrg 	    kind = 10;
696627f7eb2Smrg 	  if (flag_real8_kind == 16)
697627f7eb2Smrg 	    kind = 16;
698627f7eb2Smrg 	}
699627f7eb2Smrg       break;
700627f7eb2Smrg 
701627f7eb2Smrg     case 'q':
702627f7eb2Smrg       if (kind != -2)
703627f7eb2Smrg 	{
704627f7eb2Smrg 	  gfc_error ("Real number at %C has a %<q%> exponent and an explicit "
705627f7eb2Smrg 		     "kind");
706627f7eb2Smrg 	  goto cleanup;
707627f7eb2Smrg 	}
708627f7eb2Smrg 
709627f7eb2Smrg       /* The maximum possible real kind type parameter is 16.  First, try
710627f7eb2Smrg 	 that for the kind, then fallback to trying kind=10 (Intel 80 bit)
711627f7eb2Smrg 	 extended precision.  If neither value works, just given up.  */
712627f7eb2Smrg       kind = 16;
713627f7eb2Smrg       if (gfc_validate_kind (BT_REAL, kind, true) < 0)
714627f7eb2Smrg 	{
715627f7eb2Smrg 	  kind = 10;
716627f7eb2Smrg           if (gfc_validate_kind (BT_REAL, kind, true) < 0)
717627f7eb2Smrg 	    {
718627f7eb2Smrg 	      gfc_error ("Invalid exponent-letter %<q%> in "
719627f7eb2Smrg 			 "real-literal-constant at %C");
720627f7eb2Smrg 	      goto cleanup;
721627f7eb2Smrg 	    }
722627f7eb2Smrg 	}
723627f7eb2Smrg       break;
724627f7eb2Smrg 
725627f7eb2Smrg     default:
726627f7eb2Smrg       if (kind == -2)
727627f7eb2Smrg 	kind = gfc_default_real_kind;
728627f7eb2Smrg 
729627f7eb2Smrg       if (kind == 4)
730627f7eb2Smrg 	{
731627f7eb2Smrg 	  if (flag_real4_kind == 8)
732627f7eb2Smrg 	    kind = 8;
733627f7eb2Smrg 	  if (flag_real4_kind == 10)
734627f7eb2Smrg 	    kind = 10;
735627f7eb2Smrg 	  if (flag_real4_kind == 16)
736627f7eb2Smrg 	    kind = 16;
737627f7eb2Smrg 	}
738627f7eb2Smrg 
739627f7eb2Smrg       if (kind == 8)
740627f7eb2Smrg 	{
741627f7eb2Smrg 	  if (flag_real8_kind == 4)
742627f7eb2Smrg 	    kind = 4;
743627f7eb2Smrg 	  if (flag_real8_kind == 10)
744627f7eb2Smrg 	    kind = 10;
745627f7eb2Smrg 	  if (flag_real8_kind == 16)
746627f7eb2Smrg 	    kind = 16;
747627f7eb2Smrg 	}
748627f7eb2Smrg 
749627f7eb2Smrg       if (gfc_validate_kind (BT_REAL, kind, true) < 0)
750627f7eb2Smrg 	{
751627f7eb2Smrg 	  gfc_error ("Invalid real kind %d at %C", kind);
752627f7eb2Smrg 	  goto cleanup;
753627f7eb2Smrg 	}
754627f7eb2Smrg     }
755627f7eb2Smrg 
7564c3eb207Smrg   e = convert_real (buffer, kind, &gfc_current_locus);
757627f7eb2Smrg   if (negate)
758627f7eb2Smrg     mpfr_neg (e->value.real, e->value.real, GFC_RND_MODE);
759627f7eb2Smrg   e->ts.is_c_interop = is_iso_c;
760627f7eb2Smrg 
761627f7eb2Smrg   switch (gfc_range_check (e))
762627f7eb2Smrg     {
763627f7eb2Smrg     case ARITH_OK:
764627f7eb2Smrg       break;
765627f7eb2Smrg     case ARITH_OVERFLOW:
766627f7eb2Smrg       gfc_error ("Real constant overflows its kind at %C");
767627f7eb2Smrg       goto cleanup;
768627f7eb2Smrg 
769627f7eb2Smrg     case ARITH_UNDERFLOW:
770627f7eb2Smrg       if (warn_underflow)
771627f7eb2Smrg 	gfc_warning (OPT_Wunderflow, "Real constant underflows its kind at %C");
772627f7eb2Smrg       mpfr_set_ui (e->value.real, 0, GFC_RND_MODE);
773627f7eb2Smrg       break;
774627f7eb2Smrg 
775627f7eb2Smrg     default:
776627f7eb2Smrg       gfc_internal_error ("gfc_range_check() returned bad value");
777627f7eb2Smrg     }
778627f7eb2Smrg 
779627f7eb2Smrg   /* Warn about trailing digits which suggest the user added too many
780627f7eb2Smrg      trailing digits, which may cause the appearance of higher pecision
781627f7eb2Smrg      than the kind kan support.
782627f7eb2Smrg 
783627f7eb2Smrg      This is done by replacing the rightmost non-zero digit with zero
784627f7eb2Smrg      and comparing with the original value.  If these are equal, we
785627f7eb2Smrg      assume the user supplied more digits than intended (or forgot to
786627f7eb2Smrg      convert to the correct kind).
787627f7eb2Smrg   */
788627f7eb2Smrg 
789627f7eb2Smrg   if (warn_conversion_extra)
790627f7eb2Smrg     {
791627f7eb2Smrg       mpfr_t r;
7924c3eb207Smrg       char *c1;
793627f7eb2Smrg       bool did_break;
794627f7eb2Smrg 
7954c3eb207Smrg       c1 = strchr (buffer, 'e');
7964c3eb207Smrg       if (c1 == NULL)
7974c3eb207Smrg 	c1 = buffer + strlen(buffer);
798627f7eb2Smrg 
799627f7eb2Smrg       did_break = false;
8004c3eb207Smrg       for (p = c1; p > buffer;)
801627f7eb2Smrg 	{
8024c3eb207Smrg 	  p--;
803627f7eb2Smrg 	  if (*p == '.')
804627f7eb2Smrg 	    continue;
805627f7eb2Smrg 
806627f7eb2Smrg 	  if (*p != '0')
807627f7eb2Smrg 	    {
808627f7eb2Smrg 	      *p = '0';
809627f7eb2Smrg 	      did_break = true;
810627f7eb2Smrg 	      break;
811627f7eb2Smrg 	    }
812627f7eb2Smrg 	}
813627f7eb2Smrg 
814627f7eb2Smrg       if (did_break)
815627f7eb2Smrg 	{
816627f7eb2Smrg 	  mpfr_init (r);
817627f7eb2Smrg 	  mpfr_set_str (r, buffer, 10, GFC_RND_MODE);
818627f7eb2Smrg 	  if (negate)
819627f7eb2Smrg 	    mpfr_neg (r, r, GFC_RND_MODE);
820627f7eb2Smrg 
821627f7eb2Smrg 	  mpfr_sub (r, r, e->value.real, GFC_RND_MODE);
822627f7eb2Smrg 
823627f7eb2Smrg 	  if (mpfr_cmp_ui (r, 0) == 0)
824627f7eb2Smrg 	    gfc_warning (OPT_Wconversion_extra, "Non-significant digits "
825627f7eb2Smrg 			 "in %qs number at %C, maybe incorrect KIND",
826627f7eb2Smrg 			 gfc_typename (&e->ts));
827627f7eb2Smrg 
828627f7eb2Smrg 	  mpfr_clear (r);
829627f7eb2Smrg 	}
830627f7eb2Smrg     }
831627f7eb2Smrg 
832627f7eb2Smrg   *result = e;
833627f7eb2Smrg   return MATCH_YES;
834627f7eb2Smrg 
835627f7eb2Smrg cleanup:
836627f7eb2Smrg   gfc_free_expr (e);
837627f7eb2Smrg   return MATCH_ERROR;
838627f7eb2Smrg }
839627f7eb2Smrg 
840627f7eb2Smrg 
841627f7eb2Smrg /* Match a substring reference.  */
842627f7eb2Smrg 
843627f7eb2Smrg static match
match_substring(gfc_charlen * cl,int init,gfc_ref ** result,bool deferred)844627f7eb2Smrg match_substring (gfc_charlen *cl, int init, gfc_ref **result, bool deferred)
845627f7eb2Smrg {
846627f7eb2Smrg   gfc_expr *start, *end;
847627f7eb2Smrg   locus old_loc;
848627f7eb2Smrg   gfc_ref *ref;
849627f7eb2Smrg   match m;
850627f7eb2Smrg 
851627f7eb2Smrg   start = NULL;
852627f7eb2Smrg   end = NULL;
853627f7eb2Smrg 
854627f7eb2Smrg   old_loc = gfc_current_locus;
855627f7eb2Smrg 
856627f7eb2Smrg   m = gfc_match_char ('(');
857627f7eb2Smrg   if (m != MATCH_YES)
858627f7eb2Smrg     return MATCH_NO;
859627f7eb2Smrg 
860627f7eb2Smrg   if (gfc_match_char (':') != MATCH_YES)
861627f7eb2Smrg     {
862627f7eb2Smrg       if (init)
863627f7eb2Smrg 	m = gfc_match_init_expr (&start);
864627f7eb2Smrg       else
865627f7eb2Smrg 	m = gfc_match_expr (&start);
866627f7eb2Smrg 
867627f7eb2Smrg       if (m != MATCH_YES)
868627f7eb2Smrg 	{
869627f7eb2Smrg 	  m = MATCH_NO;
870627f7eb2Smrg 	  goto cleanup;
871627f7eb2Smrg 	}
872627f7eb2Smrg 
873627f7eb2Smrg       m = gfc_match_char (':');
874627f7eb2Smrg       if (m != MATCH_YES)
875627f7eb2Smrg 	goto cleanup;
876627f7eb2Smrg     }
877627f7eb2Smrg 
878627f7eb2Smrg   if (gfc_match_char (')') != MATCH_YES)
879627f7eb2Smrg     {
880627f7eb2Smrg       if (init)
881627f7eb2Smrg 	m = gfc_match_init_expr (&end);
882627f7eb2Smrg       else
883627f7eb2Smrg 	m = gfc_match_expr (&end);
884627f7eb2Smrg 
885627f7eb2Smrg       if (m == MATCH_NO)
886627f7eb2Smrg 	goto syntax;
887627f7eb2Smrg       if (m == MATCH_ERROR)
888627f7eb2Smrg 	goto cleanup;
889627f7eb2Smrg 
890627f7eb2Smrg       m = gfc_match_char (')');
891627f7eb2Smrg       if (m == MATCH_NO)
892627f7eb2Smrg 	goto syntax;
893627f7eb2Smrg     }
894627f7eb2Smrg 
895627f7eb2Smrg   /* Optimize away the (:) reference.  */
896627f7eb2Smrg   if (start == NULL && end == NULL && !deferred)
897627f7eb2Smrg     ref = NULL;
898627f7eb2Smrg   else
899627f7eb2Smrg     {
900627f7eb2Smrg       ref = gfc_get_ref ();
901627f7eb2Smrg 
902627f7eb2Smrg       ref->type = REF_SUBSTRING;
903627f7eb2Smrg       if (start == NULL)
904627f7eb2Smrg 	start = gfc_get_int_expr (gfc_charlen_int_kind, NULL, 1);
905627f7eb2Smrg       ref->u.ss.start = start;
906627f7eb2Smrg       if (end == NULL && cl)
907627f7eb2Smrg 	end = gfc_copy_expr (cl->length);
908627f7eb2Smrg       ref->u.ss.end = end;
909627f7eb2Smrg       ref->u.ss.length = cl;
910627f7eb2Smrg     }
911627f7eb2Smrg 
912627f7eb2Smrg   *result = ref;
913627f7eb2Smrg   return MATCH_YES;
914627f7eb2Smrg 
915627f7eb2Smrg syntax:
916627f7eb2Smrg   gfc_error ("Syntax error in SUBSTRING specification at %C");
917627f7eb2Smrg   m = MATCH_ERROR;
918627f7eb2Smrg 
919627f7eb2Smrg cleanup:
920627f7eb2Smrg   gfc_free_expr (start);
921627f7eb2Smrg   gfc_free_expr (end);
922627f7eb2Smrg 
923627f7eb2Smrg   gfc_current_locus = old_loc;
924627f7eb2Smrg   return m;
925627f7eb2Smrg }
926627f7eb2Smrg 
927627f7eb2Smrg 
928627f7eb2Smrg /* Reads the next character of a string constant, taking care to
929627f7eb2Smrg    return doubled delimiters on the input as a single instance of
930627f7eb2Smrg    the delimiter.
931627f7eb2Smrg 
932627f7eb2Smrg    Special return values for "ret" argument are:
933627f7eb2Smrg      -1   End of the string, as determined by the delimiter
934627f7eb2Smrg      -2   Unterminated string detected
935627f7eb2Smrg 
936627f7eb2Smrg    Backslash codes are also expanded at this time.  */
937627f7eb2Smrg 
938627f7eb2Smrg static gfc_char_t
next_string_char(gfc_char_t delimiter,int * ret)939627f7eb2Smrg next_string_char (gfc_char_t delimiter, int *ret)
940627f7eb2Smrg {
941627f7eb2Smrg   locus old_locus;
942627f7eb2Smrg   gfc_char_t c;
943627f7eb2Smrg 
944627f7eb2Smrg   c = gfc_next_char_literal (INSTRING_WARN);
945627f7eb2Smrg   *ret = 0;
946627f7eb2Smrg 
947627f7eb2Smrg   if (c == '\n')
948627f7eb2Smrg     {
949627f7eb2Smrg       *ret = -2;
950627f7eb2Smrg       return 0;
951627f7eb2Smrg     }
952627f7eb2Smrg 
953627f7eb2Smrg   if (flag_backslash && c == '\\')
954627f7eb2Smrg     {
955627f7eb2Smrg       old_locus = gfc_current_locus;
956627f7eb2Smrg 
957627f7eb2Smrg       if (gfc_match_special_char (&c) == MATCH_NO)
958627f7eb2Smrg 	gfc_current_locus = old_locus;
959627f7eb2Smrg 
960627f7eb2Smrg       if (!(gfc_option.allow_std & GFC_STD_GNU) && !inhibit_warnings)
961627f7eb2Smrg 	gfc_warning (0, "Extension: backslash character at %C");
962627f7eb2Smrg     }
963627f7eb2Smrg 
964627f7eb2Smrg   if (c != delimiter)
965627f7eb2Smrg     return c;
966627f7eb2Smrg 
967627f7eb2Smrg   old_locus = gfc_current_locus;
968627f7eb2Smrg   c = gfc_next_char_literal (NONSTRING);
969627f7eb2Smrg 
970627f7eb2Smrg   if (c == delimiter)
971627f7eb2Smrg     return c;
972627f7eb2Smrg   gfc_current_locus = old_locus;
973627f7eb2Smrg 
974627f7eb2Smrg   *ret = -1;
975627f7eb2Smrg   return 0;
976627f7eb2Smrg }
977627f7eb2Smrg 
978627f7eb2Smrg 
979627f7eb2Smrg /* Special case of gfc_match_name() that matches a parameter kind name
980627f7eb2Smrg    before a string constant.  This takes case of the weird but legal
981627f7eb2Smrg    case of:
982627f7eb2Smrg 
983627f7eb2Smrg      kind_____'string'
984627f7eb2Smrg 
985627f7eb2Smrg    where kind____ is a parameter. gfc_match_name() will happily slurp
986627f7eb2Smrg    up all the underscores, which leads to problems.  If we return
987627f7eb2Smrg    MATCH_YES, the parse pointer points to the final underscore, which
988627f7eb2Smrg    is not part of the name.  We never return MATCH_ERROR-- errors in
989627f7eb2Smrg    the name will be detected later.  */
990627f7eb2Smrg 
991627f7eb2Smrg static match
match_charkind_name(char * name)992627f7eb2Smrg match_charkind_name (char *name)
993627f7eb2Smrg {
994627f7eb2Smrg   locus old_loc;
995627f7eb2Smrg   char c, peek;
996627f7eb2Smrg   int len;
997627f7eb2Smrg 
998627f7eb2Smrg   gfc_gobble_whitespace ();
999627f7eb2Smrg   c = gfc_next_ascii_char ();
1000627f7eb2Smrg   if (!ISALPHA (c))
1001627f7eb2Smrg     return MATCH_NO;
1002627f7eb2Smrg 
1003627f7eb2Smrg   *name++ = c;
1004627f7eb2Smrg   len = 1;
1005627f7eb2Smrg 
1006627f7eb2Smrg   for (;;)
1007627f7eb2Smrg     {
1008627f7eb2Smrg       old_loc = gfc_current_locus;
1009627f7eb2Smrg       c = gfc_next_ascii_char ();
1010627f7eb2Smrg 
1011627f7eb2Smrg       if (c == '_')
1012627f7eb2Smrg 	{
1013627f7eb2Smrg 	  peek = gfc_peek_ascii_char ();
1014627f7eb2Smrg 
1015627f7eb2Smrg 	  if (peek == '\'' || peek == '\"')
1016627f7eb2Smrg 	    {
1017627f7eb2Smrg 	      gfc_current_locus = old_loc;
1018627f7eb2Smrg 	      *name = '\0';
1019627f7eb2Smrg 	      return MATCH_YES;
1020627f7eb2Smrg 	    }
1021627f7eb2Smrg 	}
1022627f7eb2Smrg 
1023627f7eb2Smrg       if (!ISALNUM (c)
1024627f7eb2Smrg 	  && c != '_'
1025627f7eb2Smrg 	  && (c != '$' || !flag_dollar_ok))
1026627f7eb2Smrg 	break;
1027627f7eb2Smrg 
1028627f7eb2Smrg       *name++ = c;
1029627f7eb2Smrg       if (++len > GFC_MAX_SYMBOL_LEN)
1030627f7eb2Smrg 	break;
1031627f7eb2Smrg     }
1032627f7eb2Smrg 
1033627f7eb2Smrg   return MATCH_NO;
1034627f7eb2Smrg }
1035627f7eb2Smrg 
1036627f7eb2Smrg 
1037627f7eb2Smrg /* See if the current input matches a character constant.  Lots of
1038627f7eb2Smrg    contortions have to be done to match the kind parameter which comes
1039627f7eb2Smrg    before the actual string.  The main consideration is that we don't
1040627f7eb2Smrg    want to error out too quickly.  For example, we don't actually do
1041627f7eb2Smrg    any validation of the kinds until we have actually seen a legal
1042627f7eb2Smrg    delimiter.  Using match_kind_param() generates errors too quickly.  */
1043627f7eb2Smrg 
1044627f7eb2Smrg static match
match_string_constant(gfc_expr ** result)1045627f7eb2Smrg match_string_constant (gfc_expr **result)
1046627f7eb2Smrg {
1047627f7eb2Smrg   char name[GFC_MAX_SYMBOL_LEN + 1], peek;
1048627f7eb2Smrg   size_t length;
1049627f7eb2Smrg   int kind,save_warn_ampersand, ret;
1050627f7eb2Smrg   locus old_locus, start_locus;
1051627f7eb2Smrg   gfc_symbol *sym;
1052627f7eb2Smrg   gfc_expr *e;
1053627f7eb2Smrg   match m;
1054627f7eb2Smrg   gfc_char_t c, delimiter, *p;
1055627f7eb2Smrg 
1056627f7eb2Smrg   old_locus = gfc_current_locus;
1057627f7eb2Smrg 
1058627f7eb2Smrg   gfc_gobble_whitespace ();
1059627f7eb2Smrg 
1060627f7eb2Smrg   c = gfc_next_char ();
1061627f7eb2Smrg   if (c == '\'' || c == '"')
1062627f7eb2Smrg     {
1063627f7eb2Smrg       kind = gfc_default_character_kind;
1064627f7eb2Smrg       start_locus = gfc_current_locus;
1065627f7eb2Smrg       goto got_delim;
1066627f7eb2Smrg     }
1067627f7eb2Smrg 
1068627f7eb2Smrg   if (gfc_wide_is_digit (c))
1069627f7eb2Smrg     {
1070627f7eb2Smrg       kind = 0;
1071627f7eb2Smrg 
1072627f7eb2Smrg       while (gfc_wide_is_digit (c))
1073627f7eb2Smrg 	{
1074627f7eb2Smrg 	  kind = kind * 10 + c - '0';
1075627f7eb2Smrg 	  if (kind > 9999999)
1076627f7eb2Smrg 	    goto no_match;
1077627f7eb2Smrg 	  c = gfc_next_char ();
1078627f7eb2Smrg 	}
1079627f7eb2Smrg 
1080627f7eb2Smrg     }
1081627f7eb2Smrg   else
1082627f7eb2Smrg     {
1083627f7eb2Smrg       gfc_current_locus = old_locus;
1084627f7eb2Smrg 
1085627f7eb2Smrg       m = match_charkind_name (name);
1086627f7eb2Smrg       if (m != MATCH_YES)
1087627f7eb2Smrg 	goto no_match;
1088627f7eb2Smrg 
1089627f7eb2Smrg       if (gfc_find_symbol (name, NULL, 1, &sym)
1090627f7eb2Smrg 	  || sym == NULL
1091627f7eb2Smrg 	  || sym->attr.flavor != FL_PARAMETER)
1092627f7eb2Smrg 	goto no_match;
1093627f7eb2Smrg 
1094627f7eb2Smrg       kind = -1;
1095627f7eb2Smrg       c = gfc_next_char ();
1096627f7eb2Smrg     }
1097627f7eb2Smrg 
1098627f7eb2Smrg   if (c == ' ')
1099627f7eb2Smrg     {
1100627f7eb2Smrg       gfc_gobble_whitespace ();
1101627f7eb2Smrg       c = gfc_next_char ();
1102627f7eb2Smrg     }
1103627f7eb2Smrg 
1104627f7eb2Smrg   if (c != '_')
1105627f7eb2Smrg     goto no_match;
1106627f7eb2Smrg 
1107627f7eb2Smrg   gfc_gobble_whitespace ();
1108627f7eb2Smrg 
1109627f7eb2Smrg   c = gfc_next_char ();
1110627f7eb2Smrg   if (c != '\'' && c != '"')
1111627f7eb2Smrg     goto no_match;
1112627f7eb2Smrg 
1113627f7eb2Smrg   start_locus = gfc_current_locus;
1114627f7eb2Smrg 
1115627f7eb2Smrg   if (kind == -1)
1116627f7eb2Smrg     {
1117627f7eb2Smrg       if (gfc_extract_int (sym->value, &kind, 1))
1118627f7eb2Smrg 	return MATCH_ERROR;
1119627f7eb2Smrg       gfc_set_sym_referenced (sym);
1120627f7eb2Smrg     }
1121627f7eb2Smrg 
1122627f7eb2Smrg   if (gfc_validate_kind (BT_CHARACTER, kind, true) < 0)
1123627f7eb2Smrg     {
1124627f7eb2Smrg       gfc_error ("Invalid kind %d for CHARACTER constant at %C", kind);
1125627f7eb2Smrg       return MATCH_ERROR;
1126627f7eb2Smrg     }
1127627f7eb2Smrg 
1128627f7eb2Smrg got_delim:
1129627f7eb2Smrg   /* Scan the string into a block of memory by first figuring out how
1130627f7eb2Smrg      long it is, allocating the structure, then re-reading it.  This
1131627f7eb2Smrg      isn't particularly efficient, but string constants aren't that
1132627f7eb2Smrg      common in most code.  TODO: Use obstacks?  */
1133627f7eb2Smrg 
1134627f7eb2Smrg   delimiter = c;
1135627f7eb2Smrg   length = 0;
1136627f7eb2Smrg 
1137627f7eb2Smrg   for (;;)
1138627f7eb2Smrg     {
1139627f7eb2Smrg       c = next_string_char (delimiter, &ret);
1140627f7eb2Smrg       if (ret == -1)
1141627f7eb2Smrg 	break;
1142627f7eb2Smrg       if (ret == -2)
1143627f7eb2Smrg 	{
1144627f7eb2Smrg 	  gfc_current_locus = start_locus;
1145627f7eb2Smrg 	  gfc_error ("Unterminated character constant beginning at %C");
1146627f7eb2Smrg 	  return MATCH_ERROR;
1147627f7eb2Smrg 	}
1148627f7eb2Smrg 
1149627f7eb2Smrg       length++;
1150627f7eb2Smrg     }
1151627f7eb2Smrg 
1152627f7eb2Smrg   /* Peek at the next character to see if it is a b, o, z, or x for the
1153627f7eb2Smrg      postfixed BOZ literal constants.  */
1154627f7eb2Smrg   peek = gfc_peek_ascii_char ();
1155627f7eb2Smrg   if (peek == 'b' || peek == 'o' || peek =='z' || peek == 'x')
1156627f7eb2Smrg     goto no_match;
1157627f7eb2Smrg 
1158627f7eb2Smrg   e = gfc_get_character_expr (kind, &start_locus, NULL, length);
1159627f7eb2Smrg 
1160627f7eb2Smrg   gfc_current_locus = start_locus;
1161627f7eb2Smrg 
1162627f7eb2Smrg   /* We disable the warning for the following loop as the warning has already
1163627f7eb2Smrg      been printed in the loop above.  */
1164627f7eb2Smrg   save_warn_ampersand = warn_ampersand;
1165627f7eb2Smrg   warn_ampersand = false;
1166627f7eb2Smrg 
1167627f7eb2Smrg   p = e->value.character.string;
1168627f7eb2Smrg   for (size_t i = 0; i < length; i++)
1169627f7eb2Smrg     {
1170627f7eb2Smrg       c = next_string_char (delimiter, &ret);
1171627f7eb2Smrg 
1172627f7eb2Smrg       if (!gfc_check_character_range (c, kind))
1173627f7eb2Smrg 	{
1174627f7eb2Smrg 	  gfc_free_expr (e);
1175627f7eb2Smrg 	  gfc_error ("Character %qs in string at %C is not representable "
1176627f7eb2Smrg 		     "in character kind %d", gfc_print_wide_char (c), kind);
1177627f7eb2Smrg 	  return MATCH_ERROR;
1178627f7eb2Smrg 	}
1179627f7eb2Smrg 
1180627f7eb2Smrg       *p++ = c;
1181627f7eb2Smrg     }
1182627f7eb2Smrg 
1183627f7eb2Smrg   *p = '\0';	/* TODO: C-style string is for development/debug purposes.  */
1184627f7eb2Smrg   warn_ampersand = save_warn_ampersand;
1185627f7eb2Smrg 
1186627f7eb2Smrg   next_string_char (delimiter, &ret);
1187627f7eb2Smrg   if (ret != -1)
1188627f7eb2Smrg     gfc_internal_error ("match_string_constant(): Delimiter not found");
1189627f7eb2Smrg 
1190627f7eb2Smrg   if (match_substring (NULL, 0, &e->ref, false) != MATCH_NO)
1191627f7eb2Smrg     e->expr_type = EXPR_SUBSTRING;
1192627f7eb2Smrg 
11934c3eb207Smrg   /* Substrings with constant starting and ending points are eligible as
11944c3eb207Smrg      designators (F2018, section 9.1).  Simplify substrings to make them usable
11954c3eb207Smrg      e.g. in data statements.  */
11964c3eb207Smrg   if (e->expr_type == EXPR_SUBSTRING
11974c3eb207Smrg       && e->ref && e->ref->type == REF_SUBSTRING
11984c3eb207Smrg       && e->ref->u.ss.start->expr_type == EXPR_CONSTANT
11994c3eb207Smrg       && (e->ref->u.ss.end == NULL
12004c3eb207Smrg 	  || e->ref->u.ss.end->expr_type == EXPR_CONSTANT))
12014c3eb207Smrg     {
12024c3eb207Smrg       gfc_expr *res;
12034c3eb207Smrg       ptrdiff_t istart, iend;
12044c3eb207Smrg       size_t length;
12054c3eb207Smrg       bool equal_length = false;
12064c3eb207Smrg 
12074c3eb207Smrg       /* Basic checks on substring starting and ending indices.  */
12084c3eb207Smrg       if (!gfc_resolve_substring (e->ref, &equal_length))
12094c3eb207Smrg 	return MATCH_ERROR;
12104c3eb207Smrg 
12114c3eb207Smrg       length = e->value.character.length;
12124c3eb207Smrg       istart = gfc_mpz_get_hwi (e->ref->u.ss.start->value.integer);
12134c3eb207Smrg       if (e->ref->u.ss.end == NULL)
12144c3eb207Smrg 	iend = length;
12154c3eb207Smrg       else
12164c3eb207Smrg 	iend = gfc_mpz_get_hwi (e->ref->u.ss.end->value.integer);
12174c3eb207Smrg 
12184c3eb207Smrg       if (istart <= iend)
12194c3eb207Smrg 	{
12204c3eb207Smrg 	  if (istart < 1)
12214c3eb207Smrg 	    {
12224c3eb207Smrg 	      gfc_error ("Substring start index (%ld) at %L below 1",
12234c3eb207Smrg 			 (long) istart, &e->ref->u.ss.start->where);
12244c3eb207Smrg 	      return MATCH_ERROR;
12254c3eb207Smrg 	    }
12264c3eb207Smrg 	  if (iend > (ssize_t) length)
12274c3eb207Smrg 	    {
12284c3eb207Smrg 	      gfc_error ("Substring end index (%ld) at %L exceeds string "
12294c3eb207Smrg 			 "length", (long) iend, &e->ref->u.ss.end->where);
12304c3eb207Smrg 	      return MATCH_ERROR;
12314c3eb207Smrg 	    }
12324c3eb207Smrg 	  length = iend - istart + 1;
12334c3eb207Smrg 	}
12344c3eb207Smrg       else
12354c3eb207Smrg 	length = 0;
12364c3eb207Smrg 
12374c3eb207Smrg       res = gfc_get_constant_expr (BT_CHARACTER, e->ts.kind, &e->where);
12384c3eb207Smrg       res->value.character.string = gfc_get_wide_string (length + 1);
12394c3eb207Smrg       res->value.character.length = length;
12404c3eb207Smrg       if (length > 0)
12414c3eb207Smrg 	memcpy (res->value.character.string,
12424c3eb207Smrg 		&e->value.character.string[istart - 1],
12434c3eb207Smrg 		length * sizeof (gfc_char_t));
12444c3eb207Smrg       res->value.character.string[length] = '\0';
12454c3eb207Smrg       e = res;
12464c3eb207Smrg     }
12474c3eb207Smrg 
1248627f7eb2Smrg   *result = e;
1249627f7eb2Smrg 
1250627f7eb2Smrg   return MATCH_YES;
1251627f7eb2Smrg 
1252627f7eb2Smrg no_match:
1253627f7eb2Smrg   gfc_current_locus = old_locus;
1254627f7eb2Smrg   return MATCH_NO;
1255627f7eb2Smrg }
1256627f7eb2Smrg 
1257627f7eb2Smrg 
1258627f7eb2Smrg /* Match a .true. or .false.  Returns 1 if a .true. was found,
1259627f7eb2Smrg    0 if a .false. was found, and -1 otherwise.  */
1260627f7eb2Smrg static int
match_logical_constant_string(void)1261627f7eb2Smrg match_logical_constant_string (void)
1262627f7eb2Smrg {
1263627f7eb2Smrg   locus orig_loc = gfc_current_locus;
1264627f7eb2Smrg 
1265627f7eb2Smrg   gfc_gobble_whitespace ();
1266627f7eb2Smrg   if (gfc_next_ascii_char () == '.')
1267627f7eb2Smrg     {
1268627f7eb2Smrg       char ch = gfc_next_ascii_char ();
1269627f7eb2Smrg       if (ch == 'f')
1270627f7eb2Smrg 	{
1271627f7eb2Smrg 	  if (gfc_next_ascii_char () == 'a'
1272627f7eb2Smrg 	      && gfc_next_ascii_char () == 'l'
1273627f7eb2Smrg 	      && gfc_next_ascii_char () == 's'
1274627f7eb2Smrg 	      && gfc_next_ascii_char () == 'e'
1275627f7eb2Smrg 	      && gfc_next_ascii_char () == '.')
1276627f7eb2Smrg 	    /* Matched ".false.".  */
1277627f7eb2Smrg 	    return 0;
1278627f7eb2Smrg 	}
1279627f7eb2Smrg       else if (ch == 't')
1280627f7eb2Smrg 	{
1281627f7eb2Smrg 	  if (gfc_next_ascii_char () == 'r'
1282627f7eb2Smrg 	      && gfc_next_ascii_char () == 'u'
1283627f7eb2Smrg 	      && gfc_next_ascii_char () == 'e'
1284627f7eb2Smrg 	      && gfc_next_ascii_char () == '.')
1285627f7eb2Smrg 	    /* Matched ".true.".  */
1286627f7eb2Smrg 	    return 1;
1287627f7eb2Smrg 	}
1288627f7eb2Smrg     }
1289627f7eb2Smrg   gfc_current_locus = orig_loc;
1290627f7eb2Smrg   return -1;
1291627f7eb2Smrg }
1292627f7eb2Smrg 
1293627f7eb2Smrg /* Match a .true. or .false.  */
1294627f7eb2Smrg 
1295627f7eb2Smrg static match
match_logical_constant(gfc_expr ** result)1296627f7eb2Smrg match_logical_constant (gfc_expr **result)
1297627f7eb2Smrg {
1298627f7eb2Smrg   gfc_expr *e;
1299627f7eb2Smrg   int i, kind, is_iso_c;
1300627f7eb2Smrg 
1301627f7eb2Smrg   i = match_logical_constant_string ();
1302627f7eb2Smrg   if (i == -1)
1303627f7eb2Smrg     return MATCH_NO;
1304627f7eb2Smrg 
1305627f7eb2Smrg   kind = get_kind (&is_iso_c);
1306627f7eb2Smrg   if (kind == -1)
1307627f7eb2Smrg     return MATCH_ERROR;
1308627f7eb2Smrg   if (kind == -2)
1309627f7eb2Smrg     kind = gfc_default_logical_kind;
1310627f7eb2Smrg 
1311627f7eb2Smrg   if (gfc_validate_kind (BT_LOGICAL, kind, true) < 0)
1312627f7eb2Smrg     {
1313627f7eb2Smrg       gfc_error ("Bad kind for logical constant at %C");
1314627f7eb2Smrg       return MATCH_ERROR;
1315627f7eb2Smrg     }
1316627f7eb2Smrg 
1317627f7eb2Smrg   e = gfc_get_logical_expr (kind, &gfc_current_locus, i);
1318627f7eb2Smrg   e->ts.is_c_interop = is_iso_c;
1319627f7eb2Smrg 
1320627f7eb2Smrg   *result = e;
1321627f7eb2Smrg   return MATCH_YES;
1322627f7eb2Smrg }
1323627f7eb2Smrg 
1324627f7eb2Smrg 
1325627f7eb2Smrg /* Match a real or imaginary part of a complex constant that is a
1326627f7eb2Smrg    symbolic constant.  */
1327627f7eb2Smrg 
1328627f7eb2Smrg static match
match_sym_complex_part(gfc_expr ** result)1329627f7eb2Smrg match_sym_complex_part (gfc_expr **result)
1330627f7eb2Smrg {
1331627f7eb2Smrg   char name[GFC_MAX_SYMBOL_LEN + 1];
1332627f7eb2Smrg   gfc_symbol *sym;
1333627f7eb2Smrg   gfc_expr *e;
1334627f7eb2Smrg   match m;
1335627f7eb2Smrg 
1336627f7eb2Smrg   m = gfc_match_name (name);
1337627f7eb2Smrg   if (m != MATCH_YES)
1338627f7eb2Smrg     return m;
1339627f7eb2Smrg 
1340627f7eb2Smrg   if (gfc_find_symbol (name, NULL, 1, &sym) || sym == NULL)
1341627f7eb2Smrg     return MATCH_NO;
1342627f7eb2Smrg 
1343627f7eb2Smrg   if (sym->attr.flavor != FL_PARAMETER)
1344627f7eb2Smrg     {
1345627f7eb2Smrg       /* Give the matcher for implied do-loops a chance to run.  This yields
1346627f7eb2Smrg 	 a much saner error message for "write(*,*) (i, i=1, 6" where the
1347627f7eb2Smrg 	 right parenthesis is missing.  */
1348627f7eb2Smrg       char c;
1349627f7eb2Smrg       gfc_gobble_whitespace ();
1350627f7eb2Smrg       c = gfc_peek_ascii_char ();
1351627f7eb2Smrg       if (c == '=' || c == ',')
1352627f7eb2Smrg 	{
1353627f7eb2Smrg 	  m = MATCH_NO;
1354627f7eb2Smrg 	}
1355627f7eb2Smrg       else
1356627f7eb2Smrg 	{
1357627f7eb2Smrg 	  gfc_error ("Expected PARAMETER symbol in complex constant at %C");
1358627f7eb2Smrg 	  m = MATCH_ERROR;
1359627f7eb2Smrg 	}
1360627f7eb2Smrg       return m;
1361627f7eb2Smrg     }
1362627f7eb2Smrg 
1363627f7eb2Smrg   if (!sym->value)
1364627f7eb2Smrg     goto error;
1365627f7eb2Smrg 
1366627f7eb2Smrg   if (!gfc_numeric_ts (&sym->value->ts))
1367627f7eb2Smrg     {
1368627f7eb2Smrg       gfc_error ("Numeric PARAMETER required in complex constant at %C");
1369627f7eb2Smrg       return MATCH_ERROR;
1370627f7eb2Smrg     }
1371627f7eb2Smrg 
1372627f7eb2Smrg   if (sym->value->rank != 0)
1373627f7eb2Smrg     {
1374627f7eb2Smrg       gfc_error ("Scalar PARAMETER required in complex constant at %C");
1375627f7eb2Smrg       return MATCH_ERROR;
1376627f7eb2Smrg     }
1377627f7eb2Smrg 
1378627f7eb2Smrg   if (!gfc_notify_std (GFC_STD_F2003, "PARAMETER symbol in "
1379627f7eb2Smrg 		       "complex constant at %C"))
1380627f7eb2Smrg     return MATCH_ERROR;
1381627f7eb2Smrg 
1382627f7eb2Smrg   switch (sym->value->ts.type)
1383627f7eb2Smrg     {
1384627f7eb2Smrg     case BT_REAL:
1385627f7eb2Smrg       e = gfc_copy_expr (sym->value);
1386627f7eb2Smrg       break;
1387627f7eb2Smrg 
1388627f7eb2Smrg     case BT_COMPLEX:
1389627f7eb2Smrg       e = gfc_complex2real (sym->value, sym->value->ts.kind);
1390627f7eb2Smrg       if (e == NULL)
1391627f7eb2Smrg 	goto error;
1392627f7eb2Smrg       break;
1393627f7eb2Smrg 
1394627f7eb2Smrg     case BT_INTEGER:
1395627f7eb2Smrg       e = gfc_int2real (sym->value, gfc_default_real_kind);
1396627f7eb2Smrg       if (e == NULL)
1397627f7eb2Smrg 	goto error;
1398627f7eb2Smrg       break;
1399627f7eb2Smrg 
1400627f7eb2Smrg     default:
1401627f7eb2Smrg       gfc_internal_error ("gfc_match_sym_complex_part(): Bad type");
1402627f7eb2Smrg     }
1403627f7eb2Smrg 
1404627f7eb2Smrg   *result = e;		/* e is a scalar, real, constant expression.  */
1405627f7eb2Smrg   return MATCH_YES;
1406627f7eb2Smrg 
1407627f7eb2Smrg error:
1408627f7eb2Smrg   gfc_error ("Error converting PARAMETER constant in complex constant at %C");
1409627f7eb2Smrg   return MATCH_ERROR;
1410627f7eb2Smrg }
1411627f7eb2Smrg 
1412627f7eb2Smrg 
1413627f7eb2Smrg /* Match a real or imaginary part of a complex number.  */
1414627f7eb2Smrg 
1415627f7eb2Smrg static match
match_complex_part(gfc_expr ** result)1416627f7eb2Smrg match_complex_part (gfc_expr **result)
1417627f7eb2Smrg {
1418627f7eb2Smrg   match m;
1419627f7eb2Smrg 
1420627f7eb2Smrg   m = match_sym_complex_part (result);
1421627f7eb2Smrg   if (m != MATCH_NO)
1422627f7eb2Smrg     return m;
1423627f7eb2Smrg 
1424627f7eb2Smrg   m = match_real_constant (result, 1);
1425627f7eb2Smrg   if (m != MATCH_NO)
1426627f7eb2Smrg     return m;
1427627f7eb2Smrg 
1428627f7eb2Smrg   return match_integer_constant (result, 1);
1429627f7eb2Smrg }
1430627f7eb2Smrg 
1431627f7eb2Smrg 
1432627f7eb2Smrg /* Try to match a complex constant.  */
1433627f7eb2Smrg 
1434627f7eb2Smrg static match
match_complex_constant(gfc_expr ** result)1435627f7eb2Smrg match_complex_constant (gfc_expr **result)
1436627f7eb2Smrg {
1437627f7eb2Smrg   gfc_expr *e, *real, *imag;
1438627f7eb2Smrg   gfc_error_buffer old_error;
1439627f7eb2Smrg   gfc_typespec target;
1440627f7eb2Smrg   locus old_loc;
1441627f7eb2Smrg   int kind;
1442627f7eb2Smrg   match m;
1443627f7eb2Smrg 
1444627f7eb2Smrg   old_loc = gfc_current_locus;
1445627f7eb2Smrg   real = imag = e = NULL;
1446627f7eb2Smrg 
1447627f7eb2Smrg   m = gfc_match_char ('(');
1448627f7eb2Smrg   if (m != MATCH_YES)
1449627f7eb2Smrg     return m;
1450627f7eb2Smrg 
1451627f7eb2Smrg   gfc_push_error (&old_error);
1452627f7eb2Smrg 
1453627f7eb2Smrg   m = match_complex_part (&real);
1454627f7eb2Smrg   if (m == MATCH_NO)
1455627f7eb2Smrg     {
1456627f7eb2Smrg       gfc_free_error (&old_error);
1457627f7eb2Smrg       goto cleanup;
1458627f7eb2Smrg     }
1459627f7eb2Smrg 
1460627f7eb2Smrg   if (gfc_match_char (',') == MATCH_NO)
1461627f7eb2Smrg     {
1462627f7eb2Smrg       /* It is possible that gfc_int2real issued a warning when
1463627f7eb2Smrg 	 converting an integer to real.  Throw this away here.  */
1464627f7eb2Smrg 
1465627f7eb2Smrg       gfc_clear_warning ();
1466627f7eb2Smrg       gfc_pop_error (&old_error);
1467627f7eb2Smrg       m = MATCH_NO;
1468627f7eb2Smrg       goto cleanup;
1469627f7eb2Smrg     }
1470627f7eb2Smrg 
1471627f7eb2Smrg   /* If m is error, then something was wrong with the real part and we
1472627f7eb2Smrg      assume we have a complex constant because we've seen the ','.  An
1473627f7eb2Smrg      ambiguous case here is the start of an iterator list of some
1474627f7eb2Smrg      sort. These sort of lists are matched prior to coming here.  */
1475627f7eb2Smrg 
1476627f7eb2Smrg   if (m == MATCH_ERROR)
1477627f7eb2Smrg     {
1478627f7eb2Smrg       gfc_free_error (&old_error);
1479627f7eb2Smrg       goto cleanup;
1480627f7eb2Smrg     }
1481627f7eb2Smrg   gfc_pop_error (&old_error);
1482627f7eb2Smrg 
1483627f7eb2Smrg   m = match_complex_part (&imag);
1484627f7eb2Smrg   if (m == MATCH_NO)
1485627f7eb2Smrg     goto syntax;
1486627f7eb2Smrg   if (m == MATCH_ERROR)
1487627f7eb2Smrg     goto cleanup;
1488627f7eb2Smrg 
1489627f7eb2Smrg   m = gfc_match_char (')');
1490627f7eb2Smrg   if (m == MATCH_NO)
1491627f7eb2Smrg     {
1492627f7eb2Smrg       /* Give the matcher for implied do-loops a chance to run.  This
1493627f7eb2Smrg 	 yields a much saner error message for (/ (i, 4=i, 6) /).  */
1494627f7eb2Smrg       if (gfc_peek_ascii_char () == '=')
1495627f7eb2Smrg 	{
1496627f7eb2Smrg 	  m = MATCH_ERROR;
1497627f7eb2Smrg 	  goto cleanup;
1498627f7eb2Smrg 	}
1499627f7eb2Smrg       else
1500627f7eb2Smrg     goto syntax;
1501627f7eb2Smrg     }
1502627f7eb2Smrg 
1503627f7eb2Smrg   if (m == MATCH_ERROR)
1504627f7eb2Smrg     goto cleanup;
1505627f7eb2Smrg 
1506627f7eb2Smrg   /* Decide on the kind of this complex number.  */
1507627f7eb2Smrg   if (real->ts.type == BT_REAL)
1508627f7eb2Smrg     {
1509627f7eb2Smrg       if (imag->ts.type == BT_REAL)
1510627f7eb2Smrg 	kind = gfc_kind_max (real, imag);
1511627f7eb2Smrg       else
1512627f7eb2Smrg 	kind = real->ts.kind;
1513627f7eb2Smrg     }
1514627f7eb2Smrg   else
1515627f7eb2Smrg     {
1516627f7eb2Smrg       if (imag->ts.type == BT_REAL)
1517627f7eb2Smrg 	kind = imag->ts.kind;
1518627f7eb2Smrg       else
1519627f7eb2Smrg 	kind = gfc_default_real_kind;
1520627f7eb2Smrg     }
1521627f7eb2Smrg   gfc_clear_ts (&target);
1522627f7eb2Smrg   target.type = BT_REAL;
1523627f7eb2Smrg   target.kind = kind;
1524627f7eb2Smrg 
1525627f7eb2Smrg   if (real->ts.type != BT_REAL || kind != real->ts.kind)
1526627f7eb2Smrg     gfc_convert_type (real, &target, 2);
1527627f7eb2Smrg   if (imag->ts.type != BT_REAL || kind != imag->ts.kind)
1528627f7eb2Smrg     gfc_convert_type (imag, &target, 2);
1529627f7eb2Smrg 
15304c3eb207Smrg   e = convert_complex (real, imag, kind);
1531627f7eb2Smrg   e->where = gfc_current_locus;
1532627f7eb2Smrg 
1533627f7eb2Smrg   gfc_free_expr (real);
1534627f7eb2Smrg   gfc_free_expr (imag);
1535627f7eb2Smrg 
1536627f7eb2Smrg   *result = e;
1537627f7eb2Smrg   return MATCH_YES;
1538627f7eb2Smrg 
1539627f7eb2Smrg syntax:
1540627f7eb2Smrg   gfc_error ("Syntax error in COMPLEX constant at %C");
1541627f7eb2Smrg   m = MATCH_ERROR;
1542627f7eb2Smrg 
1543627f7eb2Smrg cleanup:
1544627f7eb2Smrg   gfc_free_expr (e);
1545627f7eb2Smrg   gfc_free_expr (real);
1546627f7eb2Smrg   gfc_free_expr (imag);
1547627f7eb2Smrg   gfc_current_locus = old_loc;
1548627f7eb2Smrg 
1549627f7eb2Smrg   return m;
1550627f7eb2Smrg }
1551627f7eb2Smrg 
1552627f7eb2Smrg 
1553627f7eb2Smrg /* Match constants in any of several forms.  Returns nonzero for a
1554627f7eb2Smrg    match, zero for no match.  */
1555627f7eb2Smrg 
1556627f7eb2Smrg match
gfc_match_literal_constant(gfc_expr ** result,int signflag)1557627f7eb2Smrg gfc_match_literal_constant (gfc_expr **result, int signflag)
1558627f7eb2Smrg {
1559627f7eb2Smrg   match m;
1560627f7eb2Smrg 
1561627f7eb2Smrg   m = match_complex_constant (result);
1562627f7eb2Smrg   if (m != MATCH_NO)
1563627f7eb2Smrg     return m;
1564627f7eb2Smrg 
1565627f7eb2Smrg   m = match_string_constant (result);
1566627f7eb2Smrg   if (m != MATCH_NO)
1567627f7eb2Smrg     return m;
1568627f7eb2Smrg 
1569627f7eb2Smrg   m = match_boz_constant (result);
1570627f7eb2Smrg   if (m != MATCH_NO)
1571627f7eb2Smrg     return m;
1572627f7eb2Smrg 
1573627f7eb2Smrg   m = match_real_constant (result, signflag);
1574627f7eb2Smrg   if (m != MATCH_NO)
1575627f7eb2Smrg     return m;
1576627f7eb2Smrg 
1577627f7eb2Smrg   m = match_hollerith_constant (result);
1578627f7eb2Smrg   if (m != MATCH_NO)
1579627f7eb2Smrg     return m;
1580627f7eb2Smrg 
1581627f7eb2Smrg   m = match_integer_constant (result, signflag);
1582627f7eb2Smrg   if (m != MATCH_NO)
1583627f7eb2Smrg     return m;
1584627f7eb2Smrg 
1585627f7eb2Smrg   m = match_logical_constant (result);
1586627f7eb2Smrg   if (m != MATCH_NO)
1587627f7eb2Smrg     return m;
1588627f7eb2Smrg 
1589627f7eb2Smrg   return MATCH_NO;
1590627f7eb2Smrg }
1591627f7eb2Smrg 
1592627f7eb2Smrg 
1593627f7eb2Smrg /* This checks if a symbol is the return value of an encompassing function.
1594627f7eb2Smrg    Function nesting can be maximally two levels deep, but we may have
1595627f7eb2Smrg    additional local namespaces like BLOCK etc.  */
1596627f7eb2Smrg 
1597627f7eb2Smrg bool
gfc_is_function_return_value(gfc_symbol * sym,gfc_namespace * ns)1598627f7eb2Smrg gfc_is_function_return_value (gfc_symbol *sym, gfc_namespace *ns)
1599627f7eb2Smrg {
1600627f7eb2Smrg   if (!sym->attr.function || (sym->result != sym))
1601627f7eb2Smrg     return false;
1602627f7eb2Smrg   while (ns)
1603627f7eb2Smrg     {
1604627f7eb2Smrg       if (ns->proc_name == sym)
1605627f7eb2Smrg 	return true;
1606627f7eb2Smrg       ns = ns->parent;
1607627f7eb2Smrg     }
1608627f7eb2Smrg   return false;
1609627f7eb2Smrg }
1610627f7eb2Smrg 
1611627f7eb2Smrg 
1612627f7eb2Smrg /* Match a single actual argument value.  An actual argument is
1613627f7eb2Smrg    usually an expression, but can also be a procedure name.  If the
1614627f7eb2Smrg    argument is a single name, it is not always possible to tell
1615627f7eb2Smrg    whether the name is a dummy procedure or not.  We treat these cases
1616627f7eb2Smrg    by creating an argument that looks like a dummy procedure and
1617627f7eb2Smrg    fixing things later during resolution.  */
1618627f7eb2Smrg 
1619627f7eb2Smrg static match
match_actual_arg(gfc_expr ** result)1620627f7eb2Smrg match_actual_arg (gfc_expr **result)
1621627f7eb2Smrg {
1622627f7eb2Smrg   char name[GFC_MAX_SYMBOL_LEN + 1];
1623627f7eb2Smrg   gfc_symtree *symtree;
1624627f7eb2Smrg   locus where, w;
1625627f7eb2Smrg   gfc_expr *e;
1626627f7eb2Smrg   char c;
1627627f7eb2Smrg 
1628627f7eb2Smrg   gfc_gobble_whitespace ();
1629627f7eb2Smrg   where = gfc_current_locus;
1630627f7eb2Smrg 
1631627f7eb2Smrg   switch (gfc_match_name (name))
1632627f7eb2Smrg     {
1633627f7eb2Smrg     case MATCH_ERROR:
1634627f7eb2Smrg       return MATCH_ERROR;
1635627f7eb2Smrg 
1636627f7eb2Smrg     case MATCH_NO:
1637627f7eb2Smrg       break;
1638627f7eb2Smrg 
1639627f7eb2Smrg     case MATCH_YES:
1640627f7eb2Smrg       w = gfc_current_locus;
1641627f7eb2Smrg       gfc_gobble_whitespace ();
1642627f7eb2Smrg       c = gfc_next_ascii_char ();
1643627f7eb2Smrg       gfc_current_locus = w;
1644627f7eb2Smrg 
1645627f7eb2Smrg       if (c != ',' && c != ')')
1646627f7eb2Smrg 	break;
1647627f7eb2Smrg 
1648627f7eb2Smrg       if (gfc_find_sym_tree (name, NULL, 1, &symtree))
1649627f7eb2Smrg 	break;
1650627f7eb2Smrg       /* Handle error elsewhere.  */
1651627f7eb2Smrg 
1652627f7eb2Smrg       /* Eliminate a couple of common cases where we know we don't
1653627f7eb2Smrg 	 have a function argument.  */
1654627f7eb2Smrg       if (symtree == NULL)
1655627f7eb2Smrg 	{
1656627f7eb2Smrg 	  gfc_get_sym_tree (name, NULL, &symtree, false);
1657627f7eb2Smrg 	  gfc_set_sym_referenced (symtree->n.sym);
1658627f7eb2Smrg 	}
1659627f7eb2Smrg       else
1660627f7eb2Smrg 	{
1661627f7eb2Smrg 	  gfc_symbol *sym;
1662627f7eb2Smrg 
1663627f7eb2Smrg 	  sym = symtree->n.sym;
1664627f7eb2Smrg 	  gfc_set_sym_referenced (sym);
1665627f7eb2Smrg 	  if (sym->attr.flavor == FL_NAMELIST)
1666627f7eb2Smrg 	    {
1667627f7eb2Smrg 	      gfc_error ("Namelist %qs cannot be an argument at %L",
1668627f7eb2Smrg 	      sym->name, &where);
1669627f7eb2Smrg 	      break;
1670627f7eb2Smrg 	    }
1671627f7eb2Smrg 	  if (sym->attr.flavor != FL_PROCEDURE
1672627f7eb2Smrg 	      && sym->attr.flavor != FL_UNKNOWN)
1673627f7eb2Smrg 	    break;
1674627f7eb2Smrg 
1675627f7eb2Smrg 	  if (sym->attr.in_common && !sym->attr.proc_pointer)
1676627f7eb2Smrg 	    {
1677627f7eb2Smrg 	      if (!gfc_add_flavor (&sym->attr, FL_VARIABLE,
1678627f7eb2Smrg 				   sym->name, &sym->declared_at))
1679627f7eb2Smrg 		return MATCH_ERROR;
1680627f7eb2Smrg 	      break;
1681627f7eb2Smrg 	    }
1682627f7eb2Smrg 
1683627f7eb2Smrg 	  /* If the symbol is a function with itself as the result and
1684627f7eb2Smrg 	     is being defined, then we have a variable.  */
1685627f7eb2Smrg 	  if (sym->attr.function && sym->result == sym)
1686627f7eb2Smrg 	    {
1687627f7eb2Smrg 	      if (gfc_is_function_return_value (sym, gfc_current_ns))
1688627f7eb2Smrg 		break;
1689627f7eb2Smrg 
1690627f7eb2Smrg 	      if (sym->attr.entry
1691627f7eb2Smrg 		  && (sym->ns == gfc_current_ns
1692627f7eb2Smrg 		      || sym->ns == gfc_current_ns->parent))
1693627f7eb2Smrg 		{
1694627f7eb2Smrg 		  gfc_entry_list *el = NULL;
1695627f7eb2Smrg 
1696627f7eb2Smrg 		  for (el = sym->ns->entries; el; el = el->next)
1697627f7eb2Smrg 		    if (sym == el->sym)
1698627f7eb2Smrg 		      break;
1699627f7eb2Smrg 
1700627f7eb2Smrg 		  if (el)
1701627f7eb2Smrg 		    break;
1702627f7eb2Smrg 		}
1703627f7eb2Smrg 	    }
1704627f7eb2Smrg 	}
1705627f7eb2Smrg 
1706627f7eb2Smrg       e = gfc_get_expr ();	/* Leave it unknown for now */
1707627f7eb2Smrg       e->symtree = symtree;
1708627f7eb2Smrg       e->expr_type = EXPR_VARIABLE;
1709627f7eb2Smrg       e->ts.type = BT_PROCEDURE;
1710627f7eb2Smrg       e->where = where;
1711627f7eb2Smrg 
1712627f7eb2Smrg       *result = e;
1713627f7eb2Smrg       return MATCH_YES;
1714627f7eb2Smrg     }
1715627f7eb2Smrg 
1716627f7eb2Smrg   gfc_current_locus = where;
1717627f7eb2Smrg   return gfc_match_expr (result);
1718627f7eb2Smrg }
1719627f7eb2Smrg 
1720627f7eb2Smrg 
1721627f7eb2Smrg /* Match a keyword argument or type parameter spec list..  */
1722627f7eb2Smrg 
1723627f7eb2Smrg static match
match_keyword_arg(gfc_actual_arglist * actual,gfc_actual_arglist * base,bool pdt)1724627f7eb2Smrg match_keyword_arg (gfc_actual_arglist *actual, gfc_actual_arglist *base, bool pdt)
1725627f7eb2Smrg {
1726627f7eb2Smrg   char name[GFC_MAX_SYMBOL_LEN + 1];
1727627f7eb2Smrg   gfc_actual_arglist *a;
1728627f7eb2Smrg   locus name_locus;
1729627f7eb2Smrg   match m;
1730627f7eb2Smrg 
1731627f7eb2Smrg   name_locus = gfc_current_locus;
1732627f7eb2Smrg   m = gfc_match_name (name);
1733627f7eb2Smrg 
1734627f7eb2Smrg   if (m != MATCH_YES)
1735627f7eb2Smrg     goto cleanup;
1736627f7eb2Smrg   if (gfc_match_char ('=') != MATCH_YES)
1737627f7eb2Smrg     {
1738627f7eb2Smrg       m = MATCH_NO;
1739627f7eb2Smrg       goto cleanup;
1740627f7eb2Smrg     }
1741627f7eb2Smrg 
1742627f7eb2Smrg   if (pdt)
1743627f7eb2Smrg     {
1744627f7eb2Smrg       if (gfc_match_char ('*') == MATCH_YES)
1745627f7eb2Smrg 	{
1746627f7eb2Smrg 	  actual->spec_type = SPEC_ASSUMED;
1747627f7eb2Smrg 	  goto add_name;
1748627f7eb2Smrg 	}
1749627f7eb2Smrg       else if (gfc_match_char (':') == MATCH_YES)
1750627f7eb2Smrg 	{
1751627f7eb2Smrg 	  actual->spec_type = SPEC_DEFERRED;
1752627f7eb2Smrg 	  goto add_name;
1753627f7eb2Smrg 	}
1754627f7eb2Smrg       else
1755627f7eb2Smrg 	actual->spec_type = SPEC_EXPLICIT;
1756627f7eb2Smrg     }
1757627f7eb2Smrg 
1758627f7eb2Smrg   m = match_actual_arg (&actual->expr);
1759627f7eb2Smrg   if (m != MATCH_YES)
1760627f7eb2Smrg     goto cleanup;
1761627f7eb2Smrg 
1762627f7eb2Smrg   /* Make sure this name has not appeared yet.  */
1763627f7eb2Smrg add_name:
1764627f7eb2Smrg   if (name[0] != '\0')
1765627f7eb2Smrg     {
1766627f7eb2Smrg       for (a = base; a; a = a->next)
1767627f7eb2Smrg 	if (a->name != NULL && strcmp (a->name, name) == 0)
1768627f7eb2Smrg 	  {
1769627f7eb2Smrg 	    gfc_error ("Keyword %qs at %C has already appeared in the "
1770627f7eb2Smrg 		       "current argument list", name);
1771627f7eb2Smrg 	    return MATCH_ERROR;
1772627f7eb2Smrg 	  }
1773627f7eb2Smrg     }
1774627f7eb2Smrg 
1775627f7eb2Smrg   actual->name = gfc_get_string ("%s", name);
1776627f7eb2Smrg   return MATCH_YES;
1777627f7eb2Smrg 
1778627f7eb2Smrg cleanup:
1779627f7eb2Smrg   gfc_current_locus = name_locus;
1780627f7eb2Smrg   return m;
1781627f7eb2Smrg }
1782627f7eb2Smrg 
1783627f7eb2Smrg 
1784627f7eb2Smrg /* Match an argument list function, such as %VAL.  */
1785627f7eb2Smrg 
1786627f7eb2Smrg static match
match_arg_list_function(gfc_actual_arglist * result)1787627f7eb2Smrg match_arg_list_function (gfc_actual_arglist *result)
1788627f7eb2Smrg {
1789627f7eb2Smrg   char name[GFC_MAX_SYMBOL_LEN + 1];
1790627f7eb2Smrg   locus old_locus;
1791627f7eb2Smrg   match m;
1792627f7eb2Smrg 
1793627f7eb2Smrg   old_locus = gfc_current_locus;
1794627f7eb2Smrg 
1795627f7eb2Smrg   if (gfc_match_char ('%') != MATCH_YES)
1796627f7eb2Smrg     {
1797627f7eb2Smrg       m = MATCH_NO;
1798627f7eb2Smrg       goto cleanup;
1799627f7eb2Smrg     }
1800627f7eb2Smrg 
1801627f7eb2Smrg   m = gfc_match ("%n (", name);
1802627f7eb2Smrg   if (m != MATCH_YES)
1803627f7eb2Smrg     goto cleanup;
1804627f7eb2Smrg 
1805627f7eb2Smrg   if (name[0] != '\0')
1806627f7eb2Smrg     {
1807627f7eb2Smrg       switch (name[0])
1808627f7eb2Smrg 	{
1809627f7eb2Smrg 	case 'l':
1810627f7eb2Smrg 	  if (gfc_str_startswith (name, "loc"))
1811627f7eb2Smrg 	    {
1812627f7eb2Smrg 	      result->name = "%LOC";
1813627f7eb2Smrg 	      break;
1814627f7eb2Smrg 	    }
1815627f7eb2Smrg 	  /* FALLTHRU */
1816627f7eb2Smrg 	case 'r':
1817627f7eb2Smrg 	  if (gfc_str_startswith (name, "ref"))
1818627f7eb2Smrg 	    {
1819627f7eb2Smrg 	      result->name = "%REF";
1820627f7eb2Smrg 	      break;
1821627f7eb2Smrg 	    }
1822627f7eb2Smrg 	  /* FALLTHRU */
1823627f7eb2Smrg 	case 'v':
1824627f7eb2Smrg 	  if (gfc_str_startswith (name, "val"))
1825627f7eb2Smrg 	    {
1826627f7eb2Smrg 	      result->name = "%VAL";
1827627f7eb2Smrg 	      break;
1828627f7eb2Smrg 	    }
1829627f7eb2Smrg 	  /* FALLTHRU */
1830627f7eb2Smrg 	default:
1831627f7eb2Smrg 	  m = MATCH_ERROR;
1832627f7eb2Smrg 	  goto cleanup;
1833627f7eb2Smrg 	}
1834627f7eb2Smrg     }
1835627f7eb2Smrg 
1836627f7eb2Smrg   if (!gfc_notify_std (GFC_STD_GNU, "argument list function at %C"))
1837627f7eb2Smrg     {
1838627f7eb2Smrg       m = MATCH_ERROR;
1839627f7eb2Smrg       goto cleanup;
1840627f7eb2Smrg     }
1841627f7eb2Smrg 
1842627f7eb2Smrg   m = match_actual_arg (&result->expr);
1843627f7eb2Smrg   if (m != MATCH_YES)
1844627f7eb2Smrg     goto cleanup;
1845627f7eb2Smrg 
1846627f7eb2Smrg   if (gfc_match_char (')') != MATCH_YES)
1847627f7eb2Smrg     {
1848627f7eb2Smrg       m = MATCH_NO;
1849627f7eb2Smrg       goto cleanup;
1850627f7eb2Smrg     }
1851627f7eb2Smrg 
1852627f7eb2Smrg   return MATCH_YES;
1853627f7eb2Smrg 
1854627f7eb2Smrg cleanup:
1855627f7eb2Smrg   gfc_current_locus = old_locus;
1856627f7eb2Smrg   return m;
1857627f7eb2Smrg }
1858627f7eb2Smrg 
1859627f7eb2Smrg 
1860627f7eb2Smrg /* Matches an actual argument list of a function or subroutine, from
1861627f7eb2Smrg    the opening parenthesis to the closing parenthesis.  The argument
1862627f7eb2Smrg    list is assumed to allow keyword arguments because we don't know if
1863627f7eb2Smrg    the symbol associated with the procedure has an implicit interface
1864627f7eb2Smrg    or not.  We make sure keywords are unique. If sub_flag is set,
1865627f7eb2Smrg    we're matching the argument list of a subroutine.
1866627f7eb2Smrg 
1867627f7eb2Smrg    NOTE: An alternative use for this function is to match type parameter
1868627f7eb2Smrg    spec lists, which are so similar to actual argument lists that the
1869627f7eb2Smrg    machinery can be reused. This use is flagged by the optional argument
1870627f7eb2Smrg    'pdt'.  */
1871627f7eb2Smrg 
1872627f7eb2Smrg match
gfc_match_actual_arglist(int sub_flag,gfc_actual_arglist ** argp,bool pdt)1873627f7eb2Smrg gfc_match_actual_arglist (int sub_flag, gfc_actual_arglist **argp, bool pdt)
1874627f7eb2Smrg {
1875627f7eb2Smrg   gfc_actual_arglist *head, *tail;
1876627f7eb2Smrg   int seen_keyword;
1877627f7eb2Smrg   gfc_st_label *label;
1878627f7eb2Smrg   locus old_loc;
1879627f7eb2Smrg   match m;
1880627f7eb2Smrg 
1881627f7eb2Smrg   *argp = tail = NULL;
1882627f7eb2Smrg   old_loc = gfc_current_locus;
1883627f7eb2Smrg 
1884627f7eb2Smrg   seen_keyword = 0;
1885627f7eb2Smrg 
1886627f7eb2Smrg   if (gfc_match_char ('(') == MATCH_NO)
1887627f7eb2Smrg     return (sub_flag) ? MATCH_YES : MATCH_NO;
1888627f7eb2Smrg 
1889627f7eb2Smrg   if (gfc_match_char (')') == MATCH_YES)
1890627f7eb2Smrg     return MATCH_YES;
1891627f7eb2Smrg 
1892627f7eb2Smrg   head = NULL;
1893627f7eb2Smrg 
1894627f7eb2Smrg   matching_actual_arglist++;
1895627f7eb2Smrg 
1896627f7eb2Smrg   for (;;)
1897627f7eb2Smrg     {
1898627f7eb2Smrg       if (head == NULL)
1899627f7eb2Smrg 	head = tail = gfc_get_actual_arglist ();
1900627f7eb2Smrg       else
1901627f7eb2Smrg 	{
1902627f7eb2Smrg 	  tail->next = gfc_get_actual_arglist ();
1903627f7eb2Smrg 	  tail = tail->next;
1904627f7eb2Smrg 	}
1905627f7eb2Smrg 
1906627f7eb2Smrg       if (sub_flag && !pdt && gfc_match_char ('*') == MATCH_YES)
1907627f7eb2Smrg 	{
1908627f7eb2Smrg 	  m = gfc_match_st_label (&label);
1909627f7eb2Smrg 	  if (m == MATCH_NO)
1910627f7eb2Smrg 	    gfc_error ("Expected alternate return label at %C");
1911627f7eb2Smrg 	  if (m != MATCH_YES)
1912627f7eb2Smrg 	    goto cleanup;
1913627f7eb2Smrg 
1914627f7eb2Smrg 	  if (!gfc_notify_std (GFC_STD_F95_OBS, "Alternate-return argument "
1915627f7eb2Smrg 			       "at %C"))
1916627f7eb2Smrg 	    goto cleanup;
1917627f7eb2Smrg 
1918627f7eb2Smrg 	  tail->label = label;
1919627f7eb2Smrg 	  goto next;
1920627f7eb2Smrg 	}
1921627f7eb2Smrg 
1922627f7eb2Smrg       if (pdt && !seen_keyword)
1923627f7eb2Smrg 	{
1924627f7eb2Smrg 	  if (gfc_match_char (':') == MATCH_YES)
1925627f7eb2Smrg 	    {
1926627f7eb2Smrg 	      tail->spec_type = SPEC_DEFERRED;
1927627f7eb2Smrg 	      goto next;
1928627f7eb2Smrg 	    }
1929627f7eb2Smrg 	  else if (gfc_match_char ('*') == MATCH_YES)
1930627f7eb2Smrg 	    {
1931627f7eb2Smrg 	      tail->spec_type = SPEC_ASSUMED;
1932627f7eb2Smrg 	      goto next;
1933627f7eb2Smrg 	    }
1934627f7eb2Smrg 	  else
1935627f7eb2Smrg 	    tail->spec_type = SPEC_EXPLICIT;
1936627f7eb2Smrg 
1937627f7eb2Smrg 	  m = match_keyword_arg (tail, head, pdt);
1938627f7eb2Smrg 	  if (m == MATCH_YES)
1939627f7eb2Smrg 	    {
1940627f7eb2Smrg 	      seen_keyword = 1;
1941627f7eb2Smrg 	      goto next;
1942627f7eb2Smrg 	    }
1943627f7eb2Smrg 	  if (m == MATCH_ERROR)
1944627f7eb2Smrg 	    goto cleanup;
1945627f7eb2Smrg 	}
1946627f7eb2Smrg 
1947627f7eb2Smrg       /* After the first keyword argument is seen, the following
1948627f7eb2Smrg 	 arguments must also have keywords.  */
1949627f7eb2Smrg       if (seen_keyword)
1950627f7eb2Smrg 	{
1951627f7eb2Smrg 	  m = match_keyword_arg (tail, head, pdt);
1952627f7eb2Smrg 
1953627f7eb2Smrg 	  if (m == MATCH_ERROR)
1954627f7eb2Smrg 	    goto cleanup;
1955627f7eb2Smrg 	  if (m == MATCH_NO)
1956627f7eb2Smrg 	    {
1957627f7eb2Smrg 	      gfc_error ("Missing keyword name in actual argument list at %C");
1958627f7eb2Smrg 	      goto cleanup;
1959627f7eb2Smrg 	    }
1960627f7eb2Smrg 
1961627f7eb2Smrg 	}
1962627f7eb2Smrg       else
1963627f7eb2Smrg 	{
1964627f7eb2Smrg 	  /* Try an argument list function, like %VAL.  */
1965627f7eb2Smrg 	  m = match_arg_list_function (tail);
1966627f7eb2Smrg 	  if (m == MATCH_ERROR)
1967627f7eb2Smrg 	    goto cleanup;
1968627f7eb2Smrg 
1969627f7eb2Smrg 	  /* See if we have the first keyword argument.  */
1970627f7eb2Smrg 	  if (m == MATCH_NO)
1971627f7eb2Smrg 	    {
1972627f7eb2Smrg 	      m = match_keyword_arg (tail, head, false);
1973627f7eb2Smrg 	      if (m == MATCH_YES)
1974627f7eb2Smrg 		seen_keyword = 1;
1975627f7eb2Smrg 	      if (m == MATCH_ERROR)
1976627f7eb2Smrg 		goto cleanup;
1977627f7eb2Smrg 	    }
1978627f7eb2Smrg 
1979627f7eb2Smrg 	  if (m == MATCH_NO)
1980627f7eb2Smrg 	    {
1981627f7eb2Smrg 	      /* Try for a non-keyword argument.  */
1982627f7eb2Smrg 	      m = match_actual_arg (&tail->expr);
1983627f7eb2Smrg 	      if (m == MATCH_ERROR)
1984627f7eb2Smrg 		goto cleanup;
1985627f7eb2Smrg 	      if (m == MATCH_NO)
1986627f7eb2Smrg 		goto syntax;
1987627f7eb2Smrg 	    }
1988627f7eb2Smrg 	}
1989627f7eb2Smrg 
1990627f7eb2Smrg 
1991627f7eb2Smrg     next:
1992627f7eb2Smrg       if (gfc_match_char (')') == MATCH_YES)
1993627f7eb2Smrg 	break;
1994627f7eb2Smrg       if (gfc_match_char (',') != MATCH_YES)
1995627f7eb2Smrg 	goto syntax;
1996627f7eb2Smrg     }
1997627f7eb2Smrg 
1998627f7eb2Smrg   *argp = head;
1999627f7eb2Smrg   matching_actual_arglist--;
2000627f7eb2Smrg   return MATCH_YES;
2001627f7eb2Smrg 
2002627f7eb2Smrg syntax:
2003627f7eb2Smrg   gfc_error ("Syntax error in argument list at %C");
2004627f7eb2Smrg 
2005627f7eb2Smrg cleanup:
2006627f7eb2Smrg   gfc_free_actual_arglist (head);
2007627f7eb2Smrg   gfc_current_locus = old_loc;
2008627f7eb2Smrg   matching_actual_arglist--;
2009627f7eb2Smrg   return MATCH_ERROR;
2010627f7eb2Smrg }
2011627f7eb2Smrg 
2012627f7eb2Smrg 
2013627f7eb2Smrg /* Used by gfc_match_varspec() to extend the reference list by one
2014627f7eb2Smrg    element.  */
2015627f7eb2Smrg 
2016627f7eb2Smrg static gfc_ref *
extend_ref(gfc_expr * primary,gfc_ref * tail)2017627f7eb2Smrg extend_ref (gfc_expr *primary, gfc_ref *tail)
2018627f7eb2Smrg {
2019627f7eb2Smrg   if (primary->ref == NULL)
2020627f7eb2Smrg     primary->ref = tail = gfc_get_ref ();
2021627f7eb2Smrg   else
2022627f7eb2Smrg     {
2023627f7eb2Smrg       if (tail == NULL)
2024627f7eb2Smrg 	gfc_internal_error ("extend_ref(): Bad tail");
2025627f7eb2Smrg       tail->next = gfc_get_ref ();
2026627f7eb2Smrg       tail = tail->next;
2027627f7eb2Smrg     }
2028627f7eb2Smrg 
2029627f7eb2Smrg   return tail;
2030627f7eb2Smrg }
2031627f7eb2Smrg 
2032627f7eb2Smrg 
2033627f7eb2Smrg /* Used by gfc_match_varspec() to match an inquiry reference.  */
2034627f7eb2Smrg 
2035627f7eb2Smrg static bool
is_inquiry_ref(const char * name,gfc_ref ** ref)2036627f7eb2Smrg is_inquiry_ref (const char *name, gfc_ref **ref)
2037627f7eb2Smrg {
2038627f7eb2Smrg   inquiry_type type;
2039627f7eb2Smrg 
2040627f7eb2Smrg   if (name == NULL)
2041627f7eb2Smrg     return false;
2042627f7eb2Smrg 
2043627f7eb2Smrg   if (ref) *ref = NULL;
2044627f7eb2Smrg 
2045627f7eb2Smrg   if (strcmp (name, "re") == 0)
2046627f7eb2Smrg     type = INQUIRY_RE;
2047627f7eb2Smrg   else if (strcmp (name, "im") == 0)
2048627f7eb2Smrg     type = INQUIRY_IM;
2049627f7eb2Smrg   else if (strcmp (name, "kind") == 0)
2050627f7eb2Smrg     type = INQUIRY_KIND;
2051627f7eb2Smrg   else if (strcmp (name, "len") == 0)
2052627f7eb2Smrg     type = INQUIRY_LEN;
2053627f7eb2Smrg   else
2054627f7eb2Smrg     return false;
2055627f7eb2Smrg 
2056627f7eb2Smrg   if (ref)
2057627f7eb2Smrg     {
2058627f7eb2Smrg       *ref = gfc_get_ref ();
2059627f7eb2Smrg       (*ref)->type = REF_INQUIRY;
2060627f7eb2Smrg       (*ref)->u.i = type;
2061627f7eb2Smrg     }
2062627f7eb2Smrg 
2063627f7eb2Smrg   return true;
2064627f7eb2Smrg }
2065627f7eb2Smrg 
2066627f7eb2Smrg 
2067627f7eb2Smrg /* Match any additional specifications associated with the current
2068627f7eb2Smrg    variable like member references or substrings.  If equiv_flag is
2069627f7eb2Smrg    set we only match stuff that is allowed inside an EQUIVALENCE
2070627f7eb2Smrg    statement.  sub_flag tells whether we expect a type-bound procedure found
2071627f7eb2Smrg    to be a subroutine as part of CALL or a FUNCTION. For procedure pointer
2072627f7eb2Smrg    components, 'ppc_arg' determines whether the PPC may be called (with an
2073627f7eb2Smrg    argument list), or whether it may just be referred to as a pointer.  */
2074627f7eb2Smrg 
2075627f7eb2Smrg match
gfc_match_varspec(gfc_expr * primary,int equiv_flag,bool sub_flag,bool ppc_arg)2076627f7eb2Smrg gfc_match_varspec (gfc_expr *primary, int equiv_flag, bool sub_flag,
2077627f7eb2Smrg 		   bool ppc_arg)
2078627f7eb2Smrg {
2079627f7eb2Smrg   char name[GFC_MAX_SYMBOL_LEN + 1];
2080627f7eb2Smrg   gfc_ref *substring, *tail, *tmp;
20814c3eb207Smrg   gfc_component *component = NULL;
20824c3eb207Smrg   gfc_component *previous = NULL;
2083627f7eb2Smrg   gfc_symbol *sym = primary->symtree->n.sym;
2084627f7eb2Smrg   gfc_expr *tgt_expr = NULL;
2085627f7eb2Smrg   match m;
2086627f7eb2Smrg   bool unknown;
2087627f7eb2Smrg   bool inquiry;
2088627f7eb2Smrg   bool intrinsic;
2089627f7eb2Smrg   locus old_loc;
2090627f7eb2Smrg   char sep;
2091627f7eb2Smrg 
2092627f7eb2Smrg   tail = NULL;
2093627f7eb2Smrg 
2094627f7eb2Smrg   gfc_gobble_whitespace ();
2095627f7eb2Smrg 
2096627f7eb2Smrg   if (gfc_peek_ascii_char () == '[')
2097627f7eb2Smrg     {
2098627f7eb2Smrg       if ((sym->ts.type != BT_CLASS && sym->attr.dimension)
2099627f7eb2Smrg 	  || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
2100627f7eb2Smrg 	      && CLASS_DATA (sym)->attr.dimension))
2101627f7eb2Smrg 	{
2102627f7eb2Smrg 	  gfc_error ("Array section designator, e.g. '(:)', is required "
2103627f7eb2Smrg 		     "besides the coarray designator '[...]' at %C");
2104627f7eb2Smrg 	  return MATCH_ERROR;
2105627f7eb2Smrg 	}
2106627f7eb2Smrg       if ((sym->ts.type != BT_CLASS && !sym->attr.codimension)
2107627f7eb2Smrg 	  || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
2108627f7eb2Smrg 	      && !CLASS_DATA (sym)->attr.codimension))
2109627f7eb2Smrg 	{
2110627f7eb2Smrg 	  gfc_error ("Coarray designator at %C but %qs is not a coarray",
2111627f7eb2Smrg 		     sym->name);
2112627f7eb2Smrg 	  return MATCH_ERROR;
2113627f7eb2Smrg 	}
2114627f7eb2Smrg     }
2115627f7eb2Smrg 
2116627f7eb2Smrg   if (sym->assoc && sym->assoc->target)
2117627f7eb2Smrg     tgt_expr = sym->assoc->target;
2118627f7eb2Smrg 
2119627f7eb2Smrg   /* For associate names, we may not yet know whether they are arrays or not.
2120627f7eb2Smrg      If the selector expression is unambiguously an array; eg. a full array
2121627f7eb2Smrg      or an array section, then the associate name must be an array and we can
2122627f7eb2Smrg      fix it now. Otherwise, if parentheses follow and it is not a character
2123627f7eb2Smrg      type, we have to assume that it actually is one for now.  The final
2124627f7eb2Smrg      decision will be made at resolution, of course.  */
2125627f7eb2Smrg   if (sym->assoc
2126627f7eb2Smrg       && gfc_peek_ascii_char () == '('
2127627f7eb2Smrg       && sym->ts.type != BT_CLASS
2128627f7eb2Smrg       && !sym->attr.dimension)
2129627f7eb2Smrg     {
2130627f7eb2Smrg       gfc_ref *ref = NULL;
2131627f7eb2Smrg 
2132627f7eb2Smrg       if (!sym->assoc->dangling && tgt_expr)
2133627f7eb2Smrg 	{
2134627f7eb2Smrg 	   if (tgt_expr->expr_type == EXPR_VARIABLE)
2135627f7eb2Smrg 	     gfc_resolve_expr (tgt_expr);
2136627f7eb2Smrg 
2137627f7eb2Smrg 	   ref = tgt_expr->ref;
2138627f7eb2Smrg 	   for (; ref; ref = ref->next)
2139627f7eb2Smrg 	      if (ref->type == REF_ARRAY
2140627f7eb2Smrg 		  && (ref->u.ar.type == AR_FULL
2141627f7eb2Smrg 		      || ref->u.ar.type == AR_SECTION))
2142627f7eb2Smrg 		break;
2143627f7eb2Smrg 	}
2144627f7eb2Smrg 
2145627f7eb2Smrg       if (ref || (!(sym->assoc->dangling || sym->ts.type == BT_CHARACTER)
2146627f7eb2Smrg 		  && sym->assoc->st
2147627f7eb2Smrg 		  && sym->assoc->st->n.sym
2148627f7eb2Smrg 		  && sym->assoc->st->n.sym->attr.dimension == 0))
2149627f7eb2Smrg 	{
2150627f7eb2Smrg 	  sym->attr.dimension = 1;
2151627f7eb2Smrg 	  if (sym->as == NULL
2152627f7eb2Smrg 	      && sym->assoc->st
2153627f7eb2Smrg 	      && sym->assoc->st->n.sym
2154627f7eb2Smrg 	      && sym->assoc->st->n.sym->as)
2155627f7eb2Smrg 	    sym->as = gfc_copy_array_spec (sym->assoc->st->n.sym->as);
2156627f7eb2Smrg 	}
2157627f7eb2Smrg     }
2158627f7eb2Smrg   else if (sym->ts.type == BT_CLASS
2159627f7eb2Smrg 	   && tgt_expr
2160627f7eb2Smrg 	   && tgt_expr->expr_type == EXPR_VARIABLE
2161627f7eb2Smrg 	   && sym->ts.u.derived != tgt_expr->ts.u.derived)
2162627f7eb2Smrg     {
2163627f7eb2Smrg       gfc_resolve_expr (tgt_expr);
2164627f7eb2Smrg       if (tgt_expr->rank)
2165627f7eb2Smrg 	sym->ts.u.derived = tgt_expr->ts.u.derived;
2166627f7eb2Smrg     }
2167627f7eb2Smrg 
2168627f7eb2Smrg   if ((equiv_flag && gfc_peek_ascii_char () == '(')
2169627f7eb2Smrg       || gfc_peek_ascii_char () == '[' || sym->attr.codimension
2170627f7eb2Smrg       || (sym->attr.dimension && sym->ts.type != BT_CLASS
2171627f7eb2Smrg 	  && !sym->attr.proc_pointer && !gfc_is_proc_ptr_comp (primary)
2172627f7eb2Smrg 	  && !(gfc_matching_procptr_assignment
2173627f7eb2Smrg 	       && sym->attr.flavor == FL_PROCEDURE))
2174627f7eb2Smrg       || (sym->ts.type == BT_CLASS && sym->attr.class_ok
21754c3eb207Smrg 	  && sym->ts.u.derived && CLASS_DATA (sym)
2176627f7eb2Smrg 	  && (CLASS_DATA (sym)->attr.dimension
2177627f7eb2Smrg 	      || CLASS_DATA (sym)->attr.codimension)))
2178627f7eb2Smrg     {
2179627f7eb2Smrg       gfc_array_spec *as;
2180627f7eb2Smrg 
2181627f7eb2Smrg       tail = extend_ref (primary, tail);
2182627f7eb2Smrg       tail->type = REF_ARRAY;
2183627f7eb2Smrg 
2184627f7eb2Smrg       /* In EQUIVALENCE, we don't know yet whether we are seeing
2185627f7eb2Smrg 	 an array, character variable or array of character
2186627f7eb2Smrg 	 variables.  We'll leave the decision till resolve time.  */
2187627f7eb2Smrg 
2188627f7eb2Smrg       if (equiv_flag)
2189627f7eb2Smrg 	as = NULL;
2190627f7eb2Smrg       else if (sym->ts.type == BT_CLASS && CLASS_DATA (sym))
2191627f7eb2Smrg 	as = CLASS_DATA (sym)->as;
2192627f7eb2Smrg       else
2193627f7eb2Smrg 	as = sym->as;
2194627f7eb2Smrg 
2195627f7eb2Smrg       m = gfc_match_array_ref (&tail->u.ar, as, equiv_flag,
2196627f7eb2Smrg 			       as ? as->corank : 0);
2197627f7eb2Smrg       if (m != MATCH_YES)
2198627f7eb2Smrg 	return m;
2199627f7eb2Smrg 
2200627f7eb2Smrg       gfc_gobble_whitespace ();
2201627f7eb2Smrg       if (equiv_flag && gfc_peek_ascii_char () == '(')
2202627f7eb2Smrg 	{
2203627f7eb2Smrg 	  tail = extend_ref (primary, tail);
2204627f7eb2Smrg 	  tail->type = REF_ARRAY;
2205627f7eb2Smrg 
2206627f7eb2Smrg 	  m = gfc_match_array_ref (&tail->u.ar, NULL, equiv_flag, 0);
2207627f7eb2Smrg 	  if (m != MATCH_YES)
2208627f7eb2Smrg 	    return m;
2209627f7eb2Smrg 	}
2210627f7eb2Smrg     }
2211627f7eb2Smrg 
2212627f7eb2Smrg   primary->ts = sym->ts;
2213627f7eb2Smrg 
2214627f7eb2Smrg   if (equiv_flag)
2215627f7eb2Smrg     return MATCH_YES;
2216627f7eb2Smrg 
2217627f7eb2Smrg   /* With DEC extensions, member separator may be '.' or '%'.  */
2218627f7eb2Smrg   sep = gfc_peek_ascii_char ();
2219627f7eb2Smrg   m = gfc_match_member_sep (sym);
2220627f7eb2Smrg   if (m == MATCH_ERROR)
2221627f7eb2Smrg     return MATCH_ERROR;
2222627f7eb2Smrg 
2223627f7eb2Smrg   inquiry = false;
2224627f7eb2Smrg   if (m == MATCH_YES && sep == '%'
2225627f7eb2Smrg       && primary->ts.type != BT_CLASS
2226627f7eb2Smrg       && primary->ts.type != BT_DERIVED)
2227627f7eb2Smrg     {
2228627f7eb2Smrg       match mm;
2229627f7eb2Smrg       old_loc = gfc_current_locus;
2230627f7eb2Smrg       mm = gfc_match_name (name);
2231627f7eb2Smrg       if (mm == MATCH_YES && is_inquiry_ref (name, &tmp))
2232627f7eb2Smrg 	inquiry = true;
2233627f7eb2Smrg       gfc_current_locus = old_loc;
2234627f7eb2Smrg     }
2235627f7eb2Smrg 
2236627f7eb2Smrg   if (sym->ts.type == BT_UNKNOWN && m == MATCH_YES
2237627f7eb2Smrg       && gfc_get_default_type (sym->name, sym->ns)->type == BT_DERIVED)
2238627f7eb2Smrg     gfc_set_default_type (sym, 0, sym->ns);
2239627f7eb2Smrg 
2240627f7eb2Smrg   /* See if there is a usable typespec in the "no IMPLICIT type" error.  */
2241627f7eb2Smrg   if (sym->ts.type == BT_UNKNOWN && m == MATCH_YES)
2242627f7eb2Smrg     {
2243627f7eb2Smrg       bool permissible;
2244627f7eb2Smrg 
2245627f7eb2Smrg       /* These target expressions can be resolved at any time.  */
2246627f7eb2Smrg       permissible = tgt_expr && tgt_expr->symtree && tgt_expr->symtree->n.sym
2247627f7eb2Smrg 		    && (tgt_expr->symtree->n.sym->attr.use_assoc
2248627f7eb2Smrg 			|| tgt_expr->symtree->n.sym->attr.host_assoc
2249627f7eb2Smrg 			|| tgt_expr->symtree->n.sym->attr.if_source
2250627f7eb2Smrg 								== IFSRC_DECL);
2251627f7eb2Smrg       permissible = permissible
2252627f7eb2Smrg 		    || (tgt_expr && tgt_expr->expr_type == EXPR_OP);
2253627f7eb2Smrg 
2254627f7eb2Smrg       if (permissible)
2255627f7eb2Smrg 	{
2256627f7eb2Smrg 	  gfc_resolve_expr (tgt_expr);
2257627f7eb2Smrg 	  sym->ts = tgt_expr->ts;
2258627f7eb2Smrg 	}
2259627f7eb2Smrg 
2260627f7eb2Smrg       if (sym->ts.type == BT_UNKNOWN)
2261627f7eb2Smrg 	{
2262627f7eb2Smrg 	  gfc_error ("Symbol %qs at %C has no IMPLICIT type", sym->name);
2263627f7eb2Smrg 	  return MATCH_ERROR;
2264627f7eb2Smrg 	}
2265627f7eb2Smrg     }
2266627f7eb2Smrg   else if ((sym->ts.type != BT_DERIVED && sym->ts.type != BT_CLASS)
2267627f7eb2Smrg            && m == MATCH_YES && !inquiry)
2268627f7eb2Smrg     {
2269627f7eb2Smrg       gfc_error ("Unexpected %<%c%> for nonderived-type variable %qs at %C",
2270627f7eb2Smrg 		 sep, sym->name);
2271627f7eb2Smrg       return MATCH_ERROR;
2272627f7eb2Smrg     }
2273627f7eb2Smrg 
2274627f7eb2Smrg   if ((sym->ts.type != BT_DERIVED && sym->ts.type != BT_CLASS && !inquiry)
2275627f7eb2Smrg       || m != MATCH_YES)
2276627f7eb2Smrg     goto check_substring;
2277627f7eb2Smrg 
2278627f7eb2Smrg   if (!inquiry)
2279627f7eb2Smrg     sym = sym->ts.u.derived;
2280627f7eb2Smrg   else
2281627f7eb2Smrg     sym = NULL;
2282627f7eb2Smrg 
2283627f7eb2Smrg   for (;;)
2284627f7eb2Smrg     {
2285627f7eb2Smrg       bool t;
2286627f7eb2Smrg       gfc_symtree *tbp;
2287627f7eb2Smrg 
2288627f7eb2Smrg       m = gfc_match_name (name);
2289627f7eb2Smrg       if (m == MATCH_NO)
2290627f7eb2Smrg 	gfc_error ("Expected structure component name at %C");
2291627f7eb2Smrg       if (m != MATCH_YES)
2292627f7eb2Smrg 	return MATCH_ERROR;
2293627f7eb2Smrg 
2294627f7eb2Smrg       intrinsic = false;
2295627f7eb2Smrg       if (primary->ts.type != BT_CLASS && primary->ts.type != BT_DERIVED)
2296627f7eb2Smrg 	{
2297627f7eb2Smrg 	  inquiry = is_inquiry_ref (name, &tmp);
2298627f7eb2Smrg 	  if (inquiry)
2299627f7eb2Smrg 	    sym = NULL;
2300627f7eb2Smrg 
2301627f7eb2Smrg 	  if (sep == '%')
2302627f7eb2Smrg 	    {
2303627f7eb2Smrg 	      if (tmp)
2304627f7eb2Smrg 		{
23054c3eb207Smrg 		  switch (tmp->u.i)
23064c3eb207Smrg 		    {
23074c3eb207Smrg 		    case INQUIRY_RE:
23084c3eb207Smrg 		    case INQUIRY_IM:
23094c3eb207Smrg 		      if (!gfc_notify_std (GFC_STD_F2008,
23104c3eb207Smrg 					   "RE or IM part_ref at %C"))
23114c3eb207Smrg 			return MATCH_ERROR;
23124c3eb207Smrg 		      break;
23134c3eb207Smrg 
23144c3eb207Smrg 		    case INQUIRY_KIND:
23154c3eb207Smrg 		      if (!gfc_notify_std (GFC_STD_F2003,
23164c3eb207Smrg 					   "KIND part_ref at %C"))
23174c3eb207Smrg 			return MATCH_ERROR;
23184c3eb207Smrg 		      break;
23194c3eb207Smrg 
23204c3eb207Smrg 		    case INQUIRY_LEN:
23214c3eb207Smrg 		      if (!gfc_notify_std (GFC_STD_F2003, "LEN part_ref at %C"))
23224c3eb207Smrg 			return MATCH_ERROR;
23234c3eb207Smrg 		      break;
23244c3eb207Smrg 		    }
23254c3eb207Smrg 
2326627f7eb2Smrg 		  if ((tmp->u.i == INQUIRY_RE || tmp->u.i == INQUIRY_IM)
2327627f7eb2Smrg 		      && primary->ts.type != BT_COMPLEX)
2328627f7eb2Smrg 		    {
2329627f7eb2Smrg 			gfc_error ("The RE or IM part_ref at %C must be "
2330627f7eb2Smrg 				   "applied to a COMPLEX expression");
2331627f7eb2Smrg 			return MATCH_ERROR;
2332627f7eb2Smrg 		    }
2333627f7eb2Smrg 		  else if (tmp->u.i == INQUIRY_LEN
2334627f7eb2Smrg 			   && primary->ts.type != BT_CHARACTER)
2335627f7eb2Smrg 		    {
2336627f7eb2Smrg 			gfc_error ("The LEN part_ref at %C must be applied "
2337627f7eb2Smrg 				   "to a CHARACTER expression");
2338627f7eb2Smrg 			return MATCH_ERROR;
2339627f7eb2Smrg 		    }
2340627f7eb2Smrg 		}
2341627f7eb2Smrg 	      if (primary->ts.type != BT_UNKNOWN)
2342627f7eb2Smrg 		intrinsic = true;
2343627f7eb2Smrg 	    }
2344627f7eb2Smrg 	}
2345627f7eb2Smrg       else
2346627f7eb2Smrg 	inquiry = false;
2347627f7eb2Smrg 
2348627f7eb2Smrg       if (sym && sym->f2k_derived)
2349627f7eb2Smrg 	tbp = gfc_find_typebound_proc (sym, &t, name, false, &gfc_current_locus);
2350627f7eb2Smrg       else
2351627f7eb2Smrg 	tbp = NULL;
2352627f7eb2Smrg 
2353627f7eb2Smrg       if (tbp)
2354627f7eb2Smrg 	{
2355627f7eb2Smrg 	  gfc_symbol* tbp_sym;
2356627f7eb2Smrg 
2357627f7eb2Smrg 	  if (!t)
2358627f7eb2Smrg 	    return MATCH_ERROR;
2359627f7eb2Smrg 
2360627f7eb2Smrg 	  gcc_assert (!tail || !tail->next);
2361627f7eb2Smrg 
2362627f7eb2Smrg 	  if (!(primary->expr_type == EXPR_VARIABLE
2363627f7eb2Smrg 		|| (primary->expr_type == EXPR_STRUCTURE
2364627f7eb2Smrg 		    && primary->symtree && primary->symtree->n.sym
2365627f7eb2Smrg 		    && primary->symtree->n.sym->attr.flavor)))
2366627f7eb2Smrg 	    return MATCH_ERROR;
2367627f7eb2Smrg 
2368627f7eb2Smrg 	  if (tbp->n.tb->is_generic)
2369627f7eb2Smrg 	    tbp_sym = NULL;
2370627f7eb2Smrg 	  else
2371627f7eb2Smrg 	    tbp_sym = tbp->n.tb->u.specific->n.sym;
2372627f7eb2Smrg 
2373627f7eb2Smrg 	  primary->expr_type = EXPR_COMPCALL;
2374627f7eb2Smrg 	  primary->value.compcall.tbp = tbp->n.tb;
2375627f7eb2Smrg 	  primary->value.compcall.name = tbp->name;
2376627f7eb2Smrg 	  primary->value.compcall.ignore_pass = 0;
2377627f7eb2Smrg 	  primary->value.compcall.assign = 0;
2378627f7eb2Smrg 	  primary->value.compcall.base_object = NULL;
2379627f7eb2Smrg 	  gcc_assert (primary->symtree->n.sym->attr.referenced);
2380627f7eb2Smrg 	  if (tbp_sym)
2381627f7eb2Smrg 	    primary->ts = tbp_sym->ts;
2382627f7eb2Smrg 	  else
2383627f7eb2Smrg 	    gfc_clear_ts (&primary->ts);
2384627f7eb2Smrg 
2385627f7eb2Smrg 	  m = gfc_match_actual_arglist (tbp->n.tb->subroutine,
2386627f7eb2Smrg 					&primary->value.compcall.actual);
2387627f7eb2Smrg 	  if (m == MATCH_ERROR)
2388627f7eb2Smrg 	    return MATCH_ERROR;
2389627f7eb2Smrg 	  if (m == MATCH_NO)
2390627f7eb2Smrg 	    {
2391627f7eb2Smrg 	      if (sub_flag)
2392627f7eb2Smrg 		primary->value.compcall.actual = NULL;
2393627f7eb2Smrg 	      else
2394627f7eb2Smrg 		{
2395627f7eb2Smrg 		  gfc_error ("Expected argument list at %C");
2396627f7eb2Smrg 		  return MATCH_ERROR;
2397627f7eb2Smrg 		}
2398627f7eb2Smrg 	    }
2399627f7eb2Smrg 
2400627f7eb2Smrg 	  break;
2401627f7eb2Smrg 	}
2402627f7eb2Smrg 
24034c3eb207Smrg       previous = component;
24044c3eb207Smrg 
2405627f7eb2Smrg       if (!inquiry && !intrinsic)
2406627f7eb2Smrg 	component = gfc_find_component (sym, name, false, false, &tmp);
2407627f7eb2Smrg       else
2408627f7eb2Smrg 	component = NULL;
2409627f7eb2Smrg 
2410627f7eb2Smrg       if (intrinsic && !inquiry)
24114c3eb207Smrg 	{
24124c3eb207Smrg 	  if (previous)
24134c3eb207Smrg 	    gfc_error ("%qs at %C is not an inquiry reference to an intrinsic "
24144c3eb207Smrg 			"type component %qs", name, previous->name);
24154c3eb207Smrg 	  else
24164c3eb207Smrg 	    gfc_error ("%qs at %C is not an inquiry reference to an intrinsic "
24174c3eb207Smrg 			"type component", name);
24184c3eb207Smrg 	  return MATCH_ERROR;
24194c3eb207Smrg 	}
2420627f7eb2Smrg       else if (component == NULL && !inquiry)
2421627f7eb2Smrg 	return MATCH_ERROR;
2422627f7eb2Smrg 
2423627f7eb2Smrg       /* Extend the reference chain determined by gfc_find_component or
2424627f7eb2Smrg 	 is_inquiry_ref.  */
2425627f7eb2Smrg       if (primary->ref == NULL)
2426627f7eb2Smrg 	primary->ref = tmp;
2427627f7eb2Smrg       else
2428627f7eb2Smrg 	{
2429627f7eb2Smrg 	  /* Set by the for loop below for the last component ref.  */
2430627f7eb2Smrg 	  gcc_assert (tail != NULL);
2431627f7eb2Smrg 	  tail->next = tmp;
2432627f7eb2Smrg 	}
2433627f7eb2Smrg 
2434627f7eb2Smrg       /* The reference chain may be longer than one hop for union
2435627f7eb2Smrg 	 subcomponents; find the new tail.  */
2436627f7eb2Smrg       for (tail = tmp; tail->next; tail = tail->next)
2437627f7eb2Smrg 	;
2438627f7eb2Smrg 
2439627f7eb2Smrg       if (tmp && tmp->type == REF_INQUIRY)
2440627f7eb2Smrg 	{
2441627f7eb2Smrg 	  if (!primary->where.lb || !primary->where.nextc)
2442627f7eb2Smrg 	    primary->where = gfc_current_locus;
2443627f7eb2Smrg 	  gfc_simplify_expr (primary, 0);
2444627f7eb2Smrg 
2445627f7eb2Smrg 	  if (primary->expr_type == EXPR_CONSTANT)
2446627f7eb2Smrg 	    goto check_done;
2447627f7eb2Smrg 
2448627f7eb2Smrg 	  switch (tmp->u.i)
2449627f7eb2Smrg 	    {
2450627f7eb2Smrg 	    case INQUIRY_RE:
2451627f7eb2Smrg 	    case INQUIRY_IM:
2452627f7eb2Smrg 	      if (!gfc_notify_std (GFC_STD_F2008, "RE or IM part_ref at %C"))
2453627f7eb2Smrg 		return MATCH_ERROR;
2454627f7eb2Smrg 
2455627f7eb2Smrg 	      if (primary->ts.type != BT_COMPLEX)
2456627f7eb2Smrg 		{
2457627f7eb2Smrg 		  gfc_error ("The RE or IM part_ref at %C must be "
2458627f7eb2Smrg 			     "applied to a COMPLEX expression");
2459627f7eb2Smrg 		  return MATCH_ERROR;
2460627f7eb2Smrg 		}
2461627f7eb2Smrg 	      primary->ts.type = BT_REAL;
2462627f7eb2Smrg 	      break;
2463627f7eb2Smrg 
2464627f7eb2Smrg 	    case INQUIRY_LEN:
2465627f7eb2Smrg 	      if (!gfc_notify_std (GFC_STD_F2003, "LEN part_ref at %C"))
2466627f7eb2Smrg 		return MATCH_ERROR;
2467627f7eb2Smrg 
2468627f7eb2Smrg 	      if (primary->ts.type != BT_CHARACTER)
2469627f7eb2Smrg 		{
2470627f7eb2Smrg 		  gfc_error ("The LEN part_ref at %C must be applied "
2471627f7eb2Smrg 			     "to a CHARACTER expression");
2472627f7eb2Smrg 		  return MATCH_ERROR;
2473627f7eb2Smrg 		}
2474627f7eb2Smrg 	      primary->ts.u.cl = NULL;
2475627f7eb2Smrg 	      primary->ts.type = BT_INTEGER;
2476627f7eb2Smrg 	      primary->ts.kind = gfc_default_integer_kind;
2477627f7eb2Smrg 	      break;
2478627f7eb2Smrg 
2479627f7eb2Smrg 	    case INQUIRY_KIND:
2480627f7eb2Smrg 	      if (!gfc_notify_std (GFC_STD_F2003, "KIND part_ref at %C"))
2481627f7eb2Smrg 		return MATCH_ERROR;
2482627f7eb2Smrg 
2483627f7eb2Smrg 	      if (primary->ts.type == BT_CLASS
2484627f7eb2Smrg 		  || primary->ts.type == BT_DERIVED)
2485627f7eb2Smrg 		{
2486627f7eb2Smrg 		  gfc_error ("The KIND part_ref at %C must be applied "
2487627f7eb2Smrg 			     "to an expression of intrinsic type");
2488627f7eb2Smrg 		  return MATCH_ERROR;
2489627f7eb2Smrg 		}
2490627f7eb2Smrg 	      primary->ts.type = BT_INTEGER;
2491627f7eb2Smrg 	      primary->ts.kind = gfc_default_integer_kind;
2492627f7eb2Smrg 	      break;
2493627f7eb2Smrg 
2494627f7eb2Smrg 	    default:
2495627f7eb2Smrg 	      gcc_unreachable ();
2496627f7eb2Smrg 	    }
2497627f7eb2Smrg 
2498627f7eb2Smrg 	  goto check_done;
2499627f7eb2Smrg 	}
2500627f7eb2Smrg 
2501627f7eb2Smrg       primary->ts = component->ts;
2502627f7eb2Smrg 
2503627f7eb2Smrg       if (component->attr.proc_pointer && ppc_arg)
2504627f7eb2Smrg 	{
2505627f7eb2Smrg 	  /* Procedure pointer component call: Look for argument list.  */
2506627f7eb2Smrg 	  m = gfc_match_actual_arglist (sub_flag,
2507627f7eb2Smrg 					&primary->value.compcall.actual);
2508627f7eb2Smrg 	  if (m == MATCH_ERROR)
2509627f7eb2Smrg 	    return MATCH_ERROR;
2510627f7eb2Smrg 
2511627f7eb2Smrg 	  if (m == MATCH_NO && !gfc_matching_ptr_assignment
2512627f7eb2Smrg 	      && !gfc_matching_procptr_assignment && !matching_actual_arglist)
2513627f7eb2Smrg 	    {
2514627f7eb2Smrg 	      gfc_error ("Procedure pointer component %qs requires an "
2515627f7eb2Smrg 			 "argument list at %C", component->name);
2516627f7eb2Smrg 	      return MATCH_ERROR;
2517627f7eb2Smrg 	    }
2518627f7eb2Smrg 
2519627f7eb2Smrg 	  if (m == MATCH_YES)
2520627f7eb2Smrg 	    primary->expr_type = EXPR_PPC;
2521627f7eb2Smrg 
2522627f7eb2Smrg           break;
2523627f7eb2Smrg 	}
2524627f7eb2Smrg 
2525627f7eb2Smrg       if (component->as != NULL && !component->attr.proc_pointer)
2526627f7eb2Smrg 	{
2527627f7eb2Smrg 	  tail = extend_ref (primary, tail);
2528627f7eb2Smrg 	  tail->type = REF_ARRAY;
2529627f7eb2Smrg 
2530627f7eb2Smrg 	  m = gfc_match_array_ref (&tail->u.ar, component->as, equiv_flag,
2531627f7eb2Smrg 			  component->as->corank);
2532627f7eb2Smrg 	  if (m != MATCH_YES)
2533627f7eb2Smrg 	    return m;
2534627f7eb2Smrg 	}
2535627f7eb2Smrg       else if (component->ts.type == BT_CLASS && component->attr.class_ok
2536627f7eb2Smrg 	       && CLASS_DATA (component)->as && !component->attr.proc_pointer)
2537627f7eb2Smrg 	{
2538627f7eb2Smrg 	  tail = extend_ref (primary, tail);
2539627f7eb2Smrg 	  tail->type = REF_ARRAY;
2540627f7eb2Smrg 
2541627f7eb2Smrg 	  m = gfc_match_array_ref (&tail->u.ar, CLASS_DATA (component)->as,
2542627f7eb2Smrg 				   equiv_flag,
2543627f7eb2Smrg 				   CLASS_DATA (component)->as->corank);
2544627f7eb2Smrg 	  if (m != MATCH_YES)
2545627f7eb2Smrg 	    return m;
2546627f7eb2Smrg 	}
2547627f7eb2Smrg 
2548627f7eb2Smrg check_done:
2549627f7eb2Smrg       /* In principle, we could have eg. expr%re%kind so we must allow for
2550627f7eb2Smrg 	 this possibility.  */
2551627f7eb2Smrg       if (gfc_match_char ('%') == MATCH_YES)
2552627f7eb2Smrg 	{
2553627f7eb2Smrg 	  if (component && (component->ts.type == BT_DERIVED
2554627f7eb2Smrg 			    || component->ts.type == BT_CLASS))
2555627f7eb2Smrg 	    sym = component->ts.u.derived;
2556627f7eb2Smrg 	  continue;
2557627f7eb2Smrg 	}
2558627f7eb2Smrg       else if (inquiry)
2559627f7eb2Smrg 	break;
2560627f7eb2Smrg 
2561627f7eb2Smrg       if ((component->ts.type != BT_DERIVED && component->ts.type != BT_CLASS)
2562627f7eb2Smrg   	  || gfc_match_member_sep (component->ts.u.derived) != MATCH_YES)
2563627f7eb2Smrg 	break;
2564627f7eb2Smrg 
2565627f7eb2Smrg       if (component->ts.type == BT_DERIVED || component->ts.type == BT_CLASS)
2566627f7eb2Smrg 	sym = component->ts.u.derived;
2567627f7eb2Smrg     }
2568627f7eb2Smrg 
2569627f7eb2Smrg check_substring:
2570627f7eb2Smrg   unknown = false;
2571627f7eb2Smrg   if (primary->ts.type == BT_UNKNOWN && !gfc_fl_struct (sym->attr.flavor))
2572627f7eb2Smrg     {
2573627f7eb2Smrg       if (gfc_get_default_type (sym->name, sym->ns)->type == BT_CHARACTER)
2574627f7eb2Smrg        {
2575627f7eb2Smrg 	 gfc_set_default_type (sym, 0, sym->ns);
2576627f7eb2Smrg 	 primary->ts = sym->ts;
2577627f7eb2Smrg 	 unknown = true;
2578627f7eb2Smrg        }
2579627f7eb2Smrg     }
2580627f7eb2Smrg 
2581627f7eb2Smrg   if (primary->ts.type == BT_CHARACTER)
2582627f7eb2Smrg     {
2583627f7eb2Smrg       bool def = primary->ts.deferred == 1;
2584627f7eb2Smrg       switch (match_substring (primary->ts.u.cl, equiv_flag, &substring, def))
2585627f7eb2Smrg 	{
2586627f7eb2Smrg 	case MATCH_YES:
2587627f7eb2Smrg 	  if (tail == NULL)
2588627f7eb2Smrg 	    primary->ref = substring;
2589627f7eb2Smrg 	  else
2590627f7eb2Smrg 	    tail->next = substring;
2591627f7eb2Smrg 
2592627f7eb2Smrg 	  if (primary->expr_type == EXPR_CONSTANT)
2593627f7eb2Smrg 	    primary->expr_type = EXPR_SUBSTRING;
2594627f7eb2Smrg 
2595627f7eb2Smrg 	  if (substring)
2596627f7eb2Smrg 	    primary->ts.u.cl = NULL;
2597627f7eb2Smrg 
2598627f7eb2Smrg 	  break;
2599627f7eb2Smrg 
2600627f7eb2Smrg 	case MATCH_NO:
2601627f7eb2Smrg 	  if (unknown)
2602627f7eb2Smrg 	    {
2603627f7eb2Smrg 	      gfc_clear_ts (&primary->ts);
2604627f7eb2Smrg 	      gfc_clear_ts (&sym->ts);
2605627f7eb2Smrg 	    }
2606627f7eb2Smrg 	  break;
2607627f7eb2Smrg 
2608627f7eb2Smrg 	case MATCH_ERROR:
2609627f7eb2Smrg 	  return MATCH_ERROR;
2610627f7eb2Smrg 	}
2611627f7eb2Smrg     }
2612627f7eb2Smrg 
2613627f7eb2Smrg   /* F08:C611.  */
2614627f7eb2Smrg   if (primary->ts.type == BT_DERIVED && primary->ref
2615627f7eb2Smrg       && primary->ts.u.derived && primary->ts.u.derived->attr.abstract)
2616627f7eb2Smrg     {
2617627f7eb2Smrg       gfc_error ("Nonpolymorphic reference to abstract type at %C");
2618627f7eb2Smrg       return MATCH_ERROR;
2619627f7eb2Smrg     }
2620627f7eb2Smrg 
2621627f7eb2Smrg   /* F08:C727.  */
2622627f7eb2Smrg   if (primary->expr_type == EXPR_PPC && gfc_is_coindexed (primary))
2623627f7eb2Smrg     {
2624627f7eb2Smrg       gfc_error ("Coindexed procedure-pointer component at %C");
2625627f7eb2Smrg       return MATCH_ERROR;
2626627f7eb2Smrg     }
2627627f7eb2Smrg 
2628627f7eb2Smrg   return MATCH_YES;
2629627f7eb2Smrg }
2630627f7eb2Smrg 
2631627f7eb2Smrg 
2632627f7eb2Smrg /* Given an expression that is a variable, figure out what the
2633627f7eb2Smrg    ultimate variable's type and attribute is, traversing the reference
2634627f7eb2Smrg    structures if necessary.
2635627f7eb2Smrg 
2636627f7eb2Smrg    This subroutine is trickier than it looks.  We start at the base
2637627f7eb2Smrg    symbol and store the attribute.  Component references load a
2638627f7eb2Smrg    completely new attribute.
2639627f7eb2Smrg 
2640627f7eb2Smrg    A couple of rules come into play.  Subobjects of targets are always
2641627f7eb2Smrg    targets themselves.  If we see a component that goes through a
2642627f7eb2Smrg    pointer, then the expression must also be a target, since the
2643627f7eb2Smrg    pointer is associated with something (if it isn't core will soon be
2644627f7eb2Smrg    dumped).  If we see a full part or section of an array, the
2645627f7eb2Smrg    expression is also an array.
2646627f7eb2Smrg 
2647627f7eb2Smrg    We can have at most one full array reference.  */
2648627f7eb2Smrg 
2649627f7eb2Smrg symbol_attribute
gfc_variable_attr(gfc_expr * expr,gfc_typespec * ts)2650627f7eb2Smrg gfc_variable_attr (gfc_expr *expr, gfc_typespec *ts)
2651627f7eb2Smrg {
2652627f7eb2Smrg   int dimension, codimension, pointer, allocatable, target;
2653627f7eb2Smrg   symbol_attribute attr;
2654627f7eb2Smrg   gfc_ref *ref;
2655627f7eb2Smrg   gfc_symbol *sym;
2656627f7eb2Smrg   gfc_component *comp;
2657627f7eb2Smrg   bool has_inquiry_part;
2658627f7eb2Smrg 
2659627f7eb2Smrg   if (expr->expr_type != EXPR_VARIABLE && expr->expr_type != EXPR_FUNCTION)
2660627f7eb2Smrg     gfc_internal_error ("gfc_variable_attr(): Expression isn't a variable");
2661627f7eb2Smrg 
2662627f7eb2Smrg   sym = expr->symtree->n.sym;
2663627f7eb2Smrg   attr = sym->attr;
2664627f7eb2Smrg 
26654c3eb207Smrg   if (sym->ts.type == BT_CLASS && sym->attr.class_ok && sym->ts.u.derived)
2666627f7eb2Smrg     {
2667627f7eb2Smrg       dimension = CLASS_DATA (sym)->attr.dimension;
2668627f7eb2Smrg       codimension = CLASS_DATA (sym)->attr.codimension;
2669627f7eb2Smrg       pointer = CLASS_DATA (sym)->attr.class_pointer;
2670627f7eb2Smrg       allocatable = CLASS_DATA (sym)->attr.allocatable;
2671627f7eb2Smrg     }
2672627f7eb2Smrg   else
2673627f7eb2Smrg     {
2674627f7eb2Smrg       dimension = attr.dimension;
2675627f7eb2Smrg       codimension = attr.codimension;
2676627f7eb2Smrg       pointer = attr.pointer;
2677627f7eb2Smrg       allocatable = attr.allocatable;
2678627f7eb2Smrg     }
2679627f7eb2Smrg 
2680627f7eb2Smrg   target = attr.target;
2681627f7eb2Smrg   if (pointer || attr.proc_pointer)
2682627f7eb2Smrg     target = 1;
2683627f7eb2Smrg 
2684627f7eb2Smrg   if (ts != NULL && expr->ts.type == BT_UNKNOWN)
2685627f7eb2Smrg     *ts = sym->ts;
2686627f7eb2Smrg 
2687627f7eb2Smrg   has_inquiry_part = false;
2688627f7eb2Smrg   for (ref = expr->ref; ref; ref = ref->next)
2689627f7eb2Smrg     if (ref->type == REF_INQUIRY)
2690627f7eb2Smrg       {
2691627f7eb2Smrg 	has_inquiry_part = true;
2692627f7eb2Smrg 	break;
2693627f7eb2Smrg       }
2694627f7eb2Smrg 
2695627f7eb2Smrg   for (ref = expr->ref; ref; ref = ref->next)
2696627f7eb2Smrg     switch (ref->type)
2697627f7eb2Smrg       {
2698627f7eb2Smrg       case REF_ARRAY:
2699627f7eb2Smrg 
2700627f7eb2Smrg 	switch (ref->u.ar.type)
2701627f7eb2Smrg 	  {
2702627f7eb2Smrg 	  case AR_FULL:
2703627f7eb2Smrg 	    dimension = 1;
2704627f7eb2Smrg 	    break;
2705627f7eb2Smrg 
2706627f7eb2Smrg 	  case AR_SECTION:
2707627f7eb2Smrg 	    allocatable = pointer = 0;
2708627f7eb2Smrg 	    dimension = 1;
2709627f7eb2Smrg 	    break;
2710627f7eb2Smrg 
2711627f7eb2Smrg 	  case AR_ELEMENT:
2712627f7eb2Smrg 	    /* Handle coarrays.  */
2713627f7eb2Smrg 	    if (ref->u.ar.dimen > 0)
2714627f7eb2Smrg 	      allocatable = pointer = 0;
2715627f7eb2Smrg 	    break;
2716627f7eb2Smrg 
2717627f7eb2Smrg 	  case AR_UNKNOWN:
2718627f7eb2Smrg 	    /* For standard conforming code, AR_UNKNOWN should not happen.
2719627f7eb2Smrg 	       For nonconforming code, gfortran can end up here.  Treat it
2720627f7eb2Smrg 	       as a no-op.  */
2721627f7eb2Smrg 	    break;
2722627f7eb2Smrg 	  }
2723627f7eb2Smrg 
2724627f7eb2Smrg 	break;
2725627f7eb2Smrg 
2726627f7eb2Smrg       case REF_COMPONENT:
2727627f7eb2Smrg 	comp = ref->u.c.component;
2728627f7eb2Smrg 	attr = comp->attr;
2729627f7eb2Smrg 	if (ts != NULL && !has_inquiry_part)
2730627f7eb2Smrg 	  {
2731627f7eb2Smrg 	    *ts = comp->ts;
2732627f7eb2Smrg 	    /* Don't set the string length if a substring reference
2733627f7eb2Smrg 	       follows.  */
2734627f7eb2Smrg 	    if (ts->type == BT_CHARACTER
2735627f7eb2Smrg 		&& ref->next && ref->next->type == REF_SUBSTRING)
2736627f7eb2Smrg 		ts->u.cl = NULL;
2737627f7eb2Smrg 	  }
2738627f7eb2Smrg 
2739627f7eb2Smrg 	if (comp->ts.type == BT_CLASS)
2740627f7eb2Smrg 	  {
2741627f7eb2Smrg 	    codimension = CLASS_DATA (comp)->attr.codimension;
2742627f7eb2Smrg 	    pointer = CLASS_DATA (comp)->attr.class_pointer;
2743627f7eb2Smrg 	    allocatable = CLASS_DATA (comp)->attr.allocatable;
2744627f7eb2Smrg 	  }
2745627f7eb2Smrg 	else
2746627f7eb2Smrg 	  {
2747627f7eb2Smrg 	    codimension = comp->attr.codimension;
2748627f7eb2Smrg 	    pointer = comp->attr.pointer;
2749627f7eb2Smrg 	    allocatable = comp->attr.allocatable;
2750627f7eb2Smrg 	  }
2751627f7eb2Smrg 	if (pointer || attr.proc_pointer)
2752627f7eb2Smrg 	  target = 1;
2753627f7eb2Smrg 
2754627f7eb2Smrg 	break;
2755627f7eb2Smrg 
2756627f7eb2Smrg       case REF_INQUIRY:
2757627f7eb2Smrg       case REF_SUBSTRING:
2758627f7eb2Smrg 	allocatable = pointer = 0;
2759627f7eb2Smrg 	break;
2760627f7eb2Smrg       }
2761627f7eb2Smrg 
2762627f7eb2Smrg   attr.dimension = dimension;
2763627f7eb2Smrg   attr.codimension = codimension;
2764627f7eb2Smrg   attr.pointer = pointer;
2765627f7eb2Smrg   attr.allocatable = allocatable;
2766627f7eb2Smrg   attr.target = target;
2767627f7eb2Smrg   attr.save = sym->attr.save;
2768627f7eb2Smrg 
2769627f7eb2Smrg   return attr;
2770627f7eb2Smrg }
2771627f7eb2Smrg 
2772627f7eb2Smrg 
2773627f7eb2Smrg /* Return the attribute from a general expression.  */
2774627f7eb2Smrg 
2775627f7eb2Smrg symbol_attribute
gfc_expr_attr(gfc_expr * e)2776627f7eb2Smrg gfc_expr_attr (gfc_expr *e)
2777627f7eb2Smrg {
2778627f7eb2Smrg   symbol_attribute attr;
2779627f7eb2Smrg 
2780627f7eb2Smrg   switch (e->expr_type)
2781627f7eb2Smrg     {
2782627f7eb2Smrg     case EXPR_VARIABLE:
2783627f7eb2Smrg       attr = gfc_variable_attr (e, NULL);
2784627f7eb2Smrg       break;
2785627f7eb2Smrg 
2786627f7eb2Smrg     case EXPR_FUNCTION:
2787627f7eb2Smrg       gfc_clear_attr (&attr);
2788627f7eb2Smrg 
2789627f7eb2Smrg       if (e->value.function.esym && e->value.function.esym->result)
2790627f7eb2Smrg 	{
2791627f7eb2Smrg 	  gfc_symbol *sym = e->value.function.esym->result;
2792627f7eb2Smrg 	  attr = sym->attr;
2793627f7eb2Smrg 	  if (sym->ts.type == BT_CLASS)
2794627f7eb2Smrg 	    {
2795627f7eb2Smrg 	      attr.dimension = CLASS_DATA (sym)->attr.dimension;
2796627f7eb2Smrg 	      attr.pointer = CLASS_DATA (sym)->attr.class_pointer;
2797627f7eb2Smrg 	      attr.allocatable = CLASS_DATA (sym)->attr.allocatable;
2798627f7eb2Smrg 	    }
2799627f7eb2Smrg 	}
2800627f7eb2Smrg       else if (e->value.function.isym
2801627f7eb2Smrg 	       && e->value.function.isym->transformational
2802627f7eb2Smrg 	       && e->ts.type == BT_CLASS)
2803627f7eb2Smrg 	attr = CLASS_DATA (e)->attr;
2804627f7eb2Smrg       else
2805627f7eb2Smrg 	attr = gfc_variable_attr (e, NULL);
2806627f7eb2Smrg 
2807627f7eb2Smrg       /* TODO: NULL() returns pointers.  May have to take care of this
2808627f7eb2Smrg 	 here.  */
2809627f7eb2Smrg 
2810627f7eb2Smrg       break;
2811627f7eb2Smrg 
2812627f7eb2Smrg     default:
2813627f7eb2Smrg       gfc_clear_attr (&attr);
2814627f7eb2Smrg       break;
2815627f7eb2Smrg     }
2816627f7eb2Smrg 
2817627f7eb2Smrg   return attr;
2818627f7eb2Smrg }
2819627f7eb2Smrg 
2820627f7eb2Smrg 
2821627f7eb2Smrg /* Given an expression, figure out what the ultimate expression
2822627f7eb2Smrg    attribute is.  This routine is similar to gfc_variable_attr with
2823627f7eb2Smrg    parts of gfc_expr_attr, but focuses more on the needs of
2824627f7eb2Smrg    coarrays.  For coarrays a codimension attribute is kind of
2825627f7eb2Smrg    "infectious" being propagated once set and never cleared.
2826627f7eb2Smrg    The coarray_comp is only set, when the expression refs a coarray
2827627f7eb2Smrg    component.  REFS_COMP is set when present to true only, when this EXPR
2828627f7eb2Smrg    refs a (non-_data) component.  To check whether EXPR refs an allocatable
2829627f7eb2Smrg    component in a derived type coarray *refs_comp needs to be set and
2830627f7eb2Smrg    coarray_comp has to false.  */
2831627f7eb2Smrg 
2832627f7eb2Smrg static symbol_attribute
caf_variable_attr(gfc_expr * expr,bool in_allocate,bool * refs_comp)2833627f7eb2Smrg caf_variable_attr (gfc_expr *expr, bool in_allocate, bool *refs_comp)
2834627f7eb2Smrg {
2835627f7eb2Smrg   int dimension, codimension, pointer, allocatable, target, coarray_comp;
2836627f7eb2Smrg   symbol_attribute attr;
2837627f7eb2Smrg   gfc_ref *ref;
2838627f7eb2Smrg   gfc_symbol *sym;
2839627f7eb2Smrg   gfc_component *comp;
2840627f7eb2Smrg 
2841627f7eb2Smrg   if (expr->expr_type != EXPR_VARIABLE && expr->expr_type != EXPR_FUNCTION)
2842627f7eb2Smrg     gfc_internal_error ("gfc_caf_attr(): Expression isn't a variable");
2843627f7eb2Smrg 
2844627f7eb2Smrg   sym = expr->symtree->n.sym;
2845627f7eb2Smrg   gfc_clear_attr (&attr);
2846627f7eb2Smrg 
2847627f7eb2Smrg   if (refs_comp)
2848627f7eb2Smrg     *refs_comp = false;
2849627f7eb2Smrg 
2850627f7eb2Smrg   if (sym->ts.type == BT_CLASS && sym->attr.class_ok)
2851627f7eb2Smrg     {
2852627f7eb2Smrg       dimension = CLASS_DATA (sym)->attr.dimension;
2853627f7eb2Smrg       codimension = CLASS_DATA (sym)->attr.codimension;
2854627f7eb2Smrg       pointer = CLASS_DATA (sym)->attr.class_pointer;
2855627f7eb2Smrg       allocatable = CLASS_DATA (sym)->attr.allocatable;
2856627f7eb2Smrg       attr.alloc_comp = CLASS_DATA (sym)->ts.u.derived->attr.alloc_comp;
2857627f7eb2Smrg       attr.pointer_comp = CLASS_DATA (sym)->ts.u.derived->attr.pointer_comp;
2858627f7eb2Smrg     }
2859627f7eb2Smrg   else
2860627f7eb2Smrg     {
2861627f7eb2Smrg       dimension = sym->attr.dimension;
2862627f7eb2Smrg       codimension = sym->attr.codimension;
2863627f7eb2Smrg       pointer = sym->attr.pointer;
2864627f7eb2Smrg       allocatable = sym->attr.allocatable;
2865627f7eb2Smrg       attr.alloc_comp = sym->ts.type == BT_DERIVED
2866627f7eb2Smrg 	  ? sym->ts.u.derived->attr.alloc_comp : 0;
2867627f7eb2Smrg       attr.pointer_comp = sym->ts.type == BT_DERIVED
2868627f7eb2Smrg 	  ? sym->ts.u.derived->attr.pointer_comp : 0;
2869627f7eb2Smrg     }
2870627f7eb2Smrg 
2871627f7eb2Smrg   target = coarray_comp = 0;
2872627f7eb2Smrg   if (pointer || attr.proc_pointer)
2873627f7eb2Smrg     target = 1;
2874627f7eb2Smrg 
2875627f7eb2Smrg   for (ref = expr->ref; ref; ref = ref->next)
2876627f7eb2Smrg     switch (ref->type)
2877627f7eb2Smrg       {
2878627f7eb2Smrg       case REF_ARRAY:
2879627f7eb2Smrg 
2880627f7eb2Smrg 	switch (ref->u.ar.type)
2881627f7eb2Smrg 	  {
2882627f7eb2Smrg 	  case AR_FULL:
2883627f7eb2Smrg 	  case AR_SECTION:
2884627f7eb2Smrg 	    dimension = 1;
2885627f7eb2Smrg 	    break;
2886627f7eb2Smrg 
2887627f7eb2Smrg 	  case AR_ELEMENT:
2888627f7eb2Smrg 	    /* Handle coarrays.  */
2889627f7eb2Smrg 	    if (ref->u.ar.dimen > 0 && !in_allocate)
2890627f7eb2Smrg 	      allocatable = pointer = 0;
2891627f7eb2Smrg 	    break;
2892627f7eb2Smrg 
2893627f7eb2Smrg 	  case AR_UNKNOWN:
2894627f7eb2Smrg 	    /* If any of start, end or stride is not integer, there will
2895627f7eb2Smrg 	       already have been an error issued.  */
2896627f7eb2Smrg 	    int errors;
2897627f7eb2Smrg 	    gfc_get_errors (NULL, &errors);
2898627f7eb2Smrg 	    if (errors == 0)
2899627f7eb2Smrg 	      gfc_internal_error ("gfc_caf_attr(): Bad array reference");
2900627f7eb2Smrg 	  }
2901627f7eb2Smrg 
2902627f7eb2Smrg 	break;
2903627f7eb2Smrg 
2904627f7eb2Smrg       case REF_COMPONENT:
2905627f7eb2Smrg 	comp = ref->u.c.component;
2906627f7eb2Smrg 
2907627f7eb2Smrg 	if (comp->ts.type == BT_CLASS)
2908627f7eb2Smrg 	  {
2909627f7eb2Smrg 	    /* Set coarray_comp only, when this component introduces the
2910627f7eb2Smrg 	       coarray.  */
2911627f7eb2Smrg 	    coarray_comp = !codimension && CLASS_DATA (comp)->attr.codimension;
2912627f7eb2Smrg 	    codimension |= CLASS_DATA (comp)->attr.codimension;
2913627f7eb2Smrg 	    pointer = CLASS_DATA (comp)->attr.class_pointer;
2914627f7eb2Smrg 	    allocatable = CLASS_DATA (comp)->attr.allocatable;
2915627f7eb2Smrg 	  }
2916627f7eb2Smrg 	else
2917627f7eb2Smrg 	  {
2918627f7eb2Smrg 	    /* Set coarray_comp only, when this component introduces the
2919627f7eb2Smrg 	       coarray.  */
2920627f7eb2Smrg 	    coarray_comp = !codimension && comp->attr.codimension;
2921627f7eb2Smrg 	    codimension |= comp->attr.codimension;
2922627f7eb2Smrg 	    pointer = comp->attr.pointer;
2923627f7eb2Smrg 	    allocatable = comp->attr.allocatable;
2924627f7eb2Smrg 	  }
2925627f7eb2Smrg 
2926627f7eb2Smrg 	if (refs_comp && strcmp (comp->name, "_data") != 0
2927627f7eb2Smrg 	    && (ref->next == NULL
2928627f7eb2Smrg 		|| (ref->next->type == REF_ARRAY && ref->next->next == NULL)))
2929627f7eb2Smrg 	  *refs_comp = true;
2930627f7eb2Smrg 
2931627f7eb2Smrg 	if (pointer || attr.proc_pointer)
2932627f7eb2Smrg 	  target = 1;
2933627f7eb2Smrg 
2934627f7eb2Smrg 	break;
2935627f7eb2Smrg 
2936627f7eb2Smrg       case REF_SUBSTRING:
2937627f7eb2Smrg       case REF_INQUIRY:
2938627f7eb2Smrg 	allocatable = pointer = 0;
2939627f7eb2Smrg 	break;
2940627f7eb2Smrg       }
2941627f7eb2Smrg 
2942627f7eb2Smrg   attr.dimension = dimension;
2943627f7eb2Smrg   attr.codimension = codimension;
2944627f7eb2Smrg   attr.pointer = pointer;
2945627f7eb2Smrg   attr.allocatable = allocatable;
2946627f7eb2Smrg   attr.target = target;
2947627f7eb2Smrg   attr.save = sym->attr.save;
2948627f7eb2Smrg   attr.coarray_comp = coarray_comp;
2949627f7eb2Smrg 
2950627f7eb2Smrg   return attr;
2951627f7eb2Smrg }
2952627f7eb2Smrg 
2953627f7eb2Smrg 
2954627f7eb2Smrg symbol_attribute
gfc_caf_attr(gfc_expr * e,bool in_allocate,bool * refs_comp)2955627f7eb2Smrg gfc_caf_attr (gfc_expr *e, bool in_allocate, bool *refs_comp)
2956627f7eb2Smrg {
2957627f7eb2Smrg   symbol_attribute attr;
2958627f7eb2Smrg 
2959627f7eb2Smrg   switch (e->expr_type)
2960627f7eb2Smrg     {
2961627f7eb2Smrg     case EXPR_VARIABLE:
2962627f7eb2Smrg       attr = caf_variable_attr (e, in_allocate, refs_comp);
2963627f7eb2Smrg       break;
2964627f7eb2Smrg 
2965627f7eb2Smrg     case EXPR_FUNCTION:
2966627f7eb2Smrg       gfc_clear_attr (&attr);
2967627f7eb2Smrg 
2968627f7eb2Smrg       if (e->value.function.esym && e->value.function.esym->result)
2969627f7eb2Smrg 	{
2970627f7eb2Smrg 	  gfc_symbol *sym = e->value.function.esym->result;
2971627f7eb2Smrg 	  attr = sym->attr;
2972627f7eb2Smrg 	  if (sym->ts.type == BT_CLASS)
2973627f7eb2Smrg 	    {
2974627f7eb2Smrg 	      attr.dimension = CLASS_DATA (sym)->attr.dimension;
2975627f7eb2Smrg 	      attr.pointer = CLASS_DATA (sym)->attr.class_pointer;
2976627f7eb2Smrg 	      attr.allocatable = CLASS_DATA (sym)->attr.allocatable;
2977627f7eb2Smrg 	      attr.alloc_comp = CLASS_DATA (sym)->ts.u.derived->attr.alloc_comp;
2978627f7eb2Smrg 	      attr.pointer_comp = CLASS_DATA (sym)->ts.u.derived
2979627f7eb2Smrg 		  ->attr.pointer_comp;
2980627f7eb2Smrg 	    }
2981627f7eb2Smrg 	}
2982627f7eb2Smrg       else if (e->symtree)
2983627f7eb2Smrg 	attr = caf_variable_attr (e, in_allocate, refs_comp);
2984627f7eb2Smrg       else
2985627f7eb2Smrg 	gfc_clear_attr (&attr);
2986627f7eb2Smrg       break;
2987627f7eb2Smrg 
2988627f7eb2Smrg     default:
2989627f7eb2Smrg       gfc_clear_attr (&attr);
2990627f7eb2Smrg       break;
2991627f7eb2Smrg     }
2992627f7eb2Smrg 
2993627f7eb2Smrg   return attr;
2994627f7eb2Smrg }
2995627f7eb2Smrg 
2996627f7eb2Smrg 
2997627f7eb2Smrg /* Match a structure constructor.  The initial symbol has already been
2998627f7eb2Smrg    seen.  */
2999627f7eb2Smrg 
3000627f7eb2Smrg typedef struct gfc_structure_ctor_component
3001627f7eb2Smrg {
3002627f7eb2Smrg   char* name;
3003627f7eb2Smrg   gfc_expr* val;
3004627f7eb2Smrg   locus where;
3005627f7eb2Smrg   struct gfc_structure_ctor_component* next;
3006627f7eb2Smrg }
3007627f7eb2Smrg gfc_structure_ctor_component;
3008627f7eb2Smrg 
3009627f7eb2Smrg #define gfc_get_structure_ctor_component() XCNEW (gfc_structure_ctor_component)
3010627f7eb2Smrg 
3011627f7eb2Smrg static void
gfc_free_structure_ctor_component(gfc_structure_ctor_component * comp)3012627f7eb2Smrg gfc_free_structure_ctor_component (gfc_structure_ctor_component *comp)
3013627f7eb2Smrg {
3014627f7eb2Smrg   free (comp->name);
3015627f7eb2Smrg   gfc_free_expr (comp->val);
3016627f7eb2Smrg   free (comp);
3017627f7eb2Smrg }
3018627f7eb2Smrg 
3019627f7eb2Smrg 
3020627f7eb2Smrg /* Translate the component list into the actual constructor by sorting it in
3021627f7eb2Smrg    the order required; this also checks along the way that each and every
3022627f7eb2Smrg    component actually has an initializer and handles default initializers
3023627f7eb2Smrg    for components without explicit value given.  */
3024627f7eb2Smrg static bool
build_actual_constructor(gfc_structure_ctor_component ** comp_head,gfc_constructor_base * ctor_head,gfc_symbol * sym)3025627f7eb2Smrg build_actual_constructor (gfc_structure_ctor_component **comp_head,
3026627f7eb2Smrg 			  gfc_constructor_base *ctor_head, gfc_symbol *sym)
3027627f7eb2Smrg {
3028627f7eb2Smrg   gfc_structure_ctor_component *comp_iter;
3029627f7eb2Smrg   gfc_component *comp;
3030627f7eb2Smrg 
3031627f7eb2Smrg   for (comp = sym->components; comp; comp = comp->next)
3032627f7eb2Smrg     {
3033627f7eb2Smrg       gfc_structure_ctor_component **next_ptr;
3034627f7eb2Smrg       gfc_expr *value = NULL;
3035627f7eb2Smrg 
3036627f7eb2Smrg       /* Try to find the initializer for the current component by name.  */
3037627f7eb2Smrg       next_ptr = comp_head;
3038627f7eb2Smrg       for (comp_iter = *comp_head; comp_iter; comp_iter = comp_iter->next)
3039627f7eb2Smrg 	{
3040627f7eb2Smrg 	  if (!strcmp (comp_iter->name, comp->name))
3041627f7eb2Smrg 	    break;
3042627f7eb2Smrg 	  next_ptr = &comp_iter->next;
3043627f7eb2Smrg 	}
3044627f7eb2Smrg 
3045627f7eb2Smrg       /* If an extension, try building the parent derived type by building
3046627f7eb2Smrg 	 a value expression for the parent derived type and calling self.  */
3047627f7eb2Smrg       if (!comp_iter && comp == sym->components && sym->attr.extension)
3048627f7eb2Smrg 	{
3049627f7eb2Smrg 	  value = gfc_get_structure_constructor_expr (comp->ts.type,
3050627f7eb2Smrg 						      comp->ts.kind,
3051627f7eb2Smrg 						      &gfc_current_locus);
3052627f7eb2Smrg 	  value->ts = comp->ts;
3053627f7eb2Smrg 
3054627f7eb2Smrg 	  if (!build_actual_constructor (comp_head,
3055627f7eb2Smrg 					 &value->value.constructor,
3056627f7eb2Smrg 					 comp->ts.u.derived))
3057627f7eb2Smrg 	    {
3058627f7eb2Smrg 	      gfc_free_expr (value);
3059627f7eb2Smrg 	      return false;
3060627f7eb2Smrg 	    }
3061627f7eb2Smrg 
3062627f7eb2Smrg 	  gfc_constructor_append_expr (ctor_head, value, NULL);
3063627f7eb2Smrg 	  continue;
3064627f7eb2Smrg 	}
3065627f7eb2Smrg 
30664c3eb207Smrg       /* If it was not found, apply NULL expression to set the component as
30674c3eb207Smrg 	 unallocated. Then try the default initializer if there's any;
3068627f7eb2Smrg 	 otherwise, it's an error unless this is a deferred parameter.  */
3069627f7eb2Smrg       if (!comp_iter)
3070627f7eb2Smrg 	{
30714c3eb207Smrg 	  /* F2018 7.5.10: If an allocatable component has no corresponding
30724c3eb207Smrg 	     component-data-source, then that component has an allocation
30734c3eb207Smrg 	     status of unallocated....  */
30744c3eb207Smrg 	  if (comp->attr.allocatable
3075627f7eb2Smrg 	      || (comp->ts.type == BT_CLASS
3076627f7eb2Smrg 		  && CLASS_DATA (comp)->attr.allocatable))
3077627f7eb2Smrg 	    {
3078627f7eb2Smrg 	      if (!gfc_notify_std (GFC_STD_F2008, "No initializer for "
3079627f7eb2Smrg 				   "allocatable component %qs given in the "
3080627f7eb2Smrg 				   "structure constructor at %C", comp->name))
3081627f7eb2Smrg 		return false;
30824c3eb207Smrg 	      value = gfc_get_null_expr (&gfc_current_locus);
3083627f7eb2Smrg 	    }
30844c3eb207Smrg 	  /* ....(Preceeding sentence) If a component with default
30854c3eb207Smrg 	     initialization has no corresponding component-data-source, then
30864c3eb207Smrg 	     the default initialization is applied to that component.  */
30874c3eb207Smrg 	  else if (comp->initializer)
30884c3eb207Smrg 	    {
30894c3eb207Smrg 	      if (!gfc_notify_std (GFC_STD_F2003, "Structure constructor "
30904c3eb207Smrg 				   "with missing optional arguments at %C"))
30914c3eb207Smrg 		return false;
30924c3eb207Smrg 	      value = gfc_copy_expr (comp->initializer);
30934c3eb207Smrg 	    }
30944c3eb207Smrg 	  /* Do not trap components such as the string length for deferred
30954c3eb207Smrg 	     length character components.  */
3096627f7eb2Smrg 	  else if (!comp->attr.artificial)
3097627f7eb2Smrg 	    {
3098627f7eb2Smrg 	      gfc_error ("No initializer for component %qs given in the"
3099627f7eb2Smrg 			 " structure constructor at %C", comp->name);
3100627f7eb2Smrg 	      return false;
3101627f7eb2Smrg 	    }
3102627f7eb2Smrg 	}
3103627f7eb2Smrg       else
3104627f7eb2Smrg 	value = comp_iter->val;
3105627f7eb2Smrg 
3106627f7eb2Smrg       /* Add the value to the constructor chain built.  */
3107627f7eb2Smrg       gfc_constructor_append_expr (ctor_head, value, NULL);
3108627f7eb2Smrg 
3109627f7eb2Smrg       /* Remove the entry from the component list.  We don't want the expression
3110627f7eb2Smrg 	 value to be free'd, so set it to NULL.  */
3111627f7eb2Smrg       if (comp_iter)
3112627f7eb2Smrg 	{
3113627f7eb2Smrg 	  *next_ptr = comp_iter->next;
3114627f7eb2Smrg 	  comp_iter->val = NULL;
3115627f7eb2Smrg 	  gfc_free_structure_ctor_component (comp_iter);
3116627f7eb2Smrg 	}
3117627f7eb2Smrg     }
3118627f7eb2Smrg   return true;
3119627f7eb2Smrg }
3120627f7eb2Smrg 
3121627f7eb2Smrg 
3122627f7eb2Smrg bool
gfc_convert_to_structure_constructor(gfc_expr * e,gfc_symbol * sym,gfc_expr ** cexpr,gfc_actual_arglist ** arglist,bool parent)3123627f7eb2Smrg gfc_convert_to_structure_constructor (gfc_expr *e, gfc_symbol *sym, gfc_expr **cexpr,
3124627f7eb2Smrg 				      gfc_actual_arglist **arglist,
3125627f7eb2Smrg 				      bool parent)
3126627f7eb2Smrg {
3127627f7eb2Smrg   gfc_actual_arglist *actual;
3128627f7eb2Smrg   gfc_structure_ctor_component *comp_tail, *comp_head, *comp_iter;
3129627f7eb2Smrg   gfc_constructor_base ctor_head = NULL;
3130627f7eb2Smrg   gfc_component *comp; /* Is set NULL when named component is first seen */
3131627f7eb2Smrg   const char* last_name = NULL;
3132627f7eb2Smrg   locus old_locus;
3133627f7eb2Smrg   gfc_expr *expr;
3134627f7eb2Smrg 
3135627f7eb2Smrg   expr = parent ? *cexpr : e;
3136627f7eb2Smrg   old_locus = gfc_current_locus;
3137627f7eb2Smrg   if (parent)
3138627f7eb2Smrg     ; /* gfc_current_locus = *arglist->expr ? ->where;*/
3139627f7eb2Smrg   else
3140627f7eb2Smrg     gfc_current_locus = expr->where;
3141627f7eb2Smrg 
3142627f7eb2Smrg   comp_tail = comp_head = NULL;
3143627f7eb2Smrg 
3144627f7eb2Smrg   if (!parent && sym->attr.abstract)
3145627f7eb2Smrg     {
3146627f7eb2Smrg       gfc_error ("Cannot construct ABSTRACT type %qs at %L",
3147627f7eb2Smrg 		 sym->name, &expr->where);
3148627f7eb2Smrg       goto cleanup;
3149627f7eb2Smrg     }
3150627f7eb2Smrg 
3151627f7eb2Smrg   comp = sym->components;
3152627f7eb2Smrg   actual = parent ? *arglist : expr->value.function.actual;
3153627f7eb2Smrg   for ( ; actual; )
3154627f7eb2Smrg     {
3155627f7eb2Smrg       gfc_component *this_comp = NULL;
3156627f7eb2Smrg 
3157627f7eb2Smrg       if (!comp_head)
3158627f7eb2Smrg 	comp_tail = comp_head = gfc_get_structure_ctor_component ();
3159627f7eb2Smrg       else
3160627f7eb2Smrg 	{
3161627f7eb2Smrg 	  comp_tail->next = gfc_get_structure_ctor_component ();
3162627f7eb2Smrg 	  comp_tail = comp_tail->next;
3163627f7eb2Smrg        	}
3164627f7eb2Smrg       if (actual->name)
3165627f7eb2Smrg 	{
3166627f7eb2Smrg 	  if (!gfc_notify_std (GFC_STD_F2003, "Structure"
3167627f7eb2Smrg 			       " constructor with named arguments at %C"))
3168627f7eb2Smrg 	    goto cleanup;
3169627f7eb2Smrg 
3170627f7eb2Smrg 	  comp_tail->name = xstrdup (actual->name);
3171627f7eb2Smrg 	  last_name = comp_tail->name;
3172627f7eb2Smrg 	  comp = NULL;
3173627f7eb2Smrg 	}
3174627f7eb2Smrg       else
3175627f7eb2Smrg 	{
3176627f7eb2Smrg 	  /* Components without name are not allowed after the first named
3177627f7eb2Smrg 	     component initializer!  */
3178627f7eb2Smrg 	  if (!comp || comp->attr.artificial)
3179627f7eb2Smrg 	    {
3180627f7eb2Smrg 	      if (last_name)
3181627f7eb2Smrg 		gfc_error ("Component initializer without name after component"
3182627f7eb2Smrg 			   " named %s at %L", last_name,
3183627f7eb2Smrg 			   actual->expr ? &actual->expr->where
3184627f7eb2Smrg 					: &gfc_current_locus);
3185627f7eb2Smrg 	      else
3186627f7eb2Smrg 		gfc_error ("Too many components in structure constructor at "
3187627f7eb2Smrg 			   "%L", actual->expr ? &actual->expr->where
3188627f7eb2Smrg 					      : &gfc_current_locus);
3189627f7eb2Smrg 	      goto cleanup;
3190627f7eb2Smrg 	    }
3191627f7eb2Smrg 
3192627f7eb2Smrg 	  comp_tail->name = xstrdup (comp->name);
3193627f7eb2Smrg 	}
3194627f7eb2Smrg 
3195627f7eb2Smrg       /* Find the current component in the structure definition and check
3196627f7eb2Smrg 	     its access is not private.  */
3197627f7eb2Smrg       if (comp)
3198627f7eb2Smrg 	this_comp = gfc_find_component (sym, comp->name, false, false, NULL);
3199627f7eb2Smrg       else
3200627f7eb2Smrg 	{
3201627f7eb2Smrg 	  this_comp = gfc_find_component (sym, (const char *)comp_tail->name,
3202627f7eb2Smrg 					  false, false, NULL);
3203627f7eb2Smrg 	  comp = NULL; /* Reset needed!  */
3204627f7eb2Smrg 	}
3205627f7eb2Smrg 
3206627f7eb2Smrg       /* Here we can check if a component name is given which does not
3207627f7eb2Smrg 	 correspond to any component of the defined structure.  */
3208627f7eb2Smrg       if (!this_comp)
3209627f7eb2Smrg 	goto cleanup;
3210627f7eb2Smrg 
3211627f7eb2Smrg       /* For a constant string constructor, make sure the length is
3212*4ac76180Smrg 	 correct; truncate or fill with blanks if needed.  */
3213627f7eb2Smrg       if (this_comp->ts.type == BT_CHARACTER && !this_comp->attr.allocatable
3214627f7eb2Smrg 	  && this_comp->ts.u.cl && this_comp->ts.u.cl->length
3215627f7eb2Smrg 	  && this_comp->ts.u.cl->length->expr_type == EXPR_CONSTANT
3216*4ac76180Smrg 	  && this_comp->ts.u.cl->length->ts.type == BT_INTEGER
3217627f7eb2Smrg 	  && actual->expr->ts.type == BT_CHARACTER
3218627f7eb2Smrg 	  && actual->expr->expr_type == EXPR_CONSTANT)
3219627f7eb2Smrg 	{
32204c3eb207Smrg 	  ptrdiff_t c, e1;
3221627f7eb2Smrg 	  c = gfc_mpz_get_hwi (this_comp->ts.u.cl->length->value.integer);
32224c3eb207Smrg 	  e1 = actual->expr->value.character.length;
3223627f7eb2Smrg 
32244c3eb207Smrg 	  if (c != e1)
3225627f7eb2Smrg 	    {
3226627f7eb2Smrg 	      ptrdiff_t i, to;
3227627f7eb2Smrg 	      gfc_char_t *dest;
3228627f7eb2Smrg 	      dest = gfc_get_wide_string (c + 1);
3229627f7eb2Smrg 
32304c3eb207Smrg 	      to = e1 < c ? e1 : c;
3231627f7eb2Smrg 	      for (i = 0; i < to; i++)
3232627f7eb2Smrg 		dest[i] = actual->expr->value.character.string[i];
3233627f7eb2Smrg 
32344c3eb207Smrg 	      for (i = e1; i < c; i++)
3235627f7eb2Smrg 		dest[i] = ' ';
3236627f7eb2Smrg 
3237627f7eb2Smrg 	      dest[c] = '\0';
3238627f7eb2Smrg 	      free (actual->expr->value.character.string);
3239627f7eb2Smrg 
3240627f7eb2Smrg 	      actual->expr->value.character.length = c;
3241627f7eb2Smrg 	      actual->expr->value.character.string = dest;
3242627f7eb2Smrg 
32434c3eb207Smrg 	      if (warn_line_truncation && c < e1)
3244627f7eb2Smrg 		gfc_warning_now (OPT_Wcharacter_truncation,
3245627f7eb2Smrg 				 "CHARACTER expression will be truncated "
3246627f7eb2Smrg 				 "in constructor (%ld/%ld) at %L", (long int) c,
32474c3eb207Smrg 				 (long int) e1, &actual->expr->where);
3248627f7eb2Smrg 	    }
3249627f7eb2Smrg 	}
3250627f7eb2Smrg 
3251627f7eb2Smrg       comp_tail->val = actual->expr;
3252627f7eb2Smrg       if (actual->expr != NULL)
3253627f7eb2Smrg 	comp_tail->where = actual->expr->where;
3254627f7eb2Smrg       actual->expr = NULL;
3255627f7eb2Smrg 
3256627f7eb2Smrg       /* Check if this component is already given a value.  */
3257627f7eb2Smrg       for (comp_iter = comp_head; comp_iter != comp_tail;
3258627f7eb2Smrg 	   comp_iter = comp_iter->next)
3259627f7eb2Smrg 	{
3260627f7eb2Smrg 	  gcc_assert (comp_iter);
3261627f7eb2Smrg 	  if (!strcmp (comp_iter->name, comp_tail->name))
3262627f7eb2Smrg 	    {
3263627f7eb2Smrg 	      gfc_error ("Component %qs is initialized twice in the structure"
3264627f7eb2Smrg 			 " constructor at %L", comp_tail->name,
3265627f7eb2Smrg 			 comp_tail->val ? &comp_tail->where
3266627f7eb2Smrg 					: &gfc_current_locus);
3267627f7eb2Smrg 	      goto cleanup;
3268627f7eb2Smrg 	    }
3269627f7eb2Smrg 	}
3270627f7eb2Smrg 
3271627f7eb2Smrg       /* F2008, R457/C725, for PURE C1283.  */
3272627f7eb2Smrg       if (this_comp->attr.pointer && comp_tail->val
3273627f7eb2Smrg 	  && gfc_is_coindexed (comp_tail->val))
3274627f7eb2Smrg      	{
3275627f7eb2Smrg 	  gfc_error ("Coindexed expression to pointer component %qs in "
3276627f7eb2Smrg 		     "structure constructor at %L", comp_tail->name,
3277627f7eb2Smrg 		     &comp_tail->where);
3278627f7eb2Smrg 	  goto cleanup;
3279627f7eb2Smrg 	}
3280627f7eb2Smrg 
3281627f7eb2Smrg           /* If not explicitly a parent constructor, gather up the components
3282627f7eb2Smrg              and build one.  */
3283627f7eb2Smrg           if (comp && comp == sym->components
3284627f7eb2Smrg                 && sym->attr.extension
3285627f7eb2Smrg 		&& comp_tail->val
3286627f7eb2Smrg                 && (!gfc_bt_struct (comp_tail->val->ts.type)
3287627f7eb2Smrg                       ||
3288627f7eb2Smrg                     comp_tail->val->ts.u.derived != this_comp->ts.u.derived))
3289627f7eb2Smrg             {
3290627f7eb2Smrg               bool m;
3291627f7eb2Smrg 	      gfc_actual_arglist *arg_null = NULL;
3292627f7eb2Smrg 
3293627f7eb2Smrg 	      actual->expr = comp_tail->val;
3294627f7eb2Smrg 	      comp_tail->val = NULL;
3295627f7eb2Smrg 
3296627f7eb2Smrg               m = gfc_convert_to_structure_constructor (NULL,
3297627f7eb2Smrg 					comp->ts.u.derived, &comp_tail->val,
3298627f7eb2Smrg 					comp->ts.u.derived->attr.zero_comp
3299627f7eb2Smrg 					  ? &arg_null : &actual, true);
3300627f7eb2Smrg               if (!m)
3301627f7eb2Smrg                 goto cleanup;
3302627f7eb2Smrg 
3303627f7eb2Smrg 	      if (comp->ts.u.derived->attr.zero_comp)
3304627f7eb2Smrg 		{
3305627f7eb2Smrg 		  comp = comp->next;
3306627f7eb2Smrg 		  continue;
3307627f7eb2Smrg 		}
3308627f7eb2Smrg             }
3309627f7eb2Smrg 
3310627f7eb2Smrg       if (comp)
3311627f7eb2Smrg 	comp = comp->next;
3312627f7eb2Smrg       if (parent && !comp)
3313627f7eb2Smrg 	break;
3314627f7eb2Smrg 
3315627f7eb2Smrg       if (actual)
3316627f7eb2Smrg 	actual = actual->next;
3317627f7eb2Smrg     }
3318627f7eb2Smrg 
3319627f7eb2Smrg   if (!build_actual_constructor (&comp_head, &ctor_head, sym))
3320627f7eb2Smrg     goto cleanup;
3321627f7eb2Smrg 
3322627f7eb2Smrg   /* No component should be left, as this should have caused an error in the
3323627f7eb2Smrg      loop constructing the component-list (name that does not correspond to any
3324627f7eb2Smrg      component in the structure definition).  */
3325627f7eb2Smrg   if (comp_head && sym->attr.extension)
3326627f7eb2Smrg     {
3327627f7eb2Smrg       for (comp_iter = comp_head; comp_iter; comp_iter = comp_iter->next)
3328627f7eb2Smrg 	{
3329627f7eb2Smrg 	  gfc_error ("component %qs at %L has already been set by a "
3330627f7eb2Smrg 		     "parent derived type constructor", comp_iter->name,
3331627f7eb2Smrg 		     &comp_iter->where);
3332627f7eb2Smrg 	}
3333627f7eb2Smrg       goto cleanup;
3334627f7eb2Smrg     }
3335627f7eb2Smrg   else
3336627f7eb2Smrg     gcc_assert (!comp_head);
3337627f7eb2Smrg 
3338627f7eb2Smrg   if (parent)
3339627f7eb2Smrg     {
3340627f7eb2Smrg       expr = gfc_get_structure_constructor_expr (BT_DERIVED, 0, &gfc_current_locus);
3341627f7eb2Smrg       expr->ts.u.derived = sym;
3342627f7eb2Smrg       expr->value.constructor = ctor_head;
3343627f7eb2Smrg       *cexpr = expr;
3344627f7eb2Smrg     }
3345627f7eb2Smrg   else
3346627f7eb2Smrg     {
3347627f7eb2Smrg       expr->ts.u.derived = sym;
3348627f7eb2Smrg       expr->ts.kind = 0;
3349627f7eb2Smrg       expr->ts.type = BT_DERIVED;
3350627f7eb2Smrg       expr->value.constructor = ctor_head;
3351627f7eb2Smrg       expr->expr_type = EXPR_STRUCTURE;
3352627f7eb2Smrg     }
3353627f7eb2Smrg 
3354627f7eb2Smrg   gfc_current_locus = old_locus;
3355627f7eb2Smrg   if (parent)
3356627f7eb2Smrg     *arglist = actual;
3357627f7eb2Smrg   return true;
3358627f7eb2Smrg 
3359627f7eb2Smrg   cleanup:
3360627f7eb2Smrg   gfc_current_locus = old_locus;
3361627f7eb2Smrg 
3362627f7eb2Smrg   for (comp_iter = comp_head; comp_iter; )
3363627f7eb2Smrg     {
3364627f7eb2Smrg       gfc_structure_ctor_component *next = comp_iter->next;
3365627f7eb2Smrg       gfc_free_structure_ctor_component (comp_iter);
3366627f7eb2Smrg       comp_iter = next;
3367627f7eb2Smrg     }
3368627f7eb2Smrg   gfc_constructor_free (ctor_head);
3369627f7eb2Smrg 
3370627f7eb2Smrg   return false;
3371627f7eb2Smrg }
3372627f7eb2Smrg 
3373627f7eb2Smrg 
3374627f7eb2Smrg match
gfc_match_structure_constructor(gfc_symbol * sym,gfc_expr ** result)3375627f7eb2Smrg gfc_match_structure_constructor (gfc_symbol *sym, gfc_expr **result)
3376627f7eb2Smrg {
3377627f7eb2Smrg   match m;
3378627f7eb2Smrg   gfc_expr *e;
3379627f7eb2Smrg   gfc_symtree *symtree;
33804c3eb207Smrg   bool t = true;
3381627f7eb2Smrg 
3382627f7eb2Smrg   gfc_get_ha_sym_tree (sym->name, &symtree);
3383627f7eb2Smrg 
3384627f7eb2Smrg   e = gfc_get_expr ();
3385627f7eb2Smrg   e->symtree = symtree;
3386627f7eb2Smrg   e->expr_type = EXPR_FUNCTION;
3387627f7eb2Smrg   e->where = gfc_current_locus;
3388627f7eb2Smrg 
3389627f7eb2Smrg   gcc_assert (gfc_fl_struct (sym->attr.flavor)
3390627f7eb2Smrg 	      && symtree->n.sym->attr.flavor == FL_PROCEDURE);
3391627f7eb2Smrg   e->value.function.esym = sym;
3392627f7eb2Smrg   e->symtree->n.sym->attr.generic = 1;
3393627f7eb2Smrg 
3394627f7eb2Smrg   m = gfc_match_actual_arglist (0, &e->value.function.actual);
3395627f7eb2Smrg   if (m != MATCH_YES)
3396627f7eb2Smrg     {
3397627f7eb2Smrg       gfc_free_expr (e);
3398627f7eb2Smrg       return m;
3399627f7eb2Smrg     }
3400627f7eb2Smrg 
3401627f7eb2Smrg   if (!gfc_convert_to_structure_constructor (e, sym, NULL, NULL, false))
3402627f7eb2Smrg     {
3403627f7eb2Smrg       gfc_free_expr (e);
3404627f7eb2Smrg       return MATCH_ERROR;
3405627f7eb2Smrg     }
3406627f7eb2Smrg 
3407627f7eb2Smrg   /* If a structure constructor is in a DATA statement, then each entity
3408627f7eb2Smrg      in the structure constructor must be a constant.  Try to reduce the
3409627f7eb2Smrg      expression here.  */
3410627f7eb2Smrg   if (gfc_in_match_data ())
34114c3eb207Smrg     t = gfc_reduce_init_expr (e);
3412627f7eb2Smrg 
34134c3eb207Smrg   if (t)
34144c3eb207Smrg     {
3415627f7eb2Smrg       *result = e;
3416627f7eb2Smrg       return MATCH_YES;
3417627f7eb2Smrg     }
34184c3eb207Smrg   else
34194c3eb207Smrg     {
34204c3eb207Smrg       gfc_free_expr (e);
34214c3eb207Smrg       return MATCH_ERROR;
34224c3eb207Smrg     }
34234c3eb207Smrg }
3424627f7eb2Smrg 
3425627f7eb2Smrg 
3426627f7eb2Smrg /* If the symbol is an implicit do loop index and implicitly typed,
3427627f7eb2Smrg    it should not be host associated.  Provide a symtree from the
3428627f7eb2Smrg    current namespace.  */
3429627f7eb2Smrg static match
check_for_implicit_index(gfc_symtree ** st,gfc_symbol ** sym)3430627f7eb2Smrg check_for_implicit_index (gfc_symtree **st, gfc_symbol **sym)
3431627f7eb2Smrg {
3432627f7eb2Smrg   if ((*sym)->attr.flavor == FL_VARIABLE
3433627f7eb2Smrg       && (*sym)->ns != gfc_current_ns
3434627f7eb2Smrg       && (*sym)->attr.implied_index
3435627f7eb2Smrg       && (*sym)->attr.implicit_type
3436627f7eb2Smrg       && !(*sym)->attr.use_assoc)
3437627f7eb2Smrg     {
3438627f7eb2Smrg       int i;
3439627f7eb2Smrg       i = gfc_get_sym_tree ((*sym)->name, NULL, st, false);
3440627f7eb2Smrg       if (i)
3441627f7eb2Smrg 	return MATCH_ERROR;
3442627f7eb2Smrg       *sym = (*st)->n.sym;
3443627f7eb2Smrg     }
3444627f7eb2Smrg   return MATCH_YES;
3445627f7eb2Smrg }
3446627f7eb2Smrg 
3447627f7eb2Smrg 
3448627f7eb2Smrg /* Procedure pointer as function result: Replace the function symbol by the
3449627f7eb2Smrg    auto-generated hidden result variable named "ppr@".  */
3450627f7eb2Smrg 
3451627f7eb2Smrg static bool
replace_hidden_procptr_result(gfc_symbol ** sym,gfc_symtree ** st)3452627f7eb2Smrg replace_hidden_procptr_result (gfc_symbol **sym, gfc_symtree **st)
3453627f7eb2Smrg {
3454627f7eb2Smrg   /* Check for procedure pointer result variable.  */
3455627f7eb2Smrg   if ((*sym)->attr.function && !(*sym)->attr.external
3456627f7eb2Smrg       && (*sym)->result && (*sym)->result != *sym
3457627f7eb2Smrg       && (*sym)->result->attr.proc_pointer
3458627f7eb2Smrg       && (*sym) == gfc_current_ns->proc_name
3459627f7eb2Smrg       && (*sym) == (*sym)->result->ns->proc_name
3460627f7eb2Smrg       && strcmp ("ppr@", (*sym)->result->name) == 0)
3461627f7eb2Smrg     {
3462627f7eb2Smrg       /* Automatic replacement with "hidden" result variable.  */
3463627f7eb2Smrg       (*sym)->result->attr.referenced = (*sym)->attr.referenced;
3464627f7eb2Smrg       *sym = (*sym)->result;
3465627f7eb2Smrg       *st = gfc_find_symtree ((*sym)->ns->sym_root, (*sym)->name);
3466627f7eb2Smrg       return true;
3467627f7eb2Smrg     }
3468627f7eb2Smrg   return false;
3469627f7eb2Smrg }
3470627f7eb2Smrg 
3471627f7eb2Smrg 
3472627f7eb2Smrg /* Matches a variable name followed by anything that might follow it--
3473627f7eb2Smrg    array reference, argument list of a function, etc.  */
3474627f7eb2Smrg 
3475627f7eb2Smrg match
gfc_match_rvalue(gfc_expr ** result)3476627f7eb2Smrg gfc_match_rvalue (gfc_expr **result)
3477627f7eb2Smrg {
3478627f7eb2Smrg   gfc_actual_arglist *actual_arglist;
3479627f7eb2Smrg   char name[GFC_MAX_SYMBOL_LEN + 1], argname[GFC_MAX_SYMBOL_LEN + 1];
3480627f7eb2Smrg   gfc_state_data *st;
3481627f7eb2Smrg   gfc_symbol *sym;
3482627f7eb2Smrg   gfc_symtree *symtree;
3483627f7eb2Smrg   locus where, old_loc;
3484627f7eb2Smrg   gfc_expr *e;
3485627f7eb2Smrg   match m, m2;
3486627f7eb2Smrg   int i;
3487627f7eb2Smrg   gfc_typespec *ts;
3488627f7eb2Smrg   bool implicit_char;
3489627f7eb2Smrg   gfc_ref *ref;
3490627f7eb2Smrg 
3491627f7eb2Smrg   m = gfc_match ("%%loc");
3492627f7eb2Smrg   if (m == MATCH_YES)
3493627f7eb2Smrg     {
3494627f7eb2Smrg       if (!gfc_notify_std (GFC_STD_LEGACY, "%%LOC() as an rvalue at %C"))
3495627f7eb2Smrg         return MATCH_ERROR;
3496627f7eb2Smrg       strncpy (name, "loc", 4);
3497627f7eb2Smrg     }
3498627f7eb2Smrg 
3499627f7eb2Smrg   else
3500627f7eb2Smrg     {
3501627f7eb2Smrg       m = gfc_match_name (name);
3502627f7eb2Smrg       if (m != MATCH_YES)
3503627f7eb2Smrg         return m;
3504627f7eb2Smrg     }
3505627f7eb2Smrg 
3506627f7eb2Smrg   /* Check if the symbol exists.  */
3507627f7eb2Smrg   if (gfc_find_sym_tree (name, NULL, 1, &symtree))
3508627f7eb2Smrg     return MATCH_ERROR;
3509627f7eb2Smrg 
3510627f7eb2Smrg   /* If the symbol doesn't exist, create it unless the name matches a FL_STRUCT
3511627f7eb2Smrg      type. For derived types we create a generic symbol which links to the
3512627f7eb2Smrg      derived type symbol; STRUCTUREs are simpler and must not conflict with
3513627f7eb2Smrg      variables.  */
3514627f7eb2Smrg   if (!symtree)
3515627f7eb2Smrg     if (gfc_find_sym_tree (gfc_dt_upper_string (name), NULL, 1, &symtree))
3516627f7eb2Smrg       return MATCH_ERROR;
3517627f7eb2Smrg   if (!symtree || symtree->n.sym->attr.flavor != FL_STRUCT)
3518627f7eb2Smrg     {
3519627f7eb2Smrg       if (gfc_find_state (COMP_INTERFACE)
3520627f7eb2Smrg           && !gfc_current_ns->has_import_set)
3521627f7eb2Smrg         i = gfc_get_sym_tree (name, NULL, &symtree, false);
3522627f7eb2Smrg       else
3523627f7eb2Smrg         i = gfc_get_ha_sym_tree (name, &symtree);
3524627f7eb2Smrg       if (i)
3525627f7eb2Smrg         return MATCH_ERROR;
3526627f7eb2Smrg     }
3527627f7eb2Smrg 
3528627f7eb2Smrg 
3529627f7eb2Smrg   sym = symtree->n.sym;
3530627f7eb2Smrg   e = NULL;
3531627f7eb2Smrg   where = gfc_current_locus;
3532627f7eb2Smrg 
3533627f7eb2Smrg   replace_hidden_procptr_result (&sym, &symtree);
3534627f7eb2Smrg 
3535627f7eb2Smrg   /* If this is an implicit do loop index and implicitly typed,
3536627f7eb2Smrg      it should not be host associated.  */
3537627f7eb2Smrg   m = check_for_implicit_index (&symtree, &sym);
3538627f7eb2Smrg   if (m != MATCH_YES)
3539627f7eb2Smrg     return m;
3540627f7eb2Smrg 
3541627f7eb2Smrg   gfc_set_sym_referenced (sym);
3542627f7eb2Smrg   sym->attr.implied_index = 0;
3543627f7eb2Smrg 
3544627f7eb2Smrg   if (sym->attr.function && sym->result == sym)
3545627f7eb2Smrg     {
3546627f7eb2Smrg       /* See if this is a directly recursive function call.  */
3547627f7eb2Smrg       gfc_gobble_whitespace ();
3548627f7eb2Smrg       if (sym->attr.recursive
3549627f7eb2Smrg 	  && gfc_peek_ascii_char () == '('
3550627f7eb2Smrg 	  && gfc_current_ns->proc_name == sym
3551627f7eb2Smrg 	  && !sym->attr.dimension)
3552627f7eb2Smrg 	{
3553627f7eb2Smrg 	  gfc_error ("%qs at %C is the name of a recursive function "
3554627f7eb2Smrg 		     "and so refers to the result variable. Use an "
3555627f7eb2Smrg 		     "explicit RESULT variable for direct recursion "
3556627f7eb2Smrg 		     "(12.5.2.1)", sym->name);
3557627f7eb2Smrg 	  return MATCH_ERROR;
3558627f7eb2Smrg 	}
3559627f7eb2Smrg 
3560627f7eb2Smrg       if (gfc_is_function_return_value (sym, gfc_current_ns))
3561627f7eb2Smrg 	goto variable;
3562627f7eb2Smrg 
3563627f7eb2Smrg       if (sym->attr.entry
3564627f7eb2Smrg 	  && (sym->ns == gfc_current_ns
3565627f7eb2Smrg 	      || sym->ns == gfc_current_ns->parent))
3566627f7eb2Smrg 	{
3567627f7eb2Smrg 	  gfc_entry_list *el = NULL;
3568627f7eb2Smrg 
3569627f7eb2Smrg 	  for (el = sym->ns->entries; el; el = el->next)
3570627f7eb2Smrg 	    if (sym == el->sym)
3571627f7eb2Smrg 	      goto variable;
3572627f7eb2Smrg 	}
3573627f7eb2Smrg     }
3574627f7eb2Smrg 
3575627f7eb2Smrg   if (gfc_matching_procptr_assignment)
35764c3eb207Smrg     {
35774c3eb207Smrg       /* It can be a procedure or a derived-type procedure or a not-yet-known
35784c3eb207Smrg 	 type.  */
35794c3eb207Smrg       if (sym->attr.flavor != FL_UNKNOWN
35804c3eb207Smrg 	  && sym->attr.flavor != FL_PROCEDURE
35814c3eb207Smrg 	  && sym->attr.flavor != FL_PARAMETER
35824c3eb207Smrg 	  && sym->attr.flavor != FL_VARIABLE)
35834c3eb207Smrg 	{
35844c3eb207Smrg 	  gfc_error ("Symbol at %C is not appropriate for an expression");
35854c3eb207Smrg 	  return MATCH_ERROR;
35864c3eb207Smrg 	}
3587627f7eb2Smrg       goto procptr0;
35884c3eb207Smrg     }
3589627f7eb2Smrg 
3590627f7eb2Smrg   if (sym->attr.function || sym->attr.external || sym->attr.intrinsic)
3591627f7eb2Smrg     goto function0;
3592627f7eb2Smrg 
3593627f7eb2Smrg   if (sym->attr.generic)
3594627f7eb2Smrg     goto generic_function;
3595627f7eb2Smrg 
3596627f7eb2Smrg   switch (sym->attr.flavor)
3597627f7eb2Smrg     {
3598627f7eb2Smrg     case FL_VARIABLE:
3599627f7eb2Smrg     variable:
3600627f7eb2Smrg       e = gfc_get_expr ();
3601627f7eb2Smrg 
3602627f7eb2Smrg       e->expr_type = EXPR_VARIABLE;
3603627f7eb2Smrg       e->symtree = symtree;
3604627f7eb2Smrg 
3605627f7eb2Smrg       m = gfc_match_varspec (e, 0, false, true);
3606627f7eb2Smrg       break;
3607627f7eb2Smrg 
3608627f7eb2Smrg     case FL_PARAMETER:
3609627f7eb2Smrg       /* A statement of the form "REAL, parameter :: a(0:10) = 1" will
3610627f7eb2Smrg 	 end up here.  Unfortunately, sym->value->expr_type is set to
3611627f7eb2Smrg 	 EXPR_CONSTANT, and so the if () branch would be followed without
3612627f7eb2Smrg 	 the !sym->as check.  */
3613627f7eb2Smrg       if (sym->value && sym->value->expr_type != EXPR_ARRAY && !sym->as)
3614627f7eb2Smrg 	e = gfc_copy_expr (sym->value);
3615627f7eb2Smrg       else
3616627f7eb2Smrg 	{
3617627f7eb2Smrg 	  e = gfc_get_expr ();
3618627f7eb2Smrg 	  e->expr_type = EXPR_VARIABLE;
3619627f7eb2Smrg 	}
3620627f7eb2Smrg 
3621627f7eb2Smrg       e->symtree = symtree;
3622627f7eb2Smrg       m = gfc_match_varspec (e, 0, false, true);
3623627f7eb2Smrg 
3624627f7eb2Smrg       if (sym->ts.is_c_interop || sym->ts.is_iso_c)
3625627f7eb2Smrg 	break;
3626627f7eb2Smrg 
3627627f7eb2Smrg       /* Variable array references to derived type parameters cause
3628627f7eb2Smrg 	 all sorts of headaches in simplification. Treating such
3629627f7eb2Smrg 	 expressions as variable works just fine for all array
3630627f7eb2Smrg 	 references.  */
3631627f7eb2Smrg       if (sym->value && sym->ts.type == BT_DERIVED && e->ref)
3632627f7eb2Smrg 	{
3633627f7eb2Smrg 	  for (ref = e->ref; ref; ref = ref->next)
3634627f7eb2Smrg 	    if (ref->type == REF_ARRAY)
3635627f7eb2Smrg 	      break;
3636627f7eb2Smrg 
3637627f7eb2Smrg 	  if (ref == NULL || ref->u.ar.type == AR_FULL)
3638627f7eb2Smrg 	    break;
3639627f7eb2Smrg 
3640627f7eb2Smrg 	  ref = e->ref;
3641627f7eb2Smrg 	  e->ref = NULL;
3642627f7eb2Smrg 	  gfc_free_expr (e);
3643627f7eb2Smrg 	  e = gfc_get_expr ();
3644627f7eb2Smrg 	  e->expr_type = EXPR_VARIABLE;
3645627f7eb2Smrg 	  e->symtree = symtree;
3646627f7eb2Smrg 	  e->ref = ref;
3647627f7eb2Smrg 	}
3648627f7eb2Smrg 
3649627f7eb2Smrg       break;
3650627f7eb2Smrg 
3651627f7eb2Smrg     case FL_STRUCT:
3652627f7eb2Smrg     case FL_DERIVED:
3653627f7eb2Smrg       sym = gfc_use_derived (sym);
3654627f7eb2Smrg       if (sym == NULL)
3655627f7eb2Smrg 	m = MATCH_ERROR;
3656627f7eb2Smrg       else
3657627f7eb2Smrg 	goto generic_function;
3658627f7eb2Smrg       break;
3659627f7eb2Smrg 
3660627f7eb2Smrg     /* If we're here, then the name is known to be the name of a
3661627f7eb2Smrg        procedure, yet it is not sure to be the name of a function.  */
3662627f7eb2Smrg     case FL_PROCEDURE:
3663627f7eb2Smrg 
3664627f7eb2Smrg     /* Procedure Pointer Assignments.  */
3665627f7eb2Smrg     procptr0:
3666627f7eb2Smrg       if (gfc_matching_procptr_assignment)
3667627f7eb2Smrg 	{
3668627f7eb2Smrg 	  gfc_gobble_whitespace ();
3669627f7eb2Smrg 	  if (!sym->attr.dimension && gfc_peek_ascii_char () == '(')
3670627f7eb2Smrg 	    /* Parse functions returning a procptr.  */
3671627f7eb2Smrg 	    goto function0;
3672627f7eb2Smrg 
3673627f7eb2Smrg 	  e = gfc_get_expr ();
3674627f7eb2Smrg 	  e->expr_type = EXPR_VARIABLE;
3675627f7eb2Smrg 	  e->symtree = symtree;
3676627f7eb2Smrg 	  m = gfc_match_varspec (e, 0, false, true);
3677627f7eb2Smrg 	  if (!e->ref && sym->attr.flavor == FL_UNKNOWN
3678627f7eb2Smrg 	      && sym->ts.type == BT_UNKNOWN
3679627f7eb2Smrg 	      && !gfc_add_flavor (&sym->attr, FL_PROCEDURE, sym->name, NULL))
3680627f7eb2Smrg 	    {
3681627f7eb2Smrg 	      m = MATCH_ERROR;
3682627f7eb2Smrg 	      break;
3683627f7eb2Smrg 	    }
3684627f7eb2Smrg 	  break;
3685627f7eb2Smrg 	}
3686627f7eb2Smrg 
3687627f7eb2Smrg       if (sym->attr.subroutine)
3688627f7eb2Smrg 	{
3689627f7eb2Smrg 	  gfc_error ("Unexpected use of subroutine name %qs at %C",
3690627f7eb2Smrg 		     sym->name);
3691627f7eb2Smrg 	  m = MATCH_ERROR;
3692627f7eb2Smrg 	  break;
3693627f7eb2Smrg 	}
3694627f7eb2Smrg 
3695627f7eb2Smrg       /* At this point, the name has to be a non-statement function.
3696627f7eb2Smrg 	 If the name is the same as the current function being
3697627f7eb2Smrg 	 compiled, then we have a variable reference (to the function
3698627f7eb2Smrg 	 result) if the name is non-recursive.  */
3699627f7eb2Smrg 
3700627f7eb2Smrg       st = gfc_enclosing_unit (NULL);
3701627f7eb2Smrg 
3702627f7eb2Smrg       if (st != NULL
3703627f7eb2Smrg 	  && st->state == COMP_FUNCTION
3704627f7eb2Smrg 	  && st->sym == sym
3705627f7eb2Smrg 	  && !sym->attr.recursive)
3706627f7eb2Smrg 	{
3707627f7eb2Smrg 	  e = gfc_get_expr ();
3708627f7eb2Smrg 	  e->symtree = symtree;
3709627f7eb2Smrg 	  e->expr_type = EXPR_VARIABLE;
3710627f7eb2Smrg 
3711627f7eb2Smrg 	  m = gfc_match_varspec (e, 0, false, true);
3712627f7eb2Smrg 	  break;
3713627f7eb2Smrg 	}
3714627f7eb2Smrg 
3715627f7eb2Smrg     /* Match a function reference.  */
3716627f7eb2Smrg     function0:
3717627f7eb2Smrg       m = gfc_match_actual_arglist (0, &actual_arglist);
3718627f7eb2Smrg       if (m == MATCH_NO)
3719627f7eb2Smrg 	{
3720627f7eb2Smrg 	  if (sym->attr.proc == PROC_ST_FUNCTION)
3721627f7eb2Smrg 	    gfc_error ("Statement function %qs requires argument list at %C",
3722627f7eb2Smrg 		       sym->name);
3723627f7eb2Smrg 	  else
3724627f7eb2Smrg 	    gfc_error ("Function %qs requires an argument list at %C",
3725627f7eb2Smrg 		       sym->name);
3726627f7eb2Smrg 
3727627f7eb2Smrg 	  m = MATCH_ERROR;
3728627f7eb2Smrg 	  break;
3729627f7eb2Smrg 	}
3730627f7eb2Smrg 
3731627f7eb2Smrg       if (m != MATCH_YES)
3732627f7eb2Smrg 	{
3733627f7eb2Smrg 	  m = MATCH_ERROR;
3734627f7eb2Smrg 	  break;
3735627f7eb2Smrg 	}
3736627f7eb2Smrg 
3737627f7eb2Smrg       gfc_get_ha_sym_tree (name, &symtree);	/* Can't fail */
3738627f7eb2Smrg       sym = symtree->n.sym;
3739627f7eb2Smrg 
3740627f7eb2Smrg       replace_hidden_procptr_result (&sym, &symtree);
3741627f7eb2Smrg 
3742627f7eb2Smrg       e = gfc_get_expr ();
3743627f7eb2Smrg       e->symtree = symtree;
3744627f7eb2Smrg       e->expr_type = EXPR_FUNCTION;
3745627f7eb2Smrg       e->value.function.actual = actual_arglist;
3746627f7eb2Smrg       e->where = gfc_current_locus;
3747627f7eb2Smrg 
3748627f7eb2Smrg       if (sym->ts.type == BT_CLASS && sym->attr.class_ok
3749627f7eb2Smrg 	  && CLASS_DATA (sym)->as)
3750627f7eb2Smrg 	e->rank = CLASS_DATA (sym)->as->rank;
3751627f7eb2Smrg       else if (sym->as != NULL)
3752627f7eb2Smrg 	e->rank = sym->as->rank;
3753627f7eb2Smrg 
3754627f7eb2Smrg       if (!sym->attr.function
3755627f7eb2Smrg 	  && !gfc_add_function (&sym->attr, sym->name, NULL))
3756627f7eb2Smrg 	{
3757627f7eb2Smrg 	  m = MATCH_ERROR;
3758627f7eb2Smrg 	  break;
3759627f7eb2Smrg 	}
3760627f7eb2Smrg 
3761627f7eb2Smrg       /* Check here for the existence of at least one argument for the
3762627f7eb2Smrg          iso_c_binding functions C_LOC, C_FUNLOC, and C_ASSOCIATED.  The
3763627f7eb2Smrg          argument(s) given will be checked in gfc_iso_c_func_interface,
3764627f7eb2Smrg          during resolution of the function call.  */
3765627f7eb2Smrg       if (sym->attr.is_iso_c == 1
3766627f7eb2Smrg 	  && (sym->from_intmod == INTMOD_ISO_C_BINDING
3767627f7eb2Smrg 	      && (sym->intmod_sym_id == ISOCBINDING_LOC
3768627f7eb2Smrg 		  || sym->intmod_sym_id == ISOCBINDING_FUNLOC
3769627f7eb2Smrg 		  || sym->intmod_sym_id == ISOCBINDING_ASSOCIATED)))
3770627f7eb2Smrg         {
3771627f7eb2Smrg           /* make sure we were given a param */
3772627f7eb2Smrg           if (actual_arglist == NULL)
3773627f7eb2Smrg             {
3774627f7eb2Smrg               gfc_error ("Missing argument to %qs at %C", sym->name);
3775627f7eb2Smrg               m = MATCH_ERROR;
3776627f7eb2Smrg               break;
3777627f7eb2Smrg             }
3778627f7eb2Smrg         }
3779627f7eb2Smrg 
3780627f7eb2Smrg       if (sym->result == NULL)
3781627f7eb2Smrg 	sym->result = sym;
3782627f7eb2Smrg 
3783627f7eb2Smrg       gfc_gobble_whitespace ();
3784627f7eb2Smrg       /* F08:C612.  */
3785627f7eb2Smrg       if (gfc_peek_ascii_char() == '%')
3786627f7eb2Smrg 	{
3787627f7eb2Smrg 	  gfc_error ("The leftmost part-ref in a data-ref cannot be a "
3788627f7eb2Smrg 		     "function reference at %C");
3789627f7eb2Smrg 	  m = MATCH_ERROR;
37904c3eb207Smrg 	  break;
3791627f7eb2Smrg 	}
3792627f7eb2Smrg 
3793627f7eb2Smrg       m = MATCH_YES;
3794627f7eb2Smrg       break;
3795627f7eb2Smrg 
3796627f7eb2Smrg     case FL_UNKNOWN:
3797627f7eb2Smrg 
3798627f7eb2Smrg       /* Special case for derived type variables that get their types
3799627f7eb2Smrg 	 via an IMPLICIT statement.  This can't wait for the
3800627f7eb2Smrg 	 resolution phase.  */
3801627f7eb2Smrg 
3802627f7eb2Smrg       old_loc = gfc_current_locus;
3803627f7eb2Smrg       if (gfc_match_member_sep (sym) == MATCH_YES
3804627f7eb2Smrg 	  && sym->ts.type == BT_UNKNOWN
3805627f7eb2Smrg 	  && gfc_get_default_type (sym->name, sym->ns)->type == BT_DERIVED)
3806627f7eb2Smrg 	gfc_set_default_type (sym, 0, sym->ns);
3807627f7eb2Smrg       gfc_current_locus = old_loc;
3808627f7eb2Smrg 
3809627f7eb2Smrg       /* If the symbol has a (co)dimension attribute, the expression is a
3810627f7eb2Smrg 	 variable.  */
3811627f7eb2Smrg 
3812627f7eb2Smrg       if (sym->attr.dimension || sym->attr.codimension)
3813627f7eb2Smrg 	{
3814627f7eb2Smrg 	  if (!gfc_add_flavor (&sym->attr, FL_VARIABLE, sym->name, NULL))
3815627f7eb2Smrg 	    {
3816627f7eb2Smrg 	      m = MATCH_ERROR;
3817627f7eb2Smrg 	      break;
3818627f7eb2Smrg 	    }
3819627f7eb2Smrg 
3820627f7eb2Smrg 	  e = gfc_get_expr ();
3821627f7eb2Smrg 	  e->symtree = symtree;
3822627f7eb2Smrg 	  e->expr_type = EXPR_VARIABLE;
3823627f7eb2Smrg 	  m = gfc_match_varspec (e, 0, false, true);
3824627f7eb2Smrg 	  break;
3825627f7eb2Smrg 	}
3826627f7eb2Smrg 
3827627f7eb2Smrg       if (sym->ts.type == BT_CLASS && sym->attr.class_ok
3828627f7eb2Smrg 	  && (CLASS_DATA (sym)->attr.dimension
3829627f7eb2Smrg 	      || CLASS_DATA (sym)->attr.codimension))
3830627f7eb2Smrg 	{
3831627f7eb2Smrg 	  if (!gfc_add_flavor (&sym->attr, FL_VARIABLE, sym->name, NULL))
3832627f7eb2Smrg 	    {
3833627f7eb2Smrg 	      m = MATCH_ERROR;
3834627f7eb2Smrg 	      break;
3835627f7eb2Smrg 	    }
3836627f7eb2Smrg 
3837627f7eb2Smrg 	  e = gfc_get_expr ();
3838627f7eb2Smrg 	  e->symtree = symtree;
3839627f7eb2Smrg 	  e->expr_type = EXPR_VARIABLE;
3840627f7eb2Smrg 	  m = gfc_match_varspec (e, 0, false, true);
3841627f7eb2Smrg 	  break;
3842627f7eb2Smrg 	}
3843627f7eb2Smrg 
3844627f7eb2Smrg       /* Name is not an array, so we peek to see if a '(' implies a
3845627f7eb2Smrg 	 function call or a substring reference.  Otherwise the
3846627f7eb2Smrg 	 variable is just a scalar.  */
3847627f7eb2Smrg 
3848627f7eb2Smrg       gfc_gobble_whitespace ();
3849627f7eb2Smrg       if (gfc_peek_ascii_char () != '(')
3850627f7eb2Smrg 	{
3851627f7eb2Smrg 	  /* Assume a scalar variable */
3852627f7eb2Smrg 	  e = gfc_get_expr ();
3853627f7eb2Smrg 	  e->symtree = symtree;
3854627f7eb2Smrg 	  e->expr_type = EXPR_VARIABLE;
3855627f7eb2Smrg 
3856627f7eb2Smrg 	  if (!gfc_add_flavor (&sym->attr, FL_VARIABLE, sym->name, NULL))
3857627f7eb2Smrg 	    {
3858627f7eb2Smrg 	      m = MATCH_ERROR;
3859627f7eb2Smrg 	      break;
3860627f7eb2Smrg 	    }
3861627f7eb2Smrg 
3862627f7eb2Smrg 	  /*FIXME:??? gfc_match_varspec does set this for us: */
3863627f7eb2Smrg 	  e->ts = sym->ts;
3864627f7eb2Smrg 	  m = gfc_match_varspec (e, 0, false, true);
3865627f7eb2Smrg 	  break;
3866627f7eb2Smrg 	}
3867627f7eb2Smrg 
3868627f7eb2Smrg       /* See if this is a function reference with a keyword argument
3869627f7eb2Smrg 	 as first argument. We do this because otherwise a spurious
3870627f7eb2Smrg 	 symbol would end up in the symbol table.  */
3871627f7eb2Smrg 
3872627f7eb2Smrg       old_loc = gfc_current_locus;
3873627f7eb2Smrg       m2 = gfc_match (" ( %n =", argname);
3874627f7eb2Smrg       gfc_current_locus = old_loc;
3875627f7eb2Smrg 
3876627f7eb2Smrg       e = gfc_get_expr ();
3877627f7eb2Smrg       e->symtree = symtree;
3878627f7eb2Smrg 
3879627f7eb2Smrg       if (m2 != MATCH_YES)
3880627f7eb2Smrg 	{
3881627f7eb2Smrg 	  /* Try to figure out whether we're dealing with a character type.
3882627f7eb2Smrg 	     We're peeking ahead here, because we don't want to call
3883627f7eb2Smrg 	     match_substring if we're dealing with an implicitly typed
3884627f7eb2Smrg 	     non-character variable.  */
3885627f7eb2Smrg 	  implicit_char = false;
3886627f7eb2Smrg 	  if (sym->ts.type == BT_UNKNOWN)
3887627f7eb2Smrg 	    {
3888627f7eb2Smrg 	      ts = gfc_get_default_type (sym->name, NULL);
3889627f7eb2Smrg 	      if (ts->type == BT_CHARACTER)
3890627f7eb2Smrg 		implicit_char = true;
3891627f7eb2Smrg 	    }
3892627f7eb2Smrg 
3893627f7eb2Smrg 	  /* See if this could possibly be a substring reference of a name
3894627f7eb2Smrg 	     that we're not sure is a variable yet.  */
3895627f7eb2Smrg 
3896627f7eb2Smrg 	  if ((implicit_char || sym->ts.type == BT_CHARACTER)
3897627f7eb2Smrg 	      && match_substring (sym->ts.u.cl, 0, &e->ref, false) == MATCH_YES)
3898627f7eb2Smrg 	    {
3899627f7eb2Smrg 
3900627f7eb2Smrg 	      e->expr_type = EXPR_VARIABLE;
3901627f7eb2Smrg 
3902627f7eb2Smrg 	      if (sym->attr.flavor != FL_VARIABLE
3903627f7eb2Smrg 		  && !gfc_add_flavor (&sym->attr, FL_VARIABLE,
3904627f7eb2Smrg 				      sym->name, NULL))
3905627f7eb2Smrg 		{
3906627f7eb2Smrg 		  m = MATCH_ERROR;
3907627f7eb2Smrg 		  break;
3908627f7eb2Smrg 		}
3909627f7eb2Smrg 
3910627f7eb2Smrg 	      if (sym->ts.type == BT_UNKNOWN
3911627f7eb2Smrg 		  && !gfc_set_default_type (sym, 1, NULL))
3912627f7eb2Smrg 		{
3913627f7eb2Smrg 		  m = MATCH_ERROR;
3914627f7eb2Smrg 		  break;
3915627f7eb2Smrg 		}
3916627f7eb2Smrg 
3917627f7eb2Smrg 	      e->ts = sym->ts;
3918627f7eb2Smrg 	      if (e->ref)
3919627f7eb2Smrg 		e->ts.u.cl = NULL;
3920627f7eb2Smrg 	      m = MATCH_YES;
3921627f7eb2Smrg 	      break;
3922627f7eb2Smrg 	    }
3923627f7eb2Smrg 	}
3924627f7eb2Smrg 
3925627f7eb2Smrg       /* Give up, assume we have a function.  */
3926627f7eb2Smrg 
3927627f7eb2Smrg       gfc_get_sym_tree (name, NULL, &symtree, false);	/* Can't fail */
3928627f7eb2Smrg       sym = symtree->n.sym;
3929627f7eb2Smrg       e->expr_type = EXPR_FUNCTION;
3930627f7eb2Smrg 
3931627f7eb2Smrg       if (!sym->attr.function
3932627f7eb2Smrg 	  && !gfc_add_function (&sym->attr, sym->name, NULL))
3933627f7eb2Smrg 	{
3934627f7eb2Smrg 	  m = MATCH_ERROR;
3935627f7eb2Smrg 	  break;
3936627f7eb2Smrg 	}
3937627f7eb2Smrg 
3938627f7eb2Smrg       sym->result = sym;
3939627f7eb2Smrg 
3940627f7eb2Smrg       m = gfc_match_actual_arglist (0, &e->value.function.actual);
3941627f7eb2Smrg       if (m == MATCH_NO)
3942627f7eb2Smrg 	gfc_error ("Missing argument list in function %qs at %C", sym->name);
3943627f7eb2Smrg 
3944627f7eb2Smrg       if (m != MATCH_YES)
3945627f7eb2Smrg 	{
3946627f7eb2Smrg 	  m = MATCH_ERROR;
3947627f7eb2Smrg 	  break;
3948627f7eb2Smrg 	}
3949627f7eb2Smrg 
3950627f7eb2Smrg       /* If our new function returns a character, array or structure
3951627f7eb2Smrg 	 type, it might have subsequent references.  */
3952627f7eb2Smrg 
3953627f7eb2Smrg       m = gfc_match_varspec (e, 0, false, true);
3954627f7eb2Smrg       if (m == MATCH_NO)
3955627f7eb2Smrg 	m = MATCH_YES;
3956627f7eb2Smrg 
3957627f7eb2Smrg       break;
3958627f7eb2Smrg 
3959627f7eb2Smrg     generic_function:
3960627f7eb2Smrg       /* Look for symbol first; if not found, look for STRUCTURE type symbol
3961627f7eb2Smrg          specially. Creates a generic symbol for derived types.  */
3962627f7eb2Smrg       gfc_find_sym_tree (name, NULL, 1, &symtree);
3963627f7eb2Smrg       if (!symtree)
3964627f7eb2Smrg         gfc_find_sym_tree (gfc_dt_upper_string (name), NULL, 1, &symtree);
3965627f7eb2Smrg       if (!symtree || symtree->n.sym->attr.flavor != FL_STRUCT)
3966627f7eb2Smrg         gfc_get_sym_tree (name, NULL, &symtree, false); /* Can't fail */
3967627f7eb2Smrg 
3968627f7eb2Smrg       e = gfc_get_expr ();
3969627f7eb2Smrg       e->symtree = symtree;
3970627f7eb2Smrg       e->expr_type = EXPR_FUNCTION;
3971627f7eb2Smrg 
3972627f7eb2Smrg       if (gfc_fl_struct (sym->attr.flavor))
3973627f7eb2Smrg 	{
3974627f7eb2Smrg 	  e->value.function.esym = sym;
3975627f7eb2Smrg 	  e->symtree->n.sym->attr.generic = 1;
3976627f7eb2Smrg 	}
3977627f7eb2Smrg 
3978627f7eb2Smrg       m = gfc_match_actual_arglist (0, &e->value.function.actual);
3979627f7eb2Smrg       break;
3980627f7eb2Smrg 
3981627f7eb2Smrg     case FL_NAMELIST:
3982627f7eb2Smrg       m = MATCH_ERROR;
3983627f7eb2Smrg       break;
3984627f7eb2Smrg 
3985627f7eb2Smrg     default:
3986627f7eb2Smrg       gfc_error ("Symbol at %C is not appropriate for an expression");
3987627f7eb2Smrg       return MATCH_ERROR;
3988627f7eb2Smrg     }
3989627f7eb2Smrg 
3990627f7eb2Smrg   if (m == MATCH_YES)
3991627f7eb2Smrg     {
3992627f7eb2Smrg       e->where = where;
3993627f7eb2Smrg       *result = e;
3994627f7eb2Smrg     }
3995627f7eb2Smrg   else
3996627f7eb2Smrg     gfc_free_expr (e);
3997627f7eb2Smrg 
3998627f7eb2Smrg   return m;
3999627f7eb2Smrg }
4000627f7eb2Smrg 
4001627f7eb2Smrg 
4002627f7eb2Smrg /* Match a variable, i.e. something that can be assigned to.  This
4003627f7eb2Smrg    starts as a symbol, can be a structure component or an array
4004627f7eb2Smrg    reference.  It can be a function if the function doesn't have a
4005627f7eb2Smrg    separate RESULT variable.  If the symbol has not been previously
4006627f7eb2Smrg    seen, we assume it is a variable.
4007627f7eb2Smrg 
4008627f7eb2Smrg    This function is called by two interface functions:
4009627f7eb2Smrg    gfc_match_variable, which has host_flag = 1, and
4010627f7eb2Smrg    gfc_match_equiv_variable, with host_flag = 0, to restrict the
4011627f7eb2Smrg    match of the symbol to the local scope.  */
4012627f7eb2Smrg 
4013627f7eb2Smrg static match
match_variable(gfc_expr ** result,int equiv_flag,int host_flag)4014627f7eb2Smrg match_variable (gfc_expr **result, int equiv_flag, int host_flag)
4015627f7eb2Smrg {
4016627f7eb2Smrg   gfc_symbol *sym, *dt_sym;
4017627f7eb2Smrg   gfc_symtree *st;
4018627f7eb2Smrg   gfc_expr *expr;
4019627f7eb2Smrg   locus where, old_loc;
4020627f7eb2Smrg   match m;
4021627f7eb2Smrg 
4022627f7eb2Smrg   /* Since nothing has any business being an lvalue in a module
4023627f7eb2Smrg      specification block, an interface block or a contains section,
4024627f7eb2Smrg      we force the changed_symbols mechanism to work by setting
4025627f7eb2Smrg      host_flag to 0. This prevents valid symbols that have the name
4026627f7eb2Smrg      of keywords, such as 'end', being turned into variables by
4027627f7eb2Smrg      failed matching to assignments for, e.g., END INTERFACE.  */
4028627f7eb2Smrg   if (gfc_current_state () == COMP_MODULE
4029627f7eb2Smrg       || gfc_current_state () == COMP_SUBMODULE
4030627f7eb2Smrg       || gfc_current_state () == COMP_INTERFACE
4031627f7eb2Smrg       || gfc_current_state () == COMP_CONTAINS)
4032627f7eb2Smrg     host_flag = 0;
4033627f7eb2Smrg 
4034627f7eb2Smrg   where = gfc_current_locus;
4035627f7eb2Smrg   m = gfc_match_sym_tree (&st, host_flag);
4036627f7eb2Smrg   if (m != MATCH_YES)
4037627f7eb2Smrg     return m;
4038627f7eb2Smrg 
4039627f7eb2Smrg   sym = st->n.sym;
4040627f7eb2Smrg 
4041627f7eb2Smrg   /* If this is an implicit do loop index and implicitly typed,
4042627f7eb2Smrg      it should not be host associated.  */
4043627f7eb2Smrg   m = check_for_implicit_index (&st, &sym);
4044627f7eb2Smrg   if (m != MATCH_YES)
4045627f7eb2Smrg     return m;
4046627f7eb2Smrg 
4047627f7eb2Smrg   sym->attr.implied_index = 0;
4048627f7eb2Smrg 
4049627f7eb2Smrg   gfc_set_sym_referenced (sym);
4050627f7eb2Smrg 
4051627f7eb2Smrg   /* STRUCTUREs may share names with variables, but derived types may not.  */
4052627f7eb2Smrg   if (sym->attr.flavor == FL_PROCEDURE && sym->generic
4053627f7eb2Smrg       && (dt_sym = gfc_find_dt_in_generic (sym)))
4054627f7eb2Smrg     {
4055627f7eb2Smrg       if (dt_sym->attr.flavor == FL_DERIVED)
4056627f7eb2Smrg         gfc_error ("Derived type %qs cannot be used as a variable at %C",
4057627f7eb2Smrg                    sym->name);
4058627f7eb2Smrg       return MATCH_ERROR;
4059627f7eb2Smrg     }
4060627f7eb2Smrg 
4061627f7eb2Smrg   switch (sym->attr.flavor)
4062627f7eb2Smrg     {
4063627f7eb2Smrg     case FL_VARIABLE:
4064627f7eb2Smrg       /* Everything is alright.  */
4065627f7eb2Smrg       break;
4066627f7eb2Smrg 
4067627f7eb2Smrg     case FL_UNKNOWN:
4068627f7eb2Smrg       {
4069627f7eb2Smrg 	sym_flavor flavor = FL_UNKNOWN;
4070627f7eb2Smrg 
4071627f7eb2Smrg 	gfc_gobble_whitespace ();
4072627f7eb2Smrg 
4073627f7eb2Smrg 	if (sym->attr.external || sym->attr.procedure
4074627f7eb2Smrg 	    || sym->attr.function || sym->attr.subroutine)
4075627f7eb2Smrg 	  flavor = FL_PROCEDURE;
4076627f7eb2Smrg 
4077627f7eb2Smrg 	/* If it is not a procedure, is not typed and is host associated,
4078627f7eb2Smrg 	   we cannot give it a flavor yet.  */
4079627f7eb2Smrg 	else if (sym->ns == gfc_current_ns->parent
4080627f7eb2Smrg 		   && sym->ts.type == BT_UNKNOWN)
4081627f7eb2Smrg 	  break;
4082627f7eb2Smrg 
4083627f7eb2Smrg 	/* These are definitive indicators that this is a variable.  */
4084627f7eb2Smrg 	else if (gfc_peek_ascii_char () != '(' || sym->ts.type != BT_UNKNOWN
4085627f7eb2Smrg 		 || sym->attr.pointer || sym->as != NULL)
4086627f7eb2Smrg 	  flavor = FL_VARIABLE;
4087627f7eb2Smrg 
4088627f7eb2Smrg 	if (flavor != FL_UNKNOWN
4089627f7eb2Smrg 	    && !gfc_add_flavor (&sym->attr, flavor, sym->name, NULL))
4090627f7eb2Smrg 	  return MATCH_ERROR;
4091627f7eb2Smrg       }
4092627f7eb2Smrg       break;
4093627f7eb2Smrg 
4094627f7eb2Smrg     case FL_PARAMETER:
4095627f7eb2Smrg       if (equiv_flag)
4096627f7eb2Smrg 	{
4097627f7eb2Smrg 	  gfc_error ("Named constant at %C in an EQUIVALENCE");
4098627f7eb2Smrg 	  return MATCH_ERROR;
4099627f7eb2Smrg 	}
4100627f7eb2Smrg       /* Otherwise this is checked for and an error given in the
4101627f7eb2Smrg 	 variable definition context checks.  */
4102627f7eb2Smrg       break;
4103627f7eb2Smrg 
4104627f7eb2Smrg     case FL_PROCEDURE:
4105627f7eb2Smrg       /* Check for a nonrecursive function result variable.  */
4106627f7eb2Smrg       if (sym->attr.function
4107627f7eb2Smrg 	  && !sym->attr.external
4108627f7eb2Smrg 	  && sym->result == sym
4109627f7eb2Smrg 	  && (gfc_is_function_return_value (sym, gfc_current_ns)
4110627f7eb2Smrg 	      || (sym->attr.entry
4111627f7eb2Smrg 		  && sym->ns == gfc_current_ns)
4112627f7eb2Smrg 	      || (sym->attr.entry
4113627f7eb2Smrg 		  && sym->ns == gfc_current_ns->parent)))
4114627f7eb2Smrg 	{
4115627f7eb2Smrg 	  /* If a function result is a derived type, then the derived
4116627f7eb2Smrg 	     type may still have to be resolved.  */
4117627f7eb2Smrg 
4118627f7eb2Smrg 	  if (sym->ts.type == BT_DERIVED
4119627f7eb2Smrg 	      && gfc_use_derived (sym->ts.u.derived) == NULL)
4120627f7eb2Smrg 	    return MATCH_ERROR;
4121627f7eb2Smrg 	  break;
4122627f7eb2Smrg 	}
4123627f7eb2Smrg 
4124627f7eb2Smrg       if (sym->attr.proc_pointer
4125627f7eb2Smrg 	  || replace_hidden_procptr_result (&sym, &st))
4126627f7eb2Smrg 	break;
4127627f7eb2Smrg 
4128627f7eb2Smrg       /* Fall through to error */
4129627f7eb2Smrg       gcc_fallthrough ();
4130627f7eb2Smrg 
4131627f7eb2Smrg     default:
4132627f7eb2Smrg       gfc_error ("%qs at %C is not a variable", sym->name);
4133627f7eb2Smrg       return MATCH_ERROR;
4134627f7eb2Smrg     }
4135627f7eb2Smrg 
4136627f7eb2Smrg   /* Special case for derived type variables that get their types
4137627f7eb2Smrg      via an IMPLICIT statement.  This can't wait for the
4138627f7eb2Smrg      resolution phase.  */
4139627f7eb2Smrg 
4140627f7eb2Smrg     {
4141627f7eb2Smrg       gfc_namespace * implicit_ns;
4142627f7eb2Smrg 
4143627f7eb2Smrg       if (gfc_current_ns->proc_name == sym)
4144627f7eb2Smrg 	implicit_ns = gfc_current_ns;
4145627f7eb2Smrg       else
4146627f7eb2Smrg 	implicit_ns = sym->ns;
4147627f7eb2Smrg 
4148627f7eb2Smrg       old_loc = gfc_current_locus;
4149627f7eb2Smrg       if (gfc_match_member_sep (sym) == MATCH_YES
4150627f7eb2Smrg 	  && sym->ts.type == BT_UNKNOWN
4151627f7eb2Smrg 	  && gfc_get_default_type (sym->name, implicit_ns)->type == BT_DERIVED)
4152627f7eb2Smrg 	gfc_set_default_type (sym, 0, implicit_ns);
4153627f7eb2Smrg       gfc_current_locus = old_loc;
4154627f7eb2Smrg     }
4155627f7eb2Smrg 
4156627f7eb2Smrg   expr = gfc_get_expr ();
4157627f7eb2Smrg 
4158627f7eb2Smrg   expr->expr_type = EXPR_VARIABLE;
4159627f7eb2Smrg   expr->symtree = st;
4160627f7eb2Smrg   expr->ts = sym->ts;
4161627f7eb2Smrg   expr->where = where;
4162627f7eb2Smrg 
4163627f7eb2Smrg   /* Now see if we have to do more.  */
4164627f7eb2Smrg   m = gfc_match_varspec (expr, equiv_flag, false, false);
4165627f7eb2Smrg   if (m != MATCH_YES)
4166627f7eb2Smrg     {
4167627f7eb2Smrg       gfc_free_expr (expr);
4168627f7eb2Smrg       return m;
4169627f7eb2Smrg     }
4170627f7eb2Smrg 
4171627f7eb2Smrg   *result = expr;
4172627f7eb2Smrg   return MATCH_YES;
4173627f7eb2Smrg }
4174627f7eb2Smrg 
4175627f7eb2Smrg 
4176627f7eb2Smrg match
gfc_match_variable(gfc_expr ** result,int equiv_flag)4177627f7eb2Smrg gfc_match_variable (gfc_expr **result, int equiv_flag)
4178627f7eb2Smrg {
4179627f7eb2Smrg   return match_variable (result, equiv_flag, 1);
4180627f7eb2Smrg }
4181627f7eb2Smrg 
4182627f7eb2Smrg 
4183627f7eb2Smrg match
gfc_match_equiv_variable(gfc_expr ** result)4184627f7eb2Smrg gfc_match_equiv_variable (gfc_expr **result)
4185627f7eb2Smrg {
4186627f7eb2Smrg   return match_variable (result, 1, 0);
4187627f7eb2Smrg }
4188627f7eb2Smrg 
4189