annotate gcc/fortran/primary.c @ 136:4627f235cf2a

fix c-next example
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Thu, 08 Nov 2018 14:11:56 +0900
parents 84e7813d76e9
children 1830386684a0
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* Primary expression subroutines
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2 Copyright (C) 2000-2018 Free Software Foundation, Inc.
111
kono
parents:
diff changeset
3 Contributed by Andy Vaught
kono
parents:
diff changeset
4
kono
parents:
diff changeset
5 This file is part of GCC.
kono
parents:
diff changeset
6
kono
parents:
diff changeset
7 GCC is free software; you can redistribute it and/or modify it under
kono
parents:
diff changeset
8 the terms of the GNU General Public License as published by the Free
kono
parents:
diff changeset
9 Software Foundation; either version 3, or (at your option) any later
kono
parents:
diff changeset
10 version.
kono
parents:
diff changeset
11
kono
parents:
diff changeset
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
kono
parents:
diff changeset
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
kono
parents:
diff changeset
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
kono
parents:
diff changeset
15 for more details.
kono
parents:
diff changeset
16
kono
parents:
diff changeset
17 You should have received a copy of the GNU General Public License
kono
parents:
diff changeset
18 along with GCC; see the file COPYING3. If not see
kono
parents:
diff changeset
19 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
20
kono
parents:
diff changeset
21 #include "config.h"
kono
parents:
diff changeset
22 #include "system.h"
kono
parents:
diff changeset
23 #include "coretypes.h"
kono
parents:
diff changeset
24 #include "options.h"
kono
parents:
diff changeset
25 #include "gfortran.h"
kono
parents:
diff changeset
26 #include "arith.h"
kono
parents:
diff changeset
27 #include "match.h"
kono
parents:
diff changeset
28 #include "parse.h"
kono
parents:
diff changeset
29 #include "constructor.h"
kono
parents:
diff changeset
30
kono
parents:
diff changeset
31 int matching_actual_arglist = 0;
kono
parents:
diff changeset
32
kono
parents:
diff changeset
33 /* Matches a kind-parameter expression, which is either a named
kono
parents:
diff changeset
34 symbolic constant or a nonnegative integer constant. If
kono
parents:
diff changeset
35 successful, sets the kind value to the correct integer.
kono
parents:
diff changeset
36 The argument 'is_iso_c' signals whether the kind is an ISO_C_BINDING
kono
parents:
diff changeset
37 symbol like e.g. 'c_int'. */
kono
parents:
diff changeset
38
kono
parents:
diff changeset
39 static match
kono
parents:
diff changeset
40 match_kind_param (int *kind, int *is_iso_c)
kono
parents:
diff changeset
41 {
kono
parents:
diff changeset
42 char name[GFC_MAX_SYMBOL_LEN + 1];
kono
parents:
diff changeset
43 gfc_symbol *sym;
kono
parents:
diff changeset
44 match m;
kono
parents:
diff changeset
45
kono
parents:
diff changeset
46 *is_iso_c = 0;
kono
parents:
diff changeset
47
kono
parents:
diff changeset
48 m = gfc_match_small_literal_int (kind, NULL);
kono
parents:
diff changeset
49 if (m != MATCH_NO)
kono
parents:
diff changeset
50 return m;
kono
parents:
diff changeset
51
kono
parents:
diff changeset
52 m = gfc_match_name (name);
kono
parents:
diff changeset
53 if (m != MATCH_YES)
kono
parents:
diff changeset
54 return m;
kono
parents:
diff changeset
55
kono
parents:
diff changeset
56 if (gfc_find_symbol (name, NULL, 1, &sym))
kono
parents:
diff changeset
57 return MATCH_ERROR;
kono
parents:
diff changeset
58
kono
parents:
diff changeset
59 if (sym == NULL)
kono
parents:
diff changeset
60 return MATCH_NO;
kono
parents:
diff changeset
61
kono
parents:
diff changeset
62 *is_iso_c = sym->attr.is_iso_c;
kono
parents:
diff changeset
63
kono
parents:
diff changeset
64 if (sym->attr.flavor != FL_PARAMETER)
kono
parents:
diff changeset
65 return MATCH_NO;
kono
parents:
diff changeset
66
kono
parents:
diff changeset
67 if (sym->value == NULL)
kono
parents:
diff changeset
68 return MATCH_NO;
kono
parents:
diff changeset
69
kono
parents:
diff changeset
70 if (gfc_extract_int (sym->value, kind))
kono
parents:
diff changeset
71 return MATCH_NO;
kono
parents:
diff changeset
72
kono
parents:
diff changeset
73 gfc_set_sym_referenced (sym);
kono
parents:
diff changeset
74
kono
parents:
diff changeset
75 if (*kind < 0)
kono
parents:
diff changeset
76 return MATCH_NO;
kono
parents:
diff changeset
77
kono
parents:
diff changeset
78 return MATCH_YES;
kono
parents:
diff changeset
79 }
kono
parents:
diff changeset
80
kono
parents:
diff changeset
81
kono
parents:
diff changeset
82 /* Get a trailing kind-specification for non-character variables.
kono
parents:
diff changeset
83 Returns:
kono
parents:
diff changeset
84 * the integer kind value or
kono
parents:
diff changeset
85 * -1 if an error was generated,
kono
parents:
diff changeset
86 * -2 if no kind was found.
kono
parents:
diff changeset
87 The argument 'is_iso_c' signals whether the kind is an ISO_C_BINDING
kono
parents:
diff changeset
88 symbol like e.g. 'c_int'. */
kono
parents:
diff changeset
89
kono
parents:
diff changeset
90 static int
kono
parents:
diff changeset
91 get_kind (int *is_iso_c)
kono
parents:
diff changeset
92 {
kono
parents:
diff changeset
93 int kind;
kono
parents:
diff changeset
94 match m;
kono
parents:
diff changeset
95
kono
parents:
diff changeset
96 *is_iso_c = 0;
kono
parents:
diff changeset
97
kono
parents:
diff changeset
98 if (gfc_match_char ('_') != MATCH_YES)
kono
parents:
diff changeset
99 return -2;
kono
parents:
diff changeset
100
kono
parents:
diff changeset
101 m = match_kind_param (&kind, is_iso_c);
kono
parents:
diff changeset
102 if (m == MATCH_NO)
kono
parents:
diff changeset
103 gfc_error ("Missing kind-parameter at %C");
kono
parents:
diff changeset
104
kono
parents:
diff changeset
105 return (m == MATCH_YES) ? kind : -1;
kono
parents:
diff changeset
106 }
kono
parents:
diff changeset
107
kono
parents:
diff changeset
108
kono
parents:
diff changeset
109 /* Given a character and a radix, see if the character is a valid
kono
parents:
diff changeset
110 digit in that radix. */
kono
parents:
diff changeset
111
kono
parents:
diff changeset
112 int
kono
parents:
diff changeset
113 gfc_check_digit (char c, int radix)
kono
parents:
diff changeset
114 {
kono
parents:
diff changeset
115 int r;
kono
parents:
diff changeset
116
kono
parents:
diff changeset
117 switch (radix)
kono
parents:
diff changeset
118 {
kono
parents:
diff changeset
119 case 2:
kono
parents:
diff changeset
120 r = ('0' <= c && c <= '1');
kono
parents:
diff changeset
121 break;
kono
parents:
diff changeset
122
kono
parents:
diff changeset
123 case 8:
kono
parents:
diff changeset
124 r = ('0' <= c && c <= '7');
kono
parents:
diff changeset
125 break;
kono
parents:
diff changeset
126
kono
parents:
diff changeset
127 case 10:
kono
parents:
diff changeset
128 r = ('0' <= c && c <= '9');
kono
parents:
diff changeset
129 break;
kono
parents:
diff changeset
130
kono
parents:
diff changeset
131 case 16:
kono
parents:
diff changeset
132 r = ISXDIGIT (c);
kono
parents:
diff changeset
133 break;
kono
parents:
diff changeset
134
kono
parents:
diff changeset
135 default:
kono
parents:
diff changeset
136 gfc_internal_error ("gfc_check_digit(): bad radix");
kono
parents:
diff changeset
137 }
kono
parents:
diff changeset
138
kono
parents:
diff changeset
139 return r;
kono
parents:
diff changeset
140 }
kono
parents:
diff changeset
141
kono
parents:
diff changeset
142
kono
parents:
diff changeset
143 /* Match the digit string part of an integer if signflag is not set,
kono
parents:
diff changeset
144 the signed digit string part if signflag is set. If the buffer
kono
parents:
diff changeset
145 is NULL, we just count characters for the resolution pass. Returns
kono
parents:
diff changeset
146 the number of characters matched, -1 for no match. */
kono
parents:
diff changeset
147
kono
parents:
diff changeset
148 static int
kono
parents:
diff changeset
149 match_digits (int signflag, int radix, char *buffer)
kono
parents:
diff changeset
150 {
kono
parents:
diff changeset
151 locus old_loc;
kono
parents:
diff changeset
152 int length;
kono
parents:
diff changeset
153 char c;
kono
parents:
diff changeset
154
kono
parents:
diff changeset
155 length = 0;
kono
parents:
diff changeset
156 c = gfc_next_ascii_char ();
kono
parents:
diff changeset
157
kono
parents:
diff changeset
158 if (signflag && (c == '+' || c == '-'))
kono
parents:
diff changeset
159 {
kono
parents:
diff changeset
160 if (buffer != NULL)
kono
parents:
diff changeset
161 *buffer++ = c;
kono
parents:
diff changeset
162 gfc_gobble_whitespace ();
kono
parents:
diff changeset
163 c = gfc_next_ascii_char ();
kono
parents:
diff changeset
164 length++;
kono
parents:
diff changeset
165 }
kono
parents:
diff changeset
166
kono
parents:
diff changeset
167 if (!gfc_check_digit (c, radix))
kono
parents:
diff changeset
168 return -1;
kono
parents:
diff changeset
169
kono
parents:
diff changeset
170 length++;
kono
parents:
diff changeset
171 if (buffer != NULL)
kono
parents:
diff changeset
172 *buffer++ = c;
kono
parents:
diff changeset
173
kono
parents:
diff changeset
174 for (;;)
kono
parents:
diff changeset
175 {
kono
parents:
diff changeset
176 old_loc = gfc_current_locus;
kono
parents:
diff changeset
177 c = gfc_next_ascii_char ();
kono
parents:
diff changeset
178
kono
parents:
diff changeset
179 if (!gfc_check_digit (c, radix))
kono
parents:
diff changeset
180 break;
kono
parents:
diff changeset
181
kono
parents:
diff changeset
182 if (buffer != NULL)
kono
parents:
diff changeset
183 *buffer++ = c;
kono
parents:
diff changeset
184 length++;
kono
parents:
diff changeset
185 }
kono
parents:
diff changeset
186
kono
parents:
diff changeset
187 gfc_current_locus = old_loc;
kono
parents:
diff changeset
188
kono
parents:
diff changeset
189 return length;
kono
parents:
diff changeset
190 }
kono
parents:
diff changeset
191
kono
parents:
diff changeset
192
kono
parents:
diff changeset
193 /* Match an integer (digit string and optional kind).
kono
parents:
diff changeset
194 A sign will be accepted if signflag is set. */
kono
parents:
diff changeset
195
kono
parents:
diff changeset
196 static match
kono
parents:
diff changeset
197 match_integer_constant (gfc_expr **result, int signflag)
kono
parents:
diff changeset
198 {
kono
parents:
diff changeset
199 int length, kind, is_iso_c;
kono
parents:
diff changeset
200 locus old_loc;
kono
parents:
diff changeset
201 char *buffer;
kono
parents:
diff changeset
202 gfc_expr *e;
kono
parents:
diff changeset
203
kono
parents:
diff changeset
204 old_loc = gfc_current_locus;
kono
parents:
diff changeset
205 gfc_gobble_whitespace ();
kono
parents:
diff changeset
206
kono
parents:
diff changeset
207 length = match_digits (signflag, 10, NULL);
kono
parents:
diff changeset
208 gfc_current_locus = old_loc;
kono
parents:
diff changeset
209 if (length == -1)
kono
parents:
diff changeset
210 return MATCH_NO;
kono
parents:
diff changeset
211
kono
parents:
diff changeset
212 buffer = (char *) alloca (length + 1);
kono
parents:
diff changeset
213 memset (buffer, '\0', length + 1);
kono
parents:
diff changeset
214
kono
parents:
diff changeset
215 gfc_gobble_whitespace ();
kono
parents:
diff changeset
216
kono
parents:
diff changeset
217 match_digits (signflag, 10, buffer);
kono
parents:
diff changeset
218
kono
parents:
diff changeset
219 kind = get_kind (&is_iso_c);
kono
parents:
diff changeset
220 if (kind == -2)
kono
parents:
diff changeset
221 kind = gfc_default_integer_kind;
kono
parents:
diff changeset
222 if (kind == -1)
kono
parents:
diff changeset
223 return MATCH_ERROR;
kono
parents:
diff changeset
224
kono
parents:
diff changeset
225 if (kind == 4 && flag_integer4_kind == 8)
kono
parents:
diff changeset
226 kind = 8;
kono
parents:
diff changeset
227
kono
parents:
diff changeset
228 if (gfc_validate_kind (BT_INTEGER, kind, true) < 0)
kono
parents:
diff changeset
229 {
kono
parents:
diff changeset
230 gfc_error ("Integer kind %d at %C not available", kind);
kono
parents:
diff changeset
231 return MATCH_ERROR;
kono
parents:
diff changeset
232 }
kono
parents:
diff changeset
233
kono
parents:
diff changeset
234 e = gfc_convert_integer (buffer, kind, 10, &gfc_current_locus);
kono
parents:
diff changeset
235 e->ts.is_c_interop = is_iso_c;
kono
parents:
diff changeset
236
kono
parents:
diff changeset
237 if (gfc_range_check (e) != ARITH_OK)
kono
parents:
diff changeset
238 {
kono
parents:
diff changeset
239 gfc_error ("Integer too big for its kind at %C. This check can be "
kono
parents:
diff changeset
240 "disabled with the option -fno-range-check");
kono
parents:
diff changeset
241
kono
parents:
diff changeset
242 gfc_free_expr (e);
kono
parents:
diff changeset
243 return MATCH_ERROR;
kono
parents:
diff changeset
244 }
kono
parents:
diff changeset
245
kono
parents:
diff changeset
246 *result = e;
kono
parents:
diff changeset
247 return MATCH_YES;
kono
parents:
diff changeset
248 }
kono
parents:
diff changeset
249
kono
parents:
diff changeset
250
kono
parents:
diff changeset
251 /* Match a Hollerith constant. */
kono
parents:
diff changeset
252
kono
parents:
diff changeset
253 static match
kono
parents:
diff changeset
254 match_hollerith_constant (gfc_expr **result)
kono
parents:
diff changeset
255 {
kono
parents:
diff changeset
256 locus old_loc;
kono
parents:
diff changeset
257 gfc_expr *e = NULL;
kono
parents:
diff changeset
258 int num, pad;
kono
parents:
diff changeset
259 int i;
kono
parents:
diff changeset
260
kono
parents:
diff changeset
261 old_loc = gfc_current_locus;
kono
parents:
diff changeset
262 gfc_gobble_whitespace ();
kono
parents:
diff changeset
263
kono
parents:
diff changeset
264 if (match_integer_constant (&e, 0) == MATCH_YES
kono
parents:
diff changeset
265 && gfc_match_char ('h') == MATCH_YES)
kono
parents:
diff changeset
266 {
kono
parents:
diff changeset
267 if (!gfc_notify_std (GFC_STD_LEGACY, "Hollerith constant at %C"))
kono
parents:
diff changeset
268 goto cleanup;
kono
parents:
diff changeset
269
kono
parents:
diff changeset
270 if (gfc_extract_int (e, &num, 1))
kono
parents:
diff changeset
271 goto cleanup;
kono
parents:
diff changeset
272 if (num == 0)
kono
parents:
diff changeset
273 {
kono
parents:
diff changeset
274 gfc_error ("Invalid Hollerith constant: %L must contain at least "
kono
parents:
diff changeset
275 "one character", &old_loc);
kono
parents:
diff changeset
276 goto cleanup;
kono
parents:
diff changeset
277 }
kono
parents:
diff changeset
278 if (e->ts.kind != gfc_default_integer_kind)
kono
parents:
diff changeset
279 {
kono
parents:
diff changeset
280 gfc_error ("Invalid Hollerith constant: Integer kind at %L "
kono
parents:
diff changeset
281 "should be default", &old_loc);
kono
parents:
diff changeset
282 goto cleanup;
kono
parents:
diff changeset
283 }
kono
parents:
diff changeset
284 else
kono
parents:
diff changeset
285 {
kono
parents:
diff changeset
286 gfc_free_expr (e);
kono
parents:
diff changeset
287 e = gfc_get_constant_expr (BT_HOLLERITH, gfc_default_character_kind,
kono
parents:
diff changeset
288 &gfc_current_locus);
kono
parents:
diff changeset
289
kono
parents:
diff changeset
290 /* Calculate padding needed to fit default integer memory. */
kono
parents:
diff changeset
291 pad = gfc_default_integer_kind - (num % gfc_default_integer_kind);
kono
parents:
diff changeset
292
kono
parents:
diff changeset
293 e->representation.string = XCNEWVEC (char, num + pad + 1);
kono
parents:
diff changeset
294
kono
parents:
diff changeset
295 for (i = 0; i < num; i++)
kono
parents:
diff changeset
296 {
kono
parents:
diff changeset
297 gfc_char_t c = gfc_next_char_literal (INSTRING_WARN);
kono
parents:
diff changeset
298 if (! gfc_wide_fits_in_byte (c))
kono
parents:
diff changeset
299 {
kono
parents:
diff changeset
300 gfc_error ("Invalid Hollerith constant at %L contains a "
kono
parents:
diff changeset
301 "wide character", &old_loc);
kono
parents:
diff changeset
302 goto cleanup;
kono
parents:
diff changeset
303 }
kono
parents:
diff changeset
304
kono
parents:
diff changeset
305 e->representation.string[i] = (unsigned char) c;
kono
parents:
diff changeset
306 }
kono
parents:
diff changeset
307
kono
parents:
diff changeset
308 /* Now pad with blanks and end with a null char. */
kono
parents:
diff changeset
309 for (i = 0; i < pad; i++)
kono
parents:
diff changeset
310 e->representation.string[num + i] = ' ';
kono
parents:
diff changeset
311
kono
parents:
diff changeset
312 e->representation.string[num + i] = '\0';
kono
parents:
diff changeset
313 e->representation.length = num + pad;
kono
parents:
diff changeset
314 e->ts.u.pad = pad;
kono
parents:
diff changeset
315
kono
parents:
diff changeset
316 *result = e;
kono
parents:
diff changeset
317 return MATCH_YES;
kono
parents:
diff changeset
318 }
kono
parents:
diff changeset
319 }
kono
parents:
diff changeset
320
kono
parents:
diff changeset
321 gfc_free_expr (e);
kono
parents:
diff changeset
322 gfc_current_locus = old_loc;
kono
parents:
diff changeset
323 return MATCH_NO;
kono
parents:
diff changeset
324
kono
parents:
diff changeset
325 cleanup:
kono
parents:
diff changeset
326 gfc_free_expr (e);
kono
parents:
diff changeset
327 return MATCH_ERROR;
kono
parents:
diff changeset
328 }
kono
parents:
diff changeset
329
kono
parents:
diff changeset
330
kono
parents:
diff changeset
331 /* Match a binary, octal or hexadecimal constant that can be found in
kono
parents:
diff changeset
332 a DATA statement. The standard permits b'010...', o'73...', and
kono
parents:
diff changeset
333 z'a1...' where b, o, and z can be capital letters. This function
kono
parents:
diff changeset
334 also accepts postfixed forms of the constants: '01...'b, '73...'o,
kono
parents:
diff changeset
335 and 'a1...'z. An additional extension is the use of x for z. */
kono
parents:
diff changeset
336
kono
parents:
diff changeset
337 static match
kono
parents:
diff changeset
338 match_boz_constant (gfc_expr **result)
kono
parents:
diff changeset
339 {
kono
parents:
diff changeset
340 int radix, length, x_hex, kind;
kono
parents:
diff changeset
341 locus old_loc, start_loc;
kono
parents:
diff changeset
342 char *buffer, post, delim;
kono
parents:
diff changeset
343 gfc_expr *e;
kono
parents:
diff changeset
344
kono
parents:
diff changeset
345 start_loc = old_loc = gfc_current_locus;
kono
parents:
diff changeset
346 gfc_gobble_whitespace ();
kono
parents:
diff changeset
347
kono
parents:
diff changeset
348 x_hex = 0;
kono
parents:
diff changeset
349 switch (post = gfc_next_ascii_char ())
kono
parents:
diff changeset
350 {
kono
parents:
diff changeset
351 case 'b':
kono
parents:
diff changeset
352 radix = 2;
kono
parents:
diff changeset
353 post = 0;
kono
parents:
diff changeset
354 break;
kono
parents:
diff changeset
355 case 'o':
kono
parents:
diff changeset
356 radix = 8;
kono
parents:
diff changeset
357 post = 0;
kono
parents:
diff changeset
358 break;
kono
parents:
diff changeset
359 case 'x':
kono
parents:
diff changeset
360 x_hex = 1;
kono
parents:
diff changeset
361 /* Fall through. */
kono
parents:
diff changeset
362 case 'z':
kono
parents:
diff changeset
363 radix = 16;
kono
parents:
diff changeset
364 post = 0;
kono
parents:
diff changeset
365 break;
kono
parents:
diff changeset
366 case '\'':
kono
parents:
diff changeset
367 /* Fall through. */
kono
parents:
diff changeset
368 case '\"':
kono
parents:
diff changeset
369 delim = post;
kono
parents:
diff changeset
370 post = 1;
kono
parents:
diff changeset
371 radix = 16; /* Set to accept any valid digit string. */
kono
parents:
diff changeset
372 break;
kono
parents:
diff changeset
373 default:
kono
parents:
diff changeset
374 goto backup;
kono
parents:
diff changeset
375 }
kono
parents:
diff changeset
376
kono
parents:
diff changeset
377 /* No whitespace allowed here. */
kono
parents:
diff changeset
378
kono
parents:
diff changeset
379 if (post == 0)
kono
parents:
diff changeset
380 delim = gfc_next_ascii_char ();
kono
parents:
diff changeset
381
kono
parents:
diff changeset
382 if (delim != '\'' && delim != '\"')
kono
parents:
diff changeset
383 goto backup;
kono
parents:
diff changeset
384
kono
parents:
diff changeset
385 if (x_hex
kono
parents:
diff changeset
386 && (!gfc_notify_std(GFC_STD_GNU, "Hexadecimal "
kono
parents:
diff changeset
387 "constant at %C uses non-standard syntax")))
kono
parents:
diff changeset
388 return MATCH_ERROR;
kono
parents:
diff changeset
389
kono
parents:
diff changeset
390 old_loc = gfc_current_locus;
kono
parents:
diff changeset
391
kono
parents:
diff changeset
392 length = match_digits (0, radix, NULL);
kono
parents:
diff changeset
393 if (length == -1)
kono
parents:
diff changeset
394 {
kono
parents:
diff changeset
395 gfc_error ("Empty set of digits in BOZ constant at %C");
kono
parents:
diff changeset
396 return MATCH_ERROR;
kono
parents:
diff changeset
397 }
kono
parents:
diff changeset
398
kono
parents:
diff changeset
399 if (gfc_next_ascii_char () != delim)
kono
parents:
diff changeset
400 {
kono
parents:
diff changeset
401 gfc_error ("Illegal character in BOZ constant at %C");
kono
parents:
diff changeset
402 return MATCH_ERROR;
kono
parents:
diff changeset
403 }
kono
parents:
diff changeset
404
kono
parents:
diff changeset
405 if (post == 1)
kono
parents:
diff changeset
406 {
kono
parents:
diff changeset
407 switch (gfc_next_ascii_char ())
kono
parents:
diff changeset
408 {
kono
parents:
diff changeset
409 case 'b':
kono
parents:
diff changeset
410 radix = 2;
kono
parents:
diff changeset
411 break;
kono
parents:
diff changeset
412 case 'o':
kono
parents:
diff changeset
413 radix = 8;
kono
parents:
diff changeset
414 break;
kono
parents:
diff changeset
415 case 'x':
kono
parents:
diff changeset
416 /* Fall through. */
kono
parents:
diff changeset
417 case 'z':
kono
parents:
diff changeset
418 radix = 16;
kono
parents:
diff changeset
419 break;
kono
parents:
diff changeset
420 default:
kono
parents:
diff changeset
421 goto backup;
kono
parents:
diff changeset
422 }
kono
parents:
diff changeset
423
kono
parents:
diff changeset
424 if (!gfc_notify_std (GFC_STD_GNU, "BOZ constant "
kono
parents:
diff changeset
425 "at %C uses non-standard postfix syntax"))
kono
parents:
diff changeset
426 return MATCH_ERROR;
kono
parents:
diff changeset
427 }
kono
parents:
diff changeset
428
kono
parents:
diff changeset
429 gfc_current_locus = old_loc;
kono
parents:
diff changeset
430
kono
parents:
diff changeset
431 buffer = (char *) alloca (length + 1);
kono
parents:
diff changeset
432 memset (buffer, '\0', length + 1);
kono
parents:
diff changeset
433
kono
parents:
diff changeset
434 match_digits (0, radix, buffer);
kono
parents:
diff changeset
435 gfc_next_ascii_char (); /* Eat delimiter. */
kono
parents:
diff changeset
436 if (post == 1)
kono
parents:
diff changeset
437 gfc_next_ascii_char (); /* Eat postfixed b, o, z, or x. */
kono
parents:
diff changeset
438
kono
parents:
diff changeset
439 /* In section 5.2.5 and following C567 in the Fortran 2003 standard, we find
kono
parents:
diff changeset
440 "If a data-stmt-constant is a boz-literal-constant, the corresponding
kono
parents:
diff changeset
441 variable shall be of type integer. The boz-literal-constant is treated
kono
parents:
diff changeset
442 as if it were an int-literal-constant with a kind-param that specifies
kono
parents:
diff changeset
443 the representation method with the largest decimal exponent range
kono
parents:
diff changeset
444 supported by the processor." */
kono
parents:
diff changeset
445
kono
parents:
diff changeset
446 kind = gfc_max_integer_kind;
kono
parents:
diff changeset
447 e = gfc_convert_integer (buffer, kind, radix, &gfc_current_locus);
kono
parents:
diff changeset
448
kono
parents:
diff changeset
449 /* Mark as boz variable. */
kono
parents:
diff changeset
450 e->is_boz = 1;
kono
parents:
diff changeset
451
kono
parents:
diff changeset
452 if (gfc_range_check (e) != ARITH_OK)
kono
parents:
diff changeset
453 {
kono
parents:
diff changeset
454 gfc_error ("Integer too big for integer kind %i at %C", kind);
kono
parents:
diff changeset
455 gfc_free_expr (e);
kono
parents:
diff changeset
456 return MATCH_ERROR;
kono
parents:
diff changeset
457 }
kono
parents:
diff changeset
458
kono
parents:
diff changeset
459 if (!gfc_in_match_data ()
kono
parents:
diff changeset
460 && (!gfc_notify_std(GFC_STD_F2003, "BOZ used outside a DATA "
kono
parents:
diff changeset
461 "statement at %C")))
kono
parents:
diff changeset
462 return MATCH_ERROR;
kono
parents:
diff changeset
463
kono
parents:
diff changeset
464 *result = e;
kono
parents:
diff changeset
465 return MATCH_YES;
kono
parents:
diff changeset
466
kono
parents:
diff changeset
467 backup:
kono
parents:
diff changeset
468 gfc_current_locus = start_loc;
kono
parents:
diff changeset
469 return MATCH_NO;
kono
parents:
diff changeset
470 }
kono
parents:
diff changeset
471
kono
parents:
diff changeset
472
kono
parents:
diff changeset
473 /* Match a real constant of some sort. Allow a signed constant if signflag
kono
parents:
diff changeset
474 is nonzero. */
kono
parents:
diff changeset
475
kono
parents:
diff changeset
476 static match
kono
parents:
diff changeset
477 match_real_constant (gfc_expr **result, int signflag)
kono
parents:
diff changeset
478 {
kono
parents:
diff changeset
479 int kind, count, seen_dp, seen_digits, is_iso_c, default_exponent;
kono
parents:
diff changeset
480 locus old_loc, temp_loc;
kono
parents:
diff changeset
481 char *p, *buffer, c, exp_char;
kono
parents:
diff changeset
482 gfc_expr *e;
kono
parents:
diff changeset
483 bool negate;
kono
parents:
diff changeset
484
kono
parents:
diff changeset
485 old_loc = gfc_current_locus;
kono
parents:
diff changeset
486 gfc_gobble_whitespace ();
kono
parents:
diff changeset
487
kono
parents:
diff changeset
488 e = NULL;
kono
parents:
diff changeset
489
kono
parents:
diff changeset
490 default_exponent = 0;
kono
parents:
diff changeset
491 count = 0;
kono
parents:
diff changeset
492 seen_dp = 0;
kono
parents:
diff changeset
493 seen_digits = 0;
kono
parents:
diff changeset
494 exp_char = ' ';
kono
parents:
diff changeset
495 negate = FALSE;
kono
parents:
diff changeset
496
kono
parents:
diff changeset
497 c = gfc_next_ascii_char ();
kono
parents:
diff changeset
498 if (signflag && (c == '+' || c == '-'))
kono
parents:
diff changeset
499 {
kono
parents:
diff changeset
500 if (c == '-')
kono
parents:
diff changeset
501 negate = TRUE;
kono
parents:
diff changeset
502
kono
parents:
diff changeset
503 gfc_gobble_whitespace ();
kono
parents:
diff changeset
504 c = gfc_next_ascii_char ();
kono
parents:
diff changeset
505 }
kono
parents:
diff changeset
506
kono
parents:
diff changeset
507 /* Scan significand. */
kono
parents:
diff changeset
508 for (;; c = gfc_next_ascii_char (), count++)
kono
parents:
diff changeset
509 {
kono
parents:
diff changeset
510 if (c == '.')
kono
parents:
diff changeset
511 {
kono
parents:
diff changeset
512 if (seen_dp)
kono
parents:
diff changeset
513 goto done;
kono
parents:
diff changeset
514
kono
parents:
diff changeset
515 /* Check to see if "." goes with a following operator like
kono
parents:
diff changeset
516 ".eq.". */
kono
parents:
diff changeset
517 temp_loc = gfc_current_locus;
kono
parents:
diff changeset
518 c = gfc_next_ascii_char ();
kono
parents:
diff changeset
519
kono
parents:
diff changeset
520 if (c == 'e' || c == 'd' || c == 'q')
kono
parents:
diff changeset
521 {
kono
parents:
diff changeset
522 c = gfc_next_ascii_char ();
kono
parents:
diff changeset
523 if (c == '.')
kono
parents:
diff changeset
524 goto done; /* Operator named .e. or .d. */
kono
parents:
diff changeset
525 }
kono
parents:
diff changeset
526
kono
parents:
diff changeset
527 if (ISALPHA (c))
kono
parents:
diff changeset
528 goto done; /* Distinguish 1.e9 from 1.eq.2 */
kono
parents:
diff changeset
529
kono
parents:
diff changeset
530 gfc_current_locus = temp_loc;
kono
parents:
diff changeset
531 seen_dp = 1;
kono
parents:
diff changeset
532 continue;
kono
parents:
diff changeset
533 }
kono
parents:
diff changeset
534
kono
parents:
diff changeset
535 if (ISDIGIT (c))
kono
parents:
diff changeset
536 {
kono
parents:
diff changeset
537 seen_digits = 1;
kono
parents:
diff changeset
538 continue;
kono
parents:
diff changeset
539 }
kono
parents:
diff changeset
540
kono
parents:
diff changeset
541 break;
kono
parents:
diff changeset
542 }
kono
parents:
diff changeset
543
kono
parents:
diff changeset
544 if (!seen_digits || (c != 'e' && c != 'd' && c != 'q'))
kono
parents:
diff changeset
545 goto done;
kono
parents:
diff changeset
546 exp_char = c;
kono
parents:
diff changeset
547
kono
parents:
diff changeset
548
kono
parents:
diff changeset
549 if (c == 'q')
kono
parents:
diff changeset
550 {
kono
parents:
diff changeset
551 if (!gfc_notify_std (GFC_STD_GNU, "exponent-letter 'q' in "
kono
parents:
diff changeset
552 "real-literal-constant at %C"))
kono
parents:
diff changeset
553 return MATCH_ERROR;
kono
parents:
diff changeset
554 else if (warn_real_q_constant)
kono
parents:
diff changeset
555 gfc_warning (OPT_Wreal_q_constant,
kono
parents:
diff changeset
556 "Extension: exponent-letter %<q%> in real-literal-constant "
kono
parents:
diff changeset
557 "at %C");
kono
parents:
diff changeset
558 }
kono
parents:
diff changeset
559
kono
parents:
diff changeset
560 /* Scan exponent. */
kono
parents:
diff changeset
561 c = gfc_next_ascii_char ();
kono
parents:
diff changeset
562 count++;
kono
parents:
diff changeset
563
kono
parents:
diff changeset
564 if (c == '+' || c == '-')
kono
parents:
diff changeset
565 { /* optional sign */
kono
parents:
diff changeset
566 c = gfc_next_ascii_char ();
kono
parents:
diff changeset
567 count++;
kono
parents:
diff changeset
568 }
kono
parents:
diff changeset
569
kono
parents:
diff changeset
570 if (!ISDIGIT (c))
kono
parents:
diff changeset
571 {
kono
parents:
diff changeset
572 /* With -fdec, default exponent to 0 instead of complaining. */
kono
parents:
diff changeset
573 if (flag_dec)
kono
parents:
diff changeset
574 default_exponent = 1;
kono
parents:
diff changeset
575 else
kono
parents:
diff changeset
576 {
kono
parents:
diff changeset
577 gfc_error ("Missing exponent in real number at %C");
kono
parents:
diff changeset
578 return MATCH_ERROR;
kono
parents:
diff changeset
579 }
kono
parents:
diff changeset
580 }
kono
parents:
diff changeset
581
kono
parents:
diff changeset
582 while (ISDIGIT (c))
kono
parents:
diff changeset
583 {
kono
parents:
diff changeset
584 c = gfc_next_ascii_char ();
kono
parents:
diff changeset
585 count++;
kono
parents:
diff changeset
586 }
kono
parents:
diff changeset
587
kono
parents:
diff changeset
588 done:
kono
parents:
diff changeset
589 /* Check that we have a numeric constant. */
kono
parents:
diff changeset
590 if (!seen_digits || (!seen_dp && exp_char == ' '))
kono
parents:
diff changeset
591 {
kono
parents:
diff changeset
592 gfc_current_locus = old_loc;
kono
parents:
diff changeset
593 return MATCH_NO;
kono
parents:
diff changeset
594 }
kono
parents:
diff changeset
595
kono
parents:
diff changeset
596 /* Convert the number. */
kono
parents:
diff changeset
597 gfc_current_locus = old_loc;
kono
parents:
diff changeset
598 gfc_gobble_whitespace ();
kono
parents:
diff changeset
599
kono
parents:
diff changeset
600 buffer = (char *) alloca (count + default_exponent + 1);
kono
parents:
diff changeset
601 memset (buffer, '\0', count + default_exponent + 1);
kono
parents:
diff changeset
602
kono
parents:
diff changeset
603 p = buffer;
kono
parents:
diff changeset
604 c = gfc_next_ascii_char ();
kono
parents:
diff changeset
605 if (c == '+' || c == '-')
kono
parents:
diff changeset
606 {
kono
parents:
diff changeset
607 gfc_gobble_whitespace ();
kono
parents:
diff changeset
608 c = gfc_next_ascii_char ();
kono
parents:
diff changeset
609 }
kono
parents:
diff changeset
610
kono
parents:
diff changeset
611 /* Hack for mpfr_set_str(). */
kono
parents:
diff changeset
612 for (;;)
kono
parents:
diff changeset
613 {
kono
parents:
diff changeset
614 if (c == 'd' || c == 'q')
kono
parents:
diff changeset
615 *p = 'e';
kono
parents:
diff changeset
616 else
kono
parents:
diff changeset
617 *p = c;
kono
parents:
diff changeset
618 p++;
kono
parents:
diff changeset
619 if (--count == 0)
kono
parents:
diff changeset
620 break;
kono
parents:
diff changeset
621
kono
parents:
diff changeset
622 c = gfc_next_ascii_char ();
kono
parents:
diff changeset
623 }
kono
parents:
diff changeset
624 if (default_exponent)
kono
parents:
diff changeset
625 *p++ = '0';
kono
parents:
diff changeset
626
kono
parents:
diff changeset
627 kind = get_kind (&is_iso_c);
kono
parents:
diff changeset
628 if (kind == -1)
kono
parents:
diff changeset
629 goto cleanup;
kono
parents:
diff changeset
630
kono
parents:
diff changeset
631 switch (exp_char)
kono
parents:
diff changeset
632 {
kono
parents:
diff changeset
633 case 'd':
kono
parents:
diff changeset
634 if (kind != -2)
kono
parents:
diff changeset
635 {
kono
parents:
diff changeset
636 gfc_error ("Real number at %C has a %<d%> exponent and an explicit "
kono
parents:
diff changeset
637 "kind");
kono
parents:
diff changeset
638 goto cleanup;
kono
parents:
diff changeset
639 }
kono
parents:
diff changeset
640 kind = gfc_default_double_kind;
kono
parents:
diff changeset
641
kono
parents:
diff changeset
642 if (kind == 4)
kono
parents:
diff changeset
643 {
kono
parents:
diff changeset
644 if (flag_real4_kind == 8)
kono
parents:
diff changeset
645 kind = 8;
kono
parents:
diff changeset
646 if (flag_real4_kind == 10)
kono
parents:
diff changeset
647 kind = 10;
kono
parents:
diff changeset
648 if (flag_real4_kind == 16)
kono
parents:
diff changeset
649 kind = 16;
kono
parents:
diff changeset
650 }
kono
parents:
diff changeset
651
kono
parents:
diff changeset
652 if (kind == 8)
kono
parents:
diff changeset
653 {
kono
parents:
diff changeset
654 if (flag_real8_kind == 4)
kono
parents:
diff changeset
655 kind = 4;
kono
parents:
diff changeset
656 if (flag_real8_kind == 10)
kono
parents:
diff changeset
657 kind = 10;
kono
parents:
diff changeset
658 if (flag_real8_kind == 16)
kono
parents:
diff changeset
659 kind = 16;
kono
parents:
diff changeset
660 }
kono
parents:
diff changeset
661 break;
kono
parents:
diff changeset
662
kono
parents:
diff changeset
663 case 'q':
kono
parents:
diff changeset
664 if (kind != -2)
kono
parents:
diff changeset
665 {
kono
parents:
diff changeset
666 gfc_error ("Real number at %C has a %<q%> exponent and an explicit "
kono
parents:
diff changeset
667 "kind");
kono
parents:
diff changeset
668 goto cleanup;
kono
parents:
diff changeset
669 }
kono
parents:
diff changeset
670
kono
parents:
diff changeset
671 /* The maximum possible real kind type parameter is 16. First, try
kono
parents:
diff changeset
672 that for the kind, then fallback to trying kind=10 (Intel 80 bit)
kono
parents:
diff changeset
673 extended precision. If neither value works, just given up. */
kono
parents:
diff changeset
674 kind = 16;
kono
parents:
diff changeset
675 if (gfc_validate_kind (BT_REAL, kind, true) < 0)
kono
parents:
diff changeset
676 {
kono
parents:
diff changeset
677 kind = 10;
kono
parents:
diff changeset
678 if (gfc_validate_kind (BT_REAL, kind, true) < 0)
kono
parents:
diff changeset
679 {
kono
parents:
diff changeset
680 gfc_error ("Invalid exponent-letter %<q%> in "
kono
parents:
diff changeset
681 "real-literal-constant at %C");
kono
parents:
diff changeset
682 goto cleanup;
kono
parents:
diff changeset
683 }
kono
parents:
diff changeset
684 }
kono
parents:
diff changeset
685 break;
kono
parents:
diff changeset
686
kono
parents:
diff changeset
687 default:
kono
parents:
diff changeset
688 if (kind == -2)
kono
parents:
diff changeset
689 kind = gfc_default_real_kind;
kono
parents:
diff changeset
690
kono
parents:
diff changeset
691 if (kind == 4)
kono
parents:
diff changeset
692 {
kono
parents:
diff changeset
693 if (flag_real4_kind == 8)
kono
parents:
diff changeset
694 kind = 8;
kono
parents:
diff changeset
695 if (flag_real4_kind == 10)
kono
parents:
diff changeset
696 kind = 10;
kono
parents:
diff changeset
697 if (flag_real4_kind == 16)
kono
parents:
diff changeset
698 kind = 16;
kono
parents:
diff changeset
699 }
kono
parents:
diff changeset
700
kono
parents:
diff changeset
701 if (kind == 8)
kono
parents:
diff changeset
702 {
kono
parents:
diff changeset
703 if (flag_real8_kind == 4)
kono
parents:
diff changeset
704 kind = 4;
kono
parents:
diff changeset
705 if (flag_real8_kind == 10)
kono
parents:
diff changeset
706 kind = 10;
kono
parents:
diff changeset
707 if (flag_real8_kind == 16)
kono
parents:
diff changeset
708 kind = 16;
kono
parents:
diff changeset
709 }
kono
parents:
diff changeset
710
kono
parents:
diff changeset
711 if (gfc_validate_kind (BT_REAL, kind, true) < 0)
kono
parents:
diff changeset
712 {
kono
parents:
diff changeset
713 gfc_error ("Invalid real kind %d at %C", kind);
kono
parents:
diff changeset
714 goto cleanup;
kono
parents:
diff changeset
715 }
kono
parents:
diff changeset
716 }
kono
parents:
diff changeset
717
kono
parents:
diff changeset
718 e = gfc_convert_real (buffer, kind, &gfc_current_locus);
kono
parents:
diff changeset
719 if (negate)
kono
parents:
diff changeset
720 mpfr_neg (e->value.real, e->value.real, GFC_RND_MODE);
kono
parents:
diff changeset
721 e->ts.is_c_interop = is_iso_c;
kono
parents:
diff changeset
722
kono
parents:
diff changeset
723 switch (gfc_range_check (e))
kono
parents:
diff changeset
724 {
kono
parents:
diff changeset
725 case ARITH_OK:
kono
parents:
diff changeset
726 break;
kono
parents:
diff changeset
727 case ARITH_OVERFLOW:
kono
parents:
diff changeset
728 gfc_error ("Real constant overflows its kind at %C");
kono
parents:
diff changeset
729 goto cleanup;
kono
parents:
diff changeset
730
kono
parents:
diff changeset
731 case ARITH_UNDERFLOW:
kono
parents:
diff changeset
732 if (warn_underflow)
kono
parents:
diff changeset
733 gfc_warning (OPT_Wunderflow, "Real constant underflows its kind at %C");
kono
parents:
diff changeset
734 mpfr_set_ui (e->value.real, 0, GFC_RND_MODE);
kono
parents:
diff changeset
735 break;
kono
parents:
diff changeset
736
kono
parents:
diff changeset
737 default:
kono
parents:
diff changeset
738 gfc_internal_error ("gfc_range_check() returned bad value");
kono
parents:
diff changeset
739 }
kono
parents:
diff changeset
740
kono
parents:
diff changeset
741 /* Warn about trailing digits which suggest the user added too many
kono
parents:
diff changeset
742 trailing digits, which may cause the appearance of higher pecision
kono
parents:
diff changeset
743 than the kind kan support.
kono
parents:
diff changeset
744
kono
parents:
diff changeset
745 This is done by replacing the rightmost non-zero digit with zero
kono
parents:
diff changeset
746 and comparing with the original value. If these are equal, we
kono
parents:
diff changeset
747 assume the user supplied more digits than intended (or forgot to
kono
parents:
diff changeset
748 convert to the correct kind).
kono
parents:
diff changeset
749 */
kono
parents:
diff changeset
750
kono
parents:
diff changeset
751 if (warn_conversion_extra)
kono
parents:
diff changeset
752 {
kono
parents:
diff changeset
753 mpfr_t r;
kono
parents:
diff changeset
754 char *c, *p;
kono
parents:
diff changeset
755 bool did_break;
kono
parents:
diff changeset
756
kono
parents:
diff changeset
757 c = strchr (buffer, 'e');
kono
parents:
diff changeset
758 if (c == NULL)
kono
parents:
diff changeset
759 c = buffer + strlen(buffer);
kono
parents:
diff changeset
760
kono
parents:
diff changeset
761 did_break = false;
kono
parents:
diff changeset
762 for (p = c - 1; p >= buffer; p--)
kono
parents:
diff changeset
763 {
kono
parents:
diff changeset
764 if (*p == '.')
kono
parents:
diff changeset
765 continue;
kono
parents:
diff changeset
766
kono
parents:
diff changeset
767 if (*p != '0')
kono
parents:
diff changeset
768 {
kono
parents:
diff changeset
769 *p = '0';
kono
parents:
diff changeset
770 did_break = true;
kono
parents:
diff changeset
771 break;
kono
parents:
diff changeset
772 }
kono
parents:
diff changeset
773 }
kono
parents:
diff changeset
774
kono
parents:
diff changeset
775 if (did_break)
kono
parents:
diff changeset
776 {
kono
parents:
diff changeset
777 mpfr_init (r);
kono
parents:
diff changeset
778 mpfr_set_str (r, buffer, 10, GFC_RND_MODE);
kono
parents:
diff changeset
779 if (negate)
kono
parents:
diff changeset
780 mpfr_neg (r, r, GFC_RND_MODE);
kono
parents:
diff changeset
781
kono
parents:
diff changeset
782 mpfr_sub (r, r, e->value.real, GFC_RND_MODE);
kono
parents:
diff changeset
783
kono
parents:
diff changeset
784 if (mpfr_cmp_ui (r, 0) == 0)
kono
parents:
diff changeset
785 gfc_warning (OPT_Wconversion_extra, "Non-significant digits "
kono
parents:
diff changeset
786 "in %qs number at %C, maybe incorrect KIND",
kono
parents:
diff changeset
787 gfc_typename (&e->ts));
kono
parents:
diff changeset
788
kono
parents:
diff changeset
789 mpfr_clear (r);
kono
parents:
diff changeset
790 }
kono
parents:
diff changeset
791 }
kono
parents:
diff changeset
792
kono
parents:
diff changeset
793 *result = e;
kono
parents:
diff changeset
794 return MATCH_YES;
kono
parents:
diff changeset
795
kono
parents:
diff changeset
796 cleanup:
kono
parents:
diff changeset
797 gfc_free_expr (e);
kono
parents:
diff changeset
798 return MATCH_ERROR;
kono
parents:
diff changeset
799 }
kono
parents:
diff changeset
800
kono
parents:
diff changeset
801
kono
parents:
diff changeset
802 /* Match a substring reference. */
kono
parents:
diff changeset
803
kono
parents:
diff changeset
804 static match
kono
parents:
diff changeset
805 match_substring (gfc_charlen *cl, int init, gfc_ref **result, bool deferred)
kono
parents:
diff changeset
806 {
kono
parents:
diff changeset
807 gfc_expr *start, *end;
kono
parents:
diff changeset
808 locus old_loc;
kono
parents:
diff changeset
809 gfc_ref *ref;
kono
parents:
diff changeset
810 match m;
kono
parents:
diff changeset
811
kono
parents:
diff changeset
812 start = NULL;
kono
parents:
diff changeset
813 end = NULL;
kono
parents:
diff changeset
814
kono
parents:
diff changeset
815 old_loc = gfc_current_locus;
kono
parents:
diff changeset
816
kono
parents:
diff changeset
817 m = gfc_match_char ('(');
kono
parents:
diff changeset
818 if (m != MATCH_YES)
kono
parents:
diff changeset
819 return MATCH_NO;
kono
parents:
diff changeset
820
kono
parents:
diff changeset
821 if (gfc_match_char (':') != MATCH_YES)
kono
parents:
diff changeset
822 {
kono
parents:
diff changeset
823 if (init)
kono
parents:
diff changeset
824 m = gfc_match_init_expr (&start);
kono
parents:
diff changeset
825 else
kono
parents:
diff changeset
826 m = gfc_match_expr (&start);
kono
parents:
diff changeset
827
kono
parents:
diff changeset
828 if (m != MATCH_YES)
kono
parents:
diff changeset
829 {
kono
parents:
diff changeset
830 m = MATCH_NO;
kono
parents:
diff changeset
831 goto cleanup;
kono
parents:
diff changeset
832 }
kono
parents:
diff changeset
833
kono
parents:
diff changeset
834 m = gfc_match_char (':');
kono
parents:
diff changeset
835 if (m != MATCH_YES)
kono
parents:
diff changeset
836 goto cleanup;
kono
parents:
diff changeset
837 }
kono
parents:
diff changeset
838
kono
parents:
diff changeset
839 if (gfc_match_char (')') != MATCH_YES)
kono
parents:
diff changeset
840 {
kono
parents:
diff changeset
841 if (init)
kono
parents:
diff changeset
842 m = gfc_match_init_expr (&end);
kono
parents:
diff changeset
843 else
kono
parents:
diff changeset
844 m = gfc_match_expr (&end);
kono
parents:
diff changeset
845
kono
parents:
diff changeset
846 if (m == MATCH_NO)
kono
parents:
diff changeset
847 goto syntax;
kono
parents:
diff changeset
848 if (m == MATCH_ERROR)
kono
parents:
diff changeset
849 goto cleanup;
kono
parents:
diff changeset
850
kono
parents:
diff changeset
851 m = gfc_match_char (')');
kono
parents:
diff changeset
852 if (m == MATCH_NO)
kono
parents:
diff changeset
853 goto syntax;
kono
parents:
diff changeset
854 }
kono
parents:
diff changeset
855
kono
parents:
diff changeset
856 /* Optimize away the (:) reference. */
kono
parents:
diff changeset
857 if (start == NULL && end == NULL && !deferred)
kono
parents:
diff changeset
858 ref = NULL;
kono
parents:
diff changeset
859 else
kono
parents:
diff changeset
860 {
kono
parents:
diff changeset
861 ref = gfc_get_ref ();
kono
parents:
diff changeset
862
kono
parents:
diff changeset
863 ref->type = REF_SUBSTRING;
kono
parents:
diff changeset
864 if (start == NULL)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
865 start = gfc_get_int_expr (gfc_charlen_int_kind, NULL, 1);
111
kono
parents:
diff changeset
866 ref->u.ss.start = start;
kono
parents:
diff changeset
867 if (end == NULL && cl)
kono
parents:
diff changeset
868 end = gfc_copy_expr (cl->length);
kono
parents:
diff changeset
869 ref->u.ss.end = end;
kono
parents:
diff changeset
870 ref->u.ss.length = cl;
kono
parents:
diff changeset
871 }
kono
parents:
diff changeset
872
kono
parents:
diff changeset
873 *result = ref;
kono
parents:
diff changeset
874 return MATCH_YES;
kono
parents:
diff changeset
875
kono
parents:
diff changeset
876 syntax:
kono
parents:
diff changeset
877 gfc_error ("Syntax error in SUBSTRING specification at %C");
kono
parents:
diff changeset
878 m = MATCH_ERROR;
kono
parents:
diff changeset
879
kono
parents:
diff changeset
880 cleanup:
kono
parents:
diff changeset
881 gfc_free_expr (start);
kono
parents:
diff changeset
882 gfc_free_expr (end);
kono
parents:
diff changeset
883
kono
parents:
diff changeset
884 gfc_current_locus = old_loc;
kono
parents:
diff changeset
885 return m;
kono
parents:
diff changeset
886 }
kono
parents:
diff changeset
887
kono
parents:
diff changeset
888
kono
parents:
diff changeset
889 /* Reads the next character of a string constant, taking care to
kono
parents:
diff changeset
890 return doubled delimiters on the input as a single instance of
kono
parents:
diff changeset
891 the delimiter.
kono
parents:
diff changeset
892
kono
parents:
diff changeset
893 Special return values for "ret" argument are:
kono
parents:
diff changeset
894 -1 End of the string, as determined by the delimiter
kono
parents:
diff changeset
895 -2 Unterminated string detected
kono
parents:
diff changeset
896
kono
parents:
diff changeset
897 Backslash codes are also expanded at this time. */
kono
parents:
diff changeset
898
kono
parents:
diff changeset
899 static gfc_char_t
kono
parents:
diff changeset
900 next_string_char (gfc_char_t delimiter, int *ret)
kono
parents:
diff changeset
901 {
kono
parents:
diff changeset
902 locus old_locus;
kono
parents:
diff changeset
903 gfc_char_t c;
kono
parents:
diff changeset
904
kono
parents:
diff changeset
905 c = gfc_next_char_literal (INSTRING_WARN);
kono
parents:
diff changeset
906 *ret = 0;
kono
parents:
diff changeset
907
kono
parents:
diff changeset
908 if (c == '\n')
kono
parents:
diff changeset
909 {
kono
parents:
diff changeset
910 *ret = -2;
kono
parents:
diff changeset
911 return 0;
kono
parents:
diff changeset
912 }
kono
parents:
diff changeset
913
kono
parents:
diff changeset
914 if (flag_backslash && c == '\\')
kono
parents:
diff changeset
915 {
kono
parents:
diff changeset
916 old_locus = gfc_current_locus;
kono
parents:
diff changeset
917
kono
parents:
diff changeset
918 if (gfc_match_special_char (&c) == MATCH_NO)
kono
parents:
diff changeset
919 gfc_current_locus = old_locus;
kono
parents:
diff changeset
920
kono
parents:
diff changeset
921 if (!(gfc_option.allow_std & GFC_STD_GNU) && !inhibit_warnings)
kono
parents:
diff changeset
922 gfc_warning (0, "Extension: backslash character at %C");
kono
parents:
diff changeset
923 }
kono
parents:
diff changeset
924
kono
parents:
diff changeset
925 if (c != delimiter)
kono
parents:
diff changeset
926 return c;
kono
parents:
diff changeset
927
kono
parents:
diff changeset
928 old_locus = gfc_current_locus;
kono
parents:
diff changeset
929 c = gfc_next_char_literal (NONSTRING);
kono
parents:
diff changeset
930
kono
parents:
diff changeset
931 if (c == delimiter)
kono
parents:
diff changeset
932 return c;
kono
parents:
diff changeset
933 gfc_current_locus = old_locus;
kono
parents:
diff changeset
934
kono
parents:
diff changeset
935 *ret = -1;
kono
parents:
diff changeset
936 return 0;
kono
parents:
diff changeset
937 }
kono
parents:
diff changeset
938
kono
parents:
diff changeset
939
kono
parents:
diff changeset
940 /* Special case of gfc_match_name() that matches a parameter kind name
kono
parents:
diff changeset
941 before a string constant. This takes case of the weird but legal
kono
parents:
diff changeset
942 case of:
kono
parents:
diff changeset
943
kono
parents:
diff changeset
944 kind_____'string'
kono
parents:
diff changeset
945
kono
parents:
diff changeset
946 where kind____ is a parameter. gfc_match_name() will happily slurp
kono
parents:
diff changeset
947 up all the underscores, which leads to problems. If we return
kono
parents:
diff changeset
948 MATCH_YES, the parse pointer points to the final underscore, which
kono
parents:
diff changeset
949 is not part of the name. We never return MATCH_ERROR-- errors in
kono
parents:
diff changeset
950 the name will be detected later. */
kono
parents:
diff changeset
951
kono
parents:
diff changeset
952 static match
kono
parents:
diff changeset
953 match_charkind_name (char *name)
kono
parents:
diff changeset
954 {
kono
parents:
diff changeset
955 locus old_loc;
kono
parents:
diff changeset
956 char c, peek;
kono
parents:
diff changeset
957 int len;
kono
parents:
diff changeset
958
kono
parents:
diff changeset
959 gfc_gobble_whitespace ();
kono
parents:
diff changeset
960 c = gfc_next_ascii_char ();
kono
parents:
diff changeset
961 if (!ISALPHA (c))
kono
parents:
diff changeset
962 return MATCH_NO;
kono
parents:
diff changeset
963
kono
parents:
diff changeset
964 *name++ = c;
kono
parents:
diff changeset
965 len = 1;
kono
parents:
diff changeset
966
kono
parents:
diff changeset
967 for (;;)
kono
parents:
diff changeset
968 {
kono
parents:
diff changeset
969 old_loc = gfc_current_locus;
kono
parents:
diff changeset
970 c = gfc_next_ascii_char ();
kono
parents:
diff changeset
971
kono
parents:
diff changeset
972 if (c == '_')
kono
parents:
diff changeset
973 {
kono
parents:
diff changeset
974 peek = gfc_peek_ascii_char ();
kono
parents:
diff changeset
975
kono
parents:
diff changeset
976 if (peek == '\'' || peek == '\"')
kono
parents:
diff changeset
977 {
kono
parents:
diff changeset
978 gfc_current_locus = old_loc;
kono
parents:
diff changeset
979 *name = '\0';
kono
parents:
diff changeset
980 return MATCH_YES;
kono
parents:
diff changeset
981 }
kono
parents:
diff changeset
982 }
kono
parents:
diff changeset
983
kono
parents:
diff changeset
984 if (!ISALNUM (c)
kono
parents:
diff changeset
985 && c != '_'
kono
parents:
diff changeset
986 && (c != '$' || !flag_dollar_ok))
kono
parents:
diff changeset
987 break;
kono
parents:
diff changeset
988
kono
parents:
diff changeset
989 *name++ = c;
kono
parents:
diff changeset
990 if (++len > GFC_MAX_SYMBOL_LEN)
kono
parents:
diff changeset
991 break;
kono
parents:
diff changeset
992 }
kono
parents:
diff changeset
993
kono
parents:
diff changeset
994 return MATCH_NO;
kono
parents:
diff changeset
995 }
kono
parents:
diff changeset
996
kono
parents:
diff changeset
997
kono
parents:
diff changeset
998 /* See if the current input matches a character constant. Lots of
kono
parents:
diff changeset
999 contortions have to be done to match the kind parameter which comes
kono
parents:
diff changeset
1000 before the actual string. The main consideration is that we don't
kono
parents:
diff changeset
1001 want to error out too quickly. For example, we don't actually do
kono
parents:
diff changeset
1002 any validation of the kinds until we have actually seen a legal
kono
parents:
diff changeset
1003 delimiter. Using match_kind_param() generates errors too quickly. */
kono
parents:
diff changeset
1004
kono
parents:
diff changeset
1005 static match
kono
parents:
diff changeset
1006 match_string_constant (gfc_expr **result)
kono
parents:
diff changeset
1007 {
kono
parents:
diff changeset
1008 char name[GFC_MAX_SYMBOL_LEN + 1], peek;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1009 size_t length;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1010 int kind,save_warn_ampersand, ret;
111
kono
parents:
diff changeset
1011 locus old_locus, start_locus;
kono
parents:
diff changeset
1012 gfc_symbol *sym;
kono
parents:
diff changeset
1013 gfc_expr *e;
kono
parents:
diff changeset
1014 match m;
kono
parents:
diff changeset
1015 gfc_char_t c, delimiter, *p;
kono
parents:
diff changeset
1016
kono
parents:
diff changeset
1017 old_locus = gfc_current_locus;
kono
parents:
diff changeset
1018
kono
parents:
diff changeset
1019 gfc_gobble_whitespace ();
kono
parents:
diff changeset
1020
kono
parents:
diff changeset
1021 c = gfc_next_char ();
kono
parents:
diff changeset
1022 if (c == '\'' || c == '"')
kono
parents:
diff changeset
1023 {
kono
parents:
diff changeset
1024 kind = gfc_default_character_kind;
kono
parents:
diff changeset
1025 start_locus = gfc_current_locus;
kono
parents:
diff changeset
1026 goto got_delim;
kono
parents:
diff changeset
1027 }
kono
parents:
diff changeset
1028
kono
parents:
diff changeset
1029 if (gfc_wide_is_digit (c))
kono
parents:
diff changeset
1030 {
kono
parents:
diff changeset
1031 kind = 0;
kono
parents:
diff changeset
1032
kono
parents:
diff changeset
1033 while (gfc_wide_is_digit (c))
kono
parents:
diff changeset
1034 {
kono
parents:
diff changeset
1035 kind = kind * 10 + c - '0';
kono
parents:
diff changeset
1036 if (kind > 9999999)
kono
parents:
diff changeset
1037 goto no_match;
kono
parents:
diff changeset
1038 c = gfc_next_char ();
kono
parents:
diff changeset
1039 }
kono
parents:
diff changeset
1040
kono
parents:
diff changeset
1041 }
kono
parents:
diff changeset
1042 else
kono
parents:
diff changeset
1043 {
kono
parents:
diff changeset
1044 gfc_current_locus = old_locus;
kono
parents:
diff changeset
1045
kono
parents:
diff changeset
1046 m = match_charkind_name (name);
kono
parents:
diff changeset
1047 if (m != MATCH_YES)
kono
parents:
diff changeset
1048 goto no_match;
kono
parents:
diff changeset
1049
kono
parents:
diff changeset
1050 if (gfc_find_symbol (name, NULL, 1, &sym)
kono
parents:
diff changeset
1051 || sym == NULL
kono
parents:
diff changeset
1052 || sym->attr.flavor != FL_PARAMETER)
kono
parents:
diff changeset
1053 goto no_match;
kono
parents:
diff changeset
1054
kono
parents:
diff changeset
1055 kind = -1;
kono
parents:
diff changeset
1056 c = gfc_next_char ();
kono
parents:
diff changeset
1057 }
kono
parents:
diff changeset
1058
kono
parents:
diff changeset
1059 if (c == ' ')
kono
parents:
diff changeset
1060 {
kono
parents:
diff changeset
1061 gfc_gobble_whitespace ();
kono
parents:
diff changeset
1062 c = gfc_next_char ();
kono
parents:
diff changeset
1063 }
kono
parents:
diff changeset
1064
kono
parents:
diff changeset
1065 if (c != '_')
kono
parents:
diff changeset
1066 goto no_match;
kono
parents:
diff changeset
1067
kono
parents:
diff changeset
1068 gfc_gobble_whitespace ();
kono
parents:
diff changeset
1069
kono
parents:
diff changeset
1070 c = gfc_next_char ();
kono
parents:
diff changeset
1071 if (c != '\'' && c != '"')
kono
parents:
diff changeset
1072 goto no_match;
kono
parents:
diff changeset
1073
kono
parents:
diff changeset
1074 start_locus = gfc_current_locus;
kono
parents:
diff changeset
1075
kono
parents:
diff changeset
1076 if (kind == -1)
kono
parents:
diff changeset
1077 {
kono
parents:
diff changeset
1078 if (gfc_extract_int (sym->value, &kind, 1))
kono
parents:
diff changeset
1079 return MATCH_ERROR;
kono
parents:
diff changeset
1080 gfc_set_sym_referenced (sym);
kono
parents:
diff changeset
1081 }
kono
parents:
diff changeset
1082
kono
parents:
diff changeset
1083 if (gfc_validate_kind (BT_CHARACTER, kind, true) < 0)
kono
parents:
diff changeset
1084 {
kono
parents:
diff changeset
1085 gfc_error ("Invalid kind %d for CHARACTER constant at %C", kind);
kono
parents:
diff changeset
1086 return MATCH_ERROR;
kono
parents:
diff changeset
1087 }
kono
parents:
diff changeset
1088
kono
parents:
diff changeset
1089 got_delim:
kono
parents:
diff changeset
1090 /* Scan the string into a block of memory by first figuring out how
kono
parents:
diff changeset
1091 long it is, allocating the structure, then re-reading it. This
kono
parents:
diff changeset
1092 isn't particularly efficient, but string constants aren't that
kono
parents:
diff changeset
1093 common in most code. TODO: Use obstacks? */
kono
parents:
diff changeset
1094
kono
parents:
diff changeset
1095 delimiter = c;
kono
parents:
diff changeset
1096 length = 0;
kono
parents:
diff changeset
1097
kono
parents:
diff changeset
1098 for (;;)
kono
parents:
diff changeset
1099 {
kono
parents:
diff changeset
1100 c = next_string_char (delimiter, &ret);
kono
parents:
diff changeset
1101 if (ret == -1)
kono
parents:
diff changeset
1102 break;
kono
parents:
diff changeset
1103 if (ret == -2)
kono
parents:
diff changeset
1104 {
kono
parents:
diff changeset
1105 gfc_current_locus = start_locus;
kono
parents:
diff changeset
1106 gfc_error ("Unterminated character constant beginning at %C");
kono
parents:
diff changeset
1107 return MATCH_ERROR;
kono
parents:
diff changeset
1108 }
kono
parents:
diff changeset
1109
kono
parents:
diff changeset
1110 length++;
kono
parents:
diff changeset
1111 }
kono
parents:
diff changeset
1112
kono
parents:
diff changeset
1113 /* Peek at the next character to see if it is a b, o, z, or x for the
kono
parents:
diff changeset
1114 postfixed BOZ literal constants. */
kono
parents:
diff changeset
1115 peek = gfc_peek_ascii_char ();
kono
parents:
diff changeset
1116 if (peek == 'b' || peek == 'o' || peek =='z' || peek == 'x')
kono
parents:
diff changeset
1117 goto no_match;
kono
parents:
diff changeset
1118
kono
parents:
diff changeset
1119 e = gfc_get_character_expr (kind, &start_locus, NULL, length);
kono
parents:
diff changeset
1120
kono
parents:
diff changeset
1121 gfc_current_locus = start_locus;
kono
parents:
diff changeset
1122
kono
parents:
diff changeset
1123 /* We disable the warning for the following loop as the warning has already
kono
parents:
diff changeset
1124 been printed in the loop above. */
kono
parents:
diff changeset
1125 save_warn_ampersand = warn_ampersand;
kono
parents:
diff changeset
1126 warn_ampersand = false;
kono
parents:
diff changeset
1127
kono
parents:
diff changeset
1128 p = e->value.character.string;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1129 for (size_t i = 0; i < length; i++)
111
kono
parents:
diff changeset
1130 {
kono
parents:
diff changeset
1131 c = next_string_char (delimiter, &ret);
kono
parents:
diff changeset
1132
kono
parents:
diff changeset
1133 if (!gfc_check_character_range (c, kind))
kono
parents:
diff changeset
1134 {
kono
parents:
diff changeset
1135 gfc_free_expr (e);
kono
parents:
diff changeset
1136 gfc_error ("Character %qs in string at %C is not representable "
kono
parents:
diff changeset
1137 "in character kind %d", gfc_print_wide_char (c), kind);
kono
parents:
diff changeset
1138 return MATCH_ERROR;
kono
parents:
diff changeset
1139 }
kono
parents:
diff changeset
1140
kono
parents:
diff changeset
1141 *p++ = c;
kono
parents:
diff changeset
1142 }
kono
parents:
diff changeset
1143
kono
parents:
diff changeset
1144 *p = '\0'; /* TODO: C-style string is for development/debug purposes. */
kono
parents:
diff changeset
1145 warn_ampersand = save_warn_ampersand;
kono
parents:
diff changeset
1146
kono
parents:
diff changeset
1147 next_string_char (delimiter, &ret);
kono
parents:
diff changeset
1148 if (ret != -1)
kono
parents:
diff changeset
1149 gfc_internal_error ("match_string_constant(): Delimiter not found");
kono
parents:
diff changeset
1150
kono
parents:
diff changeset
1151 if (match_substring (NULL, 0, &e->ref, false) != MATCH_NO)
kono
parents:
diff changeset
1152 e->expr_type = EXPR_SUBSTRING;
kono
parents:
diff changeset
1153
kono
parents:
diff changeset
1154 *result = e;
kono
parents:
diff changeset
1155
kono
parents:
diff changeset
1156 return MATCH_YES;
kono
parents:
diff changeset
1157
kono
parents:
diff changeset
1158 no_match:
kono
parents:
diff changeset
1159 gfc_current_locus = old_locus;
kono
parents:
diff changeset
1160 return MATCH_NO;
kono
parents:
diff changeset
1161 }
kono
parents:
diff changeset
1162
kono
parents:
diff changeset
1163
kono
parents:
diff changeset
1164 /* Match a .true. or .false. Returns 1 if a .true. was found,
kono
parents:
diff changeset
1165 0 if a .false. was found, and -1 otherwise. */
kono
parents:
diff changeset
1166 static int
kono
parents:
diff changeset
1167 match_logical_constant_string (void)
kono
parents:
diff changeset
1168 {
kono
parents:
diff changeset
1169 locus orig_loc = gfc_current_locus;
kono
parents:
diff changeset
1170
kono
parents:
diff changeset
1171 gfc_gobble_whitespace ();
kono
parents:
diff changeset
1172 if (gfc_next_ascii_char () == '.')
kono
parents:
diff changeset
1173 {
kono
parents:
diff changeset
1174 char ch = gfc_next_ascii_char ();
kono
parents:
diff changeset
1175 if (ch == 'f')
kono
parents:
diff changeset
1176 {
kono
parents:
diff changeset
1177 if (gfc_next_ascii_char () == 'a'
kono
parents:
diff changeset
1178 && gfc_next_ascii_char () == 'l'
kono
parents:
diff changeset
1179 && gfc_next_ascii_char () == 's'
kono
parents:
diff changeset
1180 && gfc_next_ascii_char () == 'e'
kono
parents:
diff changeset
1181 && gfc_next_ascii_char () == '.')
kono
parents:
diff changeset
1182 /* Matched ".false.". */
kono
parents:
diff changeset
1183 return 0;
kono
parents:
diff changeset
1184 }
kono
parents:
diff changeset
1185 else if (ch == 't')
kono
parents:
diff changeset
1186 {
kono
parents:
diff changeset
1187 if (gfc_next_ascii_char () == 'r'
kono
parents:
diff changeset
1188 && gfc_next_ascii_char () == 'u'
kono
parents:
diff changeset
1189 && gfc_next_ascii_char () == 'e'
kono
parents:
diff changeset
1190 && gfc_next_ascii_char () == '.')
kono
parents:
diff changeset
1191 /* Matched ".true.". */
kono
parents:
diff changeset
1192 return 1;
kono
parents:
diff changeset
1193 }
kono
parents:
diff changeset
1194 }
kono
parents:
diff changeset
1195 gfc_current_locus = orig_loc;
kono
parents:
diff changeset
1196 return -1;
kono
parents:
diff changeset
1197 }
kono
parents:
diff changeset
1198
kono
parents:
diff changeset
1199 /* Match a .true. or .false. */
kono
parents:
diff changeset
1200
kono
parents:
diff changeset
1201 static match
kono
parents:
diff changeset
1202 match_logical_constant (gfc_expr **result)
kono
parents:
diff changeset
1203 {
kono
parents:
diff changeset
1204 gfc_expr *e;
kono
parents:
diff changeset
1205 int i, kind, is_iso_c;
kono
parents:
diff changeset
1206
kono
parents:
diff changeset
1207 i = match_logical_constant_string ();
kono
parents:
diff changeset
1208 if (i == -1)
kono
parents:
diff changeset
1209 return MATCH_NO;
kono
parents:
diff changeset
1210
kono
parents:
diff changeset
1211 kind = get_kind (&is_iso_c);
kono
parents:
diff changeset
1212 if (kind == -1)
kono
parents:
diff changeset
1213 return MATCH_ERROR;
kono
parents:
diff changeset
1214 if (kind == -2)
kono
parents:
diff changeset
1215 kind = gfc_default_logical_kind;
kono
parents:
diff changeset
1216
kono
parents:
diff changeset
1217 if (gfc_validate_kind (BT_LOGICAL, kind, true) < 0)
kono
parents:
diff changeset
1218 {
kono
parents:
diff changeset
1219 gfc_error ("Bad kind for logical constant at %C");
kono
parents:
diff changeset
1220 return MATCH_ERROR;
kono
parents:
diff changeset
1221 }
kono
parents:
diff changeset
1222
kono
parents:
diff changeset
1223 e = gfc_get_logical_expr (kind, &gfc_current_locus, i);
kono
parents:
diff changeset
1224 e->ts.is_c_interop = is_iso_c;
kono
parents:
diff changeset
1225
kono
parents:
diff changeset
1226 *result = e;
kono
parents:
diff changeset
1227 return MATCH_YES;
kono
parents:
diff changeset
1228 }
kono
parents:
diff changeset
1229
kono
parents:
diff changeset
1230
kono
parents:
diff changeset
1231 /* Match a real or imaginary part of a complex constant that is a
kono
parents:
diff changeset
1232 symbolic constant. */
kono
parents:
diff changeset
1233
kono
parents:
diff changeset
1234 static match
kono
parents:
diff changeset
1235 match_sym_complex_part (gfc_expr **result)
kono
parents:
diff changeset
1236 {
kono
parents:
diff changeset
1237 char name[GFC_MAX_SYMBOL_LEN + 1];
kono
parents:
diff changeset
1238 gfc_symbol *sym;
kono
parents:
diff changeset
1239 gfc_expr *e;
kono
parents:
diff changeset
1240 match m;
kono
parents:
diff changeset
1241
kono
parents:
diff changeset
1242 m = gfc_match_name (name);
kono
parents:
diff changeset
1243 if (m != MATCH_YES)
kono
parents:
diff changeset
1244 return m;
kono
parents:
diff changeset
1245
kono
parents:
diff changeset
1246 if (gfc_find_symbol (name, NULL, 1, &sym) || sym == NULL)
kono
parents:
diff changeset
1247 return MATCH_NO;
kono
parents:
diff changeset
1248
kono
parents:
diff changeset
1249 if (sym->attr.flavor != FL_PARAMETER)
kono
parents:
diff changeset
1250 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1251 /* Give the matcher for implied do-loops a chance to run. This yields
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1252 a much saner error message for "write(*,*) (i, i=1, 6" where the
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1253 right parenthesis is missing. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1254 char c;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1255 gfc_gobble_whitespace ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1256 c = gfc_peek_ascii_char ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1257 if (c == '=' || c == ',')
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1258 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1259 m = MATCH_NO;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1260 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1261 else
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1262 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1263 gfc_error ("Expected PARAMETER symbol in complex constant at %C");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1264 m = MATCH_ERROR;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1265 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1266 return m;
111
kono
parents:
diff changeset
1267 }
kono
parents:
diff changeset
1268
kono
parents:
diff changeset
1269 if (!sym->value)
kono
parents:
diff changeset
1270 goto error;
kono
parents:
diff changeset
1271
kono
parents:
diff changeset
1272 if (!gfc_numeric_ts (&sym->value->ts))
kono
parents:
diff changeset
1273 {
kono
parents:
diff changeset
1274 gfc_error ("Numeric PARAMETER required in complex constant at %C");
kono
parents:
diff changeset
1275 return MATCH_ERROR;
kono
parents:
diff changeset
1276 }
kono
parents:
diff changeset
1277
kono
parents:
diff changeset
1278 if (sym->value->rank != 0)
kono
parents:
diff changeset
1279 {
kono
parents:
diff changeset
1280 gfc_error ("Scalar PARAMETER required in complex constant at %C");
kono
parents:
diff changeset
1281 return MATCH_ERROR;
kono
parents:
diff changeset
1282 }
kono
parents:
diff changeset
1283
kono
parents:
diff changeset
1284 if (!gfc_notify_std (GFC_STD_F2003, "PARAMETER symbol in "
kono
parents:
diff changeset
1285 "complex constant at %C"))
kono
parents:
diff changeset
1286 return MATCH_ERROR;
kono
parents:
diff changeset
1287
kono
parents:
diff changeset
1288 switch (sym->value->ts.type)
kono
parents:
diff changeset
1289 {
kono
parents:
diff changeset
1290 case BT_REAL:
kono
parents:
diff changeset
1291 e = gfc_copy_expr (sym->value);
kono
parents:
diff changeset
1292 break;
kono
parents:
diff changeset
1293
kono
parents:
diff changeset
1294 case BT_COMPLEX:
kono
parents:
diff changeset
1295 e = gfc_complex2real (sym->value, sym->value->ts.kind);
kono
parents:
diff changeset
1296 if (e == NULL)
kono
parents:
diff changeset
1297 goto error;
kono
parents:
diff changeset
1298 break;
kono
parents:
diff changeset
1299
kono
parents:
diff changeset
1300 case BT_INTEGER:
kono
parents:
diff changeset
1301 e = gfc_int2real (sym->value, gfc_default_real_kind);
kono
parents:
diff changeset
1302 if (e == NULL)
kono
parents:
diff changeset
1303 goto error;
kono
parents:
diff changeset
1304 break;
kono
parents:
diff changeset
1305
kono
parents:
diff changeset
1306 default:
kono
parents:
diff changeset
1307 gfc_internal_error ("gfc_match_sym_complex_part(): Bad type");
kono
parents:
diff changeset
1308 }
kono
parents:
diff changeset
1309
kono
parents:
diff changeset
1310 *result = e; /* e is a scalar, real, constant expression. */
kono
parents:
diff changeset
1311 return MATCH_YES;
kono
parents:
diff changeset
1312
kono
parents:
diff changeset
1313 error:
kono
parents:
diff changeset
1314 gfc_error ("Error converting PARAMETER constant in complex constant at %C");
kono
parents:
diff changeset
1315 return MATCH_ERROR;
kono
parents:
diff changeset
1316 }
kono
parents:
diff changeset
1317
kono
parents:
diff changeset
1318
kono
parents:
diff changeset
1319 /* Match a real or imaginary part of a complex number. */
kono
parents:
diff changeset
1320
kono
parents:
diff changeset
1321 static match
kono
parents:
diff changeset
1322 match_complex_part (gfc_expr **result)
kono
parents:
diff changeset
1323 {
kono
parents:
diff changeset
1324 match m;
kono
parents:
diff changeset
1325
kono
parents:
diff changeset
1326 m = match_sym_complex_part (result);
kono
parents:
diff changeset
1327 if (m != MATCH_NO)
kono
parents:
diff changeset
1328 return m;
kono
parents:
diff changeset
1329
kono
parents:
diff changeset
1330 m = match_real_constant (result, 1);
kono
parents:
diff changeset
1331 if (m != MATCH_NO)
kono
parents:
diff changeset
1332 return m;
kono
parents:
diff changeset
1333
kono
parents:
diff changeset
1334 return match_integer_constant (result, 1);
kono
parents:
diff changeset
1335 }
kono
parents:
diff changeset
1336
kono
parents:
diff changeset
1337
kono
parents:
diff changeset
1338 /* Try to match a complex constant. */
kono
parents:
diff changeset
1339
kono
parents:
diff changeset
1340 static match
kono
parents:
diff changeset
1341 match_complex_constant (gfc_expr **result)
kono
parents:
diff changeset
1342 {
kono
parents:
diff changeset
1343 gfc_expr *e, *real, *imag;
kono
parents:
diff changeset
1344 gfc_error_buffer old_error;
kono
parents:
diff changeset
1345 gfc_typespec target;
kono
parents:
diff changeset
1346 locus old_loc;
kono
parents:
diff changeset
1347 int kind;
kono
parents:
diff changeset
1348 match m;
kono
parents:
diff changeset
1349
kono
parents:
diff changeset
1350 old_loc = gfc_current_locus;
kono
parents:
diff changeset
1351 real = imag = e = NULL;
kono
parents:
diff changeset
1352
kono
parents:
diff changeset
1353 m = gfc_match_char ('(');
kono
parents:
diff changeset
1354 if (m != MATCH_YES)
kono
parents:
diff changeset
1355 return m;
kono
parents:
diff changeset
1356
kono
parents:
diff changeset
1357 gfc_push_error (&old_error);
kono
parents:
diff changeset
1358
kono
parents:
diff changeset
1359 m = match_complex_part (&real);
kono
parents:
diff changeset
1360 if (m == MATCH_NO)
kono
parents:
diff changeset
1361 {
kono
parents:
diff changeset
1362 gfc_free_error (&old_error);
kono
parents:
diff changeset
1363 goto cleanup;
kono
parents:
diff changeset
1364 }
kono
parents:
diff changeset
1365
kono
parents:
diff changeset
1366 if (gfc_match_char (',') == MATCH_NO)
kono
parents:
diff changeset
1367 {
kono
parents:
diff changeset
1368 /* It is possible that gfc_int2real issued a warning when
kono
parents:
diff changeset
1369 converting an integer to real. Throw this away here. */
kono
parents:
diff changeset
1370
kono
parents:
diff changeset
1371 gfc_clear_warning ();
kono
parents:
diff changeset
1372 gfc_pop_error (&old_error);
kono
parents:
diff changeset
1373 m = MATCH_NO;
kono
parents:
diff changeset
1374 goto cleanup;
kono
parents:
diff changeset
1375 }
kono
parents:
diff changeset
1376
kono
parents:
diff changeset
1377 /* If m is error, then something was wrong with the real part and we
kono
parents:
diff changeset
1378 assume we have a complex constant because we've seen the ','. An
kono
parents:
diff changeset
1379 ambiguous case here is the start of an iterator list of some
kono
parents:
diff changeset
1380 sort. These sort of lists are matched prior to coming here. */
kono
parents:
diff changeset
1381
kono
parents:
diff changeset
1382 if (m == MATCH_ERROR)
kono
parents:
diff changeset
1383 {
kono
parents:
diff changeset
1384 gfc_free_error (&old_error);
kono
parents:
diff changeset
1385 goto cleanup;
kono
parents:
diff changeset
1386 }
kono
parents:
diff changeset
1387 gfc_pop_error (&old_error);
kono
parents:
diff changeset
1388
kono
parents:
diff changeset
1389 m = match_complex_part (&imag);
kono
parents:
diff changeset
1390 if (m == MATCH_NO)
kono
parents:
diff changeset
1391 goto syntax;
kono
parents:
diff changeset
1392 if (m == MATCH_ERROR)
kono
parents:
diff changeset
1393 goto cleanup;
kono
parents:
diff changeset
1394
kono
parents:
diff changeset
1395 m = gfc_match_char (')');
kono
parents:
diff changeset
1396 if (m == MATCH_NO)
kono
parents:
diff changeset
1397 {
kono
parents:
diff changeset
1398 /* Give the matcher for implied do-loops a chance to run. This
kono
parents:
diff changeset
1399 yields a much saner error message for (/ (i, 4=i, 6) /). */
kono
parents:
diff changeset
1400 if (gfc_peek_ascii_char () == '=')
kono
parents:
diff changeset
1401 {
kono
parents:
diff changeset
1402 m = MATCH_ERROR;
kono
parents:
diff changeset
1403 goto cleanup;
kono
parents:
diff changeset
1404 }
kono
parents:
diff changeset
1405 else
kono
parents:
diff changeset
1406 goto syntax;
kono
parents:
diff changeset
1407 }
kono
parents:
diff changeset
1408
kono
parents:
diff changeset
1409 if (m == MATCH_ERROR)
kono
parents:
diff changeset
1410 goto cleanup;
kono
parents:
diff changeset
1411
kono
parents:
diff changeset
1412 /* Decide on the kind of this complex number. */
kono
parents:
diff changeset
1413 if (real->ts.type == BT_REAL)
kono
parents:
diff changeset
1414 {
kono
parents:
diff changeset
1415 if (imag->ts.type == BT_REAL)
kono
parents:
diff changeset
1416 kind = gfc_kind_max (real, imag);
kono
parents:
diff changeset
1417 else
kono
parents:
diff changeset
1418 kind = real->ts.kind;
kono
parents:
diff changeset
1419 }
kono
parents:
diff changeset
1420 else
kono
parents:
diff changeset
1421 {
kono
parents:
diff changeset
1422 if (imag->ts.type == BT_REAL)
kono
parents:
diff changeset
1423 kind = imag->ts.kind;
kono
parents:
diff changeset
1424 else
kono
parents:
diff changeset
1425 kind = gfc_default_real_kind;
kono
parents:
diff changeset
1426 }
kono
parents:
diff changeset
1427 gfc_clear_ts (&target);
kono
parents:
diff changeset
1428 target.type = BT_REAL;
kono
parents:
diff changeset
1429 target.kind = kind;
kono
parents:
diff changeset
1430
kono
parents:
diff changeset
1431 if (real->ts.type != BT_REAL || kind != real->ts.kind)
kono
parents:
diff changeset
1432 gfc_convert_type (real, &target, 2);
kono
parents:
diff changeset
1433 if (imag->ts.type != BT_REAL || kind != imag->ts.kind)
kono
parents:
diff changeset
1434 gfc_convert_type (imag, &target, 2);
kono
parents:
diff changeset
1435
kono
parents:
diff changeset
1436 e = gfc_convert_complex (real, imag, kind);
kono
parents:
diff changeset
1437 e->where = gfc_current_locus;
kono
parents:
diff changeset
1438
kono
parents:
diff changeset
1439 gfc_free_expr (real);
kono
parents:
diff changeset
1440 gfc_free_expr (imag);
kono
parents:
diff changeset
1441
kono
parents:
diff changeset
1442 *result = e;
kono
parents:
diff changeset
1443 return MATCH_YES;
kono
parents:
diff changeset
1444
kono
parents:
diff changeset
1445 syntax:
kono
parents:
diff changeset
1446 gfc_error ("Syntax error in COMPLEX constant at %C");
kono
parents:
diff changeset
1447 m = MATCH_ERROR;
kono
parents:
diff changeset
1448
kono
parents:
diff changeset
1449 cleanup:
kono
parents:
diff changeset
1450 gfc_free_expr (e);
kono
parents:
diff changeset
1451 gfc_free_expr (real);
kono
parents:
diff changeset
1452 gfc_free_expr (imag);
kono
parents:
diff changeset
1453 gfc_current_locus = old_loc;
kono
parents:
diff changeset
1454
kono
parents:
diff changeset
1455 return m;
kono
parents:
diff changeset
1456 }
kono
parents:
diff changeset
1457
kono
parents:
diff changeset
1458
kono
parents:
diff changeset
1459 /* Match constants in any of several forms. Returns nonzero for a
kono
parents:
diff changeset
1460 match, zero for no match. */
kono
parents:
diff changeset
1461
kono
parents:
diff changeset
1462 match
kono
parents:
diff changeset
1463 gfc_match_literal_constant (gfc_expr **result, int signflag)
kono
parents:
diff changeset
1464 {
kono
parents:
diff changeset
1465 match m;
kono
parents:
diff changeset
1466
kono
parents:
diff changeset
1467 m = match_complex_constant (result);
kono
parents:
diff changeset
1468 if (m != MATCH_NO)
kono
parents:
diff changeset
1469 return m;
kono
parents:
diff changeset
1470
kono
parents:
diff changeset
1471 m = match_string_constant (result);
kono
parents:
diff changeset
1472 if (m != MATCH_NO)
kono
parents:
diff changeset
1473 return m;
kono
parents:
diff changeset
1474
kono
parents:
diff changeset
1475 m = match_boz_constant (result);
kono
parents:
diff changeset
1476 if (m != MATCH_NO)
kono
parents:
diff changeset
1477 return m;
kono
parents:
diff changeset
1478
kono
parents:
diff changeset
1479 m = match_real_constant (result, signflag);
kono
parents:
diff changeset
1480 if (m != MATCH_NO)
kono
parents:
diff changeset
1481 return m;
kono
parents:
diff changeset
1482
kono
parents:
diff changeset
1483 m = match_hollerith_constant (result);
kono
parents:
diff changeset
1484 if (m != MATCH_NO)
kono
parents:
diff changeset
1485 return m;
kono
parents:
diff changeset
1486
kono
parents:
diff changeset
1487 m = match_integer_constant (result, signflag);
kono
parents:
diff changeset
1488 if (m != MATCH_NO)
kono
parents:
diff changeset
1489 return m;
kono
parents:
diff changeset
1490
kono
parents:
diff changeset
1491 m = match_logical_constant (result);
kono
parents:
diff changeset
1492 if (m != MATCH_NO)
kono
parents:
diff changeset
1493 return m;
kono
parents:
diff changeset
1494
kono
parents:
diff changeset
1495 return MATCH_NO;
kono
parents:
diff changeset
1496 }
kono
parents:
diff changeset
1497
kono
parents:
diff changeset
1498
kono
parents:
diff changeset
1499 /* This checks if a symbol is the return value of an encompassing function.
kono
parents:
diff changeset
1500 Function nesting can be maximally two levels deep, but we may have
kono
parents:
diff changeset
1501 additional local namespaces like BLOCK etc. */
kono
parents:
diff changeset
1502
kono
parents:
diff changeset
1503 bool
kono
parents:
diff changeset
1504 gfc_is_function_return_value (gfc_symbol *sym, gfc_namespace *ns)
kono
parents:
diff changeset
1505 {
kono
parents:
diff changeset
1506 if (!sym->attr.function || (sym->result != sym))
kono
parents:
diff changeset
1507 return false;
kono
parents:
diff changeset
1508 while (ns)
kono
parents:
diff changeset
1509 {
kono
parents:
diff changeset
1510 if (ns->proc_name == sym)
kono
parents:
diff changeset
1511 return true;
kono
parents:
diff changeset
1512 ns = ns->parent;
kono
parents:
diff changeset
1513 }
kono
parents:
diff changeset
1514 return false;
kono
parents:
diff changeset
1515 }
kono
parents:
diff changeset
1516
kono
parents:
diff changeset
1517
kono
parents:
diff changeset
1518 /* Match a single actual argument value. An actual argument is
kono
parents:
diff changeset
1519 usually an expression, but can also be a procedure name. If the
kono
parents:
diff changeset
1520 argument is a single name, it is not always possible to tell
kono
parents:
diff changeset
1521 whether the name is a dummy procedure or not. We treat these cases
kono
parents:
diff changeset
1522 by creating an argument that looks like a dummy procedure and
kono
parents:
diff changeset
1523 fixing things later during resolution. */
kono
parents:
diff changeset
1524
kono
parents:
diff changeset
1525 static match
kono
parents:
diff changeset
1526 match_actual_arg (gfc_expr **result)
kono
parents:
diff changeset
1527 {
kono
parents:
diff changeset
1528 char name[GFC_MAX_SYMBOL_LEN + 1];
kono
parents:
diff changeset
1529 gfc_symtree *symtree;
kono
parents:
diff changeset
1530 locus where, w;
kono
parents:
diff changeset
1531 gfc_expr *e;
kono
parents:
diff changeset
1532 char c;
kono
parents:
diff changeset
1533
kono
parents:
diff changeset
1534 gfc_gobble_whitespace ();
kono
parents:
diff changeset
1535 where = gfc_current_locus;
kono
parents:
diff changeset
1536
kono
parents:
diff changeset
1537 switch (gfc_match_name (name))
kono
parents:
diff changeset
1538 {
kono
parents:
diff changeset
1539 case MATCH_ERROR:
kono
parents:
diff changeset
1540 return MATCH_ERROR;
kono
parents:
diff changeset
1541
kono
parents:
diff changeset
1542 case MATCH_NO:
kono
parents:
diff changeset
1543 break;
kono
parents:
diff changeset
1544
kono
parents:
diff changeset
1545 case MATCH_YES:
kono
parents:
diff changeset
1546 w = gfc_current_locus;
kono
parents:
diff changeset
1547 gfc_gobble_whitespace ();
kono
parents:
diff changeset
1548 c = gfc_next_ascii_char ();
kono
parents:
diff changeset
1549 gfc_current_locus = w;
kono
parents:
diff changeset
1550
kono
parents:
diff changeset
1551 if (c != ',' && c != ')')
kono
parents:
diff changeset
1552 break;
kono
parents:
diff changeset
1553
kono
parents:
diff changeset
1554 if (gfc_find_sym_tree (name, NULL, 1, &symtree))
kono
parents:
diff changeset
1555 break;
kono
parents:
diff changeset
1556 /* Handle error elsewhere. */
kono
parents:
diff changeset
1557
kono
parents:
diff changeset
1558 /* Eliminate a couple of common cases where we know we don't
kono
parents:
diff changeset
1559 have a function argument. */
kono
parents:
diff changeset
1560 if (symtree == NULL)
kono
parents:
diff changeset
1561 {
kono
parents:
diff changeset
1562 gfc_get_sym_tree (name, NULL, &symtree, false);
kono
parents:
diff changeset
1563 gfc_set_sym_referenced (symtree->n.sym);
kono
parents:
diff changeset
1564 }
kono
parents:
diff changeset
1565 else
kono
parents:
diff changeset
1566 {
kono
parents:
diff changeset
1567 gfc_symbol *sym;
kono
parents:
diff changeset
1568
kono
parents:
diff changeset
1569 sym = symtree->n.sym;
kono
parents:
diff changeset
1570 gfc_set_sym_referenced (sym);
kono
parents:
diff changeset
1571 if (sym->attr.flavor == FL_NAMELIST)
kono
parents:
diff changeset
1572 {
kono
parents:
diff changeset
1573 gfc_error ("Namelist %qs can not be an argument at %L",
kono
parents:
diff changeset
1574 sym->name, &where);
kono
parents:
diff changeset
1575 break;
kono
parents:
diff changeset
1576 }
kono
parents:
diff changeset
1577 if (sym->attr.flavor != FL_PROCEDURE
kono
parents:
diff changeset
1578 && sym->attr.flavor != FL_UNKNOWN)
kono
parents:
diff changeset
1579 break;
kono
parents:
diff changeset
1580
kono
parents:
diff changeset
1581 if (sym->attr.in_common && !sym->attr.proc_pointer)
kono
parents:
diff changeset
1582 {
kono
parents:
diff changeset
1583 if (!gfc_add_flavor (&sym->attr, FL_VARIABLE,
kono
parents:
diff changeset
1584 sym->name, &sym->declared_at))
kono
parents:
diff changeset
1585 return MATCH_ERROR;
kono
parents:
diff changeset
1586 break;
kono
parents:
diff changeset
1587 }
kono
parents:
diff changeset
1588
kono
parents:
diff changeset
1589 /* If the symbol is a function with itself as the result and
kono
parents:
diff changeset
1590 is being defined, then we have a variable. */
kono
parents:
diff changeset
1591 if (sym->attr.function && sym->result == sym)
kono
parents:
diff changeset
1592 {
kono
parents:
diff changeset
1593 if (gfc_is_function_return_value (sym, gfc_current_ns))
kono
parents:
diff changeset
1594 break;
kono
parents:
diff changeset
1595
kono
parents:
diff changeset
1596 if (sym->attr.entry
kono
parents:
diff changeset
1597 && (sym->ns == gfc_current_ns
kono
parents:
diff changeset
1598 || sym->ns == gfc_current_ns->parent))
kono
parents:
diff changeset
1599 {
kono
parents:
diff changeset
1600 gfc_entry_list *el = NULL;
kono
parents:
diff changeset
1601
kono
parents:
diff changeset
1602 for (el = sym->ns->entries; el; el = el->next)
kono
parents:
diff changeset
1603 if (sym == el->sym)
kono
parents:
diff changeset
1604 break;
kono
parents:
diff changeset
1605
kono
parents:
diff changeset
1606 if (el)
kono
parents:
diff changeset
1607 break;
kono
parents:
diff changeset
1608 }
kono
parents:
diff changeset
1609 }
kono
parents:
diff changeset
1610 }
kono
parents:
diff changeset
1611
kono
parents:
diff changeset
1612 e = gfc_get_expr (); /* Leave it unknown for now */
kono
parents:
diff changeset
1613 e->symtree = symtree;
kono
parents:
diff changeset
1614 e->expr_type = EXPR_VARIABLE;
kono
parents:
diff changeset
1615 e->ts.type = BT_PROCEDURE;
kono
parents:
diff changeset
1616 e->where = where;
kono
parents:
diff changeset
1617
kono
parents:
diff changeset
1618 *result = e;
kono
parents:
diff changeset
1619 return MATCH_YES;
kono
parents:
diff changeset
1620 }
kono
parents:
diff changeset
1621
kono
parents:
diff changeset
1622 gfc_current_locus = where;
kono
parents:
diff changeset
1623 return gfc_match_expr (result);
kono
parents:
diff changeset
1624 }
kono
parents:
diff changeset
1625
kono
parents:
diff changeset
1626
kono
parents:
diff changeset
1627 /* Match a keyword argument or type parameter spec list.. */
kono
parents:
diff changeset
1628
kono
parents:
diff changeset
1629 static match
kono
parents:
diff changeset
1630 match_keyword_arg (gfc_actual_arglist *actual, gfc_actual_arglist *base, bool pdt)
kono
parents:
diff changeset
1631 {
kono
parents:
diff changeset
1632 char name[GFC_MAX_SYMBOL_LEN + 1];
kono
parents:
diff changeset
1633 gfc_actual_arglist *a;
kono
parents:
diff changeset
1634 locus name_locus;
kono
parents:
diff changeset
1635 match m;
kono
parents:
diff changeset
1636
kono
parents:
diff changeset
1637 name_locus = gfc_current_locus;
kono
parents:
diff changeset
1638 m = gfc_match_name (name);
kono
parents:
diff changeset
1639
kono
parents:
diff changeset
1640 if (m != MATCH_YES)
kono
parents:
diff changeset
1641 goto cleanup;
kono
parents:
diff changeset
1642 if (gfc_match_char ('=') != MATCH_YES)
kono
parents:
diff changeset
1643 {
kono
parents:
diff changeset
1644 m = MATCH_NO;
kono
parents:
diff changeset
1645 goto cleanup;
kono
parents:
diff changeset
1646 }
kono
parents:
diff changeset
1647
kono
parents:
diff changeset
1648 if (pdt)
kono
parents:
diff changeset
1649 {
kono
parents:
diff changeset
1650 if (gfc_match_char ('*') == MATCH_YES)
kono
parents:
diff changeset
1651 {
kono
parents:
diff changeset
1652 actual->spec_type = SPEC_ASSUMED;
kono
parents:
diff changeset
1653 goto add_name;
kono
parents:
diff changeset
1654 }
kono
parents:
diff changeset
1655 else if (gfc_match_char (':') == MATCH_YES)
kono
parents:
diff changeset
1656 {
kono
parents:
diff changeset
1657 actual->spec_type = SPEC_DEFERRED;
kono
parents:
diff changeset
1658 goto add_name;
kono
parents:
diff changeset
1659 }
kono
parents:
diff changeset
1660 else
kono
parents:
diff changeset
1661 actual->spec_type = SPEC_EXPLICIT;
kono
parents:
diff changeset
1662 }
kono
parents:
diff changeset
1663
kono
parents:
diff changeset
1664 m = match_actual_arg (&actual->expr);
kono
parents:
diff changeset
1665 if (m != MATCH_YES)
kono
parents:
diff changeset
1666 goto cleanup;
kono
parents:
diff changeset
1667
kono
parents:
diff changeset
1668 /* Make sure this name has not appeared yet. */
kono
parents:
diff changeset
1669 add_name:
kono
parents:
diff changeset
1670 if (name[0] != '\0')
kono
parents:
diff changeset
1671 {
kono
parents:
diff changeset
1672 for (a = base; a; a = a->next)
kono
parents:
diff changeset
1673 if (a->name != NULL && strcmp (a->name, name) == 0)
kono
parents:
diff changeset
1674 {
kono
parents:
diff changeset
1675 gfc_error ("Keyword %qs at %C has already appeared in the "
kono
parents:
diff changeset
1676 "current argument list", name);
kono
parents:
diff changeset
1677 return MATCH_ERROR;
kono
parents:
diff changeset
1678 }
kono
parents:
diff changeset
1679 }
kono
parents:
diff changeset
1680
kono
parents:
diff changeset
1681 actual->name = gfc_get_string ("%s", name);
kono
parents:
diff changeset
1682 return MATCH_YES;
kono
parents:
diff changeset
1683
kono
parents:
diff changeset
1684 cleanup:
kono
parents:
diff changeset
1685 gfc_current_locus = name_locus;
kono
parents:
diff changeset
1686 return m;
kono
parents:
diff changeset
1687 }
kono
parents:
diff changeset
1688
kono
parents:
diff changeset
1689
kono
parents:
diff changeset
1690 /* Match an argument list function, such as %VAL. */
kono
parents:
diff changeset
1691
kono
parents:
diff changeset
1692 static match
kono
parents:
diff changeset
1693 match_arg_list_function (gfc_actual_arglist *result)
kono
parents:
diff changeset
1694 {
kono
parents:
diff changeset
1695 char name[GFC_MAX_SYMBOL_LEN + 1];
kono
parents:
diff changeset
1696 locus old_locus;
kono
parents:
diff changeset
1697 match m;
kono
parents:
diff changeset
1698
kono
parents:
diff changeset
1699 old_locus = gfc_current_locus;
kono
parents:
diff changeset
1700
kono
parents:
diff changeset
1701 if (gfc_match_char ('%') != MATCH_YES)
kono
parents:
diff changeset
1702 {
kono
parents:
diff changeset
1703 m = MATCH_NO;
kono
parents:
diff changeset
1704 goto cleanup;
kono
parents:
diff changeset
1705 }
kono
parents:
diff changeset
1706
kono
parents:
diff changeset
1707 m = gfc_match ("%n (", name);
kono
parents:
diff changeset
1708 if (m != MATCH_YES)
kono
parents:
diff changeset
1709 goto cleanup;
kono
parents:
diff changeset
1710
kono
parents:
diff changeset
1711 if (name[0] != '\0')
kono
parents:
diff changeset
1712 {
kono
parents:
diff changeset
1713 switch (name[0])
kono
parents:
diff changeset
1714 {
kono
parents:
diff changeset
1715 case 'l':
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1716 if (gfc_str_startswith (name, "loc"))
111
kono
parents:
diff changeset
1717 {
kono
parents:
diff changeset
1718 result->name = "%LOC";
kono
parents:
diff changeset
1719 break;
kono
parents:
diff changeset
1720 }
kono
parents:
diff changeset
1721 /* FALLTHRU */
kono
parents:
diff changeset
1722 case 'r':
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1723 if (gfc_str_startswith (name, "ref"))
111
kono
parents:
diff changeset
1724 {
kono
parents:
diff changeset
1725 result->name = "%REF";
kono
parents:
diff changeset
1726 break;
kono
parents:
diff changeset
1727 }
kono
parents:
diff changeset
1728 /* FALLTHRU */
kono
parents:
diff changeset
1729 case 'v':
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1730 if (gfc_str_startswith (name, "val"))
111
kono
parents:
diff changeset
1731 {
kono
parents:
diff changeset
1732 result->name = "%VAL";
kono
parents:
diff changeset
1733 break;
kono
parents:
diff changeset
1734 }
kono
parents:
diff changeset
1735 /* FALLTHRU */
kono
parents:
diff changeset
1736 default:
kono
parents:
diff changeset
1737 m = MATCH_ERROR;
kono
parents:
diff changeset
1738 goto cleanup;
kono
parents:
diff changeset
1739 }
kono
parents:
diff changeset
1740 }
kono
parents:
diff changeset
1741
kono
parents:
diff changeset
1742 if (!gfc_notify_std (GFC_STD_GNU, "argument list function at %C"))
kono
parents:
diff changeset
1743 {
kono
parents:
diff changeset
1744 m = MATCH_ERROR;
kono
parents:
diff changeset
1745 goto cleanup;
kono
parents:
diff changeset
1746 }
kono
parents:
diff changeset
1747
kono
parents:
diff changeset
1748 m = match_actual_arg (&result->expr);
kono
parents:
diff changeset
1749 if (m != MATCH_YES)
kono
parents:
diff changeset
1750 goto cleanup;
kono
parents:
diff changeset
1751
kono
parents:
diff changeset
1752 if (gfc_match_char (')') != MATCH_YES)
kono
parents:
diff changeset
1753 {
kono
parents:
diff changeset
1754 m = MATCH_NO;
kono
parents:
diff changeset
1755 goto cleanup;
kono
parents:
diff changeset
1756 }
kono
parents:
diff changeset
1757
kono
parents:
diff changeset
1758 return MATCH_YES;
kono
parents:
diff changeset
1759
kono
parents:
diff changeset
1760 cleanup:
kono
parents:
diff changeset
1761 gfc_current_locus = old_locus;
kono
parents:
diff changeset
1762 return m;
kono
parents:
diff changeset
1763 }
kono
parents:
diff changeset
1764
kono
parents:
diff changeset
1765
kono
parents:
diff changeset
1766 /* Matches an actual argument list of a function or subroutine, from
kono
parents:
diff changeset
1767 the opening parenthesis to the closing parenthesis. The argument
kono
parents:
diff changeset
1768 list is assumed to allow keyword arguments because we don't know if
kono
parents:
diff changeset
1769 the symbol associated with the procedure has an implicit interface
kono
parents:
diff changeset
1770 or not. We make sure keywords are unique. If sub_flag is set,
kono
parents:
diff changeset
1771 we're matching the argument list of a subroutine.
kono
parents:
diff changeset
1772
kono
parents:
diff changeset
1773 NOTE: An alternative use for this function is to match type parameter
kono
parents:
diff changeset
1774 spec lists, which are so similar to actual argument lists that the
kono
parents:
diff changeset
1775 machinery can be reused. This use is flagged by the optional argument
kono
parents:
diff changeset
1776 'pdt'. */
kono
parents:
diff changeset
1777
kono
parents:
diff changeset
1778 match
kono
parents:
diff changeset
1779 gfc_match_actual_arglist (int sub_flag, gfc_actual_arglist **argp, bool pdt)
kono
parents:
diff changeset
1780 {
kono
parents:
diff changeset
1781 gfc_actual_arglist *head, *tail;
kono
parents:
diff changeset
1782 int seen_keyword;
kono
parents:
diff changeset
1783 gfc_st_label *label;
kono
parents:
diff changeset
1784 locus old_loc;
kono
parents:
diff changeset
1785 match m;
kono
parents:
diff changeset
1786
kono
parents:
diff changeset
1787 *argp = tail = NULL;
kono
parents:
diff changeset
1788 old_loc = gfc_current_locus;
kono
parents:
diff changeset
1789
kono
parents:
diff changeset
1790 seen_keyword = 0;
kono
parents:
diff changeset
1791
kono
parents:
diff changeset
1792 if (gfc_match_char ('(') == MATCH_NO)
kono
parents:
diff changeset
1793 return (sub_flag) ? MATCH_YES : MATCH_NO;
kono
parents:
diff changeset
1794
kono
parents:
diff changeset
1795 if (gfc_match_char (')') == MATCH_YES)
kono
parents:
diff changeset
1796 return MATCH_YES;
kono
parents:
diff changeset
1797
kono
parents:
diff changeset
1798 head = NULL;
kono
parents:
diff changeset
1799
kono
parents:
diff changeset
1800 matching_actual_arglist++;
kono
parents:
diff changeset
1801
kono
parents:
diff changeset
1802 for (;;)
kono
parents:
diff changeset
1803 {
kono
parents:
diff changeset
1804 if (head == NULL)
kono
parents:
diff changeset
1805 head = tail = gfc_get_actual_arglist ();
kono
parents:
diff changeset
1806 else
kono
parents:
diff changeset
1807 {
kono
parents:
diff changeset
1808 tail->next = gfc_get_actual_arglist ();
kono
parents:
diff changeset
1809 tail = tail->next;
kono
parents:
diff changeset
1810 }
kono
parents:
diff changeset
1811
kono
parents:
diff changeset
1812 if (sub_flag && !pdt && gfc_match_char ('*') == MATCH_YES)
kono
parents:
diff changeset
1813 {
kono
parents:
diff changeset
1814 m = gfc_match_st_label (&label);
kono
parents:
diff changeset
1815 if (m == MATCH_NO)
kono
parents:
diff changeset
1816 gfc_error ("Expected alternate return label at %C");
kono
parents:
diff changeset
1817 if (m != MATCH_YES)
kono
parents:
diff changeset
1818 goto cleanup;
kono
parents:
diff changeset
1819
kono
parents:
diff changeset
1820 if (!gfc_notify_std (GFC_STD_F95_OBS, "Alternate-return argument "
kono
parents:
diff changeset
1821 "at %C"))
kono
parents:
diff changeset
1822 goto cleanup;
kono
parents:
diff changeset
1823
kono
parents:
diff changeset
1824 tail->label = label;
kono
parents:
diff changeset
1825 goto next;
kono
parents:
diff changeset
1826 }
kono
parents:
diff changeset
1827
kono
parents:
diff changeset
1828 if (pdt && !seen_keyword)
kono
parents:
diff changeset
1829 {
kono
parents:
diff changeset
1830 if (gfc_match_char (':') == MATCH_YES)
kono
parents:
diff changeset
1831 {
kono
parents:
diff changeset
1832 tail->spec_type = SPEC_DEFERRED;
kono
parents:
diff changeset
1833 goto next;
kono
parents:
diff changeset
1834 }
kono
parents:
diff changeset
1835 else if (gfc_match_char ('*') == MATCH_YES)
kono
parents:
diff changeset
1836 {
kono
parents:
diff changeset
1837 tail->spec_type = SPEC_ASSUMED;
kono
parents:
diff changeset
1838 goto next;
kono
parents:
diff changeset
1839 }
kono
parents:
diff changeset
1840 else
kono
parents:
diff changeset
1841 tail->spec_type = SPEC_EXPLICIT;
kono
parents:
diff changeset
1842
kono
parents:
diff changeset
1843 m = match_keyword_arg (tail, head, pdt);
kono
parents:
diff changeset
1844 if (m == MATCH_YES)
kono
parents:
diff changeset
1845 {
kono
parents:
diff changeset
1846 seen_keyword = 1;
kono
parents:
diff changeset
1847 goto next;
kono
parents:
diff changeset
1848 }
kono
parents:
diff changeset
1849 if (m == MATCH_ERROR)
kono
parents:
diff changeset
1850 goto cleanup;
kono
parents:
diff changeset
1851 }
kono
parents:
diff changeset
1852
kono
parents:
diff changeset
1853 /* After the first keyword argument is seen, the following
kono
parents:
diff changeset
1854 arguments must also have keywords. */
kono
parents:
diff changeset
1855 if (seen_keyword)
kono
parents:
diff changeset
1856 {
kono
parents:
diff changeset
1857 m = match_keyword_arg (tail, head, pdt);
kono
parents:
diff changeset
1858
kono
parents:
diff changeset
1859 if (m == MATCH_ERROR)
kono
parents:
diff changeset
1860 goto cleanup;
kono
parents:
diff changeset
1861 if (m == MATCH_NO)
kono
parents:
diff changeset
1862 {
kono
parents:
diff changeset
1863 gfc_error ("Missing keyword name in actual argument list at %C");
kono
parents:
diff changeset
1864 goto cleanup;
kono
parents:
diff changeset
1865 }
kono
parents:
diff changeset
1866
kono
parents:
diff changeset
1867 }
kono
parents:
diff changeset
1868 else
kono
parents:
diff changeset
1869 {
kono
parents:
diff changeset
1870 /* Try an argument list function, like %VAL. */
kono
parents:
diff changeset
1871 m = match_arg_list_function (tail);
kono
parents:
diff changeset
1872 if (m == MATCH_ERROR)
kono
parents:
diff changeset
1873 goto cleanup;
kono
parents:
diff changeset
1874
kono
parents:
diff changeset
1875 /* See if we have the first keyword argument. */
kono
parents:
diff changeset
1876 if (m == MATCH_NO)
kono
parents:
diff changeset
1877 {
kono
parents:
diff changeset
1878 m = match_keyword_arg (tail, head, false);
kono
parents:
diff changeset
1879 if (m == MATCH_YES)
kono
parents:
diff changeset
1880 seen_keyword = 1;
kono
parents:
diff changeset
1881 if (m == MATCH_ERROR)
kono
parents:
diff changeset
1882 goto cleanup;
kono
parents:
diff changeset
1883 }
kono
parents:
diff changeset
1884
kono
parents:
diff changeset
1885 if (m == MATCH_NO)
kono
parents:
diff changeset
1886 {
kono
parents:
diff changeset
1887 /* Try for a non-keyword argument. */
kono
parents:
diff changeset
1888 m = match_actual_arg (&tail->expr);
kono
parents:
diff changeset
1889 if (m == MATCH_ERROR)
kono
parents:
diff changeset
1890 goto cleanup;
kono
parents:
diff changeset
1891 if (m == MATCH_NO)
kono
parents:
diff changeset
1892 goto syntax;
kono
parents:
diff changeset
1893 }
kono
parents:
diff changeset
1894 }
kono
parents:
diff changeset
1895
kono
parents:
diff changeset
1896
kono
parents:
diff changeset
1897 next:
kono
parents:
diff changeset
1898 if (gfc_match_char (')') == MATCH_YES)
kono
parents:
diff changeset
1899 break;
kono
parents:
diff changeset
1900 if (gfc_match_char (',') != MATCH_YES)
kono
parents:
diff changeset
1901 goto syntax;
kono
parents:
diff changeset
1902 }
kono
parents:
diff changeset
1903
kono
parents:
diff changeset
1904 *argp = head;
kono
parents:
diff changeset
1905 matching_actual_arglist--;
kono
parents:
diff changeset
1906 return MATCH_YES;
kono
parents:
diff changeset
1907
kono
parents:
diff changeset
1908 syntax:
kono
parents:
diff changeset
1909 gfc_error ("Syntax error in argument list at %C");
kono
parents:
diff changeset
1910
kono
parents:
diff changeset
1911 cleanup:
kono
parents:
diff changeset
1912 gfc_free_actual_arglist (head);
kono
parents:
diff changeset
1913 gfc_current_locus = old_loc;
kono
parents:
diff changeset
1914 matching_actual_arglist--;
kono
parents:
diff changeset
1915 return MATCH_ERROR;
kono
parents:
diff changeset
1916 }
kono
parents:
diff changeset
1917
kono
parents:
diff changeset
1918
kono
parents:
diff changeset
1919 /* Used by gfc_match_varspec() to extend the reference list by one
kono
parents:
diff changeset
1920 element. */
kono
parents:
diff changeset
1921
kono
parents:
diff changeset
1922 static gfc_ref *
kono
parents:
diff changeset
1923 extend_ref (gfc_expr *primary, gfc_ref *tail)
kono
parents:
diff changeset
1924 {
kono
parents:
diff changeset
1925 if (primary->ref == NULL)
kono
parents:
diff changeset
1926 primary->ref = tail = gfc_get_ref ();
kono
parents:
diff changeset
1927 else
kono
parents:
diff changeset
1928 {
kono
parents:
diff changeset
1929 if (tail == NULL)
kono
parents:
diff changeset
1930 gfc_internal_error ("extend_ref(): Bad tail");
kono
parents:
diff changeset
1931 tail->next = gfc_get_ref ();
kono
parents:
diff changeset
1932 tail = tail->next;
kono
parents:
diff changeset
1933 }
kono
parents:
diff changeset
1934
kono
parents:
diff changeset
1935 return tail;
kono
parents:
diff changeset
1936 }
kono
parents:
diff changeset
1937
kono
parents:
diff changeset
1938
kono
parents:
diff changeset
1939 /* Match any additional specifications associated with the current
kono
parents:
diff changeset
1940 variable like member references or substrings. If equiv_flag is
kono
parents:
diff changeset
1941 set we only match stuff that is allowed inside an EQUIVALENCE
kono
parents:
diff changeset
1942 statement. sub_flag tells whether we expect a type-bound procedure found
kono
parents:
diff changeset
1943 to be a subroutine as part of CALL or a FUNCTION. For procedure pointer
kono
parents:
diff changeset
1944 components, 'ppc_arg' determines whether the PPC may be called (with an
kono
parents:
diff changeset
1945 argument list), or whether it may just be referred to as a pointer. */
kono
parents:
diff changeset
1946
kono
parents:
diff changeset
1947 match
kono
parents:
diff changeset
1948 gfc_match_varspec (gfc_expr *primary, int equiv_flag, bool sub_flag,
kono
parents:
diff changeset
1949 bool ppc_arg)
kono
parents:
diff changeset
1950 {
kono
parents:
diff changeset
1951 char name[GFC_MAX_SYMBOL_LEN + 1];
kono
parents:
diff changeset
1952 gfc_ref *substring, *tail, *tmp;
kono
parents:
diff changeset
1953 gfc_component *component;
kono
parents:
diff changeset
1954 gfc_symbol *sym = primary->symtree->n.sym;
kono
parents:
diff changeset
1955 gfc_expr *tgt_expr = NULL;
kono
parents:
diff changeset
1956 match m;
kono
parents:
diff changeset
1957 bool unknown;
kono
parents:
diff changeset
1958 char sep;
kono
parents:
diff changeset
1959
kono
parents:
diff changeset
1960 tail = NULL;
kono
parents:
diff changeset
1961
kono
parents:
diff changeset
1962 gfc_gobble_whitespace ();
kono
parents:
diff changeset
1963
kono
parents:
diff changeset
1964 if (gfc_peek_ascii_char () == '[')
kono
parents:
diff changeset
1965 {
kono
parents:
diff changeset
1966 if ((sym->ts.type != BT_CLASS && sym->attr.dimension)
kono
parents:
diff changeset
1967 || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
kono
parents:
diff changeset
1968 && CLASS_DATA (sym)->attr.dimension))
kono
parents:
diff changeset
1969 {
kono
parents:
diff changeset
1970 gfc_error ("Array section designator, e.g. '(:)', is required "
kono
parents:
diff changeset
1971 "besides the coarray designator '[...]' at %C");
kono
parents:
diff changeset
1972 return MATCH_ERROR;
kono
parents:
diff changeset
1973 }
kono
parents:
diff changeset
1974 if ((sym->ts.type != BT_CLASS && !sym->attr.codimension)
kono
parents:
diff changeset
1975 || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
kono
parents:
diff changeset
1976 && !CLASS_DATA (sym)->attr.codimension))
kono
parents:
diff changeset
1977 {
kono
parents:
diff changeset
1978 gfc_error ("Coarray designator at %C but %qs is not a coarray",
kono
parents:
diff changeset
1979 sym->name);
kono
parents:
diff changeset
1980 return MATCH_ERROR;
kono
parents:
diff changeset
1981 }
kono
parents:
diff changeset
1982 }
kono
parents:
diff changeset
1983
kono
parents:
diff changeset
1984 if (sym->assoc && sym->assoc->target)
kono
parents:
diff changeset
1985 tgt_expr = sym->assoc->target;
kono
parents:
diff changeset
1986
kono
parents:
diff changeset
1987 /* For associate names, we may not yet know whether they are arrays or not.
kono
parents:
diff changeset
1988 If the selector expression is unambiguously an array; eg. a full array
kono
parents:
diff changeset
1989 or an array section, then the associate name must be an array and we can
kono
parents:
diff changeset
1990 fix it now. Otherwise, if parentheses follow and it is not a character
kono
parents:
diff changeset
1991 type, we have to assume that it actually is one for now. The final
kono
parents:
diff changeset
1992 decision will be made at resolution, of course. */
kono
parents:
diff changeset
1993 if (sym->assoc
kono
parents:
diff changeset
1994 && gfc_peek_ascii_char () == '('
kono
parents:
diff changeset
1995 && sym->ts.type != BT_CLASS
kono
parents:
diff changeset
1996 && !sym->attr.dimension)
kono
parents:
diff changeset
1997 {
kono
parents:
diff changeset
1998 gfc_ref *ref = NULL;
kono
parents:
diff changeset
1999
kono
parents:
diff changeset
2000 if (!sym->assoc->dangling && tgt_expr)
kono
parents:
diff changeset
2001 {
kono
parents:
diff changeset
2002 if (tgt_expr->expr_type == EXPR_VARIABLE)
kono
parents:
diff changeset
2003 gfc_resolve_expr (tgt_expr);
kono
parents:
diff changeset
2004
kono
parents:
diff changeset
2005 ref = tgt_expr->ref;
kono
parents:
diff changeset
2006 for (; ref; ref = ref->next)
kono
parents:
diff changeset
2007 if (ref->type == REF_ARRAY
kono
parents:
diff changeset
2008 && (ref->u.ar.type == AR_FULL
kono
parents:
diff changeset
2009 || ref->u.ar.type == AR_SECTION))
kono
parents:
diff changeset
2010 break;
kono
parents:
diff changeset
2011 }
kono
parents:
diff changeset
2012
kono
parents:
diff changeset
2013 if (ref || (!(sym->assoc->dangling || sym->ts.type == BT_CHARACTER)
kono
parents:
diff changeset
2014 && sym->assoc->st
kono
parents:
diff changeset
2015 && sym->assoc->st->n.sym
kono
parents:
diff changeset
2016 && sym->assoc->st->n.sym->attr.dimension == 0))
kono
parents:
diff changeset
2017 {
kono
parents:
diff changeset
2018 sym->attr.dimension = 1;
kono
parents:
diff changeset
2019 if (sym->as == NULL
kono
parents:
diff changeset
2020 && sym->assoc->st
kono
parents:
diff changeset
2021 && sym->assoc->st->n.sym
kono
parents:
diff changeset
2022 && sym->assoc->st->n.sym->as)
kono
parents:
diff changeset
2023 sym->as = gfc_copy_array_spec (sym->assoc->st->n.sym->as);
kono
parents:
diff changeset
2024 }
kono
parents:
diff changeset
2025 }
kono
parents:
diff changeset
2026 else if (sym->ts.type == BT_CLASS
kono
parents:
diff changeset
2027 && tgt_expr
kono
parents:
diff changeset
2028 && tgt_expr->expr_type == EXPR_VARIABLE
kono
parents:
diff changeset
2029 && sym->ts.u.derived != tgt_expr->ts.u.derived)
kono
parents:
diff changeset
2030 {
kono
parents:
diff changeset
2031 gfc_resolve_expr (tgt_expr);
kono
parents:
diff changeset
2032 if (tgt_expr->rank)
kono
parents:
diff changeset
2033 sym->ts.u.derived = tgt_expr->ts.u.derived;
kono
parents:
diff changeset
2034 }
kono
parents:
diff changeset
2035
kono
parents:
diff changeset
2036 if ((equiv_flag && gfc_peek_ascii_char () == '(')
kono
parents:
diff changeset
2037 || gfc_peek_ascii_char () == '[' || sym->attr.codimension
kono
parents:
diff changeset
2038 || (sym->attr.dimension && sym->ts.type != BT_CLASS
kono
parents:
diff changeset
2039 && !sym->attr.proc_pointer && !gfc_is_proc_ptr_comp (primary)
kono
parents:
diff changeset
2040 && !(gfc_matching_procptr_assignment
kono
parents:
diff changeset
2041 && sym->attr.flavor == FL_PROCEDURE))
kono
parents:
diff changeset
2042 || (sym->ts.type == BT_CLASS && sym->attr.class_ok
kono
parents:
diff changeset
2043 && (CLASS_DATA (sym)->attr.dimension
kono
parents:
diff changeset
2044 || CLASS_DATA (sym)->attr.codimension)))
kono
parents:
diff changeset
2045 {
kono
parents:
diff changeset
2046 gfc_array_spec *as;
kono
parents:
diff changeset
2047
kono
parents:
diff changeset
2048 tail = extend_ref (primary, tail);
kono
parents:
diff changeset
2049 tail->type = REF_ARRAY;
kono
parents:
diff changeset
2050
kono
parents:
diff changeset
2051 /* In EQUIVALENCE, we don't know yet whether we are seeing
kono
parents:
diff changeset
2052 an array, character variable or array of character
kono
parents:
diff changeset
2053 variables. We'll leave the decision till resolve time. */
kono
parents:
diff changeset
2054
kono
parents:
diff changeset
2055 if (equiv_flag)
kono
parents:
diff changeset
2056 as = NULL;
kono
parents:
diff changeset
2057 else if (sym->ts.type == BT_CLASS && CLASS_DATA (sym))
kono
parents:
diff changeset
2058 as = CLASS_DATA (sym)->as;
kono
parents:
diff changeset
2059 else
kono
parents:
diff changeset
2060 as = sym->as;
kono
parents:
diff changeset
2061
kono
parents:
diff changeset
2062 m = gfc_match_array_ref (&tail->u.ar, as, equiv_flag,
kono
parents:
diff changeset
2063 as ? as->corank : 0);
kono
parents:
diff changeset
2064 if (m != MATCH_YES)
kono
parents:
diff changeset
2065 return m;
kono
parents:
diff changeset
2066
kono
parents:
diff changeset
2067 gfc_gobble_whitespace ();
kono
parents:
diff changeset
2068 if (equiv_flag && gfc_peek_ascii_char () == '(')
kono
parents:
diff changeset
2069 {
kono
parents:
diff changeset
2070 tail = extend_ref (primary, tail);
kono
parents:
diff changeset
2071 tail->type = REF_ARRAY;
kono
parents:
diff changeset
2072
kono
parents:
diff changeset
2073 m = gfc_match_array_ref (&tail->u.ar, NULL, equiv_flag, 0);
kono
parents:
diff changeset
2074 if (m != MATCH_YES)
kono
parents:
diff changeset
2075 return m;
kono
parents:
diff changeset
2076 }
kono
parents:
diff changeset
2077 }
kono
parents:
diff changeset
2078
kono
parents:
diff changeset
2079 primary->ts = sym->ts;
kono
parents:
diff changeset
2080
kono
parents:
diff changeset
2081 if (equiv_flag)
kono
parents:
diff changeset
2082 return MATCH_YES;
kono
parents:
diff changeset
2083
kono
parents:
diff changeset
2084 /* With DEC extensions, member separator may be '.' or '%'. */
kono
parents:
diff changeset
2085 sep = gfc_peek_ascii_char ();
kono
parents:
diff changeset
2086 m = gfc_match_member_sep (sym);
kono
parents:
diff changeset
2087 if (m == MATCH_ERROR)
kono
parents:
diff changeset
2088 return MATCH_ERROR;
kono
parents:
diff changeset
2089
kono
parents:
diff changeset
2090 if (sym->ts.type == BT_UNKNOWN && m == MATCH_YES
kono
parents:
diff changeset
2091 && gfc_get_default_type (sym->name, sym->ns)->type == BT_DERIVED)
kono
parents:
diff changeset
2092 gfc_set_default_type (sym, 0, sym->ns);
kono
parents:
diff changeset
2093
kono
parents:
diff changeset
2094 /* See if there is a usable typespec in the "no IMPLICIT type" error. */
kono
parents:
diff changeset
2095 if (sym->ts.type == BT_UNKNOWN && m == MATCH_YES)
kono
parents:
diff changeset
2096 {
kono
parents:
diff changeset
2097 bool permissible;
kono
parents:
diff changeset
2098
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2099 /* These target expressions can be resolved at any time. */
111
kono
parents:
diff changeset
2100 permissible = tgt_expr && tgt_expr->symtree && tgt_expr->symtree->n.sym
kono
parents:
diff changeset
2101 && (tgt_expr->symtree->n.sym->attr.use_assoc
kono
parents:
diff changeset
2102 || tgt_expr->symtree->n.sym->attr.host_assoc
kono
parents:
diff changeset
2103 || tgt_expr->symtree->n.sym->attr.if_source
kono
parents:
diff changeset
2104 == IFSRC_DECL);
kono
parents:
diff changeset
2105 permissible = permissible
kono
parents:
diff changeset
2106 || (tgt_expr && tgt_expr->expr_type == EXPR_OP);
kono
parents:
diff changeset
2107
kono
parents:
diff changeset
2108 if (permissible)
kono
parents:
diff changeset
2109 {
kono
parents:
diff changeset
2110 gfc_resolve_expr (tgt_expr);
kono
parents:
diff changeset
2111 sym->ts = tgt_expr->ts;
kono
parents:
diff changeset
2112 }
kono
parents:
diff changeset
2113
kono
parents:
diff changeset
2114 if (sym->ts.type == BT_UNKNOWN)
kono
parents:
diff changeset
2115 {
kono
parents:
diff changeset
2116 gfc_error ("Symbol %qs at %C has no IMPLICIT type", sym->name);
kono
parents:
diff changeset
2117 return MATCH_ERROR;
kono
parents:
diff changeset
2118 }
kono
parents:
diff changeset
2119 }
kono
parents:
diff changeset
2120 else if ((sym->ts.type != BT_DERIVED && sym->ts.type != BT_CLASS)
kono
parents:
diff changeset
2121 && m == MATCH_YES)
kono
parents:
diff changeset
2122 {
kono
parents:
diff changeset
2123 gfc_error ("Unexpected %<%c%> for nonderived-type variable %qs at %C",
kono
parents:
diff changeset
2124 sep, sym->name);
kono
parents:
diff changeset
2125 return MATCH_ERROR;
kono
parents:
diff changeset
2126 }
kono
parents:
diff changeset
2127
kono
parents:
diff changeset
2128 if ((sym->ts.type != BT_DERIVED && sym->ts.type != BT_CLASS)
kono
parents:
diff changeset
2129 || m != MATCH_YES)
kono
parents:
diff changeset
2130 goto check_substring;
kono
parents:
diff changeset
2131
kono
parents:
diff changeset
2132 sym = sym->ts.u.derived;
kono
parents:
diff changeset
2133
kono
parents:
diff changeset
2134 for (;;)
kono
parents:
diff changeset
2135 {
kono
parents:
diff changeset
2136 bool t;
kono
parents:
diff changeset
2137 gfc_symtree *tbp;
kono
parents:
diff changeset
2138
kono
parents:
diff changeset
2139 m = gfc_match_name (name);
kono
parents:
diff changeset
2140 if (m == MATCH_NO)
kono
parents:
diff changeset
2141 gfc_error ("Expected structure component name at %C");
kono
parents:
diff changeset
2142 if (m != MATCH_YES)
kono
parents:
diff changeset
2143 return MATCH_ERROR;
kono
parents:
diff changeset
2144
kono
parents:
diff changeset
2145 if (sym && sym->f2k_derived)
kono
parents:
diff changeset
2146 tbp = gfc_find_typebound_proc (sym, &t, name, false, &gfc_current_locus);
kono
parents:
diff changeset
2147 else
kono
parents:
diff changeset
2148 tbp = NULL;
kono
parents:
diff changeset
2149
kono
parents:
diff changeset
2150 if (tbp)
kono
parents:
diff changeset
2151 {
kono
parents:
diff changeset
2152 gfc_symbol* tbp_sym;
kono
parents:
diff changeset
2153
kono
parents:
diff changeset
2154 if (!t)
kono
parents:
diff changeset
2155 return MATCH_ERROR;
kono
parents:
diff changeset
2156
kono
parents:
diff changeset
2157 gcc_assert (!tail || !tail->next);
kono
parents:
diff changeset
2158
kono
parents:
diff changeset
2159 if (!(primary->expr_type == EXPR_VARIABLE
kono
parents:
diff changeset
2160 || (primary->expr_type == EXPR_STRUCTURE
kono
parents:
diff changeset
2161 && primary->symtree && primary->symtree->n.sym
kono
parents:
diff changeset
2162 && primary->symtree->n.sym->attr.flavor)))
kono
parents:
diff changeset
2163 return MATCH_ERROR;
kono
parents:
diff changeset
2164
kono
parents:
diff changeset
2165 if (tbp->n.tb->is_generic)
kono
parents:
diff changeset
2166 tbp_sym = NULL;
kono
parents:
diff changeset
2167 else
kono
parents:
diff changeset
2168 tbp_sym = tbp->n.tb->u.specific->n.sym;
kono
parents:
diff changeset
2169
kono
parents:
diff changeset
2170 primary->expr_type = EXPR_COMPCALL;
kono
parents:
diff changeset
2171 primary->value.compcall.tbp = tbp->n.tb;
kono
parents:
diff changeset
2172 primary->value.compcall.name = tbp->name;
kono
parents:
diff changeset
2173 primary->value.compcall.ignore_pass = 0;
kono
parents:
diff changeset
2174 primary->value.compcall.assign = 0;
kono
parents:
diff changeset
2175 primary->value.compcall.base_object = NULL;
kono
parents:
diff changeset
2176 gcc_assert (primary->symtree->n.sym->attr.referenced);
kono
parents:
diff changeset
2177 if (tbp_sym)
kono
parents:
diff changeset
2178 primary->ts = tbp_sym->ts;
kono
parents:
diff changeset
2179 else
kono
parents:
diff changeset
2180 gfc_clear_ts (&primary->ts);
kono
parents:
diff changeset
2181
kono
parents:
diff changeset
2182 m = gfc_match_actual_arglist (tbp->n.tb->subroutine,
kono
parents:
diff changeset
2183 &primary->value.compcall.actual);
kono
parents:
diff changeset
2184 if (m == MATCH_ERROR)
kono
parents:
diff changeset
2185 return MATCH_ERROR;
kono
parents:
diff changeset
2186 if (m == MATCH_NO)
kono
parents:
diff changeset
2187 {
kono
parents:
diff changeset
2188 if (sub_flag)
kono
parents:
diff changeset
2189 primary->value.compcall.actual = NULL;
kono
parents:
diff changeset
2190 else
kono
parents:
diff changeset
2191 {
kono
parents:
diff changeset
2192 gfc_error ("Expected argument list at %C");
kono
parents:
diff changeset
2193 return MATCH_ERROR;
kono
parents:
diff changeset
2194 }
kono
parents:
diff changeset
2195 }
kono
parents:
diff changeset
2196
kono
parents:
diff changeset
2197 break;
kono
parents:
diff changeset
2198 }
kono
parents:
diff changeset
2199
kono
parents:
diff changeset
2200 component = gfc_find_component (sym, name, false, false, &tmp);
kono
parents:
diff changeset
2201 if (component == NULL)
kono
parents:
diff changeset
2202 return MATCH_ERROR;
kono
parents:
diff changeset
2203
kono
parents:
diff changeset
2204 /* Extend the reference chain determined by gfc_find_component. */
kono
parents:
diff changeset
2205 if (primary->ref == NULL)
kono
parents:
diff changeset
2206 primary->ref = tmp;
kono
parents:
diff changeset
2207 else
kono
parents:
diff changeset
2208 {
kono
parents:
diff changeset
2209 /* Set by the for loop below for the last component ref. */
kono
parents:
diff changeset
2210 gcc_assert (tail != NULL);
kono
parents:
diff changeset
2211 tail->next = tmp;
kono
parents:
diff changeset
2212 }
kono
parents:
diff changeset
2213
kono
parents:
diff changeset
2214 /* The reference chain may be longer than one hop for union
kono
parents:
diff changeset
2215 subcomponents; find the new tail. */
kono
parents:
diff changeset
2216 for (tail = tmp; tail->next; tail = tail->next)
kono
parents:
diff changeset
2217 ;
kono
parents:
diff changeset
2218
kono
parents:
diff changeset
2219 primary->ts = component->ts;
kono
parents:
diff changeset
2220
kono
parents:
diff changeset
2221 if (component->attr.proc_pointer && ppc_arg)
kono
parents:
diff changeset
2222 {
kono
parents:
diff changeset
2223 /* Procedure pointer component call: Look for argument list. */
kono
parents:
diff changeset
2224 m = gfc_match_actual_arglist (sub_flag,
kono
parents:
diff changeset
2225 &primary->value.compcall.actual);
kono
parents:
diff changeset
2226 if (m == MATCH_ERROR)
kono
parents:
diff changeset
2227 return MATCH_ERROR;
kono
parents:
diff changeset
2228
kono
parents:
diff changeset
2229 if (m == MATCH_NO && !gfc_matching_ptr_assignment
kono
parents:
diff changeset
2230 && !gfc_matching_procptr_assignment && !matching_actual_arglist)
kono
parents:
diff changeset
2231 {
kono
parents:
diff changeset
2232 gfc_error ("Procedure pointer component %qs requires an "
kono
parents:
diff changeset
2233 "argument list at %C", component->name);
kono
parents:
diff changeset
2234 return MATCH_ERROR;
kono
parents:
diff changeset
2235 }
kono
parents:
diff changeset
2236
kono
parents:
diff changeset
2237 if (m == MATCH_YES)
kono
parents:
diff changeset
2238 primary->expr_type = EXPR_PPC;
kono
parents:
diff changeset
2239
kono
parents:
diff changeset
2240 break;
kono
parents:
diff changeset
2241 }
kono
parents:
diff changeset
2242
kono
parents:
diff changeset
2243 if (component->as != NULL && !component->attr.proc_pointer)
kono
parents:
diff changeset
2244 {
kono
parents:
diff changeset
2245 tail = extend_ref (primary, tail);
kono
parents:
diff changeset
2246 tail->type = REF_ARRAY;
kono
parents:
diff changeset
2247
kono
parents:
diff changeset
2248 m = gfc_match_array_ref (&tail->u.ar, component->as, equiv_flag,
kono
parents:
diff changeset
2249 component->as->corank);
kono
parents:
diff changeset
2250 if (m != MATCH_YES)
kono
parents:
diff changeset
2251 return m;
kono
parents:
diff changeset
2252 }
kono
parents:
diff changeset
2253 else if (component->ts.type == BT_CLASS && component->attr.class_ok
kono
parents:
diff changeset
2254 && CLASS_DATA (component)->as && !component->attr.proc_pointer)
kono
parents:
diff changeset
2255 {
kono
parents:
diff changeset
2256 tail = extend_ref (primary, tail);
kono
parents:
diff changeset
2257 tail->type = REF_ARRAY;
kono
parents:
diff changeset
2258
kono
parents:
diff changeset
2259 m = gfc_match_array_ref (&tail->u.ar, CLASS_DATA (component)->as,
kono
parents:
diff changeset
2260 equiv_flag,
kono
parents:
diff changeset
2261 CLASS_DATA (component)->as->corank);
kono
parents:
diff changeset
2262 if (m != MATCH_YES)
kono
parents:
diff changeset
2263 return m;
kono
parents:
diff changeset
2264 }
kono
parents:
diff changeset
2265
kono
parents:
diff changeset
2266 if ((component->ts.type != BT_DERIVED && component->ts.type != BT_CLASS)
kono
parents:
diff changeset
2267 || gfc_match_member_sep (component->ts.u.derived) != MATCH_YES)
kono
parents:
diff changeset
2268 break;
kono
parents:
diff changeset
2269
kono
parents:
diff changeset
2270 sym = component->ts.u.derived;
kono
parents:
diff changeset
2271 }
kono
parents:
diff changeset
2272
kono
parents:
diff changeset
2273 check_substring:
kono
parents:
diff changeset
2274 unknown = false;
kono
parents:
diff changeset
2275 if (primary->ts.type == BT_UNKNOWN && !gfc_fl_struct (sym->attr.flavor))
kono
parents:
diff changeset
2276 {
kono
parents:
diff changeset
2277 if (gfc_get_default_type (sym->name, sym->ns)->type == BT_CHARACTER)
kono
parents:
diff changeset
2278 {
kono
parents:
diff changeset
2279 gfc_set_default_type (sym, 0, sym->ns);
kono
parents:
diff changeset
2280 primary->ts = sym->ts;
kono
parents:
diff changeset
2281 unknown = true;
kono
parents:
diff changeset
2282 }
kono
parents:
diff changeset
2283 }
kono
parents:
diff changeset
2284
kono
parents:
diff changeset
2285 if (primary->ts.type == BT_CHARACTER)
kono
parents:
diff changeset
2286 {
kono
parents:
diff changeset
2287 bool def = primary->ts.deferred == 1;
kono
parents:
diff changeset
2288 switch (match_substring (primary->ts.u.cl, equiv_flag, &substring, def))
kono
parents:
diff changeset
2289 {
kono
parents:
diff changeset
2290 case MATCH_YES:
kono
parents:
diff changeset
2291 if (tail == NULL)
kono
parents:
diff changeset
2292 primary->ref = substring;
kono
parents:
diff changeset
2293 else
kono
parents:
diff changeset
2294 tail->next = substring;
kono
parents:
diff changeset
2295
kono
parents:
diff changeset
2296 if (primary->expr_type == EXPR_CONSTANT)
kono
parents:
diff changeset
2297 primary->expr_type = EXPR_SUBSTRING;
kono
parents:
diff changeset
2298
kono
parents:
diff changeset
2299 if (substring)
kono
parents:
diff changeset
2300 primary->ts.u.cl = NULL;
kono
parents:
diff changeset
2301
kono
parents:
diff changeset
2302 break;
kono
parents:
diff changeset
2303
kono
parents:
diff changeset
2304 case MATCH_NO:
kono
parents:
diff changeset
2305 if (unknown)
kono
parents:
diff changeset
2306 {
kono
parents:
diff changeset
2307 gfc_clear_ts (&primary->ts);
kono
parents:
diff changeset
2308 gfc_clear_ts (&sym->ts);
kono
parents:
diff changeset
2309 }
kono
parents:
diff changeset
2310 break;
kono
parents:
diff changeset
2311
kono
parents:
diff changeset
2312 case MATCH_ERROR:
kono
parents:
diff changeset
2313 return MATCH_ERROR;
kono
parents:
diff changeset
2314 }
kono
parents:
diff changeset
2315 }
kono
parents:
diff changeset
2316
kono
parents:
diff changeset
2317 /* F08:C611. */
kono
parents:
diff changeset
2318 if (primary->ts.type == BT_DERIVED && primary->ref
kono
parents:
diff changeset
2319 && primary->ts.u.derived && primary->ts.u.derived->attr.abstract)
kono
parents:
diff changeset
2320 {
kono
parents:
diff changeset
2321 gfc_error ("Nonpolymorphic reference to abstract type at %C");
kono
parents:
diff changeset
2322 return MATCH_ERROR;
kono
parents:
diff changeset
2323 }
kono
parents:
diff changeset
2324
kono
parents:
diff changeset
2325 /* F08:C727. */
kono
parents:
diff changeset
2326 if (primary->expr_type == EXPR_PPC && gfc_is_coindexed (primary))
kono
parents:
diff changeset
2327 {
kono
parents:
diff changeset
2328 gfc_error ("Coindexed procedure-pointer component at %C");
kono
parents:
diff changeset
2329 return MATCH_ERROR;
kono
parents:
diff changeset
2330 }
kono
parents:
diff changeset
2331
kono
parents:
diff changeset
2332 return MATCH_YES;
kono
parents:
diff changeset
2333 }
kono
parents:
diff changeset
2334
kono
parents:
diff changeset
2335
kono
parents:
diff changeset
2336 /* Given an expression that is a variable, figure out what the
kono
parents:
diff changeset
2337 ultimate variable's type and attribute is, traversing the reference
kono
parents:
diff changeset
2338 structures if necessary.
kono
parents:
diff changeset
2339
kono
parents:
diff changeset
2340 This subroutine is trickier than it looks. We start at the base
kono
parents:
diff changeset
2341 symbol and store the attribute. Component references load a
kono
parents:
diff changeset
2342 completely new attribute.
kono
parents:
diff changeset
2343
kono
parents:
diff changeset
2344 A couple of rules come into play. Subobjects of targets are always
kono
parents:
diff changeset
2345 targets themselves. If we see a component that goes through a
kono
parents:
diff changeset
2346 pointer, then the expression must also be a target, since the
kono
parents:
diff changeset
2347 pointer is associated with something (if it isn't core will soon be
kono
parents:
diff changeset
2348 dumped). If we see a full part or section of an array, the
kono
parents:
diff changeset
2349 expression is also an array.
kono
parents:
diff changeset
2350
kono
parents:
diff changeset
2351 We can have at most one full array reference. */
kono
parents:
diff changeset
2352
kono
parents:
diff changeset
2353 symbol_attribute
kono
parents:
diff changeset
2354 gfc_variable_attr (gfc_expr *expr, gfc_typespec *ts)
kono
parents:
diff changeset
2355 {
kono
parents:
diff changeset
2356 int dimension, codimension, pointer, allocatable, target;
kono
parents:
diff changeset
2357 symbol_attribute attr;
kono
parents:
diff changeset
2358 gfc_ref *ref;
kono
parents:
diff changeset
2359 gfc_symbol *sym;
kono
parents:
diff changeset
2360 gfc_component *comp;
kono
parents:
diff changeset
2361
kono
parents:
diff changeset
2362 if (expr->expr_type != EXPR_VARIABLE && expr->expr_type != EXPR_FUNCTION)
kono
parents:
diff changeset
2363 gfc_internal_error ("gfc_variable_attr(): Expression isn't a variable");
kono
parents:
diff changeset
2364
kono
parents:
diff changeset
2365 sym = expr->symtree->n.sym;
kono
parents:
diff changeset
2366 attr = sym->attr;
kono
parents:
diff changeset
2367
kono
parents:
diff changeset
2368 if (sym->ts.type == BT_CLASS && sym->attr.class_ok)
kono
parents:
diff changeset
2369 {
kono
parents:
diff changeset
2370 dimension = CLASS_DATA (sym)->attr.dimension;
kono
parents:
diff changeset
2371 codimension = CLASS_DATA (sym)->attr.codimension;
kono
parents:
diff changeset
2372 pointer = CLASS_DATA (sym)->attr.class_pointer;
kono
parents:
diff changeset
2373 allocatable = CLASS_DATA (sym)->attr.allocatable;
kono
parents:
diff changeset
2374 }
kono
parents:
diff changeset
2375 else
kono
parents:
diff changeset
2376 {
kono
parents:
diff changeset
2377 dimension = attr.dimension;
kono
parents:
diff changeset
2378 codimension = attr.codimension;
kono
parents:
diff changeset
2379 pointer = attr.pointer;
kono
parents:
diff changeset
2380 allocatable = attr.allocatable;
kono
parents:
diff changeset
2381 }
kono
parents:
diff changeset
2382
kono
parents:
diff changeset
2383 target = attr.target;
kono
parents:
diff changeset
2384 if (pointer || attr.proc_pointer)
kono
parents:
diff changeset
2385 target = 1;
kono
parents:
diff changeset
2386
kono
parents:
diff changeset
2387 if (ts != NULL && expr->ts.type == BT_UNKNOWN)
kono
parents:
diff changeset
2388 *ts = sym->ts;
kono
parents:
diff changeset
2389
kono
parents:
diff changeset
2390 for (ref = expr->ref; ref; ref = ref->next)
kono
parents:
diff changeset
2391 switch (ref->type)
kono
parents:
diff changeset
2392 {
kono
parents:
diff changeset
2393 case REF_ARRAY:
kono
parents:
diff changeset
2394
kono
parents:
diff changeset
2395 switch (ref->u.ar.type)
kono
parents:
diff changeset
2396 {
kono
parents:
diff changeset
2397 case AR_FULL:
kono
parents:
diff changeset
2398 dimension = 1;
kono
parents:
diff changeset
2399 break;
kono
parents:
diff changeset
2400
kono
parents:
diff changeset
2401 case AR_SECTION:
kono
parents:
diff changeset
2402 allocatable = pointer = 0;
kono
parents:
diff changeset
2403 dimension = 1;
kono
parents:
diff changeset
2404 break;
kono
parents:
diff changeset
2405
kono
parents:
diff changeset
2406 case AR_ELEMENT:
kono
parents:
diff changeset
2407 /* Handle coarrays. */
kono
parents:
diff changeset
2408 if (ref->u.ar.dimen > 0)
kono
parents:
diff changeset
2409 allocatable = pointer = 0;
kono
parents:
diff changeset
2410 break;
kono
parents:
diff changeset
2411
kono
parents:
diff changeset
2412 case AR_UNKNOWN:
kono
parents:
diff changeset
2413 /* If any of start, end or stride is not integer, there will
kono
parents:
diff changeset
2414 already have been an error issued. */
kono
parents:
diff changeset
2415 int errors;
kono
parents:
diff changeset
2416 gfc_get_errors (NULL, &errors);
kono
parents:
diff changeset
2417 if (errors == 0)
kono
parents:
diff changeset
2418 gfc_internal_error ("gfc_variable_attr(): Bad array reference");
kono
parents:
diff changeset
2419 }
kono
parents:
diff changeset
2420
kono
parents:
diff changeset
2421 break;
kono
parents:
diff changeset
2422
kono
parents:
diff changeset
2423 case REF_COMPONENT:
kono
parents:
diff changeset
2424 comp = ref->u.c.component;
kono
parents:
diff changeset
2425 attr = comp->attr;
kono
parents:
diff changeset
2426 if (ts != NULL)
kono
parents:
diff changeset
2427 {
kono
parents:
diff changeset
2428 *ts = comp->ts;
kono
parents:
diff changeset
2429 /* Don't set the string length if a substring reference
kono
parents:
diff changeset
2430 follows. */
kono
parents:
diff changeset
2431 if (ts->type == BT_CHARACTER
kono
parents:
diff changeset
2432 && ref->next && ref->next->type == REF_SUBSTRING)
kono
parents:
diff changeset
2433 ts->u.cl = NULL;
kono
parents:
diff changeset
2434 }
kono
parents:
diff changeset
2435
kono
parents:
diff changeset
2436 if (comp->ts.type == BT_CLASS)
kono
parents:
diff changeset
2437 {
kono
parents:
diff changeset
2438 codimension = CLASS_DATA (comp)->attr.codimension;
kono
parents:
diff changeset
2439 pointer = CLASS_DATA (comp)->attr.class_pointer;
kono
parents:
diff changeset
2440 allocatable = CLASS_DATA (comp)->attr.allocatable;
kono
parents:
diff changeset
2441 }
kono
parents:
diff changeset
2442 else
kono
parents:
diff changeset
2443 {
kono
parents:
diff changeset
2444 codimension = comp->attr.codimension;
kono
parents:
diff changeset
2445 pointer = comp->attr.pointer;
kono
parents:
diff changeset
2446 allocatable = comp->attr.allocatable;
kono
parents:
diff changeset
2447 }
kono
parents:
diff changeset
2448 if (pointer || attr.proc_pointer)
kono
parents:
diff changeset
2449 target = 1;
kono
parents:
diff changeset
2450
kono
parents:
diff changeset
2451 break;
kono
parents:
diff changeset
2452
kono
parents:
diff changeset
2453 case REF_SUBSTRING:
kono
parents:
diff changeset
2454 allocatable = pointer = 0;
kono
parents:
diff changeset
2455 break;
kono
parents:
diff changeset
2456 }
kono
parents:
diff changeset
2457
kono
parents:
diff changeset
2458 attr.dimension = dimension;
kono
parents:
diff changeset
2459 attr.codimension = codimension;
kono
parents:
diff changeset
2460 attr.pointer = pointer;
kono
parents:
diff changeset
2461 attr.allocatable = allocatable;
kono
parents:
diff changeset
2462 attr.target = target;
kono
parents:
diff changeset
2463 attr.save = sym->attr.save;
kono
parents:
diff changeset
2464
kono
parents:
diff changeset
2465 return attr;
kono
parents:
diff changeset
2466 }
kono
parents:
diff changeset
2467
kono
parents:
diff changeset
2468
kono
parents:
diff changeset
2469 /* Return the attribute from a general expression. */
kono
parents:
diff changeset
2470
kono
parents:
diff changeset
2471 symbol_attribute
kono
parents:
diff changeset
2472 gfc_expr_attr (gfc_expr *e)
kono
parents:
diff changeset
2473 {
kono
parents:
diff changeset
2474 symbol_attribute attr;
kono
parents:
diff changeset
2475
kono
parents:
diff changeset
2476 switch (e->expr_type)
kono
parents:
diff changeset
2477 {
kono
parents:
diff changeset
2478 case EXPR_VARIABLE:
kono
parents:
diff changeset
2479 attr = gfc_variable_attr (e, NULL);
kono
parents:
diff changeset
2480 break;
kono
parents:
diff changeset
2481
kono
parents:
diff changeset
2482 case EXPR_FUNCTION:
kono
parents:
diff changeset
2483 gfc_clear_attr (&attr);
kono
parents:
diff changeset
2484
kono
parents:
diff changeset
2485 if (e->value.function.esym && e->value.function.esym->result)
kono
parents:
diff changeset
2486 {
kono
parents:
diff changeset
2487 gfc_symbol *sym = e->value.function.esym->result;
kono
parents:
diff changeset
2488 attr = sym->attr;
kono
parents:
diff changeset
2489 if (sym->ts.type == BT_CLASS)
kono
parents:
diff changeset
2490 {
kono
parents:
diff changeset
2491 attr.dimension = CLASS_DATA (sym)->attr.dimension;
kono
parents:
diff changeset
2492 attr.pointer = CLASS_DATA (sym)->attr.class_pointer;
kono
parents:
diff changeset
2493 attr.allocatable = CLASS_DATA (sym)->attr.allocatable;
kono
parents:
diff changeset
2494 }
kono
parents:
diff changeset
2495 }
kono
parents:
diff changeset
2496 else if (e->value.function.isym
kono
parents:
diff changeset
2497 && e->value.function.isym->transformational
kono
parents:
diff changeset
2498 && e->ts.type == BT_CLASS)
kono
parents:
diff changeset
2499 attr = CLASS_DATA (e)->attr;
kono
parents:
diff changeset
2500 else
kono
parents:
diff changeset
2501 attr = gfc_variable_attr (e, NULL);
kono
parents:
diff changeset
2502
kono
parents:
diff changeset
2503 /* TODO: NULL() returns pointers. May have to take care of this
kono
parents:
diff changeset
2504 here. */
kono
parents:
diff changeset
2505
kono
parents:
diff changeset
2506 break;
kono
parents:
diff changeset
2507
kono
parents:
diff changeset
2508 default:
kono
parents:
diff changeset
2509 gfc_clear_attr (&attr);
kono
parents:
diff changeset
2510 break;
kono
parents:
diff changeset
2511 }
kono
parents:
diff changeset
2512
kono
parents:
diff changeset
2513 return attr;
kono
parents:
diff changeset
2514 }
kono
parents:
diff changeset
2515
kono
parents:
diff changeset
2516
kono
parents:
diff changeset
2517 /* Given an expression, figure out what the ultimate expression
kono
parents:
diff changeset
2518 attribute is. This routine is similar to gfc_variable_attr with
kono
parents:
diff changeset
2519 parts of gfc_expr_attr, but focuses more on the needs of
kono
parents:
diff changeset
2520 coarrays. For coarrays a codimension attribute is kind of
kono
parents:
diff changeset
2521 "infectious" being propagated once set and never cleared.
kono
parents:
diff changeset
2522 The coarray_comp is only set, when the expression refs a coarray
kono
parents:
diff changeset
2523 component. REFS_COMP is set when present to true only, when this EXPR
kono
parents:
diff changeset
2524 refs a (non-_data) component. To check whether EXPR refs an allocatable
kono
parents:
diff changeset
2525 component in a derived type coarray *refs_comp needs to be set and
kono
parents:
diff changeset
2526 coarray_comp has to false. */
kono
parents:
diff changeset
2527
kono
parents:
diff changeset
2528 static symbol_attribute
kono
parents:
diff changeset
2529 caf_variable_attr (gfc_expr *expr, bool in_allocate, bool *refs_comp)
kono
parents:
diff changeset
2530 {
kono
parents:
diff changeset
2531 int dimension, codimension, pointer, allocatable, target, coarray_comp;
kono
parents:
diff changeset
2532 symbol_attribute attr;
kono
parents:
diff changeset
2533 gfc_ref *ref;
kono
parents:
diff changeset
2534 gfc_symbol *sym;
kono
parents:
diff changeset
2535 gfc_component *comp;
kono
parents:
diff changeset
2536
kono
parents:
diff changeset
2537 if (expr->expr_type != EXPR_VARIABLE && expr->expr_type != EXPR_FUNCTION)
kono
parents:
diff changeset
2538 gfc_internal_error ("gfc_caf_attr(): Expression isn't a variable");
kono
parents:
diff changeset
2539
kono
parents:
diff changeset
2540 sym = expr->symtree->n.sym;
kono
parents:
diff changeset
2541 gfc_clear_attr (&attr);
kono
parents:
diff changeset
2542
kono
parents:
diff changeset
2543 if (refs_comp)
kono
parents:
diff changeset
2544 *refs_comp = false;
kono
parents:
diff changeset
2545
kono
parents:
diff changeset
2546 if (sym->ts.type == BT_CLASS && sym->attr.class_ok)
kono
parents:
diff changeset
2547 {
kono
parents:
diff changeset
2548 dimension = CLASS_DATA (sym)->attr.dimension;
kono
parents:
diff changeset
2549 codimension = CLASS_DATA (sym)->attr.codimension;
kono
parents:
diff changeset
2550 pointer = CLASS_DATA (sym)->attr.class_pointer;
kono
parents:
diff changeset
2551 allocatable = CLASS_DATA (sym)->attr.allocatable;
kono
parents:
diff changeset
2552 attr.alloc_comp = CLASS_DATA (sym)->ts.u.derived->attr.alloc_comp;
kono
parents:
diff changeset
2553 attr.pointer_comp = CLASS_DATA (sym)->ts.u.derived->attr.pointer_comp;
kono
parents:
diff changeset
2554 }
kono
parents:
diff changeset
2555 else
kono
parents:
diff changeset
2556 {
kono
parents:
diff changeset
2557 dimension = sym->attr.dimension;
kono
parents:
diff changeset
2558 codimension = sym->attr.codimension;
kono
parents:
diff changeset
2559 pointer = sym->attr.pointer;
kono
parents:
diff changeset
2560 allocatable = sym->attr.allocatable;
kono
parents:
diff changeset
2561 attr.alloc_comp = sym->ts.type == BT_DERIVED
kono
parents:
diff changeset
2562 ? sym->ts.u.derived->attr.alloc_comp : 0;
kono
parents:
diff changeset
2563 attr.pointer_comp = sym->ts.type == BT_DERIVED
kono
parents:
diff changeset
2564 ? sym->ts.u.derived->attr.pointer_comp : 0;
kono
parents:
diff changeset
2565 }
kono
parents:
diff changeset
2566
kono
parents:
diff changeset
2567 target = coarray_comp = 0;
kono
parents:
diff changeset
2568 if (pointer || attr.proc_pointer)
kono
parents:
diff changeset
2569 target = 1;
kono
parents:
diff changeset
2570
kono
parents:
diff changeset
2571 for (ref = expr->ref; ref; ref = ref->next)
kono
parents:
diff changeset
2572 switch (ref->type)
kono
parents:
diff changeset
2573 {
kono
parents:
diff changeset
2574 case REF_ARRAY:
kono
parents:
diff changeset
2575
kono
parents:
diff changeset
2576 switch (ref->u.ar.type)
kono
parents:
diff changeset
2577 {
kono
parents:
diff changeset
2578 case AR_FULL:
kono
parents:
diff changeset
2579 case AR_SECTION:
kono
parents:
diff changeset
2580 dimension = 1;
kono
parents:
diff changeset
2581 break;
kono
parents:
diff changeset
2582
kono
parents:
diff changeset
2583 case AR_ELEMENT:
kono
parents:
diff changeset
2584 /* Handle coarrays. */
kono
parents:
diff changeset
2585 if (ref->u.ar.dimen > 0 && !in_allocate)
kono
parents:
diff changeset
2586 allocatable = pointer = 0;
kono
parents:
diff changeset
2587 break;
kono
parents:
diff changeset
2588
kono
parents:
diff changeset
2589 case AR_UNKNOWN:
kono
parents:
diff changeset
2590 /* If any of start, end or stride is not integer, there will
kono
parents:
diff changeset
2591 already have been an error issued. */
kono
parents:
diff changeset
2592 int errors;
kono
parents:
diff changeset
2593 gfc_get_errors (NULL, &errors);
kono
parents:
diff changeset
2594 if (errors == 0)
kono
parents:
diff changeset
2595 gfc_internal_error ("gfc_caf_attr(): Bad array reference");
kono
parents:
diff changeset
2596 }
kono
parents:
diff changeset
2597
kono
parents:
diff changeset
2598 break;
kono
parents:
diff changeset
2599
kono
parents:
diff changeset
2600 case REF_COMPONENT:
kono
parents:
diff changeset
2601 comp = ref->u.c.component;
kono
parents:
diff changeset
2602
kono
parents:
diff changeset
2603 if (comp->ts.type == BT_CLASS)
kono
parents:
diff changeset
2604 {
kono
parents:
diff changeset
2605 /* Set coarray_comp only, when this component introduces the
kono
parents:
diff changeset
2606 coarray. */
kono
parents:
diff changeset
2607 coarray_comp = !codimension && CLASS_DATA (comp)->attr.codimension;
kono
parents:
diff changeset
2608 codimension |= CLASS_DATA (comp)->attr.codimension;
kono
parents:
diff changeset
2609 pointer = CLASS_DATA (comp)->attr.class_pointer;
kono
parents:
diff changeset
2610 allocatable = CLASS_DATA (comp)->attr.allocatable;
kono
parents:
diff changeset
2611 }
kono
parents:
diff changeset
2612 else
kono
parents:
diff changeset
2613 {
kono
parents:
diff changeset
2614 /* Set coarray_comp only, when this component introduces the
kono
parents:
diff changeset
2615 coarray. */
kono
parents:
diff changeset
2616 coarray_comp = !codimension && comp->attr.codimension;
kono
parents:
diff changeset
2617 codimension |= comp->attr.codimension;
kono
parents:
diff changeset
2618 pointer = comp->attr.pointer;
kono
parents:
diff changeset
2619 allocatable = comp->attr.allocatable;
kono
parents:
diff changeset
2620 }
kono
parents:
diff changeset
2621
kono
parents:
diff changeset
2622 if (refs_comp && strcmp (comp->name, "_data") != 0
kono
parents:
diff changeset
2623 && (ref->next == NULL
kono
parents:
diff changeset
2624 || (ref->next->type == REF_ARRAY && ref->next->next == NULL)))
kono
parents:
diff changeset
2625 *refs_comp = true;
kono
parents:
diff changeset
2626
kono
parents:
diff changeset
2627 if (pointer || attr.proc_pointer)
kono
parents:
diff changeset
2628 target = 1;
kono
parents:
diff changeset
2629
kono
parents:
diff changeset
2630 break;
kono
parents:
diff changeset
2631
kono
parents:
diff changeset
2632 case REF_SUBSTRING:
kono
parents:
diff changeset
2633 allocatable = pointer = 0;
kono
parents:
diff changeset
2634 break;
kono
parents:
diff changeset
2635 }
kono
parents:
diff changeset
2636
kono
parents:
diff changeset
2637 attr.dimension = dimension;
kono
parents:
diff changeset
2638 attr.codimension = codimension;
kono
parents:
diff changeset
2639 attr.pointer = pointer;
kono
parents:
diff changeset
2640 attr.allocatable = allocatable;
kono
parents:
diff changeset
2641 attr.target = target;
kono
parents:
diff changeset
2642 attr.save = sym->attr.save;
kono
parents:
diff changeset
2643 attr.coarray_comp = coarray_comp;
kono
parents:
diff changeset
2644
kono
parents:
diff changeset
2645 return attr;
kono
parents:
diff changeset
2646 }
kono
parents:
diff changeset
2647
kono
parents:
diff changeset
2648
kono
parents:
diff changeset
2649 symbol_attribute
kono
parents:
diff changeset
2650 gfc_caf_attr (gfc_expr *e, bool in_allocate, bool *refs_comp)
kono
parents:
diff changeset
2651 {
kono
parents:
diff changeset
2652 symbol_attribute attr;
kono
parents:
diff changeset
2653
kono
parents:
diff changeset
2654 switch (e->expr_type)
kono
parents:
diff changeset
2655 {
kono
parents:
diff changeset
2656 case EXPR_VARIABLE:
kono
parents:
diff changeset
2657 attr = caf_variable_attr (e, in_allocate, refs_comp);
kono
parents:
diff changeset
2658 break;
kono
parents:
diff changeset
2659
kono
parents:
diff changeset
2660 case EXPR_FUNCTION:
kono
parents:
diff changeset
2661 gfc_clear_attr (&attr);
kono
parents:
diff changeset
2662
kono
parents:
diff changeset
2663 if (e->value.function.esym && e->value.function.esym->result)
kono
parents:
diff changeset
2664 {
kono
parents:
diff changeset
2665 gfc_symbol *sym = e->value.function.esym->result;
kono
parents:
diff changeset
2666 attr = sym->attr;
kono
parents:
diff changeset
2667 if (sym->ts.type == BT_CLASS)
kono
parents:
diff changeset
2668 {
kono
parents:
diff changeset
2669 attr.dimension = CLASS_DATA (sym)->attr.dimension;
kono
parents:
diff changeset
2670 attr.pointer = CLASS_DATA (sym)->attr.class_pointer;
kono
parents:
diff changeset
2671 attr.allocatable = CLASS_DATA (sym)->attr.allocatable;
kono
parents:
diff changeset
2672 attr.alloc_comp = CLASS_DATA (sym)->ts.u.derived->attr.alloc_comp;
kono
parents:
diff changeset
2673 attr.pointer_comp = CLASS_DATA (sym)->ts.u.derived
kono
parents:
diff changeset
2674 ->attr.pointer_comp;
kono
parents:
diff changeset
2675 }
kono
parents:
diff changeset
2676 }
kono
parents:
diff changeset
2677 else if (e->symtree)
kono
parents:
diff changeset
2678 attr = caf_variable_attr (e, in_allocate, refs_comp);
kono
parents:
diff changeset
2679 else
kono
parents:
diff changeset
2680 gfc_clear_attr (&attr);
kono
parents:
diff changeset
2681 break;
kono
parents:
diff changeset
2682
kono
parents:
diff changeset
2683 default:
kono
parents:
diff changeset
2684 gfc_clear_attr (&attr);
kono
parents:
diff changeset
2685 break;
kono
parents:
diff changeset
2686 }
kono
parents:
diff changeset
2687
kono
parents:
diff changeset
2688 return attr;
kono
parents:
diff changeset
2689 }
kono
parents:
diff changeset
2690
kono
parents:
diff changeset
2691
kono
parents:
diff changeset
2692 /* Match a structure constructor. The initial symbol has already been
kono
parents:
diff changeset
2693 seen. */
kono
parents:
diff changeset
2694
kono
parents:
diff changeset
2695 typedef struct gfc_structure_ctor_component
kono
parents:
diff changeset
2696 {
kono
parents:
diff changeset
2697 char* name;
kono
parents:
diff changeset
2698 gfc_expr* val;
kono
parents:
diff changeset
2699 locus where;
kono
parents:
diff changeset
2700 struct gfc_structure_ctor_component* next;
kono
parents:
diff changeset
2701 }
kono
parents:
diff changeset
2702 gfc_structure_ctor_component;
kono
parents:
diff changeset
2703
kono
parents:
diff changeset
2704 #define gfc_get_structure_ctor_component() XCNEW (gfc_structure_ctor_component)
kono
parents:
diff changeset
2705
kono
parents:
diff changeset
2706 static void
kono
parents:
diff changeset
2707 gfc_free_structure_ctor_component (gfc_structure_ctor_component *comp)
kono
parents:
diff changeset
2708 {
kono
parents:
diff changeset
2709 free (comp->name);
kono
parents:
diff changeset
2710 gfc_free_expr (comp->val);
kono
parents:
diff changeset
2711 free (comp);
kono
parents:
diff changeset
2712 }
kono
parents:
diff changeset
2713
kono
parents:
diff changeset
2714
kono
parents:
diff changeset
2715 /* Translate the component list into the actual constructor by sorting it in
kono
parents:
diff changeset
2716 the order required; this also checks along the way that each and every
kono
parents:
diff changeset
2717 component actually has an initializer and handles default initializers
kono
parents:
diff changeset
2718 for components without explicit value given. */
kono
parents:
diff changeset
2719 static bool
kono
parents:
diff changeset
2720 build_actual_constructor (gfc_structure_ctor_component **comp_head,
kono
parents:
diff changeset
2721 gfc_constructor_base *ctor_head, gfc_symbol *sym)
kono
parents:
diff changeset
2722 {
kono
parents:
diff changeset
2723 gfc_structure_ctor_component *comp_iter;
kono
parents:
diff changeset
2724 gfc_component *comp;
kono
parents:
diff changeset
2725
kono
parents:
diff changeset
2726 for (comp = sym->components; comp; comp = comp->next)
kono
parents:
diff changeset
2727 {
kono
parents:
diff changeset
2728 gfc_structure_ctor_component **next_ptr;
kono
parents:
diff changeset
2729 gfc_expr *value = NULL;
kono
parents:
diff changeset
2730
kono
parents:
diff changeset
2731 /* Try to find the initializer for the current component by name. */
kono
parents:
diff changeset
2732 next_ptr = comp_head;
kono
parents:
diff changeset
2733 for (comp_iter = *comp_head; comp_iter; comp_iter = comp_iter->next)
kono
parents:
diff changeset
2734 {
kono
parents:
diff changeset
2735 if (!strcmp (comp_iter->name, comp->name))
kono
parents:
diff changeset
2736 break;
kono
parents:
diff changeset
2737 next_ptr = &comp_iter->next;
kono
parents:
diff changeset
2738 }
kono
parents:
diff changeset
2739
kono
parents:
diff changeset
2740 /* If an extension, try building the parent derived type by building
kono
parents:
diff changeset
2741 a value expression for the parent derived type and calling self. */
kono
parents:
diff changeset
2742 if (!comp_iter && comp == sym->components && sym->attr.extension)
kono
parents:
diff changeset
2743 {
kono
parents:
diff changeset
2744 value = gfc_get_structure_constructor_expr (comp->ts.type,
kono
parents:
diff changeset
2745 comp->ts.kind,
kono
parents:
diff changeset
2746 &gfc_current_locus);
kono
parents:
diff changeset
2747 value->ts = comp->ts;
kono
parents:
diff changeset
2748
kono
parents:
diff changeset
2749 if (!build_actual_constructor (comp_head,
kono
parents:
diff changeset
2750 &value->value.constructor,
kono
parents:
diff changeset
2751 comp->ts.u.derived))
kono
parents:
diff changeset
2752 {
kono
parents:
diff changeset
2753 gfc_free_expr (value);
kono
parents:
diff changeset
2754 return false;
kono
parents:
diff changeset
2755 }
kono
parents:
diff changeset
2756
kono
parents:
diff changeset
2757 gfc_constructor_append_expr (ctor_head, value, NULL);
kono
parents:
diff changeset
2758 continue;
kono
parents:
diff changeset
2759 }
kono
parents:
diff changeset
2760
kono
parents:
diff changeset
2761 /* If it was not found, try the default initializer if there's any;
kono
parents:
diff changeset
2762 otherwise, it's an error unless this is a deferred parameter. */
kono
parents:
diff changeset
2763 if (!comp_iter)
kono
parents:
diff changeset
2764 {
kono
parents:
diff changeset
2765 if (comp->initializer)
kono
parents:
diff changeset
2766 {
kono
parents:
diff changeset
2767 if (!gfc_notify_std (GFC_STD_F2003, "Structure constructor "
kono
parents:
diff changeset
2768 "with missing optional arguments at %C"))
kono
parents:
diff changeset
2769 return false;
kono
parents:
diff changeset
2770 value = gfc_copy_expr (comp->initializer);
kono
parents:
diff changeset
2771 }
kono
parents:
diff changeset
2772 else if (comp->attr.allocatable
kono
parents:
diff changeset
2773 || (comp->ts.type == BT_CLASS
kono
parents:
diff changeset
2774 && CLASS_DATA (comp)->attr.allocatable))
kono
parents:
diff changeset
2775 {
kono
parents:
diff changeset
2776 if (!gfc_notify_std (GFC_STD_F2008, "No initializer for "
kono
parents:
diff changeset
2777 "allocatable component %qs given in the "
kono
parents:
diff changeset
2778 "structure constructor at %C", comp->name))
kono
parents:
diff changeset
2779 return false;
kono
parents:
diff changeset
2780 }
kono
parents:
diff changeset
2781 else if (!comp->attr.artificial)
kono
parents:
diff changeset
2782 {
kono
parents:
diff changeset
2783 gfc_error ("No initializer for component %qs given in the"
kono
parents:
diff changeset
2784 " structure constructor at %C", comp->name);
kono
parents:
diff changeset
2785 return false;
kono
parents:
diff changeset
2786 }
kono
parents:
diff changeset
2787 }
kono
parents:
diff changeset
2788 else
kono
parents:
diff changeset
2789 value = comp_iter->val;
kono
parents:
diff changeset
2790
kono
parents:
diff changeset
2791 /* Add the value to the constructor chain built. */
kono
parents:
diff changeset
2792 gfc_constructor_append_expr (ctor_head, value, NULL);
kono
parents:
diff changeset
2793
kono
parents:
diff changeset
2794 /* Remove the entry from the component list. We don't want the expression
kono
parents:
diff changeset
2795 value to be free'd, so set it to NULL. */
kono
parents:
diff changeset
2796 if (comp_iter)
kono
parents:
diff changeset
2797 {
kono
parents:
diff changeset
2798 *next_ptr = comp_iter->next;
kono
parents:
diff changeset
2799 comp_iter->val = NULL;
kono
parents:
diff changeset
2800 gfc_free_structure_ctor_component (comp_iter);
kono
parents:
diff changeset
2801 }
kono
parents:
diff changeset
2802 }
kono
parents:
diff changeset
2803 return true;
kono
parents:
diff changeset
2804 }
kono
parents:
diff changeset
2805
kono
parents:
diff changeset
2806
kono
parents:
diff changeset
2807 bool
kono
parents:
diff changeset
2808 gfc_convert_to_structure_constructor (gfc_expr *e, gfc_symbol *sym, gfc_expr **cexpr,
kono
parents:
diff changeset
2809 gfc_actual_arglist **arglist,
kono
parents:
diff changeset
2810 bool parent)
kono
parents:
diff changeset
2811 {
kono
parents:
diff changeset
2812 gfc_actual_arglist *actual;
kono
parents:
diff changeset
2813 gfc_structure_ctor_component *comp_tail, *comp_head, *comp_iter;
kono
parents:
diff changeset
2814 gfc_constructor_base ctor_head = NULL;
kono
parents:
diff changeset
2815 gfc_component *comp; /* Is set NULL when named component is first seen */
kono
parents:
diff changeset
2816 const char* last_name = NULL;
kono
parents:
diff changeset
2817 locus old_locus;
kono
parents:
diff changeset
2818 gfc_expr *expr;
kono
parents:
diff changeset
2819
kono
parents:
diff changeset
2820 expr = parent ? *cexpr : e;
kono
parents:
diff changeset
2821 old_locus = gfc_current_locus;
kono
parents:
diff changeset
2822 if (parent)
kono
parents:
diff changeset
2823 ; /* gfc_current_locus = *arglist->expr ? ->where;*/
kono
parents:
diff changeset
2824 else
kono
parents:
diff changeset
2825 gfc_current_locus = expr->where;
kono
parents:
diff changeset
2826
kono
parents:
diff changeset
2827 comp_tail = comp_head = NULL;
kono
parents:
diff changeset
2828
kono
parents:
diff changeset
2829 if (!parent && sym->attr.abstract)
kono
parents:
diff changeset
2830 {
kono
parents:
diff changeset
2831 gfc_error ("Can't construct ABSTRACT type %qs at %L",
kono
parents:
diff changeset
2832 sym->name, &expr->where);
kono
parents:
diff changeset
2833 goto cleanup;
kono
parents:
diff changeset
2834 }
kono
parents:
diff changeset
2835
kono
parents:
diff changeset
2836 comp = sym->components;
kono
parents:
diff changeset
2837 actual = parent ? *arglist : expr->value.function.actual;
kono
parents:
diff changeset
2838 for ( ; actual; )
kono
parents:
diff changeset
2839 {
kono
parents:
diff changeset
2840 gfc_component *this_comp = NULL;
kono
parents:
diff changeset
2841
kono
parents:
diff changeset
2842 if (!comp_head)
kono
parents:
diff changeset
2843 comp_tail = comp_head = gfc_get_structure_ctor_component ();
kono
parents:
diff changeset
2844 else
kono
parents:
diff changeset
2845 {
kono
parents:
diff changeset
2846 comp_tail->next = gfc_get_structure_ctor_component ();
kono
parents:
diff changeset
2847 comp_tail = comp_tail->next;
kono
parents:
diff changeset
2848 }
kono
parents:
diff changeset
2849 if (actual->name)
kono
parents:
diff changeset
2850 {
kono
parents:
diff changeset
2851 if (!gfc_notify_std (GFC_STD_F2003, "Structure"
kono
parents:
diff changeset
2852 " constructor with named arguments at %C"))
kono
parents:
diff changeset
2853 goto cleanup;
kono
parents:
diff changeset
2854
kono
parents:
diff changeset
2855 comp_tail->name = xstrdup (actual->name);
kono
parents:
diff changeset
2856 last_name = comp_tail->name;
kono
parents:
diff changeset
2857 comp = NULL;
kono
parents:
diff changeset
2858 }
kono
parents:
diff changeset
2859 else
kono
parents:
diff changeset
2860 {
kono
parents:
diff changeset
2861 /* Components without name are not allowed after the first named
kono
parents:
diff changeset
2862 component initializer! */
kono
parents:
diff changeset
2863 if (!comp || comp->attr.artificial)
kono
parents:
diff changeset
2864 {
kono
parents:
diff changeset
2865 if (last_name)
kono
parents:
diff changeset
2866 gfc_error ("Component initializer without name after component"
kono
parents:
diff changeset
2867 " named %s at %L", last_name,
kono
parents:
diff changeset
2868 actual->expr ? &actual->expr->where
kono
parents:
diff changeset
2869 : &gfc_current_locus);
kono
parents:
diff changeset
2870 else
kono
parents:
diff changeset
2871 gfc_error ("Too many components in structure constructor at "
kono
parents:
diff changeset
2872 "%L", actual->expr ? &actual->expr->where
kono
parents:
diff changeset
2873 : &gfc_current_locus);
kono
parents:
diff changeset
2874 goto cleanup;
kono
parents:
diff changeset
2875 }
kono
parents:
diff changeset
2876
kono
parents:
diff changeset
2877 comp_tail->name = xstrdup (comp->name);
kono
parents:
diff changeset
2878 }
kono
parents:
diff changeset
2879
kono
parents:
diff changeset
2880 /* Find the current component in the structure definition and check
kono
parents:
diff changeset
2881 its access is not private. */
kono
parents:
diff changeset
2882 if (comp)
kono
parents:
diff changeset
2883 this_comp = gfc_find_component (sym, comp->name, false, false, NULL);
kono
parents:
diff changeset
2884 else
kono
parents:
diff changeset
2885 {
kono
parents:
diff changeset
2886 this_comp = gfc_find_component (sym, (const char *)comp_tail->name,
kono
parents:
diff changeset
2887 false, false, NULL);
kono
parents:
diff changeset
2888 comp = NULL; /* Reset needed! */
kono
parents:
diff changeset
2889 }
kono
parents:
diff changeset
2890
kono
parents:
diff changeset
2891 /* Here we can check if a component name is given which does not
kono
parents:
diff changeset
2892 correspond to any component of the defined structure. */
kono
parents:
diff changeset
2893 if (!this_comp)
kono
parents:
diff changeset
2894 goto cleanup;
kono
parents:
diff changeset
2895
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2896 /* For a constant string constructor, make sure the length is
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2897 correct; truncate of fill with blanks if needed. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2898 if (this_comp->ts.type == BT_CHARACTER && !this_comp->attr.allocatable
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2899 && this_comp->ts.u.cl && this_comp->ts.u.cl->length
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2900 && this_comp->ts.u.cl->length->expr_type == EXPR_CONSTANT
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2901 && actual->expr->ts.type == BT_CHARACTER
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2902 && actual->expr->expr_type == EXPR_CONSTANT)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2903 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2904 ptrdiff_t c, e;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2905 c = gfc_mpz_get_hwi (this_comp->ts.u.cl->length->value.integer);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2906 e = actual->expr->value.character.length;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2907
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2908 if (c != e)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2909 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2910 ptrdiff_t i, to;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2911 gfc_char_t *dest;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2912 dest = gfc_get_wide_string (c + 1);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2913
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2914 to = e < c ? e : c;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2915 for (i = 0; i < to; i++)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2916 dest[i] = actual->expr->value.character.string[i];
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2917
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2918 for (i = e; i < c; i++)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2919 dest[i] = ' ';
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2920
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2921 dest[c] = '\0';
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2922 free (actual->expr->value.character.string);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2923
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2924 actual->expr->value.character.length = c;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2925 actual->expr->value.character.string = dest;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2926 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2927 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2928
111
kono
parents:
diff changeset
2929 comp_tail->val = actual->expr;
kono
parents:
diff changeset
2930 if (actual->expr != NULL)
kono
parents:
diff changeset
2931 comp_tail->where = actual->expr->where;
kono
parents:
diff changeset
2932 actual->expr = NULL;
kono
parents:
diff changeset
2933
kono
parents:
diff changeset
2934 /* Check if this component is already given a value. */
kono
parents:
diff changeset
2935 for (comp_iter = comp_head; comp_iter != comp_tail;
kono
parents:
diff changeset
2936 comp_iter = comp_iter->next)
kono
parents:
diff changeset
2937 {
kono
parents:
diff changeset
2938 gcc_assert (comp_iter);
kono
parents:
diff changeset
2939 if (!strcmp (comp_iter->name, comp_tail->name))
kono
parents:
diff changeset
2940 {
kono
parents:
diff changeset
2941 gfc_error ("Component %qs is initialized twice in the structure"
kono
parents:
diff changeset
2942 " constructor at %L", comp_tail->name,
kono
parents:
diff changeset
2943 comp_tail->val ? &comp_tail->where
kono
parents:
diff changeset
2944 : &gfc_current_locus);
kono
parents:
diff changeset
2945 goto cleanup;
kono
parents:
diff changeset
2946 }
kono
parents:
diff changeset
2947 }
kono
parents:
diff changeset
2948
kono
parents:
diff changeset
2949 /* F2008, R457/C725, for PURE C1283. */
kono
parents:
diff changeset
2950 if (this_comp->attr.pointer && comp_tail->val
kono
parents:
diff changeset
2951 && gfc_is_coindexed (comp_tail->val))
kono
parents:
diff changeset
2952 {
kono
parents:
diff changeset
2953 gfc_error ("Coindexed expression to pointer component %qs in "
kono
parents:
diff changeset
2954 "structure constructor at %L", comp_tail->name,
kono
parents:
diff changeset
2955 &comp_tail->where);
kono
parents:
diff changeset
2956 goto cleanup;
kono
parents:
diff changeset
2957 }
kono
parents:
diff changeset
2958
kono
parents:
diff changeset
2959 /* If not explicitly a parent constructor, gather up the components
kono
parents:
diff changeset
2960 and build one. */
kono
parents:
diff changeset
2961 if (comp && comp == sym->components
kono
parents:
diff changeset
2962 && sym->attr.extension
kono
parents:
diff changeset
2963 && comp_tail->val
kono
parents:
diff changeset
2964 && (!gfc_bt_struct (comp_tail->val->ts.type)
kono
parents:
diff changeset
2965 ||
kono
parents:
diff changeset
2966 comp_tail->val->ts.u.derived != this_comp->ts.u.derived))
kono
parents:
diff changeset
2967 {
kono
parents:
diff changeset
2968 bool m;
kono
parents:
diff changeset
2969 gfc_actual_arglist *arg_null = NULL;
kono
parents:
diff changeset
2970
kono
parents:
diff changeset
2971 actual->expr = comp_tail->val;
kono
parents:
diff changeset
2972 comp_tail->val = NULL;
kono
parents:
diff changeset
2973
kono
parents:
diff changeset
2974 m = gfc_convert_to_structure_constructor (NULL,
kono
parents:
diff changeset
2975 comp->ts.u.derived, &comp_tail->val,
kono
parents:
diff changeset
2976 comp->ts.u.derived->attr.zero_comp
kono
parents:
diff changeset
2977 ? &arg_null : &actual, true);
kono
parents:
diff changeset
2978 if (!m)
kono
parents:
diff changeset
2979 goto cleanup;
kono
parents:
diff changeset
2980
kono
parents:
diff changeset
2981 if (comp->ts.u.derived->attr.zero_comp)
kono
parents:
diff changeset
2982 {
kono
parents:
diff changeset
2983 comp = comp->next;
kono
parents:
diff changeset
2984 continue;
kono
parents:
diff changeset
2985 }
kono
parents:
diff changeset
2986 }
kono
parents:
diff changeset
2987
kono
parents:
diff changeset
2988 if (comp)
kono
parents:
diff changeset
2989 comp = comp->next;
kono
parents:
diff changeset
2990 if (parent && !comp)
kono
parents:
diff changeset
2991 break;
kono
parents:
diff changeset
2992
kono
parents:
diff changeset
2993 if (actual)
kono
parents:
diff changeset
2994 actual = actual->next;
kono
parents:
diff changeset
2995 }
kono
parents:
diff changeset
2996
kono
parents:
diff changeset
2997 if (!build_actual_constructor (&comp_head, &ctor_head, sym))
kono
parents:
diff changeset
2998 goto cleanup;
kono
parents:
diff changeset
2999
kono
parents:
diff changeset
3000 /* No component should be left, as this should have caused an error in the
kono
parents:
diff changeset
3001 loop constructing the component-list (name that does not correspond to any
kono
parents:
diff changeset
3002 component in the structure definition). */
kono
parents:
diff changeset
3003 if (comp_head && sym->attr.extension)
kono
parents:
diff changeset
3004 {
kono
parents:
diff changeset
3005 for (comp_iter = comp_head; comp_iter; comp_iter = comp_iter->next)
kono
parents:
diff changeset
3006 {
kono
parents:
diff changeset
3007 gfc_error ("component %qs at %L has already been set by a "
kono
parents:
diff changeset
3008 "parent derived type constructor", comp_iter->name,
kono
parents:
diff changeset
3009 &comp_iter->where);
kono
parents:
diff changeset
3010 }
kono
parents:
diff changeset
3011 goto cleanup;
kono
parents:
diff changeset
3012 }
kono
parents:
diff changeset
3013 else
kono
parents:
diff changeset
3014 gcc_assert (!comp_head);
kono
parents:
diff changeset
3015
kono
parents:
diff changeset
3016 if (parent)
kono
parents:
diff changeset
3017 {
kono
parents:
diff changeset
3018 expr = gfc_get_structure_constructor_expr (BT_DERIVED, 0, &gfc_current_locus);
kono
parents:
diff changeset
3019 expr->ts.u.derived = sym;
kono
parents:
diff changeset
3020 expr->value.constructor = ctor_head;
kono
parents:
diff changeset
3021 *cexpr = expr;
kono
parents:
diff changeset
3022 }
kono
parents:
diff changeset
3023 else
kono
parents:
diff changeset
3024 {
kono
parents:
diff changeset
3025 expr->ts.u.derived = sym;
kono
parents:
diff changeset
3026 expr->ts.kind = 0;
kono
parents:
diff changeset
3027 expr->ts.type = BT_DERIVED;
kono
parents:
diff changeset
3028 expr->value.constructor = ctor_head;
kono
parents:
diff changeset
3029 expr->expr_type = EXPR_STRUCTURE;
kono
parents:
diff changeset
3030 }
kono
parents:
diff changeset
3031
kono
parents:
diff changeset
3032 gfc_current_locus = old_locus;
kono
parents:
diff changeset
3033 if (parent)
kono
parents:
diff changeset
3034 *arglist = actual;
kono
parents:
diff changeset
3035 return true;
kono
parents:
diff changeset
3036
kono
parents:
diff changeset
3037 cleanup:
kono
parents:
diff changeset
3038 gfc_current_locus = old_locus;
kono
parents:
diff changeset
3039
kono
parents:
diff changeset
3040 for (comp_iter = comp_head; comp_iter; )
kono
parents:
diff changeset
3041 {
kono
parents:
diff changeset
3042 gfc_structure_ctor_component *next = comp_iter->next;
kono
parents:
diff changeset
3043 gfc_free_structure_ctor_component (comp_iter);
kono
parents:
diff changeset
3044 comp_iter = next;
kono
parents:
diff changeset
3045 }
kono
parents:
diff changeset
3046 gfc_constructor_free (ctor_head);
kono
parents:
diff changeset
3047
kono
parents:
diff changeset
3048 return false;
kono
parents:
diff changeset
3049 }
kono
parents:
diff changeset
3050
kono
parents:
diff changeset
3051
kono
parents:
diff changeset
3052 match
kono
parents:
diff changeset
3053 gfc_match_structure_constructor (gfc_symbol *sym, gfc_expr **result)
kono
parents:
diff changeset
3054 {
kono
parents:
diff changeset
3055 match m;
kono
parents:
diff changeset
3056 gfc_expr *e;
kono
parents:
diff changeset
3057 gfc_symtree *symtree;
kono
parents:
diff changeset
3058
kono
parents:
diff changeset
3059 gfc_get_ha_sym_tree (sym->name, &symtree);
kono
parents:
diff changeset
3060
kono
parents:
diff changeset
3061 e = gfc_get_expr ();
kono
parents:
diff changeset
3062 e->symtree = symtree;
kono
parents:
diff changeset
3063 e->expr_type = EXPR_FUNCTION;
kono
parents:
diff changeset
3064
kono
parents:
diff changeset
3065 gcc_assert (gfc_fl_struct (sym->attr.flavor)
kono
parents:
diff changeset
3066 && symtree->n.sym->attr.flavor == FL_PROCEDURE);
kono
parents:
diff changeset
3067 e->value.function.esym = sym;
kono
parents:
diff changeset
3068 e->symtree->n.sym->attr.generic = 1;
kono
parents:
diff changeset
3069
kono
parents:
diff changeset
3070 m = gfc_match_actual_arglist (0, &e->value.function.actual);
kono
parents:
diff changeset
3071 if (m != MATCH_YES)
kono
parents:
diff changeset
3072 {
kono
parents:
diff changeset
3073 gfc_free_expr (e);
kono
parents:
diff changeset
3074 return m;
kono
parents:
diff changeset
3075 }
kono
parents:
diff changeset
3076
kono
parents:
diff changeset
3077 if (!gfc_convert_to_structure_constructor (e, sym, NULL, NULL, false))
kono
parents:
diff changeset
3078 {
kono
parents:
diff changeset
3079 gfc_free_expr (e);
kono
parents:
diff changeset
3080 return MATCH_ERROR;
kono
parents:
diff changeset
3081 }
kono
parents:
diff changeset
3082
kono
parents:
diff changeset
3083 /* If a structure constructor is in a DATA statement, then each entity
kono
parents:
diff changeset
3084 in the structure constructor must be a constant. Try to reduce the
kono
parents:
diff changeset
3085 expression here. */
kono
parents:
diff changeset
3086 if (gfc_in_match_data ())
kono
parents:
diff changeset
3087 gfc_reduce_init_expr (e);
kono
parents:
diff changeset
3088
kono
parents:
diff changeset
3089 *result = e;
kono
parents:
diff changeset
3090 return MATCH_YES;
kono
parents:
diff changeset
3091 }
kono
parents:
diff changeset
3092
kono
parents:
diff changeset
3093
kono
parents:
diff changeset
3094 /* If the symbol is an implicit do loop index and implicitly typed,
kono
parents:
diff changeset
3095 it should not be host associated. Provide a symtree from the
kono
parents:
diff changeset
3096 current namespace. */
kono
parents:
diff changeset
3097 static match
kono
parents:
diff changeset
3098 check_for_implicit_index (gfc_symtree **st, gfc_symbol **sym)
kono
parents:
diff changeset
3099 {
kono
parents:
diff changeset
3100 if ((*sym)->attr.flavor == FL_VARIABLE
kono
parents:
diff changeset
3101 && (*sym)->ns != gfc_current_ns
kono
parents:
diff changeset
3102 && (*sym)->attr.implied_index
kono
parents:
diff changeset
3103 && (*sym)->attr.implicit_type
kono
parents:
diff changeset
3104 && !(*sym)->attr.use_assoc)
kono
parents:
diff changeset
3105 {
kono
parents:
diff changeset
3106 int i;
kono
parents:
diff changeset
3107 i = gfc_get_sym_tree ((*sym)->name, NULL, st, false);
kono
parents:
diff changeset
3108 if (i)
kono
parents:
diff changeset
3109 return MATCH_ERROR;
kono
parents:
diff changeset
3110 *sym = (*st)->n.sym;
kono
parents:
diff changeset
3111 }
kono
parents:
diff changeset
3112 return MATCH_YES;
kono
parents:
diff changeset
3113 }
kono
parents:
diff changeset
3114
kono
parents:
diff changeset
3115
kono
parents:
diff changeset
3116 /* Procedure pointer as function result: Replace the function symbol by the
kono
parents:
diff changeset
3117 auto-generated hidden result variable named "ppr@". */
kono
parents:
diff changeset
3118
kono
parents:
diff changeset
3119 static bool
kono
parents:
diff changeset
3120 replace_hidden_procptr_result (gfc_symbol **sym, gfc_symtree **st)
kono
parents:
diff changeset
3121 {
kono
parents:
diff changeset
3122 /* Check for procedure pointer result variable. */
kono
parents:
diff changeset
3123 if ((*sym)->attr.function && !(*sym)->attr.external
kono
parents:
diff changeset
3124 && (*sym)->result && (*sym)->result != *sym
kono
parents:
diff changeset
3125 && (*sym)->result->attr.proc_pointer
kono
parents:
diff changeset
3126 && (*sym) == gfc_current_ns->proc_name
kono
parents:
diff changeset
3127 && (*sym) == (*sym)->result->ns->proc_name
kono
parents:
diff changeset
3128 && strcmp ("ppr@", (*sym)->result->name) == 0)
kono
parents:
diff changeset
3129 {
kono
parents:
diff changeset
3130 /* Automatic replacement with "hidden" result variable. */
kono
parents:
diff changeset
3131 (*sym)->result->attr.referenced = (*sym)->attr.referenced;
kono
parents:
diff changeset
3132 *sym = (*sym)->result;
kono
parents:
diff changeset
3133 *st = gfc_find_symtree ((*sym)->ns->sym_root, (*sym)->name);
kono
parents:
diff changeset
3134 return true;
kono
parents:
diff changeset
3135 }
kono
parents:
diff changeset
3136 return false;
kono
parents:
diff changeset
3137 }
kono
parents:
diff changeset
3138
kono
parents:
diff changeset
3139
kono
parents:
diff changeset
3140 /* Matches a variable name followed by anything that might follow it--
kono
parents:
diff changeset
3141 array reference, argument list of a function, etc. */
kono
parents:
diff changeset
3142
kono
parents:
diff changeset
3143 match
kono
parents:
diff changeset
3144 gfc_match_rvalue (gfc_expr **result)
kono
parents:
diff changeset
3145 {
kono
parents:
diff changeset
3146 gfc_actual_arglist *actual_arglist;
kono
parents:
diff changeset
3147 char name[GFC_MAX_SYMBOL_LEN + 1], argname[GFC_MAX_SYMBOL_LEN + 1];
kono
parents:
diff changeset
3148 gfc_state_data *st;
kono
parents:
diff changeset
3149 gfc_symbol *sym;
kono
parents:
diff changeset
3150 gfc_symtree *symtree;
kono
parents:
diff changeset
3151 locus where, old_loc;
kono
parents:
diff changeset
3152 gfc_expr *e;
kono
parents:
diff changeset
3153 match m, m2;
kono
parents:
diff changeset
3154 int i;
kono
parents:
diff changeset
3155 gfc_typespec *ts;
kono
parents:
diff changeset
3156 bool implicit_char;
kono
parents:
diff changeset
3157 gfc_ref *ref;
kono
parents:
diff changeset
3158
kono
parents:
diff changeset
3159 m = gfc_match ("%%loc");
kono
parents:
diff changeset
3160 if (m == MATCH_YES)
kono
parents:
diff changeset
3161 {
kono
parents:
diff changeset
3162 if (!gfc_notify_std (GFC_STD_LEGACY, "%%LOC() as an rvalue at %C"))
kono
parents:
diff changeset
3163 return MATCH_ERROR;
kono
parents:
diff changeset
3164 strncpy (name, "loc", 4);
kono
parents:
diff changeset
3165 }
kono
parents:
diff changeset
3166
kono
parents:
diff changeset
3167 else
kono
parents:
diff changeset
3168 {
kono
parents:
diff changeset
3169 m = gfc_match_name (name);
kono
parents:
diff changeset
3170 if (m != MATCH_YES)
kono
parents:
diff changeset
3171 return m;
kono
parents:
diff changeset
3172 }
kono
parents:
diff changeset
3173
kono
parents:
diff changeset
3174 /* Check if the symbol exists. */
kono
parents:
diff changeset
3175 if (gfc_find_sym_tree (name, NULL, 1, &symtree))
kono
parents:
diff changeset
3176 return MATCH_ERROR;
kono
parents:
diff changeset
3177
kono
parents:
diff changeset
3178 /* If the symbol doesn't exist, create it unless the name matches a FL_STRUCT
kono
parents:
diff changeset
3179 type. For derived types we create a generic symbol which links to the
kono
parents:
diff changeset
3180 derived type symbol; STRUCTUREs are simpler and must not conflict with
kono
parents:
diff changeset
3181 variables. */
kono
parents:
diff changeset
3182 if (!symtree)
kono
parents:
diff changeset
3183 if (gfc_find_sym_tree (gfc_dt_upper_string (name), NULL, 1, &symtree))
kono
parents:
diff changeset
3184 return MATCH_ERROR;
kono
parents:
diff changeset
3185 if (!symtree || symtree->n.sym->attr.flavor != FL_STRUCT)
kono
parents:
diff changeset
3186 {
kono
parents:
diff changeset
3187 if (gfc_find_state (COMP_INTERFACE)
kono
parents:
diff changeset
3188 && !gfc_current_ns->has_import_set)
kono
parents:
diff changeset
3189 i = gfc_get_sym_tree (name, NULL, &symtree, false);
kono
parents:
diff changeset
3190 else
kono
parents:
diff changeset
3191 i = gfc_get_ha_sym_tree (name, &symtree);
kono
parents:
diff changeset
3192 if (i)
kono
parents:
diff changeset
3193 return MATCH_ERROR;
kono
parents:
diff changeset
3194 }
kono
parents:
diff changeset
3195
kono
parents:
diff changeset
3196
kono
parents:
diff changeset
3197 sym = symtree->n.sym;
kono
parents:
diff changeset
3198 e = NULL;
kono
parents:
diff changeset
3199 where = gfc_current_locus;
kono
parents:
diff changeset
3200
kono
parents:
diff changeset
3201 replace_hidden_procptr_result (&sym, &symtree);
kono
parents:
diff changeset
3202
kono
parents:
diff changeset
3203 /* If this is an implicit do loop index and implicitly typed,
kono
parents:
diff changeset
3204 it should not be host associated. */
kono
parents:
diff changeset
3205 m = check_for_implicit_index (&symtree, &sym);
kono
parents:
diff changeset
3206 if (m != MATCH_YES)
kono
parents:
diff changeset
3207 return m;
kono
parents:
diff changeset
3208
kono
parents:
diff changeset
3209 gfc_set_sym_referenced (sym);
kono
parents:
diff changeset
3210 sym->attr.implied_index = 0;
kono
parents:
diff changeset
3211
kono
parents:
diff changeset
3212 if (sym->attr.function && sym->result == sym)
kono
parents:
diff changeset
3213 {
kono
parents:
diff changeset
3214 /* See if this is a directly recursive function call. */
kono
parents:
diff changeset
3215 gfc_gobble_whitespace ();
kono
parents:
diff changeset
3216 if (sym->attr.recursive
kono
parents:
diff changeset
3217 && gfc_peek_ascii_char () == '('
kono
parents:
diff changeset
3218 && gfc_current_ns->proc_name == sym
kono
parents:
diff changeset
3219 && !sym->attr.dimension)
kono
parents:
diff changeset
3220 {
kono
parents:
diff changeset
3221 gfc_error ("%qs at %C is the name of a recursive function "
kono
parents:
diff changeset
3222 "and so refers to the result variable. Use an "
kono
parents:
diff changeset
3223 "explicit RESULT variable for direct recursion "
kono
parents:
diff changeset
3224 "(12.5.2.1)", sym->name);
kono
parents:
diff changeset
3225 return MATCH_ERROR;
kono
parents:
diff changeset
3226 }
kono
parents:
diff changeset
3227
kono
parents:
diff changeset
3228 if (gfc_is_function_return_value (sym, gfc_current_ns))
kono
parents:
diff changeset
3229 goto variable;
kono
parents:
diff changeset
3230
kono
parents:
diff changeset
3231 if (sym->attr.entry
kono
parents:
diff changeset
3232 && (sym->ns == gfc_current_ns
kono
parents:
diff changeset
3233 || sym->ns == gfc_current_ns->parent))
kono
parents:
diff changeset
3234 {
kono
parents:
diff changeset
3235 gfc_entry_list *el = NULL;
kono
parents:
diff changeset
3236
kono
parents:
diff changeset
3237 for (el = sym->ns->entries; el; el = el->next)
kono
parents:
diff changeset
3238 if (sym == el->sym)
kono
parents:
diff changeset
3239 goto variable;
kono
parents:
diff changeset
3240 }
kono
parents:
diff changeset
3241 }
kono
parents:
diff changeset
3242
kono
parents:
diff changeset
3243 if (gfc_matching_procptr_assignment)
kono
parents:
diff changeset
3244 goto procptr0;
kono
parents:
diff changeset
3245
kono
parents:
diff changeset
3246 if (sym->attr.function || sym->attr.external || sym->attr.intrinsic)
kono
parents:
diff changeset
3247 goto function0;
kono
parents:
diff changeset
3248
kono
parents:
diff changeset
3249 if (sym->attr.generic)
kono
parents:
diff changeset
3250 goto generic_function;
kono
parents:
diff changeset
3251
kono
parents:
diff changeset
3252 switch (sym->attr.flavor)
kono
parents:
diff changeset
3253 {
kono
parents:
diff changeset
3254 case FL_VARIABLE:
kono
parents:
diff changeset
3255 variable:
kono
parents:
diff changeset
3256 e = gfc_get_expr ();
kono
parents:
diff changeset
3257
kono
parents:
diff changeset
3258 e->expr_type = EXPR_VARIABLE;
kono
parents:
diff changeset
3259 e->symtree = symtree;
kono
parents:
diff changeset
3260
kono
parents:
diff changeset
3261 m = gfc_match_varspec (e, 0, false, true);
kono
parents:
diff changeset
3262 break;
kono
parents:
diff changeset
3263
kono
parents:
diff changeset
3264 case FL_PARAMETER:
kono
parents:
diff changeset
3265 /* A statement of the form "REAL, parameter :: a(0:10) = 1" will
kono
parents:
diff changeset
3266 end up here. Unfortunately, sym->value->expr_type is set to
kono
parents:
diff changeset
3267 EXPR_CONSTANT, and so the if () branch would be followed without
kono
parents:
diff changeset
3268 the !sym->as check. */
kono
parents:
diff changeset
3269 if (sym->value && sym->value->expr_type != EXPR_ARRAY && !sym->as)
kono
parents:
diff changeset
3270 e = gfc_copy_expr (sym->value);
kono
parents:
diff changeset
3271 else
kono
parents:
diff changeset
3272 {
kono
parents:
diff changeset
3273 e = gfc_get_expr ();
kono
parents:
diff changeset
3274 e->expr_type = EXPR_VARIABLE;
kono
parents:
diff changeset
3275 }
kono
parents:
diff changeset
3276
kono
parents:
diff changeset
3277 e->symtree = symtree;
kono
parents:
diff changeset
3278 m = gfc_match_varspec (e, 0, false, true);
kono
parents:
diff changeset
3279
kono
parents:
diff changeset
3280 if (sym->ts.is_c_interop || sym->ts.is_iso_c)
kono
parents:
diff changeset
3281 break;
kono
parents:
diff changeset
3282
kono
parents:
diff changeset
3283 /* Variable array references to derived type parameters cause
kono
parents:
diff changeset
3284 all sorts of headaches in simplification. Treating such
kono
parents:
diff changeset
3285 expressions as variable works just fine for all array
kono
parents:
diff changeset
3286 references. */
kono
parents:
diff changeset
3287 if (sym->value && sym->ts.type == BT_DERIVED && e->ref)
kono
parents:
diff changeset
3288 {
kono
parents:
diff changeset
3289 for (ref = e->ref; ref; ref = ref->next)
kono
parents:
diff changeset
3290 if (ref->type == REF_ARRAY)
kono
parents:
diff changeset
3291 break;
kono
parents:
diff changeset
3292
kono
parents:
diff changeset
3293 if (ref == NULL || ref->u.ar.type == AR_FULL)
kono
parents:
diff changeset
3294 break;
kono
parents:
diff changeset
3295
kono
parents:
diff changeset
3296 ref = e->ref;
kono
parents:
diff changeset
3297 e->ref = NULL;
kono
parents:
diff changeset
3298 gfc_free_expr (e);
kono
parents:
diff changeset
3299 e = gfc_get_expr ();
kono
parents:
diff changeset
3300 e->expr_type = EXPR_VARIABLE;
kono
parents:
diff changeset
3301 e->symtree = symtree;
kono
parents:
diff changeset
3302 e->ref = ref;
kono
parents:
diff changeset
3303 }
kono
parents:
diff changeset
3304
kono
parents:
diff changeset
3305 break;
kono
parents:
diff changeset
3306
kono
parents:
diff changeset
3307 case FL_STRUCT:
kono
parents:
diff changeset
3308 case FL_DERIVED:
kono
parents:
diff changeset
3309 sym = gfc_use_derived (sym);
kono
parents:
diff changeset
3310 if (sym == NULL)
kono
parents:
diff changeset
3311 m = MATCH_ERROR;
kono
parents:
diff changeset
3312 else
kono
parents:
diff changeset
3313 goto generic_function;
kono
parents:
diff changeset
3314 break;
kono
parents:
diff changeset
3315
kono
parents:
diff changeset
3316 /* If we're here, then the name is known to be the name of a
kono
parents:
diff changeset
3317 procedure, yet it is not sure to be the name of a function. */
kono
parents:
diff changeset
3318 case FL_PROCEDURE:
kono
parents:
diff changeset
3319
kono
parents:
diff changeset
3320 /* Procedure Pointer Assignments. */
kono
parents:
diff changeset
3321 procptr0:
kono
parents:
diff changeset
3322 if (gfc_matching_procptr_assignment)
kono
parents:
diff changeset
3323 {
kono
parents:
diff changeset
3324 gfc_gobble_whitespace ();
kono
parents:
diff changeset
3325 if (!sym->attr.dimension && gfc_peek_ascii_char () == '(')
kono
parents:
diff changeset
3326 /* Parse functions returning a procptr. */
kono
parents:
diff changeset
3327 goto function0;
kono
parents:
diff changeset
3328
kono
parents:
diff changeset
3329 e = gfc_get_expr ();
kono
parents:
diff changeset
3330 e->expr_type = EXPR_VARIABLE;
kono
parents:
diff changeset
3331 e->symtree = symtree;
kono
parents:
diff changeset
3332 m = gfc_match_varspec (e, 0, false, true);
kono
parents:
diff changeset
3333 if (!e->ref && sym->attr.flavor == FL_UNKNOWN
kono
parents:
diff changeset
3334 && sym->ts.type == BT_UNKNOWN
kono
parents:
diff changeset
3335 && !gfc_add_flavor (&sym->attr, FL_PROCEDURE, sym->name, NULL))
kono
parents:
diff changeset
3336 {
kono
parents:
diff changeset
3337 m = MATCH_ERROR;
kono
parents:
diff changeset
3338 break;
kono
parents:
diff changeset
3339 }
kono
parents:
diff changeset
3340 break;
kono
parents:
diff changeset
3341 }
kono
parents:
diff changeset
3342
kono
parents:
diff changeset
3343 if (sym->attr.subroutine)
kono
parents:
diff changeset
3344 {
kono
parents:
diff changeset
3345 gfc_error ("Unexpected use of subroutine name %qs at %C",
kono
parents:
diff changeset
3346 sym->name);
kono
parents:
diff changeset
3347 m = MATCH_ERROR;
kono
parents:
diff changeset
3348 break;
kono
parents:
diff changeset
3349 }
kono
parents:
diff changeset
3350
kono
parents:
diff changeset
3351 /* At this point, the name has to be a non-statement function.
kono
parents:
diff changeset
3352 If the name is the same as the current function being
kono
parents:
diff changeset
3353 compiled, then we have a variable reference (to the function
kono
parents:
diff changeset
3354 result) if the name is non-recursive. */
kono
parents:
diff changeset
3355
kono
parents:
diff changeset
3356 st = gfc_enclosing_unit (NULL);
kono
parents:
diff changeset
3357
kono
parents:
diff changeset
3358 if (st != NULL
kono
parents:
diff changeset
3359 && st->state == COMP_FUNCTION
kono
parents:
diff changeset
3360 && st->sym == sym
kono
parents:
diff changeset
3361 && !sym->attr.recursive)
kono
parents:
diff changeset
3362 {
kono
parents:
diff changeset
3363 e = gfc_get_expr ();
kono
parents:
diff changeset
3364 e->symtree = symtree;
kono
parents:
diff changeset
3365 e->expr_type = EXPR_VARIABLE;
kono
parents:
diff changeset
3366
kono
parents:
diff changeset
3367 m = gfc_match_varspec (e, 0, false, true);
kono
parents:
diff changeset
3368 break;
kono
parents:
diff changeset
3369 }
kono
parents:
diff changeset
3370
kono
parents:
diff changeset
3371 /* Match a function reference. */
kono
parents:
diff changeset
3372 function0:
kono
parents:
diff changeset
3373 m = gfc_match_actual_arglist (0, &actual_arglist);
kono
parents:
diff changeset
3374 if (m == MATCH_NO)
kono
parents:
diff changeset
3375 {
kono
parents:
diff changeset
3376 if (sym->attr.proc == PROC_ST_FUNCTION)
kono
parents:
diff changeset
3377 gfc_error ("Statement function %qs requires argument list at %C",
kono
parents:
diff changeset
3378 sym->name);
kono
parents:
diff changeset
3379 else
kono
parents:
diff changeset
3380 gfc_error ("Function %qs requires an argument list at %C",
kono
parents:
diff changeset
3381 sym->name);
kono
parents:
diff changeset
3382
kono
parents:
diff changeset
3383 m = MATCH_ERROR;
kono
parents:
diff changeset
3384 break;
kono
parents:
diff changeset
3385 }
kono
parents:
diff changeset
3386
kono
parents:
diff changeset
3387 if (m != MATCH_YES)
kono
parents:
diff changeset
3388 {
kono
parents:
diff changeset
3389 m = MATCH_ERROR;
kono
parents:
diff changeset
3390 break;
kono
parents:
diff changeset
3391 }
kono
parents:
diff changeset
3392
kono
parents:
diff changeset
3393 gfc_get_ha_sym_tree (name, &symtree); /* Can't fail */
kono
parents:
diff changeset
3394 sym = symtree->n.sym;
kono
parents:
diff changeset
3395
kono
parents:
diff changeset
3396 replace_hidden_procptr_result (&sym, &symtree);
kono
parents:
diff changeset
3397
kono
parents:
diff changeset
3398 e = gfc_get_expr ();
kono
parents:
diff changeset
3399 e->symtree = symtree;
kono
parents:
diff changeset
3400 e->expr_type = EXPR_FUNCTION;
kono
parents:
diff changeset
3401 e->value.function.actual = actual_arglist;
kono
parents:
diff changeset
3402 e->where = gfc_current_locus;
kono
parents:
diff changeset
3403
kono
parents:
diff changeset
3404 if (sym->ts.type == BT_CLASS && sym->attr.class_ok
kono
parents:
diff changeset
3405 && CLASS_DATA (sym)->as)
kono
parents:
diff changeset
3406 e->rank = CLASS_DATA (sym)->as->rank;
kono
parents:
diff changeset
3407 else if (sym->as != NULL)
kono
parents:
diff changeset
3408 e->rank = sym->as->rank;
kono
parents:
diff changeset
3409
kono
parents:
diff changeset
3410 if (!sym->attr.function
kono
parents:
diff changeset
3411 && !gfc_add_function (&sym->attr, sym->name, NULL))
kono
parents:
diff changeset
3412 {
kono
parents:
diff changeset
3413 m = MATCH_ERROR;
kono
parents:
diff changeset
3414 break;
kono
parents:
diff changeset
3415 }
kono
parents:
diff changeset
3416
kono
parents:
diff changeset
3417 /* Check here for the existence of at least one argument for the
kono
parents:
diff changeset
3418 iso_c_binding functions C_LOC, C_FUNLOC, and C_ASSOCIATED. The
kono
parents:
diff changeset
3419 argument(s) given will be checked in gfc_iso_c_func_interface,
kono
parents:
diff changeset
3420 during resolution of the function call. */
kono
parents:
diff changeset
3421 if (sym->attr.is_iso_c == 1
kono
parents:
diff changeset
3422 && (sym->from_intmod == INTMOD_ISO_C_BINDING
kono
parents:
diff changeset
3423 && (sym->intmod_sym_id == ISOCBINDING_LOC
kono
parents:
diff changeset
3424 || sym->intmod_sym_id == ISOCBINDING_FUNLOC
kono
parents:
diff changeset
3425 || sym->intmod_sym_id == ISOCBINDING_ASSOCIATED)))
kono
parents:
diff changeset
3426 {
kono
parents:
diff changeset
3427 /* make sure we were given a param */
kono
parents:
diff changeset
3428 if (actual_arglist == NULL)
kono
parents:
diff changeset
3429 {
kono
parents:
diff changeset
3430 gfc_error ("Missing argument to %qs at %C", sym->name);
kono
parents:
diff changeset
3431 m = MATCH_ERROR;
kono
parents:
diff changeset
3432 break;
kono
parents:
diff changeset
3433 }
kono
parents:
diff changeset
3434 }
kono
parents:
diff changeset
3435
kono
parents:
diff changeset
3436 if (sym->result == NULL)
kono
parents:
diff changeset
3437 sym->result = sym;
kono
parents:
diff changeset
3438
kono
parents:
diff changeset
3439 gfc_gobble_whitespace ();
kono
parents:
diff changeset
3440 /* F08:C612. */
kono
parents:
diff changeset
3441 if (gfc_peek_ascii_char() == '%')
kono
parents:
diff changeset
3442 {
kono
parents:
diff changeset
3443 gfc_error ("The leftmost part-ref in a data-ref can not be a "
kono
parents:
diff changeset
3444 "function reference at %C");
kono
parents:
diff changeset
3445 m = MATCH_ERROR;
kono
parents:
diff changeset
3446 }
kono
parents:
diff changeset
3447
kono
parents:
diff changeset
3448 m = MATCH_YES;
kono
parents:
diff changeset
3449 break;
kono
parents:
diff changeset
3450
kono
parents:
diff changeset
3451 case FL_UNKNOWN:
kono
parents:
diff changeset
3452
kono
parents:
diff changeset
3453 /* Special case for derived type variables that get their types
kono
parents:
diff changeset
3454 via an IMPLICIT statement. This can't wait for the
kono
parents:
diff changeset
3455 resolution phase. */
kono
parents:
diff changeset
3456
kono
parents:
diff changeset
3457 old_loc = gfc_current_locus;
kono
parents:
diff changeset
3458 if (gfc_match_member_sep (sym) == MATCH_YES
kono
parents:
diff changeset
3459 && sym->ts.type == BT_UNKNOWN
kono
parents:
diff changeset
3460 && gfc_get_default_type (sym->name, sym->ns)->type == BT_DERIVED)
kono
parents:
diff changeset
3461 gfc_set_default_type (sym, 0, sym->ns);
kono
parents:
diff changeset
3462 gfc_current_locus = old_loc;
kono
parents:
diff changeset
3463
kono
parents:
diff changeset
3464 /* If the symbol has a (co)dimension attribute, the expression is a
kono
parents:
diff changeset
3465 variable. */
kono
parents:
diff changeset
3466
kono
parents:
diff changeset
3467 if (sym->attr.dimension || sym->attr.codimension)
kono
parents:
diff changeset
3468 {
kono
parents:
diff changeset
3469 if (!gfc_add_flavor (&sym->attr, FL_VARIABLE, sym->name, NULL))
kono
parents:
diff changeset
3470 {
kono
parents:
diff changeset
3471 m = MATCH_ERROR;
kono
parents:
diff changeset
3472 break;
kono
parents:
diff changeset
3473 }
kono
parents:
diff changeset
3474
kono
parents:
diff changeset
3475 e = gfc_get_expr ();
kono
parents:
diff changeset
3476 e->symtree = symtree;
kono
parents:
diff changeset
3477 e->expr_type = EXPR_VARIABLE;
kono
parents:
diff changeset
3478 m = gfc_match_varspec (e, 0, false, true);
kono
parents:
diff changeset
3479 break;
kono
parents:
diff changeset
3480 }
kono
parents:
diff changeset
3481
kono
parents:
diff changeset
3482 if (sym->ts.type == BT_CLASS && sym->attr.class_ok
kono
parents:
diff changeset
3483 && (CLASS_DATA (sym)->attr.dimension
kono
parents:
diff changeset
3484 || CLASS_DATA (sym)->attr.codimension))
kono
parents:
diff changeset
3485 {
kono
parents:
diff changeset
3486 if (!gfc_add_flavor (&sym->attr, FL_VARIABLE, sym->name, NULL))
kono
parents:
diff changeset
3487 {
kono
parents:
diff changeset
3488 m = MATCH_ERROR;
kono
parents:
diff changeset
3489 break;
kono
parents:
diff changeset
3490 }
kono
parents:
diff changeset
3491
kono
parents:
diff changeset
3492 e = gfc_get_expr ();
kono
parents:
diff changeset
3493 e->symtree = symtree;
kono
parents:
diff changeset
3494 e->expr_type = EXPR_VARIABLE;
kono
parents:
diff changeset
3495 m = gfc_match_varspec (e, 0, false, true);
kono
parents:
diff changeset
3496 break;
kono
parents:
diff changeset
3497 }
kono
parents:
diff changeset
3498
kono
parents:
diff changeset
3499 /* Name is not an array, so we peek to see if a '(' implies a
kono
parents:
diff changeset
3500 function call or a substring reference. Otherwise the
kono
parents:
diff changeset
3501 variable is just a scalar. */
kono
parents:
diff changeset
3502
kono
parents:
diff changeset
3503 gfc_gobble_whitespace ();
kono
parents:
diff changeset
3504 if (gfc_peek_ascii_char () != '(')
kono
parents:
diff changeset
3505 {
kono
parents:
diff changeset
3506 /* Assume a scalar variable */
kono
parents:
diff changeset
3507 e = gfc_get_expr ();
kono
parents:
diff changeset
3508 e->symtree = symtree;
kono
parents:
diff changeset
3509 e->expr_type = EXPR_VARIABLE;
kono
parents:
diff changeset
3510
kono
parents:
diff changeset
3511 if (!gfc_add_flavor (&sym->attr, FL_VARIABLE, sym->name, NULL))
kono
parents:
diff changeset
3512 {
kono
parents:
diff changeset
3513 m = MATCH_ERROR;
kono
parents:
diff changeset
3514 break;
kono
parents:
diff changeset
3515 }
kono
parents:
diff changeset
3516
kono
parents:
diff changeset
3517 /*FIXME:??? gfc_match_varspec does set this for us: */
kono
parents:
diff changeset
3518 e->ts = sym->ts;
kono
parents:
diff changeset
3519 m = gfc_match_varspec (e, 0, false, true);
kono
parents:
diff changeset
3520 break;
kono
parents:
diff changeset
3521 }
kono
parents:
diff changeset
3522
kono
parents:
diff changeset
3523 /* See if this is a function reference with a keyword argument
kono
parents:
diff changeset
3524 as first argument. We do this because otherwise a spurious
kono
parents:
diff changeset
3525 symbol would end up in the symbol table. */
kono
parents:
diff changeset
3526
kono
parents:
diff changeset
3527 old_loc = gfc_current_locus;
kono
parents:
diff changeset
3528 m2 = gfc_match (" ( %n =", argname);
kono
parents:
diff changeset
3529 gfc_current_locus = old_loc;
kono
parents:
diff changeset
3530
kono
parents:
diff changeset
3531 e = gfc_get_expr ();
kono
parents:
diff changeset
3532 e->symtree = symtree;
kono
parents:
diff changeset
3533
kono
parents:
diff changeset
3534 if (m2 != MATCH_YES)
kono
parents:
diff changeset
3535 {
kono
parents:
diff changeset
3536 /* Try to figure out whether we're dealing with a character type.
kono
parents:
diff changeset
3537 We're peeking ahead here, because we don't want to call
kono
parents:
diff changeset
3538 match_substring if we're dealing with an implicitly typed
kono
parents:
diff changeset
3539 non-character variable. */
kono
parents:
diff changeset
3540 implicit_char = false;
kono
parents:
diff changeset
3541 if (sym->ts.type == BT_UNKNOWN)
kono
parents:
diff changeset
3542 {
kono
parents:
diff changeset
3543 ts = gfc_get_default_type (sym->name, NULL);
kono
parents:
diff changeset
3544 if (ts->type == BT_CHARACTER)
kono
parents:
diff changeset
3545 implicit_char = true;
kono
parents:
diff changeset
3546 }
kono
parents:
diff changeset
3547
kono
parents:
diff changeset
3548 /* See if this could possibly be a substring reference of a name
kono
parents:
diff changeset
3549 that we're not sure is a variable yet. */
kono
parents:
diff changeset
3550
kono
parents:
diff changeset
3551 if ((implicit_char || sym->ts.type == BT_CHARACTER)
kono
parents:
diff changeset
3552 && match_substring (sym->ts.u.cl, 0, &e->ref, false) == MATCH_YES)
kono
parents:
diff changeset
3553 {
kono
parents:
diff changeset
3554
kono
parents:
diff changeset
3555 e->expr_type = EXPR_VARIABLE;
kono
parents:
diff changeset
3556
kono
parents:
diff changeset
3557 if (sym->attr.flavor != FL_VARIABLE
kono
parents:
diff changeset
3558 && !gfc_add_flavor (&sym->attr, FL_VARIABLE,
kono
parents:
diff changeset
3559 sym->name, NULL))
kono
parents:
diff changeset
3560 {
kono
parents:
diff changeset
3561 m = MATCH_ERROR;
kono
parents:
diff changeset
3562 break;
kono
parents:
diff changeset
3563 }
kono
parents:
diff changeset
3564
kono
parents:
diff changeset
3565 if (sym->ts.type == BT_UNKNOWN
kono
parents:
diff changeset
3566 && !gfc_set_default_type (sym, 1, NULL))
kono
parents:
diff changeset
3567 {
kono
parents:
diff changeset
3568 m = MATCH_ERROR;
kono
parents:
diff changeset
3569 break;
kono
parents:
diff changeset
3570 }
kono
parents:
diff changeset
3571
kono
parents:
diff changeset
3572 e->ts = sym->ts;
kono
parents:
diff changeset
3573 if (e->ref)
kono
parents:
diff changeset
3574 e->ts.u.cl = NULL;
kono
parents:
diff changeset
3575 m = MATCH_YES;
kono
parents:
diff changeset
3576 break;
kono
parents:
diff changeset
3577 }
kono
parents:
diff changeset
3578 }
kono
parents:
diff changeset
3579
kono
parents:
diff changeset
3580 /* Give up, assume we have a function. */
kono
parents:
diff changeset
3581
kono
parents:
diff changeset
3582 gfc_get_sym_tree (name, NULL, &symtree, false); /* Can't fail */
kono
parents:
diff changeset
3583 sym = symtree->n.sym;
kono
parents:
diff changeset
3584 e->expr_type = EXPR_FUNCTION;
kono
parents:
diff changeset
3585
kono
parents:
diff changeset
3586 if (!sym->attr.function
kono
parents:
diff changeset
3587 && !gfc_add_function (&sym->attr, sym->name, NULL))
kono
parents:
diff changeset
3588 {
kono
parents:
diff changeset
3589 m = MATCH_ERROR;
kono
parents:
diff changeset
3590 break;
kono
parents:
diff changeset
3591 }
kono
parents:
diff changeset
3592
kono
parents:
diff changeset
3593 sym->result = sym;
kono
parents:
diff changeset
3594
kono
parents:
diff changeset
3595 m = gfc_match_actual_arglist (0, &e->value.function.actual);
kono
parents:
diff changeset
3596 if (m == MATCH_NO)
kono
parents:
diff changeset
3597 gfc_error ("Missing argument list in function %qs at %C", sym->name);
kono
parents:
diff changeset
3598
kono
parents:
diff changeset
3599 if (m != MATCH_YES)
kono
parents:
diff changeset
3600 {
kono
parents:
diff changeset
3601 m = MATCH_ERROR;
kono
parents:
diff changeset
3602 break;
kono
parents:
diff changeset
3603 }
kono
parents:
diff changeset
3604
kono
parents:
diff changeset
3605 /* If our new function returns a character, array or structure
kono
parents:
diff changeset
3606 type, it might have subsequent references. */
kono
parents:
diff changeset
3607
kono
parents:
diff changeset
3608 m = gfc_match_varspec (e, 0, false, true);
kono
parents:
diff changeset
3609 if (m == MATCH_NO)
kono
parents:
diff changeset
3610 m = MATCH_YES;
kono
parents:
diff changeset
3611
kono
parents:
diff changeset
3612 break;
kono
parents:
diff changeset
3613
kono
parents:
diff changeset
3614 generic_function:
kono
parents:
diff changeset
3615 /* Look for symbol first; if not found, look for STRUCTURE type symbol
kono
parents:
diff changeset
3616 specially. Creates a generic symbol for derived types. */
kono
parents:
diff changeset
3617 gfc_find_sym_tree (name, NULL, 1, &symtree);
kono
parents:
diff changeset
3618 if (!symtree)
kono
parents:
diff changeset
3619 gfc_find_sym_tree (gfc_dt_upper_string (name), NULL, 1, &symtree);
kono
parents:
diff changeset
3620 if (!symtree || symtree->n.sym->attr.flavor != FL_STRUCT)
kono
parents:
diff changeset
3621 gfc_get_sym_tree (name, NULL, &symtree, false); /* Can't fail */
kono
parents:
diff changeset
3622
kono
parents:
diff changeset
3623 e = gfc_get_expr ();
kono
parents:
diff changeset
3624 e->symtree = symtree;
kono
parents:
diff changeset
3625 e->expr_type = EXPR_FUNCTION;
kono
parents:
diff changeset
3626
kono
parents:
diff changeset
3627 if (gfc_fl_struct (sym->attr.flavor))
kono
parents:
diff changeset
3628 {
kono
parents:
diff changeset
3629 e->value.function.esym = sym;
kono
parents:
diff changeset
3630 e->symtree->n.sym->attr.generic = 1;
kono
parents:
diff changeset
3631 }
kono
parents:
diff changeset
3632
kono
parents:
diff changeset
3633 m = gfc_match_actual_arglist (0, &e->value.function.actual);
kono
parents:
diff changeset
3634 break;
kono
parents:
diff changeset
3635
kono
parents:
diff changeset
3636 case FL_NAMELIST:
kono
parents:
diff changeset
3637 m = MATCH_ERROR;
kono
parents:
diff changeset
3638 break;
kono
parents:
diff changeset
3639
kono
parents:
diff changeset
3640 default:
kono
parents:
diff changeset
3641 gfc_error ("Symbol at %C is not appropriate for an expression");
kono
parents:
diff changeset
3642 return MATCH_ERROR;
kono
parents:
diff changeset
3643 }
kono
parents:
diff changeset
3644
kono
parents:
diff changeset
3645 if (m == MATCH_YES)
kono
parents:
diff changeset
3646 {
kono
parents:
diff changeset
3647 e->where = where;
kono
parents:
diff changeset
3648 *result = e;
kono
parents:
diff changeset
3649 }
kono
parents:
diff changeset
3650 else
kono
parents:
diff changeset
3651 gfc_free_expr (e);
kono
parents:
diff changeset
3652
kono
parents:
diff changeset
3653 return m;
kono
parents:
diff changeset
3654 }
kono
parents:
diff changeset
3655
kono
parents:
diff changeset
3656
kono
parents:
diff changeset
3657 /* Match a variable, i.e. something that can be assigned to. This
kono
parents:
diff changeset
3658 starts as a symbol, can be a structure component or an array
kono
parents:
diff changeset
3659 reference. It can be a function if the function doesn't have a
kono
parents:
diff changeset
3660 separate RESULT variable. If the symbol has not been previously
kono
parents:
diff changeset
3661 seen, we assume it is a variable.
kono
parents:
diff changeset
3662
kono
parents:
diff changeset
3663 This function is called by two interface functions:
kono
parents:
diff changeset
3664 gfc_match_variable, which has host_flag = 1, and
kono
parents:
diff changeset
3665 gfc_match_equiv_variable, with host_flag = 0, to restrict the
kono
parents:
diff changeset
3666 match of the symbol to the local scope. */
kono
parents:
diff changeset
3667
kono
parents:
diff changeset
3668 static match
kono
parents:
diff changeset
3669 match_variable (gfc_expr **result, int equiv_flag, int host_flag)
kono
parents:
diff changeset
3670 {
kono
parents:
diff changeset
3671 gfc_symbol *sym, *dt_sym;
kono
parents:
diff changeset
3672 gfc_symtree *st;
kono
parents:
diff changeset
3673 gfc_expr *expr;
kono
parents:
diff changeset
3674 locus where, old_loc;
kono
parents:
diff changeset
3675 match m;
kono
parents:
diff changeset
3676
kono
parents:
diff changeset
3677 /* Since nothing has any business being an lvalue in a module
kono
parents:
diff changeset
3678 specification block, an interface block or a contains section,
kono
parents:
diff changeset
3679 we force the changed_symbols mechanism to work by setting
kono
parents:
diff changeset
3680 host_flag to 0. This prevents valid symbols that have the name
kono
parents:
diff changeset
3681 of keywords, such as 'end', being turned into variables by
kono
parents:
diff changeset
3682 failed matching to assignments for, e.g., END INTERFACE. */
kono
parents:
diff changeset
3683 if (gfc_current_state () == COMP_MODULE
kono
parents:
diff changeset
3684 || gfc_current_state () == COMP_SUBMODULE
kono
parents:
diff changeset
3685 || gfc_current_state () == COMP_INTERFACE
kono
parents:
diff changeset
3686 || gfc_current_state () == COMP_CONTAINS)
kono
parents:
diff changeset
3687 host_flag = 0;
kono
parents:
diff changeset
3688
kono
parents:
diff changeset
3689 where = gfc_current_locus;
kono
parents:
diff changeset
3690 m = gfc_match_sym_tree (&st, host_flag);
kono
parents:
diff changeset
3691 if (m != MATCH_YES)
kono
parents:
diff changeset
3692 return m;
kono
parents:
diff changeset
3693
kono
parents:
diff changeset
3694 sym = st->n.sym;
kono
parents:
diff changeset
3695
kono
parents:
diff changeset
3696 /* If this is an implicit do loop index and implicitly typed,
kono
parents:
diff changeset
3697 it should not be host associated. */
kono
parents:
diff changeset
3698 m = check_for_implicit_index (&st, &sym);
kono
parents:
diff changeset
3699 if (m != MATCH_YES)
kono
parents:
diff changeset
3700 return m;
kono
parents:
diff changeset
3701
kono
parents:
diff changeset
3702 sym->attr.implied_index = 0;
kono
parents:
diff changeset
3703
kono
parents:
diff changeset
3704 gfc_set_sym_referenced (sym);
kono
parents:
diff changeset
3705
kono
parents:
diff changeset
3706 /* STRUCTUREs may share names with variables, but derived types may not. */
kono
parents:
diff changeset
3707 if (sym->attr.flavor == FL_PROCEDURE && sym->generic
kono
parents:
diff changeset
3708 && (dt_sym = gfc_find_dt_in_generic (sym)))
kono
parents:
diff changeset
3709 {
kono
parents:
diff changeset
3710 if (dt_sym->attr.flavor == FL_DERIVED)
kono
parents:
diff changeset
3711 gfc_error ("Derived type %qs cannot be used as a variable at %C",
kono
parents:
diff changeset
3712 sym->name);
kono
parents:
diff changeset
3713 return MATCH_ERROR;
kono
parents:
diff changeset
3714 }
kono
parents:
diff changeset
3715
kono
parents:
diff changeset
3716 switch (sym->attr.flavor)
kono
parents:
diff changeset
3717 {
kono
parents:
diff changeset
3718 case FL_VARIABLE:
kono
parents:
diff changeset
3719 /* Everything is alright. */
kono
parents:
diff changeset
3720 break;
kono
parents:
diff changeset
3721
kono
parents:
diff changeset
3722 case FL_UNKNOWN:
kono
parents:
diff changeset
3723 {
kono
parents:
diff changeset
3724 sym_flavor flavor = FL_UNKNOWN;
kono
parents:
diff changeset
3725
kono
parents:
diff changeset
3726 gfc_gobble_whitespace ();
kono
parents:
diff changeset
3727
kono
parents:
diff changeset
3728 if (sym->attr.external || sym->attr.procedure
kono
parents:
diff changeset
3729 || sym->attr.function || sym->attr.subroutine)
kono
parents:
diff changeset
3730 flavor = FL_PROCEDURE;
kono
parents:
diff changeset
3731
kono
parents:
diff changeset
3732 /* If it is not a procedure, is not typed and is host associated,
kono
parents:
diff changeset
3733 we cannot give it a flavor yet. */
kono
parents:
diff changeset
3734 else if (sym->ns == gfc_current_ns->parent
kono
parents:
diff changeset
3735 && sym->ts.type == BT_UNKNOWN)
kono
parents:
diff changeset
3736 break;
kono
parents:
diff changeset
3737
kono
parents:
diff changeset
3738 /* These are definitive indicators that this is a variable. */
kono
parents:
diff changeset
3739 else if (gfc_peek_ascii_char () != '(' || sym->ts.type != BT_UNKNOWN
kono
parents:
diff changeset
3740 || sym->attr.pointer || sym->as != NULL)
kono
parents:
diff changeset
3741 flavor = FL_VARIABLE;
kono
parents:
diff changeset
3742
kono
parents:
diff changeset
3743 if (flavor != FL_UNKNOWN
kono
parents:
diff changeset
3744 && !gfc_add_flavor (&sym->attr, flavor, sym->name, NULL))
kono
parents:
diff changeset
3745 return MATCH_ERROR;
kono
parents:
diff changeset
3746 }
kono
parents:
diff changeset
3747 break;
kono
parents:
diff changeset
3748
kono
parents:
diff changeset
3749 case FL_PARAMETER:
kono
parents:
diff changeset
3750 if (equiv_flag)
kono
parents:
diff changeset
3751 {
kono
parents:
diff changeset
3752 gfc_error ("Named constant at %C in an EQUIVALENCE");
kono
parents:
diff changeset
3753 return MATCH_ERROR;
kono
parents:
diff changeset
3754 }
kono
parents:
diff changeset
3755 /* Otherwise this is checked for and an error given in the
kono
parents:
diff changeset
3756 variable definition context checks. */
kono
parents:
diff changeset
3757 break;
kono
parents:
diff changeset
3758
kono
parents:
diff changeset
3759 case FL_PROCEDURE:
kono
parents:
diff changeset
3760 /* Check for a nonrecursive function result variable. */
kono
parents:
diff changeset
3761 if (sym->attr.function
kono
parents:
diff changeset
3762 && !sym->attr.external
kono
parents:
diff changeset
3763 && sym->result == sym
kono
parents:
diff changeset
3764 && (gfc_is_function_return_value (sym, gfc_current_ns)
kono
parents:
diff changeset
3765 || (sym->attr.entry
kono
parents:
diff changeset
3766 && sym->ns == gfc_current_ns)
kono
parents:
diff changeset
3767 || (sym->attr.entry
kono
parents:
diff changeset
3768 && sym->ns == gfc_current_ns->parent)))
kono
parents:
diff changeset
3769 {
kono
parents:
diff changeset
3770 /* If a function result is a derived type, then the derived
kono
parents:
diff changeset
3771 type may still have to be resolved. */
kono
parents:
diff changeset
3772
kono
parents:
diff changeset
3773 if (sym->ts.type == BT_DERIVED
kono
parents:
diff changeset
3774 && gfc_use_derived (sym->ts.u.derived) == NULL)
kono
parents:
diff changeset
3775 return MATCH_ERROR;
kono
parents:
diff changeset
3776 break;
kono
parents:
diff changeset
3777 }
kono
parents:
diff changeset
3778
kono
parents:
diff changeset
3779 if (sym->attr.proc_pointer
kono
parents:
diff changeset
3780 || replace_hidden_procptr_result (&sym, &st))
kono
parents:
diff changeset
3781 break;
kono
parents:
diff changeset
3782
kono
parents:
diff changeset
3783 /* Fall through to error */
kono
parents:
diff changeset
3784 gcc_fallthrough ();
kono
parents:
diff changeset
3785
kono
parents:
diff changeset
3786 default:
kono
parents:
diff changeset
3787 gfc_error ("%qs at %C is not a variable", sym->name);
kono
parents:
diff changeset
3788 return MATCH_ERROR;
kono
parents:
diff changeset
3789 }
kono
parents:
diff changeset
3790
kono
parents:
diff changeset
3791 /* Special case for derived type variables that get their types
kono
parents:
diff changeset
3792 via an IMPLICIT statement. This can't wait for the
kono
parents:
diff changeset
3793 resolution phase. */
kono
parents:
diff changeset
3794
kono
parents:
diff changeset
3795 {
kono
parents:
diff changeset
3796 gfc_namespace * implicit_ns;
kono
parents:
diff changeset
3797
kono
parents:
diff changeset
3798 if (gfc_current_ns->proc_name == sym)
kono
parents:
diff changeset
3799 implicit_ns = gfc_current_ns;
kono
parents:
diff changeset
3800 else
kono
parents:
diff changeset
3801 implicit_ns = sym->ns;
kono
parents:
diff changeset
3802
kono
parents:
diff changeset
3803 old_loc = gfc_current_locus;
kono
parents:
diff changeset
3804 if (gfc_match_member_sep (sym) == MATCH_YES
kono
parents:
diff changeset
3805 && sym->ts.type == BT_UNKNOWN
kono
parents:
diff changeset
3806 && gfc_get_default_type (sym->name, implicit_ns)->type == BT_DERIVED)
kono
parents:
diff changeset
3807 gfc_set_default_type (sym, 0, implicit_ns);
kono
parents:
diff changeset
3808 gfc_current_locus = old_loc;
kono
parents:
diff changeset
3809 }
kono
parents:
diff changeset
3810
kono
parents:
diff changeset
3811 expr = gfc_get_expr ();
kono
parents:
diff changeset
3812
kono
parents:
diff changeset
3813 expr->expr_type = EXPR_VARIABLE;
kono
parents:
diff changeset
3814 expr->symtree = st;
kono
parents:
diff changeset
3815 expr->ts = sym->ts;
kono
parents:
diff changeset
3816 expr->where = where;
kono
parents:
diff changeset
3817
kono
parents:
diff changeset
3818 /* Now see if we have to do more. */
kono
parents:
diff changeset
3819 m = gfc_match_varspec (expr, equiv_flag, false, false);
kono
parents:
diff changeset
3820 if (m != MATCH_YES)
kono
parents:
diff changeset
3821 {
kono
parents:
diff changeset
3822 gfc_free_expr (expr);
kono
parents:
diff changeset
3823 return m;
kono
parents:
diff changeset
3824 }
kono
parents:
diff changeset
3825
kono
parents:
diff changeset
3826 *result = expr;
kono
parents:
diff changeset
3827 return MATCH_YES;
kono
parents:
diff changeset
3828 }
kono
parents:
diff changeset
3829
kono
parents:
diff changeset
3830
kono
parents:
diff changeset
3831 match
kono
parents:
diff changeset
3832 gfc_match_variable (gfc_expr **result, int equiv_flag)
kono
parents:
diff changeset
3833 {
kono
parents:
diff changeset
3834 return match_variable (result, equiv_flag, 1);
kono
parents:
diff changeset
3835 }
kono
parents:
diff changeset
3836
kono
parents:
diff changeset
3837
kono
parents:
diff changeset
3838 match
kono
parents:
diff changeset
3839 gfc_match_equiv_variable (gfc_expr **result)
kono
parents:
diff changeset
3840 {
kono
parents:
diff changeset
3841 return match_variable (result, 1, 0);
kono
parents:
diff changeset
3842 }
kono
parents:
diff changeset
3843