File: | build/gcc/fortran/match.cc |
Warning: | line 2414, column 15 Assigned value is garbage or undefined |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* Matching subroutines in all sizes, shapes and colors. | |||
2 | Copyright (C) 2000-2023 Free Software Foundation, Inc. | |||
3 | Contributed by Andy Vaught | |||
4 | ||||
5 | This file is part of GCC. | |||
6 | ||||
7 | GCC is free software; you can redistribute it and/or modify it under | |||
8 | the terms of the GNU General Public License as published by the Free | |||
9 | Software Foundation; either version 3, or (at your option) any later | |||
10 | version. | |||
11 | ||||
12 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |||
13 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |||
14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |||
15 | for more details. | |||
16 | ||||
17 | You should have received a copy of the GNU General Public License | |||
18 | along with GCC; see the file COPYING3. If not see | |||
19 | <http://www.gnu.org/licenses/>. */ | |||
20 | ||||
21 | #include "config.h" | |||
22 | #include "system.h" | |||
23 | #include "coretypes.h" | |||
24 | #include "options.h" | |||
25 | #include "gfortran.h" | |||
26 | #include "match.h" | |||
27 | #include "parse.h" | |||
28 | ||||
29 | int gfc_matching_ptr_assignment = 0; | |||
30 | int gfc_matching_procptr_assignment = 0; | |||
31 | bool gfc_matching_prefix = false; | |||
32 | ||||
33 | /* Stack of SELECT TYPE statements. */ | |||
34 | gfc_select_type_stack *select_type_stack = NULL__null; | |||
35 | ||||
36 | /* List of type parameter expressions. */ | |||
37 | gfc_actual_arglist *type_param_spec_list; | |||
38 | ||||
39 | /* For debugging and diagnostic purposes. Return the textual representation | |||
40 | of the intrinsic operator OP. */ | |||
41 | const char * | |||
42 | gfc_op2string (gfc_intrinsic_op op) | |||
43 | { | |||
44 | switch (op) | |||
45 | { | |||
46 | case INTRINSIC_UPLUS: | |||
47 | case INTRINSIC_PLUS: | |||
48 | return "+"; | |||
49 | ||||
50 | case INTRINSIC_UMINUS: | |||
51 | case INTRINSIC_MINUS: | |||
52 | return "-"; | |||
53 | ||||
54 | case INTRINSIC_POWER: | |||
55 | return "**"; | |||
56 | case INTRINSIC_CONCAT: | |||
57 | return "//"; | |||
58 | case INTRINSIC_TIMES: | |||
59 | return "*"; | |||
60 | case INTRINSIC_DIVIDE: | |||
61 | return "/"; | |||
62 | ||||
63 | case INTRINSIC_AND: | |||
64 | return ".and."; | |||
65 | case INTRINSIC_OR: | |||
66 | return ".or."; | |||
67 | case INTRINSIC_EQV: | |||
68 | return ".eqv."; | |||
69 | case INTRINSIC_NEQV: | |||
70 | return ".neqv."; | |||
71 | ||||
72 | case INTRINSIC_EQ_OS: | |||
73 | return ".eq."; | |||
74 | case INTRINSIC_EQ: | |||
75 | return "=="; | |||
76 | case INTRINSIC_NE_OS: | |||
77 | return ".ne."; | |||
78 | case INTRINSIC_NE: | |||
79 | return "/="; | |||
80 | case INTRINSIC_GE_OS: | |||
81 | return ".ge."; | |||
82 | case INTRINSIC_GE: | |||
83 | return ">="; | |||
84 | case INTRINSIC_LE_OS: | |||
85 | return ".le."; | |||
86 | case INTRINSIC_LE: | |||
87 | return "<="; | |||
88 | case INTRINSIC_LT_OS: | |||
89 | return ".lt."; | |||
90 | case INTRINSIC_LT: | |||
91 | return "<"; | |||
92 | case INTRINSIC_GT_OS: | |||
93 | return ".gt."; | |||
94 | case INTRINSIC_GT: | |||
95 | return ">"; | |||
96 | case INTRINSIC_NOT: | |||
97 | return ".not."; | |||
98 | ||||
99 | case INTRINSIC_ASSIGN: | |||
100 | return "="; | |||
101 | ||||
102 | case INTRINSIC_PARENTHESES: | |||
103 | return "parens"; | |||
104 | ||||
105 | case INTRINSIC_NONE: | |||
106 | return "none"; | |||
107 | ||||
108 | /* DTIO */ | |||
109 | case INTRINSIC_FORMATTED: | |||
110 | return "formatted"; | |||
111 | case INTRINSIC_UNFORMATTED: | |||
112 | return "unformatted"; | |||
113 | ||||
114 | default: | |||
115 | break; | |||
116 | } | |||
117 | ||||
118 | gfc_internal_error ("gfc_op2string(): Bad code"); | |||
119 | /* Not reached. */ | |||
120 | } | |||
121 | ||||
122 | ||||
123 | /******************** Generic matching subroutines ************************/ | |||
124 | ||||
125 | /* Matches a member separator. With standard FORTRAN this is '%', but with | |||
126 | DEC structures we must carefully match dot ('.'). | |||
127 | Because operators are spelled ".op.", a dotted string such as "x.y.z..." | |||
128 | can be either a component reference chain or a combination of binary | |||
129 | operations. | |||
130 | There is no real way to win because the string may be grammatically | |||
131 | ambiguous. The following rules help avoid ambiguities - they match | |||
132 | some behavior of other (older) compilers. If the rules here are changed | |||
133 | the test cases should be updated. If the user has problems with these rules | |||
134 | they probably deserve the consequences. Consider "x.y.z": | |||
135 | (1) If any user defined operator ".y." exists, this is always y(x,z) | |||
136 | (even if ".y." is the wrong type and/or x has a member y). | |||
137 | (2) Otherwise if x has a member y, and y is itself a derived type, | |||
138 | this is (x->y)->z, even if an intrinsic operator exists which | |||
139 | can handle (x,z). | |||
140 | (3) If x has no member y or (x->y) is not a derived type but ".y." | |||
141 | is an intrinsic operator (such as ".eq."), this is y(x,z). | |||
142 | (4) Lastly if there is no operator ".y." and x has no member "y", it is an | |||
143 | error. | |||
144 | It is worth noting that the logic here does not support mixed use of member | |||
145 | accessors within a single string. That is, even if x has component y and y | |||
146 | has component z, the following are all syntax errors: | |||
147 | "x%y.z" "x.y%z" "(x.y).z" "(x%y)%z" | |||
148 | */ | |||
149 | ||||
150 | match | |||
151 | gfc_match_member_sep(gfc_symbol *sym) | |||
152 | { | |||
153 | char name[GFC_MAX_SYMBOL_LEN63 + 1]; | |||
154 | locus dot_loc, start_loc; | |||
155 | gfc_intrinsic_op iop; | |||
156 | match m; | |||
157 | gfc_symbol *tsym; | |||
158 | gfc_component *c = NULL__null; | |||
159 | ||||
160 | /* What a relief: '%' is an unambiguous member separator. */ | |||
161 | if (gfc_match_char ('%') == MATCH_YES) | |||
162 | return MATCH_YES; | |||
163 | ||||
164 | /* Beware ye who enter here. */ | |||
165 | if (!flag_dec_structureglobal_options.x_flag_dec_structure || !sym) | |||
166 | return MATCH_NO; | |||
167 | ||||
168 | tsym = NULL__null; | |||
169 | ||||
170 | /* We may be given either a derived type variable or the derived type | |||
171 | declaration itself (which actually contains the components); | |||
172 | we need the latter to search for components. */ | |||
173 | if (gfc_fl_struct (sym->attr.flavor)((sym->attr.flavor) == FL_DERIVED || (sym->attr.flavor) == FL_UNION || (sym->attr.flavor) == FL_STRUCT)) | |||
174 | tsym = sym; | |||
175 | else if (gfc_bt_struct (sym->ts.type)((sym->ts.type) == BT_DERIVED || (sym->ts.type) == BT_UNION )) | |||
176 | tsym = sym->ts.u.derived; | |||
177 | ||||
178 | iop = INTRINSIC_NONE; | |||
179 | name[0] = '\0'; | |||
180 | m = MATCH_NO; | |||
181 | ||||
182 | /* If we have to reject come back here later. */ | |||
183 | start_loc = gfc_current_locus; | |||
184 | ||||
185 | /* Look for a component access next. */ | |||
186 | if (gfc_match_char ('.') != MATCH_YES) | |||
187 | return MATCH_NO; | |||
188 | ||||
189 | /* If we accept, come back here. */ | |||
190 | dot_loc = gfc_current_locus; | |||
191 | ||||
192 | /* Try to match a symbol name following the dot. */ | |||
193 | if (gfc_match_name (name) != MATCH_YES) | |||
194 | { | |||
195 | gfc_error ("Expected structure component or operator name " | |||
196 | "after %<.%> at %C"); | |||
197 | goto error; | |||
198 | } | |||
199 | ||||
200 | /* If no dot follows we have "x.y" which should be a component access. */ | |||
201 | if (gfc_match_char ('.') != MATCH_YES) | |||
202 | goto yes; | |||
203 | ||||
204 | /* Now we have a string "x.y.z" which could be a nested member access | |||
205 | (x->y)->z or a binary operation y on x and z. */ | |||
206 | ||||
207 | /* First use any user-defined operators ".y." */ | |||
208 | if (gfc_find_uop (name, sym->ns) != NULL__null) | |||
209 | goto no; | |||
210 | ||||
211 | /* Match accesses to existing derived-type components for | |||
212 | derived-type vars: "x.y.z" = (x->y)->z */ | |||
213 | c = gfc_find_component(tsym, name, false, true, NULL__null); | |||
214 | if (c && (gfc_bt_struct (c->ts.type)((c->ts.type) == BT_DERIVED || (c->ts.type) == BT_UNION ) || c->ts.type == BT_CLASS)) | |||
215 | goto yes; | |||
216 | ||||
217 | /* If y is not a component or has no members, try intrinsic operators. */ | |||
218 | gfc_current_locus = start_loc; | |||
219 | if (gfc_match_intrinsic_op (&iop) != MATCH_YES) | |||
220 | { | |||
221 | /* If ".y." is not an intrinsic operator but y was a valid non- | |||
222 | structure component, match and leave the trailing dot to be | |||
223 | dealt with later. */ | |||
224 | if (c) | |||
225 | goto yes; | |||
226 | ||||
227 | gfc_error ("%qs is neither a defined operator nor a " | |||
228 | "structure component in dotted string at %C", name); | |||
229 | goto error; | |||
230 | } | |||
231 | ||||
232 | /* .y. is an intrinsic operator, overriding any possible member access. */ | |||
233 | goto no; | |||
234 | ||||
235 | /* Return keeping the current locus consistent with the match result. */ | |||
236 | error: | |||
237 | m = MATCH_ERROR; | |||
238 | no: | |||
239 | gfc_current_locus = start_loc; | |||
240 | return m; | |||
241 | yes: | |||
242 | gfc_current_locus = dot_loc; | |||
243 | return MATCH_YES; | |||
244 | } | |||
245 | ||||
246 | ||||
247 | /* This function scans the current statement counting the opened and closed | |||
248 | parenthesis to make sure they are balanced. */ | |||
249 | ||||
250 | match | |||
251 | gfc_match_parens (void) | |||
252 | { | |||
253 | locus old_loc, where; | |||
254 | int count; | |||
255 | gfc_instring instring; | |||
256 | gfc_char_t c, quote; | |||
257 | ||||
258 | old_loc = gfc_current_locus; | |||
259 | count = 0; | |||
260 | instring = NONSTRING; | |||
261 | quote = ' '; | |||
262 | ||||
263 | for (;;) | |||
264 | { | |||
265 | if (count > 0) | |||
266 | where = gfc_current_locus; | |||
267 | c = gfc_next_char_literal (instring); | |||
268 | if (c == '\n') | |||
269 | break; | |||
270 | if (quote == ' ' && ((c == '\'') || (c == '"'))) | |||
271 | { | |||
272 | quote = c; | |||
273 | instring = INSTRING_WARN; | |||
274 | continue; | |||
275 | } | |||
276 | if (quote != ' ' && c == quote) | |||
277 | { | |||
278 | quote = ' '; | |||
279 | instring = NONSTRING; | |||
280 | continue; | |||
281 | } | |||
282 | ||||
283 | if (c == '(' && quote == ' ') | |||
284 | { | |||
285 | count++; | |||
286 | } | |||
287 | if (c == ')' && quote == ' ') | |||
288 | { | |||
289 | count--; | |||
290 | where = gfc_current_locus; | |||
291 | } | |||
292 | } | |||
293 | ||||
294 | gfc_current_locus = old_loc; | |||
295 | ||||
296 | if (count != 0) | |||
297 | { | |||
298 | gfc_error ("Missing %qs in statement at or before %L", | |||
299 | count > 0? ")":"(", &where); | |||
300 | return MATCH_ERROR; | |||
301 | } | |||
302 | ||||
303 | return MATCH_YES; | |||
304 | } | |||
305 | ||||
306 | ||||
307 | /* See if the next character is a special character that has | |||
308 | escaped by a \ via the -fbackslash option. */ | |||
309 | ||||
310 | match | |||
311 | gfc_match_special_char (gfc_char_t *res) | |||
312 | { | |||
313 | int len, i; | |||
314 | gfc_char_t c, n; | |||
315 | match m; | |||
316 | ||||
317 | m = MATCH_YES; | |||
318 | ||||
319 | switch ((c = gfc_next_char_literal (INSTRING_WARN))) | |||
320 | { | |||
321 | case 'a': | |||
322 | *res = '\a'; | |||
323 | break; | |||
324 | case 'b': | |||
325 | *res = '\b'; | |||
326 | break; | |||
327 | case 't': | |||
328 | *res = '\t'; | |||
329 | break; | |||
330 | case 'f': | |||
331 | *res = '\f'; | |||
332 | break; | |||
333 | case 'n': | |||
334 | *res = '\n'; | |||
335 | break; | |||
336 | case 'r': | |||
337 | *res = '\r'; | |||
338 | break; | |||
339 | case 'v': | |||
340 | *res = '\v'; | |||
341 | break; | |||
342 | case '\\': | |||
343 | *res = '\\'; | |||
344 | break; | |||
345 | case '0': | |||
346 | *res = '\0'; | |||
347 | break; | |||
348 | ||||
349 | case 'x': | |||
350 | case 'u': | |||
351 | case 'U': | |||
352 | /* Hexadecimal form of wide characters. */ | |||
353 | len = (c == 'x' ? 2 : (c == 'u' ? 4 : 8)); | |||
354 | n = 0; | |||
355 | for (i = 0; i < len; i++) | |||
356 | { | |||
357 | char buf[2] = { '\0', '\0' }; | |||
358 | ||||
359 | c = gfc_next_char_literal (INSTRING_WARN); | |||
360 | if (!gfc_wide_fits_in_byte (c) | |||
361 | || !gfc_check_digit ((unsigned char) c, 16)) | |||
362 | return MATCH_NO; | |||
363 | ||||
364 | buf[0] = (unsigned char) c; | |||
365 | n = n << 4; | |||
366 | n += strtol (buf, NULL__null, 16); | |||
367 | } | |||
368 | *res = n; | |||
369 | break; | |||
370 | ||||
371 | default: | |||
372 | /* Unknown backslash codes are simply not expanded. */ | |||
373 | m = MATCH_NO; | |||
374 | break; | |||
375 | } | |||
376 | ||||
377 | return m; | |||
378 | } | |||
379 | ||||
380 | ||||
381 | /* In free form, match at least one space. Always matches in fixed | |||
382 | form. */ | |||
383 | ||||
384 | match | |||
385 | gfc_match_space (void) | |||
386 | { | |||
387 | locus old_loc; | |||
388 | char c; | |||
389 | ||||
390 | if (gfc_current_form == FORM_FIXED) | |||
391 | return MATCH_YES; | |||
392 | ||||
393 | old_loc = gfc_current_locus; | |||
394 | ||||
395 | c = gfc_next_ascii_char (); | |||
396 | if (!gfc_is_whitespace (c)((c==' ') || (c=='\t') || (c=='\f'))) | |||
397 | { | |||
398 | gfc_current_locus = old_loc; | |||
399 | return MATCH_NO; | |||
400 | } | |||
401 | ||||
402 | gfc_gobble_whitespace (); | |||
403 | ||||
404 | return MATCH_YES; | |||
405 | } | |||
406 | ||||
407 | ||||
408 | /* Match an end of statement. End of statement is optional | |||
409 | whitespace, followed by a ';' or '\n' or comment '!'. If a | |||
410 | semicolon is found, we continue to eat whitespace and semicolons. */ | |||
411 | ||||
412 | match | |||
413 | gfc_match_eos (void) | |||
414 | { | |||
415 | locus old_loc; | |||
416 | int flag; | |||
417 | char c; | |||
418 | ||||
419 | flag = 0; | |||
420 | ||||
421 | for (;;) | |||
422 | { | |||
423 | old_loc = gfc_current_locus; | |||
424 | gfc_gobble_whitespace (); | |||
425 | ||||
426 | c = gfc_next_ascii_char (); | |||
427 | switch (c) | |||
428 | { | |||
429 | case '!': | |||
430 | do | |||
431 | { | |||
432 | c = gfc_next_ascii_char (); | |||
433 | } | |||
434 | while (c != '\n'); | |||
435 | ||||
436 | /* Fall through. */ | |||
437 | ||||
438 | case '\n': | |||
439 | return MATCH_YES; | |||
440 | ||||
441 | case ';': | |||
442 | flag = 1; | |||
443 | continue; | |||
444 | } | |||
445 | ||||
446 | break; | |||
447 | } | |||
448 | ||||
449 | gfc_current_locus = old_loc; | |||
450 | return (flag) ? MATCH_YES : MATCH_NO; | |||
451 | } | |||
452 | ||||
453 | ||||
454 | /* Match a literal integer on the input, setting the value on | |||
455 | MATCH_YES. Literal ints occur in kind-parameters as well as | |||
456 | old-style character length specifications. If cnt is non-NULL it | |||
457 | will be set to the number of digits. | |||
458 | When gobble_ws is false, do not skip over leading blanks. */ | |||
459 | ||||
460 | match | |||
461 | gfc_match_small_literal_int (int *value, int *cnt, bool gobble_ws) | |||
462 | { | |||
463 | locus old_loc; | |||
464 | char c; | |||
465 | int i, j; | |||
466 | ||||
467 | old_loc = gfc_current_locus; | |||
468 | ||||
469 | *value = -1; | |||
470 | if (gobble_ws) | |||
471 | gfc_gobble_whitespace (); | |||
472 | c = gfc_next_ascii_char (); | |||
473 | if (cnt) | |||
474 | *cnt = 0; | |||
475 | ||||
476 | if (!ISDIGIT (c)(_sch_istable[(c) & 0xff] & (unsigned short)(_sch_isdigit ))) | |||
477 | { | |||
478 | gfc_current_locus = old_loc; | |||
479 | return MATCH_NO; | |||
480 | } | |||
481 | ||||
482 | i = c - '0'; | |||
483 | j = 1; | |||
484 | ||||
485 | for (;;) | |||
486 | { | |||
487 | old_loc = gfc_current_locus; | |||
488 | c = gfc_next_ascii_char (); | |||
489 | ||||
490 | if (!ISDIGIT (c)(_sch_istable[(c) & 0xff] & (unsigned short)(_sch_isdigit ))) | |||
491 | break; | |||
492 | ||||
493 | i = 10 * i + c - '0'; | |||
494 | j++; | |||
495 | ||||
496 | if (i > 99999999) | |||
497 | { | |||
498 | gfc_error ("Integer too large at %C"); | |||
499 | return MATCH_ERROR; | |||
500 | } | |||
501 | } | |||
502 | ||||
503 | gfc_current_locus = old_loc; | |||
504 | ||||
505 | *value = i; | |||
506 | if (cnt) | |||
507 | *cnt = j; | |||
508 | return MATCH_YES; | |||
509 | } | |||
510 | ||||
511 | ||||
512 | /* Match a small, constant integer expression, like in a kind | |||
513 | statement. On MATCH_YES, 'value' is set. */ | |||
514 | ||||
515 | match | |||
516 | gfc_match_small_int (int *value) | |||
517 | { | |||
518 | gfc_expr *expr; | |||
519 | match m; | |||
520 | int i; | |||
521 | ||||
522 | m = gfc_match_expr (&expr); | |||
523 | if (m != MATCH_YES) | |||
524 | return m; | |||
525 | ||||
526 | if (gfc_extract_int (expr, &i, 1)) | |||
527 | m = MATCH_ERROR; | |||
528 | gfc_free_expr (expr); | |||
529 | ||||
530 | *value = i; | |||
531 | return m; | |||
532 | } | |||
533 | ||||
534 | ||||
535 | /* Matches a statement label. Uses gfc_match_small_literal_int() to | |||
536 | do most of the work. */ | |||
537 | ||||
538 | match | |||
539 | gfc_match_st_label (gfc_st_label **label) | |||
540 | { | |||
541 | locus old_loc; | |||
542 | match m; | |||
543 | int i, cnt; | |||
544 | ||||
545 | old_loc = gfc_current_locus; | |||
546 | ||||
547 | m = gfc_match_small_literal_int (&i, &cnt); | |||
548 | if (m != MATCH_YES) | |||
549 | return m; | |||
550 | ||||
551 | if (cnt > 5) | |||
552 | { | |||
553 | gfc_error ("Too many digits in statement label at %C"); | |||
554 | goto cleanup; | |||
555 | } | |||
556 | ||||
557 | if (i == 0) | |||
558 | { | |||
559 | gfc_error ("Statement label at %C is zero"); | |||
560 | goto cleanup; | |||
561 | } | |||
562 | ||||
563 | *label = gfc_get_st_label (i); | |||
564 | return MATCH_YES; | |||
565 | ||||
566 | cleanup: | |||
567 | ||||
568 | gfc_current_locus = old_loc; | |||
569 | return MATCH_ERROR; | |||
570 | } | |||
571 | ||||
572 | ||||
573 | /* Match and validate a label associated with a named IF, DO or SELECT | |||
574 | statement. If the symbol does not have the label attribute, we add | |||
575 | it. We also make sure the symbol does not refer to another | |||
576 | (active) block. A matched label is pointed to by gfc_new_block. */ | |||
577 | ||||
578 | static match | |||
579 | gfc_match_label (void) | |||
580 | { | |||
581 | char name[GFC_MAX_SYMBOL_LEN63 + 1]; | |||
582 | match m; | |||
583 | ||||
584 | gfc_new_block = NULL__null; | |||
585 | ||||
586 | m = gfc_match (" %n :", name); | |||
587 | if (m != MATCH_YES) | |||
588 | return m; | |||
589 | ||||
590 | if (gfc_get_symbol (name, NULL__null, &gfc_new_block)) | |||
591 | { | |||
592 | gfc_error ("Label name %qs at %C is ambiguous", name); | |||
593 | return MATCH_ERROR; | |||
594 | } | |||
595 | ||||
596 | if (gfc_new_block->attr.flavor == FL_LABEL) | |||
597 | { | |||
598 | gfc_error ("Duplicate construct label %qs at %C", name); | |||
599 | return MATCH_ERROR; | |||
600 | } | |||
601 | ||||
602 | if (!gfc_add_flavor (&gfc_new_block->attr, FL_LABEL, | |||
603 | gfc_new_block->name, NULL__null)) | |||
604 | return MATCH_ERROR; | |||
605 | ||||
606 | return MATCH_YES; | |||
607 | } | |||
608 | ||||
609 | ||||
610 | /* See if the current input looks like a name of some sort. Modifies | |||
611 | the passed buffer which must be GFC_MAX_SYMBOL_LEN+1 bytes long. | |||
612 | Note that options.cc restricts max_identifier_length to not more | |||
613 | than GFC_MAX_SYMBOL_LEN. | |||
614 | When gobble_ws is false, do not skip over leading blanks. */ | |||
615 | ||||
616 | match | |||
617 | gfc_match_name (char *buffer, bool gobble_ws) | |||
618 | { | |||
619 | locus old_loc; | |||
620 | int i; | |||
621 | char c; | |||
622 | ||||
623 | old_loc = gfc_current_locus; | |||
624 | if (gobble_ws) | |||
625 | gfc_gobble_whitespace (); | |||
626 | ||||
627 | c = gfc_next_ascii_char (); | |||
628 | if (!(ISALPHA (c)(_sch_istable[(c) & 0xff] & (unsigned short)(_sch_isalpha )) || (c == '_' && flag_allow_leading_underscoreglobal_options.x_flag_allow_leading_underscore))) | |||
629 | { | |||
630 | /* Special cases for unary minus and plus, which allows for a sensible | |||
631 | error message for code of the form 'c = exp(-a*b) )' where an | |||
632 | extra ')' appears at the end of statement. */ | |||
633 | if (!gfc_error_flag_test () && c != '(' && c != '-' && c != '+') | |||
634 | gfc_error ("Invalid character in name at %C"); | |||
635 | gfc_current_locus = old_loc; | |||
636 | return MATCH_NO; | |||
637 | } | |||
638 | ||||
639 | i = 0; | |||
640 | ||||
641 | do | |||
642 | { | |||
643 | buffer[i++] = c; | |||
644 | ||||
645 | if (i > gfc_option.max_identifier_length) | |||
646 | { | |||
647 | gfc_error ("Name at %C is too long"); | |||
648 | return MATCH_ERROR; | |||
649 | } | |||
650 | ||||
651 | old_loc = gfc_current_locus; | |||
652 | c = gfc_next_ascii_char (); | |||
653 | } | |||
654 | while (ISALNUM (c)(_sch_istable[(c) & 0xff] & (unsigned short)(_sch_isalnum )) || c == '_' || (flag_dollar_okglobal_options.x_flag_dollar_ok && c == '$')); | |||
655 | ||||
656 | if (c == '$' && !flag_dollar_okglobal_options.x_flag_dollar_ok) | |||
657 | { | |||
658 | gfc_fatal_error ("Invalid character %<$%> at %L. Use %<-fdollar-ok%> to " | |||
659 | "allow it as an extension", &old_loc); | |||
660 | return MATCH_ERROR; | |||
661 | } | |||
662 | ||||
663 | buffer[i] = '\0'; | |||
664 | gfc_current_locus = old_loc; | |||
665 | ||||
666 | return MATCH_YES; | |||
667 | } | |||
668 | ||||
669 | ||||
670 | /* Match a symbol on the input. Modifies the pointer to the symbol | |||
671 | pointer if successful. */ | |||
672 | ||||
673 | match | |||
674 | gfc_match_sym_tree (gfc_symtree **matched_symbol, int host_assoc) | |||
675 | { | |||
676 | char buffer[GFC_MAX_SYMBOL_LEN63 + 1]; | |||
677 | match m; | |||
678 | ||||
679 | m = gfc_match_name (buffer); | |||
680 | if (m != MATCH_YES) | |||
681 | return m; | |||
682 | ||||
683 | if (host_assoc) | |||
684 | return (gfc_get_ha_sym_tree (buffer, matched_symbol)) | |||
685 | ? MATCH_ERROR : MATCH_YES; | |||
686 | ||||
687 | if (gfc_get_sym_tree (buffer, NULL__null, matched_symbol, false)) | |||
688 | return MATCH_ERROR; | |||
689 | ||||
690 | return MATCH_YES; | |||
691 | } | |||
692 | ||||
693 | ||||
694 | match | |||
695 | gfc_match_symbol (gfc_symbol **matched_symbol, int host_assoc) | |||
696 | { | |||
697 | gfc_symtree *st; | |||
698 | match m; | |||
699 | ||||
700 | m = gfc_match_sym_tree (&st, host_assoc); | |||
701 | ||||
702 | if (m == MATCH_YES) | |||
703 | { | |||
704 | if (st) | |||
705 | *matched_symbol = st->n.sym; | |||
706 | else | |||
707 | *matched_symbol = NULL__null; | |||
708 | } | |||
709 | else | |||
710 | *matched_symbol = NULL__null; | |||
711 | return m; | |||
712 | } | |||
713 | ||||
714 | ||||
715 | /* Match an intrinsic operator. Returns an INTRINSIC enum. While matching, | |||
716 | we always find INTRINSIC_PLUS before INTRINSIC_UPLUS. We work around this | |||
717 | in matchexp.cc. */ | |||
718 | ||||
719 | match | |||
720 | gfc_match_intrinsic_op (gfc_intrinsic_op *result) | |||
721 | { | |||
722 | locus orig_loc = gfc_current_locus; | |||
723 | char ch; | |||
724 | ||||
725 | gfc_gobble_whitespace (); | |||
726 | ch = gfc_next_ascii_char (); | |||
727 | switch (ch) | |||
728 | { | |||
729 | case '+': | |||
730 | /* Matched "+". */ | |||
731 | *result = INTRINSIC_PLUS; | |||
732 | return MATCH_YES; | |||
733 | ||||
734 | case '-': | |||
735 | /* Matched "-". */ | |||
736 | *result = INTRINSIC_MINUS; | |||
737 | return MATCH_YES; | |||
738 | ||||
739 | case '=': | |||
740 | if (gfc_next_ascii_char () == '=') | |||
741 | { | |||
742 | /* Matched "==". */ | |||
743 | *result = INTRINSIC_EQ; | |||
744 | return MATCH_YES; | |||
745 | } | |||
746 | break; | |||
747 | ||||
748 | case '<': | |||
749 | if (gfc_peek_ascii_char () == '=') | |||
750 | { | |||
751 | /* Matched "<=". */ | |||
752 | gfc_next_ascii_char (); | |||
753 | *result = INTRINSIC_LE; | |||
754 | return MATCH_YES; | |||
755 | } | |||
756 | /* Matched "<". */ | |||
757 | *result = INTRINSIC_LT; | |||
758 | return MATCH_YES; | |||
759 | ||||
760 | case '>': | |||
761 | if (gfc_peek_ascii_char () == '=') | |||
762 | { | |||
763 | /* Matched ">=". */ | |||
764 | gfc_next_ascii_char (); | |||
765 | *result = INTRINSIC_GE; | |||
766 | return MATCH_YES; | |||
767 | } | |||
768 | /* Matched ">". */ | |||
769 | *result = INTRINSIC_GT; | |||
770 | return MATCH_YES; | |||
771 | ||||
772 | case '*': | |||
773 | if (gfc_peek_ascii_char () == '*') | |||
774 | { | |||
775 | /* Matched "**". */ | |||
776 | gfc_next_ascii_char (); | |||
777 | *result = INTRINSIC_POWER; | |||
778 | return MATCH_YES; | |||
779 | } | |||
780 | /* Matched "*". */ | |||
781 | *result = INTRINSIC_TIMES; | |||
782 | return MATCH_YES; | |||
783 | ||||
784 | case '/': | |||
785 | ch = gfc_peek_ascii_char (); | |||
786 | if (ch == '=') | |||
787 | { | |||
788 | /* Matched "/=". */ | |||
789 | gfc_next_ascii_char (); | |||
790 | *result = INTRINSIC_NE; | |||
791 | return MATCH_YES; | |||
792 | } | |||
793 | else if (ch == '/') | |||
794 | { | |||
795 | /* Matched "//". */ | |||
796 | gfc_next_ascii_char (); | |||
797 | *result = INTRINSIC_CONCAT; | |||
798 | return MATCH_YES; | |||
799 | } | |||
800 | /* Matched "/". */ | |||
801 | *result = INTRINSIC_DIVIDE; | |||
802 | return MATCH_YES; | |||
803 | ||||
804 | case '.': | |||
805 | ch = gfc_next_ascii_char (); | |||
806 | switch (ch) | |||
807 | { | |||
808 | case 'a': | |||
809 | if (gfc_next_ascii_char () == 'n' | |||
810 | && gfc_next_ascii_char () == 'd' | |||
811 | && gfc_next_ascii_char () == '.') | |||
812 | { | |||
813 | /* Matched ".and.". */ | |||
814 | *result = INTRINSIC_AND; | |||
815 | return MATCH_YES; | |||
816 | } | |||
817 | break; | |||
818 | ||||
819 | case 'e': | |||
820 | if (gfc_next_ascii_char () == 'q') | |||
821 | { | |||
822 | ch = gfc_next_ascii_char (); | |||
823 | if (ch == '.') | |||
824 | { | |||
825 | /* Matched ".eq.". */ | |||
826 | *result = INTRINSIC_EQ_OS; | |||
827 | return MATCH_YES; | |||
828 | } | |||
829 | else if (ch == 'v') | |||
830 | { | |||
831 | if (gfc_next_ascii_char () == '.') | |||
832 | { | |||
833 | /* Matched ".eqv.". */ | |||
834 | *result = INTRINSIC_EQV; | |||
835 | return MATCH_YES; | |||
836 | } | |||
837 | } | |||
838 | } | |||
839 | break; | |||
840 | ||||
841 | case 'g': | |||
842 | ch = gfc_next_ascii_char (); | |||
843 | if (ch == 'e') | |||
844 | { | |||
845 | if (gfc_next_ascii_char () == '.') | |||
846 | { | |||
847 | /* Matched ".ge.". */ | |||
848 | *result = INTRINSIC_GE_OS; | |||
849 | return MATCH_YES; | |||
850 | } | |||
851 | } | |||
852 | else if (ch == 't') | |||
853 | { | |||
854 | if (gfc_next_ascii_char () == '.') | |||
855 | { | |||
856 | /* Matched ".gt.". */ | |||
857 | *result = INTRINSIC_GT_OS; | |||
858 | return MATCH_YES; | |||
859 | } | |||
860 | } | |||
861 | break; | |||
862 | ||||
863 | case 'l': | |||
864 | ch = gfc_next_ascii_char (); | |||
865 | if (ch == 'e') | |||
866 | { | |||
867 | if (gfc_next_ascii_char () == '.') | |||
868 | { | |||
869 | /* Matched ".le.". */ | |||
870 | *result = INTRINSIC_LE_OS; | |||
871 | return MATCH_YES; | |||
872 | } | |||
873 | } | |||
874 | else if (ch == 't') | |||
875 | { | |||
876 | if (gfc_next_ascii_char () == '.') | |||
877 | { | |||
878 | /* Matched ".lt.". */ | |||
879 | *result = INTRINSIC_LT_OS; | |||
880 | return MATCH_YES; | |||
881 | } | |||
882 | } | |||
883 | break; | |||
884 | ||||
885 | case 'n': | |||
886 | ch = gfc_next_ascii_char (); | |||
887 | if (ch == 'e') | |||
888 | { | |||
889 | ch = gfc_next_ascii_char (); | |||
890 | if (ch == '.') | |||
891 | { | |||
892 | /* Matched ".ne.". */ | |||
893 | *result = INTRINSIC_NE_OS; | |||
894 | return MATCH_YES; | |||
895 | } | |||
896 | else if (ch == 'q') | |||
897 | { | |||
898 | if (gfc_next_ascii_char () == 'v' | |||
899 | && gfc_next_ascii_char () == '.') | |||
900 | { | |||
901 | /* Matched ".neqv.". */ | |||
902 | *result = INTRINSIC_NEQV; | |||
903 | return MATCH_YES; | |||
904 | } | |||
905 | } | |||
906 | } | |||
907 | else if (ch == 'o') | |||
908 | { | |||
909 | if (gfc_next_ascii_char () == 't' | |||
910 | && gfc_next_ascii_char () == '.') | |||
911 | { | |||
912 | /* Matched ".not.". */ | |||
913 | *result = INTRINSIC_NOT; | |||
914 | return MATCH_YES; | |||
915 | } | |||
916 | } | |||
917 | break; | |||
918 | ||||
919 | case 'o': | |||
920 | if (gfc_next_ascii_char () == 'r' | |||
921 | && gfc_next_ascii_char () == '.') | |||
922 | { | |||
923 | /* Matched ".or.". */ | |||
924 | *result = INTRINSIC_OR; | |||
925 | return MATCH_YES; | |||
926 | } | |||
927 | break; | |||
928 | ||||
929 | case 'x': | |||
930 | if (gfc_next_ascii_char () == 'o' | |||
931 | && gfc_next_ascii_char () == 'r' | |||
932 | && gfc_next_ascii_char () == '.') | |||
933 | { | |||
934 | if (!gfc_notify_std (GFC_STD_LEGACY(1<<6), ".XOR. operator at %C")) | |||
935 | return MATCH_ERROR; | |||
936 | /* Matched ".xor." - equivalent to ".neqv.". */ | |||
937 | *result = INTRINSIC_NEQV; | |||
938 | return MATCH_YES; | |||
939 | } | |||
940 | break; | |||
941 | ||||
942 | default: | |||
943 | break; | |||
944 | } | |||
945 | break; | |||
946 | ||||
947 | default: | |||
948 | break; | |||
949 | } | |||
950 | ||||
951 | gfc_current_locus = orig_loc; | |||
952 | return MATCH_NO; | |||
953 | } | |||
954 | ||||
955 | ||||
956 | /* Match a loop control phrase: | |||
957 | ||||
958 | <LVALUE> = <EXPR>, <EXPR> [, <EXPR> ] | |||
959 | ||||
960 | If the final integer expression is not present, a constant unity | |||
961 | expression is returned. We don't return MATCH_ERROR until after | |||
962 | the equals sign is seen. */ | |||
963 | ||||
964 | match | |||
965 | gfc_match_iterator (gfc_iterator *iter, int init_flag) | |||
966 | { | |||
967 | char name[GFC_MAX_SYMBOL_LEN63 + 1]; | |||
968 | gfc_expr *var, *e1, *e2, *e3; | |||
969 | locus start; | |||
970 | match m; | |||
971 | ||||
972 | e1 = e2 = e3 = NULL__null; | |||
973 | ||||
974 | /* Match the start of an iterator without affecting the symbol table. */ | |||
975 | ||||
976 | start = gfc_current_locus; | |||
977 | m = gfc_match (" %n =", name); | |||
978 | gfc_current_locus = start; | |||
979 | ||||
980 | if (m != MATCH_YES) | |||
981 | return MATCH_NO; | |||
982 | ||||
983 | m = gfc_match_variable (&var, 0); | |||
984 | if (m != MATCH_YES) | |||
985 | return MATCH_NO; | |||
986 | ||||
987 | if (var->symtree->n.sym->attr.dimension) | |||
988 | { | |||
989 | gfc_error ("Loop variable at %C cannot be an array"); | |||
990 | goto cleanup; | |||
991 | } | |||
992 | ||||
993 | /* F2008, C617 & C565. */ | |||
994 | if (var->symtree->n.sym->attr.codimension) | |||
995 | { | |||
996 | gfc_error ("Loop variable at %C cannot be a coarray"); | |||
997 | goto cleanup; | |||
998 | } | |||
999 | ||||
1000 | if (var->ref != NULL__null) | |||
1001 | { | |||
1002 | gfc_error ("Loop variable at %C cannot be a sub-component"); | |||
1003 | goto cleanup; | |||
1004 | } | |||
1005 | ||||
1006 | gfc_match_char ('='); | |||
1007 | ||||
1008 | var->symtree->n.sym->attr.implied_index = 1; | |||
1009 | ||||
1010 | m = init_flag ? gfc_match_init_expr (&e1) : gfc_match_expr (&e1); | |||
1011 | if (m == MATCH_NO) | |||
1012 | goto syntax; | |||
1013 | if (m == MATCH_ERROR) | |||
1014 | goto cleanup; | |||
1015 | ||||
1016 | if (gfc_match_char (',') != MATCH_YES) | |||
1017 | goto syntax; | |||
1018 | ||||
1019 | m = init_flag ? gfc_match_init_expr (&e2) : gfc_match_expr (&e2); | |||
1020 | if (m == MATCH_NO) | |||
1021 | goto syntax; | |||
1022 | if (m == MATCH_ERROR) | |||
1023 | goto cleanup; | |||
1024 | ||||
1025 | if (gfc_match_char (',') != MATCH_YES) | |||
1026 | { | |||
1027 | e3 = gfc_get_int_expr (gfc_default_integer_kind, NULL__null, 1); | |||
1028 | goto done; | |||
1029 | } | |||
1030 | ||||
1031 | m = init_flag ? gfc_match_init_expr (&e3) : gfc_match_expr (&e3); | |||
1032 | if (m == MATCH_ERROR) | |||
1033 | goto cleanup; | |||
1034 | if (m == MATCH_NO) | |||
1035 | { | |||
1036 | gfc_error ("Expected a step value in iterator at %C"); | |||
1037 | goto cleanup; | |||
1038 | } | |||
1039 | ||||
1040 | done: | |||
1041 | iter->var = var; | |||
1042 | iter->start = e1; | |||
1043 | iter->end = e2; | |||
1044 | iter->step = e3; | |||
1045 | return MATCH_YES; | |||
1046 | ||||
1047 | syntax: | |||
1048 | gfc_error ("Syntax error in iterator at %C"); | |||
1049 | ||||
1050 | cleanup: | |||
1051 | gfc_free_expr (e1); | |||
1052 | gfc_free_expr (e2); | |||
1053 | gfc_free_expr (e3); | |||
1054 | ||||
1055 | return MATCH_ERROR; | |||
1056 | } | |||
1057 | ||||
1058 | ||||
1059 | /* Tries to match the next non-whitespace character on the input. | |||
1060 | This subroutine does not return MATCH_ERROR. | |||
1061 | When gobble_ws is false, do not skip over leading blanks. */ | |||
1062 | ||||
1063 | match | |||
1064 | gfc_match_char (char c, bool gobble_ws) | |||
1065 | { | |||
1066 | locus where; | |||
1067 | ||||
1068 | where = gfc_current_locus; | |||
1069 | if (gobble_ws) | |||
1070 | gfc_gobble_whitespace (); | |||
1071 | ||||
1072 | if (gfc_next_ascii_char () == c) | |||
1073 | return MATCH_YES; | |||
1074 | ||||
1075 | gfc_current_locus = where; | |||
1076 | return MATCH_NO; | |||
1077 | } | |||
1078 | ||||
1079 | ||||
1080 | /* General purpose matching subroutine. The target string is a | |||
1081 | scanf-like format string in which spaces correspond to arbitrary | |||
1082 | whitespace (including no whitespace), characters correspond to | |||
1083 | themselves. The %-codes are: | |||
1084 | ||||
1085 | %% Literal percent sign | |||
1086 | %e Expression, pointer to a pointer is set | |||
1087 | %s Symbol, pointer to the symbol is set | |||
1088 | %n Name, character buffer is set to name | |||
1089 | %t Matches end of statement. | |||
1090 | %o Matches an intrinsic operator, returned as an INTRINSIC enum. | |||
1091 | %l Matches a statement label | |||
1092 | %v Matches a variable expression (an lvalue, except function references | |||
1093 | having a data pointer result) | |||
1094 | % Matches a required space (in free form) and optional spaces. */ | |||
1095 | ||||
1096 | match | |||
1097 | gfc_match (const char *target, ...) | |||
1098 | { | |||
1099 | gfc_st_label **label; | |||
1100 | int matches, *ip; | |||
1101 | locus old_loc; | |||
1102 | va_list argp; | |||
1103 | char c, *np; | |||
1104 | match m, n; | |||
1105 | void **vp; | |||
1106 | const char *p; | |||
1107 | ||||
1108 | old_loc = gfc_current_locus; | |||
1109 | va_start (argp, target)__builtin_va_start(argp, target); | |||
1110 | m = MATCH_NO; | |||
1111 | matches = 0; | |||
1112 | p = target; | |||
1113 | ||||
1114 | loop: | |||
1115 | c = *p++; | |||
1116 | switch (c) | |||
1117 | { | |||
1118 | case ' ': | |||
1119 | gfc_gobble_whitespace (); | |||
1120 | goto loop; | |||
1121 | case '\0': | |||
1122 | m = MATCH_YES; | |||
1123 | break; | |||
1124 | ||||
1125 | case '%': | |||
1126 | c = *p++; | |||
1127 | switch (c) | |||
1128 | { | |||
1129 | case 'e': | |||
1130 | vp = va_arg (argp, void **)__builtin_va_arg(argp, void **); | |||
1131 | n = gfc_match_expr ((gfc_expr **) vp); | |||
1132 | if (n != MATCH_YES) | |||
1133 | { | |||
1134 | m = n; | |||
1135 | goto not_yes; | |||
1136 | } | |||
1137 | ||||
1138 | matches++; | |||
1139 | goto loop; | |||
1140 | ||||
1141 | case 'v': | |||
1142 | vp = va_arg (argp, void **)__builtin_va_arg(argp, void **); | |||
1143 | n = gfc_match_variable ((gfc_expr **) vp, 0); | |||
1144 | if (n != MATCH_YES) | |||
1145 | { | |||
1146 | m = n; | |||
1147 | goto not_yes; | |||
1148 | } | |||
1149 | ||||
1150 | matches++; | |||
1151 | goto loop; | |||
1152 | ||||
1153 | case 's': | |||
1154 | vp = va_arg (argp, void **)__builtin_va_arg(argp, void **); | |||
1155 | n = gfc_match_symbol ((gfc_symbol **) vp, 0); | |||
1156 | if (n != MATCH_YES) | |||
1157 | { | |||
1158 | m = n; | |||
1159 | goto not_yes; | |||
1160 | } | |||
1161 | ||||
1162 | matches++; | |||
1163 | goto loop; | |||
1164 | ||||
1165 | case 'n': | |||
1166 | np = va_arg (argp, char *)__builtin_va_arg(argp, char *); | |||
1167 | n = gfc_match_name (np); | |||
1168 | if (n != MATCH_YES) | |||
1169 | { | |||
1170 | m = n; | |||
1171 | goto not_yes; | |||
1172 | } | |||
1173 | ||||
1174 | matches++; | |||
1175 | goto loop; | |||
1176 | ||||
1177 | case 'l': | |||
1178 | label = va_arg (argp, gfc_st_label **)__builtin_va_arg(argp, gfc_st_label **); | |||
1179 | n = gfc_match_st_label (label); | |||
1180 | if (n != MATCH_YES) | |||
1181 | { | |||
1182 | m = n; | |||
1183 | goto not_yes; | |||
1184 | } | |||
1185 | ||||
1186 | matches++; | |||
1187 | goto loop; | |||
1188 | ||||
1189 | case 'o': | |||
1190 | ip = va_arg (argp, int *)__builtin_va_arg(argp, int *); | |||
1191 | n = gfc_match_intrinsic_op ((gfc_intrinsic_op *) ip); | |||
1192 | if (n != MATCH_YES) | |||
1193 | { | |||
1194 | m = n; | |||
1195 | goto not_yes; | |||
1196 | } | |||
1197 | ||||
1198 | matches++; | |||
1199 | goto loop; | |||
1200 | ||||
1201 | case 't': | |||
1202 | if (gfc_match_eos () != MATCH_YES) | |||
1203 | { | |||
1204 | m = MATCH_NO; | |||
1205 | goto not_yes; | |||
1206 | } | |||
1207 | goto loop; | |||
1208 | ||||
1209 | case ' ': | |||
1210 | if (gfc_match_space () == MATCH_YES) | |||
1211 | goto loop; | |||
1212 | m = MATCH_NO; | |||
1213 | goto not_yes; | |||
1214 | ||||
1215 | case '%': | |||
1216 | break; /* Fall through to character matcher. */ | |||
1217 | ||||
1218 | default: | |||
1219 | gfc_internal_error ("gfc_match(): Bad match code %c", c); | |||
1220 | } | |||
1221 | /* FALLTHRU */ | |||
1222 | ||||
1223 | default: | |||
1224 | ||||
1225 | /* gfc_next_ascii_char converts characters to lower-case, so we shouldn't | |||
1226 | expect an upper case character here! */ | |||
1227 | gcc_assert (TOLOWER (c) == c)((void)(!(_sch_tolower[(c) & 0xff] == c) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/match.cc" , 1227, __FUNCTION__), 0 : 0)); | |||
1228 | ||||
1229 | if (c == gfc_next_ascii_char ()) | |||
1230 | goto loop; | |||
1231 | break; | |||
1232 | } | |||
1233 | ||||
1234 | not_yes: | |||
1235 | va_end (argp)__builtin_va_end(argp); | |||
1236 | ||||
1237 | if (m != MATCH_YES) | |||
1238 | { | |||
1239 | /* Clean up after a failed match. */ | |||
1240 | gfc_current_locus = old_loc; | |||
1241 | va_start (argp, target)__builtin_va_start(argp, target); | |||
1242 | ||||
1243 | p = target; | |||
1244 | for (; matches > 0; matches--) | |||
1245 | { | |||
1246 | while (*p++ != '%'); | |||
1247 | ||||
1248 | switch (*p++) | |||
1249 | { | |||
1250 | case '%': | |||
1251 | matches++; | |||
1252 | break; /* Skip. */ | |||
1253 | ||||
1254 | /* Matches that don't have to be undone */ | |||
1255 | case 'o': | |||
1256 | case 'l': | |||
1257 | case 'n': | |||
1258 | case 's': | |||
1259 | (void) va_arg (argp, void **)__builtin_va_arg(argp, void **); | |||
1260 | break; | |||
1261 | ||||
1262 | case 'e': | |||
1263 | case 'v': | |||
1264 | vp = va_arg (argp, void **)__builtin_va_arg(argp, void **); | |||
1265 | gfc_free_expr ((struct gfc_expr *)*vp); | |||
1266 | *vp = NULL__null; | |||
1267 | break; | |||
1268 | } | |||
1269 | } | |||
1270 | ||||
1271 | va_end (argp)__builtin_va_end(argp); | |||
1272 | } | |||
1273 | ||||
1274 | return m; | |||
1275 | } | |||
1276 | ||||
1277 | ||||
1278 | /*********************** Statement level matching **********************/ | |||
1279 | ||||
1280 | /* Matches the start of a program unit, which is the program keyword | |||
1281 | followed by an obligatory symbol. */ | |||
1282 | ||||
1283 | match | |||
1284 | gfc_match_program (void) | |||
1285 | { | |||
1286 | gfc_symbol *sym; | |||
1287 | match m; | |||
1288 | ||||
1289 | m = gfc_match ("% %s%t", &sym); | |||
1290 | ||||
1291 | if (m == MATCH_NO) | |||
1292 | { | |||
1293 | gfc_error ("Invalid form of PROGRAM statement at %C"); | |||
1294 | m = MATCH_ERROR; | |||
1295 | } | |||
1296 | ||||
1297 | if (m == MATCH_ERROR) | |||
1298 | return m; | |||
1299 | ||||
1300 | if (!gfc_add_flavor (&sym->attr, FL_PROGRAM, sym->name, NULL__null)) | |||
1301 | return MATCH_ERROR; | |||
1302 | ||||
1303 | gfc_new_block = sym; | |||
1304 | ||||
1305 | return MATCH_YES; | |||
1306 | } | |||
1307 | ||||
1308 | ||||
1309 | /* Match a simple assignment statement. */ | |||
1310 | ||||
1311 | match | |||
1312 | gfc_match_assignment (void) | |||
1313 | { | |||
1314 | gfc_expr *lvalue, *rvalue; | |||
1315 | locus old_loc; | |||
1316 | match m; | |||
1317 | ||||
1318 | old_loc = gfc_current_locus; | |||
1319 | ||||
1320 | lvalue = NULL__null; | |||
1321 | m = gfc_match (" %v =", &lvalue); | |||
1322 | if (m != MATCH_YES) | |||
1323 | { | |||
1324 | gfc_current_locus = old_loc; | |||
1325 | gfc_free_expr (lvalue); | |||
1326 | return MATCH_NO; | |||
1327 | } | |||
1328 | ||||
1329 | rvalue = NULL__null; | |||
1330 | m = gfc_match (" %e%t", &rvalue); | |||
1331 | ||||
1332 | if (m == MATCH_YES | |||
1333 | && rvalue->ts.type == BT_BOZ | |||
1334 | && lvalue->ts.type == BT_CLASS) | |||
1335 | { | |||
1336 | m = MATCH_ERROR; | |||
1337 | gfc_error ("BOZ literal constant at %L is neither a DATA statement " | |||
1338 | "value nor an actual argument of INT/REAL/DBLE/CMPLX " | |||
1339 | "intrinsic subprogram", &rvalue->where); | |||
1340 | } | |||
1341 | ||||
1342 | if (lvalue->expr_type == EXPR_CONSTANT) | |||
1343 | { | |||
1344 | /* This clobbers %len and %kind. */ | |||
1345 | m = MATCH_ERROR; | |||
1346 | gfc_error ("Assignment to a constant expression at %C"); | |||
1347 | } | |||
1348 | ||||
1349 | if (m != MATCH_YES) | |||
1350 | { | |||
1351 | gfc_current_locus = old_loc; | |||
1352 | gfc_free_expr (lvalue); | |||
1353 | gfc_free_expr (rvalue); | |||
1354 | return m; | |||
1355 | } | |||
1356 | ||||
1357 | if (!lvalue->symtree) | |||
1358 | { | |||
1359 | gfc_free_expr (lvalue); | |||
1360 | gfc_free_expr (rvalue); | |||
1361 | return MATCH_ERROR; | |||
1362 | } | |||
1363 | ||||
1364 | ||||
1365 | gfc_set_sym_referenced (lvalue->symtree->n.sym); | |||
1366 | ||||
1367 | new_st.op = EXEC_ASSIGN; | |||
1368 | new_st.expr1 = lvalue; | |||
1369 | new_st.expr2 = rvalue; | |||
1370 | ||||
1371 | gfc_check_do_variable (lvalue->symtree); | |||
1372 | ||||
1373 | return MATCH_YES; | |||
1374 | } | |||
1375 | ||||
1376 | ||||
1377 | /* Match a pointer assignment statement. */ | |||
1378 | ||||
1379 | match | |||
1380 | gfc_match_pointer_assignment (void) | |||
1381 | { | |||
1382 | gfc_expr *lvalue, *rvalue; | |||
1383 | locus old_loc; | |||
1384 | match m; | |||
1385 | ||||
1386 | old_loc = gfc_current_locus; | |||
1387 | ||||
1388 | lvalue = rvalue = NULL__null; | |||
1389 | gfc_matching_ptr_assignment = 0; | |||
1390 | gfc_matching_procptr_assignment = 0; | |||
1391 | ||||
1392 | m = gfc_match (" %v =>", &lvalue); | |||
1393 | if (m != MATCH_YES || !lvalue->symtree) | |||
1394 | { | |||
1395 | m = MATCH_NO; | |||
1396 | goto cleanup; | |||
1397 | } | |||
1398 | ||||
1399 | if (lvalue->symtree->n.sym->attr.proc_pointer | |||
1400 | || gfc_is_proc_ptr_comp (lvalue)) | |||
1401 | gfc_matching_procptr_assignment = 1; | |||
1402 | else | |||
1403 | gfc_matching_ptr_assignment = 1; | |||
1404 | ||||
1405 | m = gfc_match (" %e%t", &rvalue); | |||
1406 | gfc_matching_ptr_assignment = 0; | |||
1407 | gfc_matching_procptr_assignment = 0; | |||
1408 | if (m != MATCH_YES) | |||
1409 | goto cleanup; | |||
1410 | ||||
1411 | new_st.op = EXEC_POINTER_ASSIGN; | |||
1412 | new_st.expr1 = lvalue; | |||
1413 | new_st.expr2 = rvalue; | |||
1414 | ||||
1415 | return MATCH_YES; | |||
1416 | ||||
1417 | cleanup: | |||
1418 | gfc_current_locus = old_loc; | |||
1419 | gfc_free_expr (lvalue); | |||
1420 | gfc_free_expr (rvalue); | |||
1421 | return m; | |||
1422 | } | |||
1423 | ||||
1424 | ||||
1425 | /* We try to match an easy arithmetic IF statement. This only happens | |||
1426 | when just after having encountered a simple IF statement. This code | |||
1427 | is really duplicate with parts of the gfc_match_if code, but this is | |||
1428 | *much* easier. */ | |||
1429 | ||||
1430 | static match | |||
1431 | match_arithmetic_if (void) | |||
1432 | { | |||
1433 | gfc_st_label *l1, *l2, *l3; | |||
1434 | gfc_expr *expr; | |||
1435 | match m; | |||
1436 | ||||
1437 | m = gfc_match (" ( %e ) %l , %l , %l%t", &expr, &l1, &l2, &l3); | |||
1438 | if (m != MATCH_YES) | |||
1439 | return m; | |||
1440 | ||||
1441 | if (!gfc_reference_st_label (l1, ST_LABEL_TARGET) | |||
1442 | || !gfc_reference_st_label (l2, ST_LABEL_TARGET) | |||
1443 | || !gfc_reference_st_label (l3, ST_LABEL_TARGET)) | |||
1444 | { | |||
1445 | gfc_free_expr (expr); | |||
1446 | return MATCH_ERROR; | |||
1447 | } | |||
1448 | ||||
1449 | if (!gfc_notify_std (GFC_STD_F95_OBS(1<<1) | GFC_STD_F2018_DEL(1<<11), | |||
1450 | "Arithmetic IF statement at %C")) | |||
1451 | return MATCH_ERROR; | |||
1452 | ||||
1453 | new_st.op = EXEC_ARITHMETIC_IF; | |||
1454 | new_st.expr1 = expr; | |||
1455 | new_st.label1 = l1; | |||
1456 | new_st.label2 = l2; | |||
1457 | new_st.label3 = l3; | |||
1458 | ||||
1459 | return MATCH_YES; | |||
1460 | } | |||
1461 | ||||
1462 | ||||
1463 | /* The IF statement is a bit of a pain. First of all, there are three | |||
1464 | forms of it, the simple IF, the IF that starts a block and the | |||
1465 | arithmetic IF. | |||
1466 | ||||
1467 | There is a problem with the simple IF and that is the fact that we | |||
1468 | only have a single level of undo information on symbols. What this | |||
1469 | means is for a simple IF, we must re-match the whole IF statement | |||
1470 | multiple times in order to guarantee that the symbol table ends up | |||
1471 | in the proper state. */ | |||
1472 | ||||
1473 | static match match_simple_forall (void); | |||
1474 | static match match_simple_where (void); | |||
1475 | ||||
1476 | match | |||
1477 | gfc_match_if (gfc_statement *if_type) | |||
1478 | { | |||
1479 | gfc_expr *expr; | |||
1480 | gfc_st_label *l1, *l2, *l3; | |||
1481 | locus old_loc, old_loc2; | |||
1482 | gfc_code *p; | |||
1483 | match m, n; | |||
1484 | ||||
1485 | n = gfc_match_label (); | |||
1486 | if (n == MATCH_ERROR) | |||
1487 | return n; | |||
1488 | ||||
1489 | old_loc = gfc_current_locus; | |||
1490 | ||||
1491 | m = gfc_match (" if ", &expr); | |||
1492 | if (m != MATCH_YES) | |||
1493 | return m; | |||
1494 | ||||
1495 | if (gfc_match_char ('(') != MATCH_YES) | |||
1496 | { | |||
1497 | gfc_error ("Missing %<(%> in IF-expression at %C"); | |||
1498 | return MATCH_ERROR; | |||
1499 | } | |||
1500 | ||||
1501 | m = gfc_match ("%e", &expr); | |||
1502 | if (m != MATCH_YES) | |||
1503 | return m; | |||
1504 | ||||
1505 | old_loc2 = gfc_current_locus; | |||
1506 | gfc_current_locus = old_loc; | |||
1507 | ||||
1508 | if (gfc_match_parens () == MATCH_ERROR) | |||
1509 | return MATCH_ERROR; | |||
1510 | ||||
1511 | gfc_current_locus = old_loc2; | |||
1512 | ||||
1513 | if (gfc_match_char (')') != MATCH_YES) | |||
1514 | { | |||
1515 | gfc_error ("Syntax error in IF-expression at %C"); | |||
1516 | gfc_free_expr (expr); | |||
1517 | return MATCH_ERROR; | |||
1518 | } | |||
1519 | ||||
1520 | m = gfc_match (" %l , %l , %l%t", &l1, &l2, &l3); | |||
1521 | ||||
1522 | if (m == MATCH_YES) | |||
1523 | { | |||
1524 | if (n == MATCH_YES) | |||
1525 | { | |||
1526 | gfc_error ("Block label not appropriate for arithmetic IF " | |||
1527 | "statement at %C"); | |||
1528 | gfc_free_expr (expr); | |||
1529 | return MATCH_ERROR; | |||
1530 | } | |||
1531 | ||||
1532 | if (!gfc_reference_st_label (l1, ST_LABEL_TARGET) | |||
1533 | || !gfc_reference_st_label (l2, ST_LABEL_TARGET) | |||
1534 | || !gfc_reference_st_label (l3, ST_LABEL_TARGET)) | |||
1535 | { | |||
1536 | gfc_free_expr (expr); | |||
1537 | return MATCH_ERROR; | |||
1538 | } | |||
1539 | ||||
1540 | if (!gfc_notify_std (GFC_STD_F95_OBS(1<<1) | GFC_STD_F2018_DEL(1<<11), | |||
1541 | "Arithmetic IF statement at %C")) | |||
1542 | return MATCH_ERROR; | |||
1543 | ||||
1544 | new_st.op = EXEC_ARITHMETIC_IF; | |||
1545 | new_st.expr1 = expr; | |||
1546 | new_st.label1 = l1; | |||
1547 | new_st.label2 = l2; | |||
1548 | new_st.label3 = l3; | |||
1549 | ||||
1550 | *if_type = ST_ARITHMETIC_IF; | |||
1551 | return MATCH_YES; | |||
1552 | } | |||
1553 | ||||
1554 | if (gfc_match (" then%t") == MATCH_YES) | |||
1555 | { | |||
1556 | new_st.op = EXEC_IF; | |||
1557 | new_st.expr1 = expr; | |||
1558 | *if_type = ST_IF_BLOCK; | |||
1559 | return MATCH_YES; | |||
1560 | } | |||
1561 | ||||
1562 | if (n == MATCH_YES) | |||
1563 | { | |||
1564 | gfc_error ("Block label is not appropriate for IF statement at %C"); | |||
1565 | gfc_free_expr (expr); | |||
1566 | return MATCH_ERROR; | |||
1567 | } | |||
1568 | ||||
1569 | /* At this point the only thing left is a simple IF statement. At | |||
1570 | this point, n has to be MATCH_NO, so we don't have to worry about | |||
1571 | re-matching a block label. From what we've got so far, try | |||
1572 | matching an assignment. */ | |||
1573 | ||||
1574 | *if_type = ST_SIMPLE_IF; | |||
1575 | ||||
1576 | m = gfc_match_assignment (); | |||
1577 | if (m == MATCH_YES) | |||
1578 | goto got_match; | |||
1579 | ||||
1580 | gfc_free_expr (expr); | |||
1581 | gfc_undo_symbols (); | |||
1582 | gfc_current_locus = old_loc; | |||
1583 | ||||
1584 | /* m can be MATCH_NO or MATCH_ERROR, here. For MATCH_ERROR, a mangled | |||
1585 | assignment was found. For MATCH_NO, continue to call the various | |||
1586 | matchers. */ | |||
1587 | if (m == MATCH_ERROR) | |||
1588 | return MATCH_ERROR; | |||
1589 | ||||
1590 | gfc_match (" if ( %e ) ", &expr); /* Guaranteed to match. */ | |||
1591 | ||||
1592 | m = gfc_match_pointer_assignment (); | |||
1593 | if (m == MATCH_YES) | |||
1594 | goto got_match; | |||
1595 | ||||
1596 | gfc_free_expr (expr); | |||
1597 | gfc_undo_symbols (); | |||
1598 | gfc_current_locus = old_loc; | |||
1599 | ||||
1600 | gfc_match (" if ( %e ) ", &expr); /* Guaranteed to match. */ | |||
1601 | ||||
1602 | /* Look at the next keyword to see which matcher to call. Matching | |||
1603 | the keyword doesn't affect the symbol table, so we don't have to | |||
1604 | restore between tries. */ | |||
1605 | ||||
1606 | #define match(string, subr, statement) \ | |||
1607 | if (gfc_match (string) == MATCH_YES) { m = subr(); goto got_match; } | |||
1608 | ||||
1609 | gfc_clear_error (); | |||
1610 | ||||
1611 | match ("allocate", gfc_match_allocate, ST_ALLOCATE) | |||
1612 | match ("assign", gfc_match_assign, ST_LABEL_ASSIGNMENT) | |||
1613 | match ("backspace", gfc_match_backspace, ST_BACKSPACE) | |||
1614 | match ("call", gfc_match_call, ST_CALL) | |||
1615 | match ("change% team", gfc_match_change_team, ST_CHANGE_TEAM) | |||
1616 | match ("close", gfc_match_close, ST_CLOSE) | |||
1617 | match ("continue", gfc_match_continue, ST_CONTINUE) | |||
1618 | match ("cycle", gfc_match_cycle, ST_CYCLE) | |||
1619 | match ("deallocate", gfc_match_deallocate, ST_DEALLOCATE) | |||
1620 | match ("end file", gfc_match_endfile, ST_END_FILE) | |||
1621 | match ("end team", gfc_match_end_team, ST_END_TEAM) | |||
1622 | match ("error% stop", gfc_match_error_stop, ST_ERROR_STOP) | |||
1623 | match ("event% post", gfc_match_event_post, ST_EVENT_POST) | |||
1624 | match ("event% wait", gfc_match_event_wait, ST_EVENT_WAIT) | |||
1625 | match ("exit", gfc_match_exit, ST_EXIT) | |||
1626 | match ("fail% image", gfc_match_fail_image, ST_FAIL_IMAGE) | |||
1627 | match ("flush", gfc_match_flush, ST_FLUSH) | |||
1628 | match ("forall", match_simple_forall, ST_FORALL) | |||
1629 | match ("form% team", gfc_match_form_team, ST_FORM_TEAM) | |||
1630 | match ("go to", gfc_match_goto, ST_GOTO) | |||
1631 | match ("if", match_arithmetic_if, ST_ARITHMETIC_IF) | |||
1632 | match ("inquire", gfc_match_inquire, ST_INQUIRE) | |||
1633 | match ("lock", gfc_match_lock, ST_LOCK) | |||
1634 | match ("nullify", gfc_match_nullify, ST_NULLIFY) | |||
1635 | match ("open", gfc_match_open, ST_OPEN) | |||
1636 | match ("pause", gfc_match_pause, ST_NONE) | |||
1637 | match ("print", gfc_match_print, ST_WRITE) | |||
1638 | match ("read", gfc_match_read, ST_READ) | |||
1639 | match ("return", gfc_match_return, ST_RETURN) | |||
1640 | match ("rewind", gfc_match_rewind, ST_REWIND) | |||
1641 | match ("stop", gfc_match_stop, ST_STOP) | |||
1642 | match ("wait", gfc_match_wait, ST_WAIT) | |||
1643 | match ("sync% all", gfc_match_sync_all, ST_SYNC_CALL); | |||
1644 | match ("sync% images", gfc_match_sync_images, ST_SYNC_IMAGES); | |||
1645 | match ("sync% memory", gfc_match_sync_memory, ST_SYNC_MEMORY); | |||
1646 | match ("sync% team", gfc_match_sync_team, ST_SYNC_TEAM) | |||
1647 | match ("unlock", gfc_match_unlock, ST_UNLOCK) | |||
1648 | match ("where", match_simple_where, ST_WHERE) | |||
1649 | match ("write", gfc_match_write, ST_WRITE) | |||
1650 | ||||
1651 | if (flag_decglobal_options.x_flag_dec) | |||
1652 | match ("type", gfc_match_print, ST_WRITE) | |||
1653 | ||||
1654 | /* All else has failed, so give up. See if any of the matchers has | |||
1655 | stored an error message of some sort. */ | |||
1656 | if (!gfc_error_check ()) | |||
1657 | gfc_error ("Syntax error in IF-clause after %C"); | |||
1658 | ||||
1659 | gfc_free_expr (expr); | |||
1660 | return MATCH_ERROR; | |||
1661 | ||||
1662 | got_match: | |||
1663 | if (m == MATCH_NO) | |||
1664 | gfc_error ("Syntax error in IF-clause after %C"); | |||
1665 | if (m != MATCH_YES) | |||
1666 | { | |||
1667 | gfc_free_expr (expr); | |||
1668 | return MATCH_ERROR; | |||
1669 | } | |||
1670 | ||||
1671 | /* At this point, we've matched the single IF and the action clause | |||
1672 | is in new_st. Rearrange things so that the IF statement appears | |||
1673 | in new_st. */ | |||
1674 | ||||
1675 | p = gfc_get_code (EXEC_IF); | |||
1676 | p->next = XCNEW (gfc_code)((gfc_code *) xcalloc (1, sizeof (gfc_code))); | |||
1677 | *p->next = new_st; | |||
1678 | p->next->loc = gfc_current_locus; | |||
1679 | ||||
1680 | p->expr1 = expr; | |||
1681 | ||||
1682 | gfc_clear_new_st (); | |||
1683 | ||||
1684 | new_st.op = EXEC_IF; | |||
1685 | new_st.block = p; | |||
1686 | ||||
1687 | return MATCH_YES; | |||
1688 | } | |||
1689 | ||||
1690 | #undef match | |||
1691 | ||||
1692 | ||||
1693 | /* Match an ELSE statement. */ | |||
1694 | ||||
1695 | match | |||
1696 | gfc_match_else (void) | |||
1697 | { | |||
1698 | char name[GFC_MAX_SYMBOL_LEN63 + 1]; | |||
1699 | ||||
1700 | if (gfc_match_eos () == MATCH_YES) | |||
1701 | return MATCH_YES; | |||
1702 | ||||
1703 | if (gfc_match_name (name) != MATCH_YES | |||
1704 | || gfc_current_block ()(gfc_state_stack->sym) == NULL__null | |||
1705 | || gfc_match_eos () != MATCH_YES) | |||
1706 | { | |||
1707 | gfc_error ("Invalid character(s) in ELSE statement after %C"); | |||
1708 | return MATCH_ERROR; | |||
1709 | } | |||
1710 | ||||
1711 | if (strcmp (name, gfc_current_block ()(gfc_state_stack->sym)->name) != 0) | |||
1712 | { | |||
1713 | gfc_error ("Label %qs at %C doesn't match IF label %qs", | |||
1714 | name, gfc_current_block ()(gfc_state_stack->sym)->name); | |||
1715 | return MATCH_ERROR; | |||
1716 | } | |||
1717 | ||||
1718 | return MATCH_YES; | |||
1719 | } | |||
1720 | ||||
1721 | ||||
1722 | /* Match an ELSE IF statement. */ | |||
1723 | ||||
1724 | match | |||
1725 | gfc_match_elseif (void) | |||
1726 | { | |||
1727 | char name[GFC_MAX_SYMBOL_LEN63 + 1]; | |||
1728 | gfc_expr *expr, *then; | |||
1729 | locus where; | |||
1730 | match m; | |||
1731 | ||||
1732 | if (gfc_match_char ('(') != MATCH_YES) | |||
1733 | { | |||
1734 | gfc_error ("Missing %<(%> in ELSE IF expression at %C"); | |||
1735 | return MATCH_ERROR; | |||
1736 | } | |||
1737 | ||||
1738 | m = gfc_match (" %e ", &expr); | |||
1739 | if (m != MATCH_YES) | |||
1740 | return m; | |||
1741 | ||||
1742 | if (gfc_match_char (')') != MATCH_YES) | |||
1743 | { | |||
1744 | gfc_error ("Missing %<)%> in ELSE IF expression at %C"); | |||
1745 | goto cleanup; | |||
1746 | } | |||
1747 | ||||
1748 | m = gfc_match (" then ", &then); | |||
1749 | ||||
1750 | where = gfc_current_locus; | |||
1751 | ||||
1752 | if (m == MATCH_YES && (gfc_match_eos () == MATCH_YES | |||
1753 | || (gfc_current_block ()(gfc_state_stack->sym) | |||
1754 | && gfc_match_name (name) == MATCH_YES))) | |||
1755 | goto done; | |||
1756 | ||||
1757 | if (gfc_match_eos () == MATCH_YES) | |||
1758 | { | |||
1759 | gfc_error ("Missing THEN in ELSE IF statement after %L", &where); | |||
1760 | goto cleanup; | |||
1761 | } | |||
1762 | ||||
1763 | if (gfc_match_name (name) != MATCH_YES | |||
1764 | || gfc_current_block ()(gfc_state_stack->sym) == NULL__null | |||
1765 | || gfc_match_eos () != MATCH_YES) | |||
1766 | { | |||
1767 | gfc_error ("Syntax error in ELSE IF statement after %L", &where); | |||
1768 | goto cleanup; | |||
1769 | } | |||
1770 | ||||
1771 | if (strcmp (name, gfc_current_block ()(gfc_state_stack->sym)->name) != 0) | |||
1772 | { | |||
1773 | gfc_error ("Label %qs after %L doesn't match IF label %qs", | |||
1774 | name, &where, gfc_current_block ()(gfc_state_stack->sym)->name); | |||
1775 | goto cleanup; | |||
1776 | } | |||
1777 | ||||
1778 | if (m != MATCH_YES) | |||
1779 | return m; | |||
1780 | ||||
1781 | done: | |||
1782 | new_st.op = EXEC_IF; | |||
1783 | new_st.expr1 = expr; | |||
1784 | return MATCH_YES; | |||
1785 | ||||
1786 | cleanup: | |||
1787 | gfc_free_expr (expr); | |||
1788 | return MATCH_ERROR; | |||
1789 | } | |||
1790 | ||||
1791 | ||||
1792 | /* Free a gfc_iterator structure. */ | |||
1793 | ||||
1794 | void | |||
1795 | gfc_free_iterator (gfc_iterator *iter, int flag) | |||
1796 | { | |||
1797 | ||||
1798 | if (iter == NULL__null) | |||
1799 | return; | |||
1800 | ||||
1801 | gfc_free_expr (iter->var); | |||
1802 | gfc_free_expr (iter->start); | |||
1803 | gfc_free_expr (iter->end); | |||
1804 | gfc_free_expr (iter->step); | |||
1805 | ||||
1806 | if (flag) | |||
1807 | free (iter); | |||
1808 | } | |||
1809 | ||||
1810 | ||||
1811 | /* Match a CRITICAL statement. */ | |||
1812 | match | |||
1813 | gfc_match_critical (void) | |||
1814 | { | |||
1815 | gfc_st_label *label = NULL__null; | |||
1816 | ||||
1817 | if (gfc_match_label () == MATCH_ERROR) | |||
1818 | return MATCH_ERROR; | |||
1819 | ||||
1820 | if (gfc_match (" critical") != MATCH_YES) | |||
1821 | return MATCH_NO; | |||
1822 | ||||
1823 | if (gfc_match_st_label (&label) == MATCH_ERROR) | |||
1824 | return MATCH_ERROR; | |||
1825 | ||||
1826 | if (gfc_match_eos () != MATCH_YES) | |||
1827 | { | |||
1828 | gfc_syntax_error (ST_CRITICAL)gfc_error ("Syntax error in %s statement at %C", gfc_ascii_statement (ST_CRITICAL));; | |||
1829 | return MATCH_ERROR; | |||
1830 | } | |||
1831 | ||||
1832 | if (gfc_pure (NULL__null)) | |||
1833 | { | |||
1834 | gfc_error ("Image control statement CRITICAL at %C in PURE procedure"); | |||
1835 | return MATCH_ERROR; | |||
1836 | } | |||
1837 | ||||
1838 | if (gfc_find_state (COMP_DO_CONCURRENT)) | |||
1839 | { | |||
1840 | gfc_error ("Image control statement CRITICAL at %C in DO CONCURRENT " | |||
1841 | "block"); | |||
1842 | return MATCH_ERROR; | |||
1843 | } | |||
1844 | ||||
1845 | gfc_unset_implicit_pure (NULL__null); | |||
1846 | ||||
1847 | if (!gfc_notify_std (GFC_STD_F2008(1<<7), "CRITICAL statement at %C")) | |||
1848 | return MATCH_ERROR; | |||
1849 | ||||
1850 | if (flag_coarrayglobal_options.x_flag_coarray == GFC_FCOARRAY_NONE) | |||
1851 | { | |||
1852 | gfc_fatal_error ("Coarrays disabled at %C, use %<-fcoarray=%> to " | |||
1853 | "enable"); | |||
1854 | return MATCH_ERROR; | |||
1855 | } | |||
1856 | ||||
1857 | if (gfc_find_state (COMP_CRITICAL)) | |||
1858 | { | |||
1859 | gfc_error ("Nested CRITICAL block at %C"); | |||
1860 | return MATCH_ERROR; | |||
1861 | } | |||
1862 | ||||
1863 | new_st.op = EXEC_CRITICAL; | |||
1864 | ||||
1865 | if (label != NULL__null | |||
1866 | && !gfc_reference_st_label (label, ST_LABEL_TARGET)) | |||
1867 | return MATCH_ERROR; | |||
1868 | ||||
1869 | return MATCH_YES; | |||
1870 | } | |||
1871 | ||||
1872 | ||||
1873 | /* Match a BLOCK statement. */ | |||
1874 | ||||
1875 | match | |||
1876 | gfc_match_block (void) | |||
1877 | { | |||
1878 | match m; | |||
1879 | ||||
1880 | if (gfc_match_label () == MATCH_ERROR) | |||
1881 | return MATCH_ERROR; | |||
1882 | ||||
1883 | if (gfc_match (" block") != MATCH_YES) | |||
1884 | return MATCH_NO; | |||
1885 | ||||
1886 | /* For this to be a correct BLOCK statement, the line must end now. */ | |||
1887 | m = gfc_match_eos (); | |||
1888 | if (m == MATCH_ERROR) | |||
1889 | return MATCH_ERROR; | |||
1890 | if (m == MATCH_NO) | |||
1891 | return MATCH_NO; | |||
1892 | ||||
1893 | return MATCH_YES; | |||
1894 | } | |||
1895 | ||||
1896 | ||||
1897 | /* Match an ASSOCIATE statement. */ | |||
1898 | ||||
1899 | match | |||
1900 | gfc_match_associate (void) | |||
1901 | { | |||
1902 | if (gfc_match_label () == MATCH_ERROR) | |||
1903 | return MATCH_ERROR; | |||
1904 | ||||
1905 | if (gfc_match (" associate") != MATCH_YES) | |||
1906 | return MATCH_NO; | |||
1907 | ||||
1908 | /* Match the association list. */ | |||
1909 | if (gfc_match_char ('(') != MATCH_YES) | |||
1910 | { | |||
1911 | gfc_error ("Expected association list at %C"); | |||
1912 | return MATCH_ERROR; | |||
1913 | } | |||
1914 | new_st.ext.block.assoc = NULL__null; | |||
1915 | while (true) | |||
1916 | { | |||
1917 | gfc_association_list* newAssoc = gfc_get_association_list ()((gfc_association_list *) xcalloc (1, sizeof (gfc_association_list ))); | |||
1918 | gfc_association_list* a; | |||
1919 | ||||
1920 | /* Match the next association. */ | |||
1921 | if (gfc_match (" %n =>", newAssoc->name) != MATCH_YES) | |||
1922 | { | |||
1923 | gfc_error ("Expected association at %C"); | |||
1924 | goto assocListError; | |||
1925 | } | |||
1926 | ||||
1927 | if (gfc_match (" %e", &newAssoc->target) != MATCH_YES) | |||
1928 | { | |||
1929 | /* Have another go, allowing for procedure pointer selectors. */ | |||
1930 | gfc_matching_procptr_assignment = 1; | |||
1931 | if (gfc_match (" %e", &newAssoc->target) != MATCH_YES) | |||
1932 | { | |||
1933 | gfc_error ("Invalid association target at %C"); | |||
1934 | goto assocListError; | |||
1935 | } | |||
1936 | gfc_matching_procptr_assignment = 0; | |||
1937 | } | |||
1938 | newAssoc->where = gfc_current_locus; | |||
1939 | ||||
1940 | /* Check that the current name is not yet in the list. */ | |||
1941 | for (a = new_st.ext.block.assoc; a; a = a->next) | |||
1942 | if (!strcmp (a->name, newAssoc->name)) | |||
1943 | { | |||
1944 | gfc_error ("Duplicate name %qs in association at %C", | |||
1945 | newAssoc->name); | |||
1946 | goto assocListError; | |||
1947 | } | |||
1948 | ||||
1949 | /* The target expression must not be coindexed. */ | |||
1950 | if (gfc_is_coindexed (newAssoc->target)) | |||
1951 | { | |||
1952 | gfc_error ("Association target at %C must not be coindexed"); | |||
1953 | goto assocListError; | |||
1954 | } | |||
1955 | ||||
1956 | /* The target expression cannot be a BOZ literal constant. */ | |||
1957 | if (newAssoc->target->ts.type == BT_BOZ) | |||
1958 | { | |||
1959 | gfc_error ("Association target at %L cannot be a BOZ literal " | |||
1960 | "constant", &newAssoc->target->where); | |||
1961 | goto assocListError; | |||
1962 | } | |||
1963 | ||||
1964 | /* The `variable' field is left blank for now; because the target is not | |||
1965 | yet resolved, we can't use gfc_has_vector_subscript to determine it | |||
1966 | for now. This is set during resolution. */ | |||
1967 | ||||
1968 | /* Put it into the list. */ | |||
1969 | newAssoc->next = new_st.ext.block.assoc; | |||
1970 | new_st.ext.block.assoc = newAssoc; | |||
1971 | ||||
1972 | /* Try next one or end if closing parenthesis is found. */ | |||
1973 | gfc_gobble_whitespace (); | |||
1974 | if (gfc_peek_char () == ')') | |||
1975 | break; | |||
1976 | if (gfc_match_char (',') != MATCH_YES) | |||
1977 | { | |||
1978 | gfc_error ("Expected %<)%> or %<,%> at %C"); | |||
1979 | return MATCH_ERROR; | |||
1980 | } | |||
1981 | ||||
1982 | continue; | |||
1983 | ||||
1984 | assocListError: | |||
1985 | free (newAssoc); | |||
1986 | goto error; | |||
1987 | } | |||
1988 | if (gfc_match_char (')') != MATCH_YES) | |||
1989 | { | |||
1990 | /* This should never happen as we peek above. */ | |||
1991 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/match.cc" , 1991, __FUNCTION__)); | |||
1992 | } | |||
1993 | ||||
1994 | if (gfc_match_eos () != MATCH_YES) | |||
1995 | { | |||
1996 | gfc_error ("Junk after ASSOCIATE statement at %C"); | |||
1997 | goto error; | |||
1998 | } | |||
1999 | ||||
2000 | return MATCH_YES; | |||
2001 | ||||
2002 | error: | |||
2003 | gfc_free_association_list (new_st.ext.block.assoc); | |||
2004 | return MATCH_ERROR; | |||
2005 | } | |||
2006 | ||||
2007 | ||||
2008 | /* Match a Fortran 2003 derived-type-spec (F03:R455), which is just the name of | |||
2009 | an accessible derived type. */ | |||
2010 | ||||
2011 | static match | |||
2012 | match_derived_type_spec (gfc_typespec *ts) | |||
2013 | { | |||
2014 | char name[GFC_MAX_SYMBOL_LEN63 + 1]; | |||
2015 | locus old_locus; | |||
2016 | gfc_symbol *derived, *der_type; | |||
2017 | match m = MATCH_YES; | |||
2018 | gfc_actual_arglist *decl_type_param_list = NULL__null; | |||
2019 | bool is_pdt_template = false; | |||
2020 | ||||
2021 | old_locus = gfc_current_locus; | |||
2022 | ||||
2023 | if (gfc_match ("%n", name) != MATCH_YES) | |||
2024 | { | |||
2025 | gfc_current_locus = old_locus; | |||
2026 | return MATCH_NO; | |||
2027 | } | |||
2028 | ||||
2029 | gfc_find_symbol (name, NULL__null, 1, &derived); | |||
2030 | ||||
2031 | /* Match the PDT spec list, if there. */ | |||
2032 | if (derived && derived->attr.flavor == FL_PROCEDURE) | |||
2033 | { | |||
2034 | gfc_find_symbol (gfc_dt_upper_string (name), NULL__null, 1, &der_type); | |||
2035 | is_pdt_template = der_type | |||
2036 | && der_type->attr.flavor == FL_DERIVED | |||
2037 | && der_type->attr.pdt_template; | |||
2038 | } | |||
2039 | ||||
2040 | if (is_pdt_template) | |||
2041 | m = gfc_match_actual_arglist (1, &decl_type_param_list, true); | |||
2042 | ||||
2043 | if (m == MATCH_ERROR) | |||
2044 | { | |||
2045 | gfc_free_actual_arglist (decl_type_param_list); | |||
2046 | return m; | |||
2047 | } | |||
2048 | ||||
2049 | if (derived && derived->attr.flavor == FL_PROCEDURE && derived->attr.generic) | |||
2050 | derived = gfc_find_dt_in_generic (derived); | |||
2051 | ||||
2052 | /* If this is a PDT, find the specific instance. */ | |||
2053 | if (m == MATCH_YES && is_pdt_template) | |||
2054 | { | |||
2055 | gfc_namespace *old_ns; | |||
2056 | ||||
2057 | old_ns = gfc_current_ns; | |||
2058 | while (gfc_current_ns && gfc_current_ns->parent) | |||
2059 | gfc_current_ns = gfc_current_ns->parent; | |||
2060 | ||||
2061 | if (type_param_spec_list) | |||
2062 | gfc_free_actual_arglist (type_param_spec_list); | |||
2063 | m = gfc_get_pdt_instance (decl_type_param_list, &der_type, | |||
2064 | &type_param_spec_list); | |||
2065 | gfc_free_actual_arglist (decl_type_param_list); | |||
2066 | ||||
2067 | if (m != MATCH_YES) | |||
2068 | return m; | |||
2069 | derived = der_type; | |||
2070 | gcc_assert (!derived->attr.pdt_template && derived->attr.pdt_type)((void)(!(!derived->attr.pdt_template && derived-> attr.pdt_type) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/match.cc" , 2070, __FUNCTION__), 0 : 0)); | |||
2071 | gfc_set_sym_referenced (derived); | |||
2072 | ||||
2073 | gfc_current_ns = old_ns; | |||
2074 | } | |||
2075 | ||||
2076 | if (derived && derived->attr.flavor == FL_DERIVED) | |||
2077 | { | |||
2078 | ts->type = BT_DERIVED; | |||
2079 | ts->u.derived = derived; | |||
2080 | return MATCH_YES; | |||
2081 | } | |||
2082 | ||||
2083 | gfc_current_locus = old_locus; | |||
2084 | return MATCH_NO; | |||
2085 | } | |||
2086 | ||||
2087 | ||||
2088 | /* Match a Fortran 2003 type-spec (F03:R401). This is similar to | |||
2089 | gfc_match_decl_type_spec() from decl.cc, with the following exceptions: | |||
2090 | It only includes the intrinsic types from the Fortran 2003 standard | |||
2091 | (thus, neither BYTE nor forms like REAL*4 are allowed). Additionally, | |||
2092 | the implicit_flag is not needed, so it was removed. Derived types are | |||
2093 | identified by their name alone. */ | |||
2094 | ||||
2095 | match | |||
2096 | gfc_match_type_spec (gfc_typespec *ts) | |||
2097 | { | |||
2098 | match m; | |||
2099 | locus old_locus; | |||
2100 | char c, name[GFC_MAX_SYMBOL_LEN63 + 1]; | |||
2101 | ||||
2102 | gfc_clear_ts (ts); | |||
2103 | gfc_gobble_whitespace (); | |||
2104 | old_locus = gfc_current_locus; | |||
2105 | ||||
2106 | /* If c isn't [a-z], then return immediately. */ | |||
2107 | c = gfc_peek_ascii_char (); | |||
2108 | if (!ISALPHA(c)(_sch_istable[(c) & 0xff] & (unsigned short)(_sch_isalpha ))) | |||
2109 | return MATCH_NO; | |||
2110 | ||||
2111 | type_param_spec_list = NULL__null; | |||
2112 | ||||
2113 | if (match_derived_type_spec (ts) == MATCH_YES) | |||
2114 | { | |||
2115 | /* Enforce F03:C401. */ | |||
2116 | if (ts->u.derived->attr.abstract) | |||
2117 | { | |||
2118 | gfc_error ("Derived type %qs at %L may not be ABSTRACT", | |||
2119 | ts->u.derived->name, &old_locus); | |||
2120 | return MATCH_ERROR; | |||
2121 | } | |||
2122 | return MATCH_YES; | |||
2123 | } | |||
2124 | ||||
2125 | if (gfc_match ("integer") == MATCH_YES) | |||
2126 | { | |||
2127 | ts->type = BT_INTEGER; | |||
2128 | ts->kind = gfc_default_integer_kind; | |||
2129 | goto kind_selector; | |||
2130 | } | |||
2131 | ||||
2132 | if (gfc_match ("double precision") == MATCH_YES) | |||
2133 | { | |||
2134 | ts->type = BT_REAL; | |||
2135 | ts->kind = gfc_default_double_kind; | |||
2136 | return MATCH_YES; | |||
2137 | } | |||
2138 | ||||
2139 | if (gfc_match ("complex") == MATCH_YES) | |||
2140 | { | |||
2141 | ts->type = BT_COMPLEX; | |||
2142 | ts->kind = gfc_default_complex_kind; | |||
2143 | goto kind_selector; | |||
2144 | } | |||
2145 | ||||
2146 | if (gfc_match ("character") == MATCH_YES) | |||
2147 | { | |||
2148 | ts->type = BT_CHARACTER; | |||
2149 | ||||
2150 | m = gfc_match_char_spec (ts); | |||
2151 | ||||
2152 | if (m == MATCH_NO) | |||
2153 | m = MATCH_YES; | |||
2154 | ||||
2155 | return m; | |||
2156 | } | |||
2157 | ||||
2158 | /* REAL is a real pain because it can be a type, intrinsic subprogram, | |||
2159 | or list item in a type-list of an OpenMP reduction clause. Need to | |||
2160 | differentiate REAL([KIND]=scalar-int-initialization-expr) from | |||
2161 | REAL(A,[KIND]) and REAL(KIND,A). Logically, when this code was | |||
2162 | written the use of LOGICAL as a type-spec or intrinsic subprogram | |||
2163 | was overlooked. */ | |||
2164 | ||||
2165 | m = gfc_match (" %n", name); | |||
2166 | if (m == MATCH_YES | |||
2167 | && (strcmp (name, "real") == 0 || strcmp (name, "logical") == 0)) | |||
2168 | { | |||
2169 | char c; | |||
2170 | gfc_expr *e; | |||
2171 | locus where; | |||
2172 | ||||
2173 | if (*name == 'r') | |||
2174 | { | |||
2175 | ts->type = BT_REAL; | |||
2176 | ts->kind = gfc_default_real_kind; | |||
2177 | } | |||
2178 | else | |||
2179 | { | |||
2180 | ts->type = BT_LOGICAL; | |||
2181 | ts->kind = gfc_default_logical_kind; | |||
2182 | } | |||
2183 | ||||
2184 | gfc_gobble_whitespace (); | |||
2185 | ||||
2186 | /* Prevent REAL*4, etc. */ | |||
2187 | c = gfc_peek_ascii_char (); | |||
2188 | if (c == '*') | |||
2189 | { | |||
2190 | gfc_error ("Invalid type-spec at %C"); | |||
2191 | return MATCH_ERROR; | |||
2192 | } | |||
2193 | ||||
2194 | /* Found leading colon in REAL::, a trailing ')' in for example | |||
2195 | TYPE IS (REAL), or REAL, for an OpenMP list-item. */ | |||
2196 | if (c == ':' || c == ')' || (flag_openmpglobal_options.x_flag_openmp && c == ',')) | |||
2197 | return MATCH_YES; | |||
2198 | ||||
2199 | /* Found something other than the opening '(' in REAL(... */ | |||
2200 | if (c != '(') | |||
2201 | return MATCH_NO; | |||
2202 | else | |||
2203 | gfc_next_char (); /* Burn the '('. */ | |||
2204 | ||||
2205 | /* Look for the optional KIND=. */ | |||
2206 | where = gfc_current_locus; | |||
2207 | m = gfc_match ("%n", name); | |||
2208 | if (m == MATCH_YES) | |||
2209 | { | |||
2210 | gfc_gobble_whitespace (); | |||
2211 | c = gfc_next_char (); | |||
2212 | if (c == '=') | |||
2213 | { | |||
2214 | if (strcmp(name, "a") == 0 || strcmp(name, "l") == 0) | |||
2215 | return MATCH_NO; | |||
2216 | else if (strcmp(name, "kind") == 0) | |||
2217 | goto found; | |||
2218 | else | |||
2219 | return MATCH_ERROR; | |||
2220 | } | |||
2221 | else | |||
2222 | gfc_current_locus = where; | |||
2223 | } | |||
2224 | else | |||
2225 | gfc_current_locus = where; | |||
2226 | ||||
2227 | found: | |||
2228 | ||||
2229 | m = gfc_match_expr (&e); | |||
2230 | if (m == MATCH_NO || m == MATCH_ERROR) | |||
2231 | return m; | |||
2232 | ||||
2233 | /* If a comma appears, it is an intrinsic subprogram. */ | |||
2234 | gfc_gobble_whitespace (); | |||
2235 | c = gfc_peek_ascii_char (); | |||
2236 | if (c == ',') | |||
2237 | { | |||
2238 | gfc_free_expr (e); | |||
2239 | return MATCH_NO; | |||
2240 | } | |||
2241 | ||||
2242 | /* If ')' appears, we have REAL(initialization-expr), here check for | |||
2243 | a scalar integer initialization-expr and valid kind parameter. */ | |||
2244 | if (c == ')') | |||
2245 | { | |||
2246 | bool ok = true; | |||
2247 | if (e->expr_type != EXPR_CONSTANT && e->expr_type != EXPR_VARIABLE) | |||
2248 | ok = gfc_reduce_init_expr (e); | |||
2249 | if (!ok || e->ts.type != BT_INTEGER || e->rank > 0) | |||
2250 | { | |||
2251 | gfc_free_expr (e); | |||
2252 | return MATCH_NO; | |||
2253 | } | |||
2254 | ||||
2255 | if (e->expr_type != EXPR_CONSTANT) | |||
2256 | goto ohno; | |||
2257 | ||||
2258 | gfc_next_char (); /* Burn the ')'. */ | |||
2259 | ts->kind = (int) mpz_get_si__gmpz_get_si (e->value.integer); | |||
2260 | if (gfc_validate_kind (ts->type, ts->kind , true) == -1) | |||
2261 | { | |||
2262 | gfc_error ("Invalid type-spec at %C"); | |||
2263 | return MATCH_ERROR; | |||
2264 | } | |||
2265 | ||||
2266 | gfc_free_expr (e); | |||
2267 | ||||
2268 | return MATCH_YES; | |||
2269 | } | |||
2270 | } | |||
2271 | ||||
2272 | ohno: | |||
2273 | ||||
2274 | /* If a type is not matched, simply return MATCH_NO. */ | |||
2275 | gfc_current_locus = old_locus; | |||
2276 | return MATCH_NO; | |||
2277 | ||||
2278 | kind_selector: | |||
2279 | ||||
2280 | gfc_gobble_whitespace (); | |||
2281 | ||||
2282 | /* This prevents INTEGER*4, etc. */ | |||
2283 | if (gfc_peek_ascii_char () == '*') | |||
2284 | { | |||
2285 | gfc_error ("Invalid type-spec at %C"); | |||
2286 | return MATCH_ERROR; | |||
2287 | } | |||
2288 | ||||
2289 | m = gfc_match_kind_spec (ts, false); | |||
2290 | ||||
2291 | /* No kind specifier found. */ | |||
2292 | if (m == MATCH_NO) | |||
2293 | m = MATCH_YES; | |||
2294 | ||||
2295 | return m; | |||
2296 | } | |||
2297 | ||||
2298 | ||||
2299 | /******************** FORALL subroutines ********************/ | |||
2300 | ||||
2301 | /* Free a list of FORALL iterators. */ | |||
2302 | ||||
2303 | void | |||
2304 | gfc_free_forall_iterator (gfc_forall_iterator *iter) | |||
2305 | { | |||
2306 | gfc_forall_iterator *next; | |||
2307 | ||||
2308 | while (iter) | |||
2309 | { | |||
2310 | next = iter->next; | |||
2311 | gfc_free_expr (iter->var); | |||
2312 | gfc_free_expr (iter->start); | |||
2313 | gfc_free_expr (iter->end); | |||
2314 | gfc_free_expr (iter->stride); | |||
2315 | free (iter); | |||
2316 | iter = next; | |||
2317 | } | |||
2318 | } | |||
2319 | ||||
2320 | ||||
2321 | /* Match an iterator as part of a FORALL statement. The format is: | |||
2322 | ||||
2323 | <var> = <start>:<end>[:<stride>] | |||
2324 | ||||
2325 | On MATCH_NO, the caller tests for the possibility that there is a | |||
2326 | scalar mask expression. */ | |||
2327 | ||||
2328 | static match | |||
2329 | match_forall_iterator (gfc_forall_iterator **result) | |||
2330 | { | |||
2331 | gfc_forall_iterator *iter; | |||
2332 | locus where; | |||
2333 | match m; | |||
2334 | ||||
2335 | where = gfc_current_locus; | |||
2336 | iter = XCNEW (gfc_forall_iterator)((gfc_forall_iterator *) xcalloc (1, sizeof (gfc_forall_iterator ))); | |||
2337 | ||||
2338 | m = gfc_match_expr (&iter->var); | |||
2339 | if (m != MATCH_YES) | |||
2340 | goto cleanup; | |||
2341 | ||||
2342 | if (gfc_match_char ('=') != MATCH_YES | |||
2343 | || iter->var->expr_type != EXPR_VARIABLE) | |||
2344 | { | |||
2345 | m = MATCH_NO; | |||
2346 | goto cleanup; | |||
2347 | } | |||
2348 | ||||
2349 | m = gfc_match_expr (&iter->start); | |||
2350 | if (m != MATCH_YES) | |||
2351 | goto cleanup; | |||
2352 | ||||
2353 | if (gfc_match_char (':') != MATCH_YES) | |||
2354 | goto syntax; | |||
2355 | ||||
2356 | m = gfc_match_expr (&iter->end); | |||
2357 | if (m == MATCH_NO) | |||
2358 | goto syntax; | |||
2359 | if (m == MATCH_ERROR) | |||
2360 | goto cleanup; | |||
2361 | ||||
2362 | if (gfc_match_char (':') == MATCH_NO) | |||
2363 | iter->stride = gfc_get_int_expr (gfc_default_integer_kind, NULL__null, 1); | |||
2364 | else | |||
2365 | { | |||
2366 | m = gfc_match_expr (&iter->stride); | |||
2367 | if (m == MATCH_NO) | |||
2368 | goto syntax; | |||
2369 | if (m == MATCH_ERROR) | |||
2370 | goto cleanup; | |||
2371 | } | |||
2372 | ||||
2373 | /* Mark the iteration variable's symbol as used as a FORALL index. */ | |||
2374 | iter->var->symtree->n.sym->forall_index = true; | |||
2375 | ||||
2376 | *result = iter; | |||
2377 | return MATCH_YES; | |||
2378 | ||||
2379 | syntax: | |||
2380 | gfc_error ("Syntax error in FORALL iterator at %C"); | |||
2381 | m = MATCH_ERROR; | |||
2382 | ||||
2383 | cleanup: | |||
2384 | ||||
2385 | gfc_current_locus = where; | |||
2386 | gfc_free_forall_iterator (iter); | |||
2387 | return m; | |||
2388 | } | |||
2389 | ||||
2390 | ||||
2391 | /* Match the header of a FORALL statement. */ | |||
2392 | ||||
2393 | static match | |||
2394 | match_forall_header (gfc_forall_iterator **phead, gfc_expr **mask) | |||
2395 | { | |||
2396 | gfc_forall_iterator *head, *tail, *new_iter; | |||
2397 | gfc_expr *msk; | |||
2398 | match m; | |||
2399 | ||||
2400 | gfc_gobble_whitespace (); | |||
2401 | ||||
2402 | head = tail = NULL__null; | |||
2403 | msk = NULL__null; | |||
2404 | ||||
2405 | if (gfc_match_char ('(') != MATCH_YES) | |||
2406 | return MATCH_NO; | |||
2407 | ||||
2408 | m = match_forall_iterator (&new_iter); | |||
2409 | if (m == MATCH_ERROR) | |||
2410 | goto cleanup; | |||
2411 | if (m == MATCH_NO) | |||
2412 | goto syntax; | |||
2413 | ||||
2414 | head = tail = new_iter; | |||
| ||||
2415 | ||||
2416 | for (;;) | |||
2417 | { | |||
2418 | if (gfc_match_char (',') != MATCH_YES) | |||
2419 | break; | |||
2420 | ||||
2421 | m = match_forall_iterator (&new_iter); | |||
2422 | if (m == MATCH_ERROR) | |||
2423 | goto cleanup; | |||
2424 | ||||
2425 | if (m == MATCH_YES) | |||
2426 | { | |||
2427 | tail->next = new_iter; | |||
2428 | tail = new_iter; | |||
2429 | continue; | |||
2430 | } | |||
2431 | ||||
2432 | /* Have to have a mask expression. */ | |||
2433 | ||||
2434 | m = gfc_match_expr (&msk); | |||
2435 | if (m == MATCH_NO) | |||
2436 | goto syntax; | |||
2437 | if (m == MATCH_ERROR) | |||
2438 | goto cleanup; | |||
2439 | ||||
2440 | break; | |||
2441 | } | |||
2442 | ||||
2443 | if (gfc_match_char (')') == MATCH_NO) | |||
2444 | goto syntax; | |||
2445 | ||||
2446 | *phead = head; | |||
2447 | *mask = msk; | |||
2448 | return MATCH_YES; | |||
2449 | ||||
2450 | syntax: | |||
2451 | gfc_syntax_error (ST_FORALL)gfc_error ("Syntax error in %s statement at %C", gfc_ascii_statement (ST_FORALL));; | |||
2452 | ||||
2453 | cleanup: | |||
2454 | gfc_free_expr (msk); | |||
2455 | gfc_free_forall_iterator (head); | |||
2456 | ||||
2457 | return MATCH_ERROR; | |||
2458 | } | |||
2459 | ||||
2460 | /* Match the rest of a simple FORALL statement that follows an | |||
2461 | IF statement. */ | |||
2462 | ||||
2463 | static match | |||
2464 | match_simple_forall (void) | |||
2465 | { | |||
2466 | gfc_forall_iterator *head; | |||
2467 | gfc_expr *mask; | |||
2468 | gfc_code *c; | |||
2469 | match m; | |||
2470 | ||||
2471 | mask = NULL__null; | |||
2472 | head = NULL__null; | |||
2473 | c = NULL__null; | |||
2474 | ||||
2475 | m = match_forall_header (&head, &mask); | |||
2476 | ||||
2477 | if (m == MATCH_NO) | |||
2478 | goto syntax; | |||
2479 | if (m != MATCH_YES) | |||
2480 | goto cleanup; | |||
2481 | ||||
2482 | m = gfc_match_assignment (); | |||
2483 | ||||
2484 | if (m == MATCH_ERROR) | |||
2485 | goto cleanup; | |||
2486 | if (m == MATCH_NO) | |||
2487 | { | |||
2488 | m = gfc_match_pointer_assignment (); | |||
2489 | if (m == MATCH_ERROR) | |||
2490 | goto cleanup; | |||
2491 | if (m == MATCH_NO) | |||
2492 | goto syntax; | |||
2493 | } | |||
2494 | ||||
2495 | c = XCNEW (gfc_code)((gfc_code *) xcalloc (1, sizeof (gfc_code))); | |||
2496 | *c = new_st; | |||
2497 | c->loc = gfc_current_locus; | |||
2498 | ||||
2499 | if (gfc_match_eos () != MATCH_YES) | |||
2500 | goto syntax; | |||
2501 | ||||
2502 | gfc_clear_new_st (); | |||
2503 | new_st.op = EXEC_FORALL; | |||
2504 | new_st.expr1 = mask; | |||
2505 | new_st.ext.forall_iterator = head; | |||
2506 | new_st.block = gfc_get_code (EXEC_FORALL); | |||
2507 | new_st.block->next = c; | |||
2508 | ||||
2509 | return MATCH_YES; | |||
2510 | ||||
2511 | syntax: | |||
2512 | gfc_syntax_error (ST_FORALL)gfc_error ("Syntax error in %s statement at %C", gfc_ascii_statement (ST_FORALL));; | |||
2513 | ||||
2514 | cleanup: | |||
2515 | gfc_free_forall_iterator (head); | |||
2516 | gfc_free_expr (mask); | |||
2517 | ||||
2518 | return MATCH_ERROR; | |||
2519 | } | |||
2520 | ||||
2521 | ||||
2522 | /* Match a FORALL statement. */ | |||
2523 | ||||
2524 | match | |||
2525 | gfc_match_forall (gfc_statement *st) | |||
2526 | { | |||
2527 | gfc_forall_iterator *head; | |||
2528 | gfc_expr *mask; | |||
2529 | gfc_code *c; | |||
2530 | match m0, m; | |||
2531 | ||||
2532 | head = NULL__null; | |||
2533 | mask = NULL__null; | |||
2534 | c = NULL__null; | |||
2535 | ||||
2536 | m0 = gfc_match_label (); | |||
2537 | if (m0 == MATCH_ERROR) | |||
2538 | return MATCH_ERROR; | |||
2539 | ||||
2540 | m = gfc_match (" forall"); | |||
2541 | if (m != MATCH_YES) | |||
2542 | return m; | |||
2543 | ||||
2544 | m = match_forall_header (&head, &mask); | |||
2545 | if (m == MATCH_ERROR) | |||
2546 | goto cleanup; | |||
2547 | if (m == MATCH_NO) | |||
2548 | goto syntax; | |||
2549 | ||||
2550 | if (gfc_match_eos () == MATCH_YES) | |||
2551 | { | |||
2552 | *st = ST_FORALL_BLOCK; | |||
2553 | new_st.op = EXEC_FORALL; | |||
2554 | new_st.expr1 = mask; | |||
2555 | new_st.ext.forall_iterator = head; | |||
2556 | return MATCH_YES; | |||
2557 | } | |||
2558 | ||||
2559 | m = gfc_match_assignment (); | |||
2560 | if (m == MATCH_ERROR) | |||
2561 | goto cleanup; | |||
2562 | if (m == MATCH_NO) | |||
2563 | { | |||
2564 | m = gfc_match_pointer_assignment (); | |||
2565 | if (m == MATCH_ERROR) | |||
2566 | goto cleanup; | |||
2567 | if (m == MATCH_NO) | |||
2568 | goto syntax; | |||
2569 | } | |||
2570 | ||||
2571 | c = XCNEW (gfc_code)((gfc_code *) xcalloc (1, sizeof (gfc_code))); | |||
2572 | *c = new_st; | |||
2573 | c->loc = gfc_current_locus; | |||
2574 | ||||
2575 | gfc_clear_new_st (); | |||
2576 | new_st.op = EXEC_FORALL; | |||
2577 | new_st.expr1 = mask; | |||
2578 | new_st.ext.forall_iterator = head; | |||
2579 | new_st.block = gfc_get_code (EXEC_FORALL); | |||
2580 | new_st.block->next = c; | |||
2581 | ||||
2582 | *st = ST_FORALL; | |||
2583 | return MATCH_YES; | |||
2584 | ||||
2585 | syntax: | |||
2586 | gfc_syntax_error (ST_FORALL)gfc_error ("Syntax error in %s statement at %C", gfc_ascii_statement (ST_FORALL));; | |||
2587 | ||||
2588 | cleanup: | |||
2589 | gfc_free_forall_iterator (head); | |||
2590 | gfc_free_expr (mask); | |||
2591 | gfc_free_statements (c); | |||
2592 | return MATCH_NO; | |||
2593 | } | |||
2594 | ||||
2595 | ||||
2596 | /* Match a DO statement. */ | |||
2597 | ||||
2598 | match | |||
2599 | gfc_match_do (void) | |||
2600 | { | |||
2601 | gfc_iterator iter, *ip; | |||
2602 | locus old_loc; | |||
2603 | gfc_st_label *label; | |||
2604 | match m; | |||
2605 | ||||
2606 | old_loc = gfc_current_locus; | |||
2607 | ||||
2608 | memset (&iter, '\0', sizeof (gfc_iterator)); | |||
2609 | label = NULL__null; | |||
2610 | ||||
2611 | m = gfc_match_label (); | |||
2612 | if (m == MATCH_ERROR) | |||
| ||||
2613 | return m; | |||
2614 | ||||
2615 | if (gfc_match (" do") != MATCH_YES) | |||
2616 | return MATCH_NO; | |||
2617 | ||||
2618 | m = gfc_match_st_label (&label); | |||
2619 | if (m == MATCH_ERROR) | |||
2620 | goto cleanup; | |||
2621 | ||||
2622 | /* Match an infinite DO, make it like a DO WHILE(.TRUE.). */ | |||
2623 | ||||
2624 | if (gfc_match_eos () == MATCH_YES) | |||
2625 | { | |||
2626 | iter.end = gfc_get_logical_expr (gfc_default_logical_kind, NULL__null, true); | |||
2627 | new_st.op = EXEC_DO_WHILE; | |||
2628 | goto done; | |||
2629 | } | |||
2630 | ||||
2631 | /* Match an optional comma, if no comma is found, a space is obligatory. */ | |||
2632 | if (gfc_match_char (',') != MATCH_YES && gfc_match ("% ") != MATCH_YES) | |||
2633 | return MATCH_NO; | |||
2634 | ||||
2635 | /* Check for balanced parens. */ | |||
2636 | ||||
2637 | if (gfc_match_parens () == MATCH_ERROR) | |||
2638 | return MATCH_ERROR; | |||
2639 | ||||
2640 | if (gfc_match (" concurrent") == MATCH_YES) | |||
2641 | { | |||
2642 | gfc_forall_iterator *head; | |||
2643 | gfc_expr *mask; | |||
2644 | ||||
2645 | if (!gfc_notify_std (GFC_STD_F2008(1<<7), "DO CONCURRENT construct at %C")) | |||
2646 | return MATCH_ERROR; | |||
2647 | ||||
2648 | ||||
2649 | mask = NULL__null; | |||
2650 | head = NULL__null; | |||
2651 | m = match_forall_header (&head, &mask); | |||
2652 | ||||
2653 | if (m == MATCH_NO) | |||
2654 | return m; | |||
2655 | if (m == MATCH_ERROR) | |||
2656 | goto concurr_cleanup; | |||
2657 | ||||
2658 | if (gfc_match_eos () != MATCH_YES) | |||
2659 | goto concurr_cleanup; | |||
2660 | ||||
2661 | if (label != NULL__null | |||
2662 | && !gfc_reference_st_label (label, ST_LABEL_DO_TARGET)) | |||
2663 | goto concurr_cleanup; | |||
2664 | ||||
2665 | new_st.label1 = label; | |||
2666 | new_st.op = EXEC_DO_CONCURRENT; | |||
2667 | new_st.expr1 = mask; | |||
2668 | new_st.ext.forall_iterator = head; | |||
2669 | ||||
2670 | return MATCH_YES; | |||
2671 | ||||
2672 | concurr_cleanup: | |||
2673 | gfc_syntax_error (ST_DO)gfc_error ("Syntax error in %s statement at %C", gfc_ascii_statement (ST_DO));; | |||
2674 | gfc_free_expr (mask); | |||
2675 | gfc_free_forall_iterator (head); | |||
2676 | return MATCH_ERROR; | |||
2677 | } | |||
2678 | ||||
2679 | /* See if we have a DO WHILE. */ | |||
2680 | if (gfc_match (" while ( %e )%t", &iter.end) == MATCH_YES) | |||
2681 | { | |||
2682 | new_st.op = EXEC_DO_WHILE; | |||
2683 | goto done; | |||
2684 | } | |||
2685 | ||||
2686 | /* The abortive DO WHILE may have done something to the symbol | |||
2687 | table, so we start over. */ | |||
2688 | gfc_undo_symbols (); | |||
2689 | gfc_current_locus = old_loc; | |||
2690 | ||||
2691 | gfc_match_label (); /* This won't error. */ | |||
2692 | gfc_match (" do "); /* This will work. */ | |||
2693 | ||||
2694 | gfc_match_st_label (&label); /* Can't error out. */ | |||
2695 | gfc_match_char (','); /* Optional comma. */ | |||
2696 | ||||
2697 | m = gfc_match_iterator (&iter, 0); | |||
2698 | if (m == MATCH_NO) | |||
2699 | return MATCH_NO; | |||
2700 | if (m == MATCH_ERROR) | |||
2701 | goto cleanup; | |||
2702 | ||||
2703 | iter.var->symtree->n.sym->attr.implied_index = 0; | |||
2704 | gfc_check_do_variable (iter.var->symtree); | |||
2705 | ||||
2706 | if (gfc_match_eos () != MATCH_YES) | |||
2707 | { | |||
2708 | gfc_syntax_error (ST_DO)gfc_error ("Syntax error in %s statement at %C", gfc_ascii_statement (ST_DO));; | |||
2709 | goto cleanup; | |||
2710 | } | |||
2711 | ||||
2712 | new_st.op = EXEC_DO; | |||
2713 | ||||
2714 | done: | |||
2715 | if (label != NULL__null | |||
2716 | && !gfc_reference_st_label (label, ST_LABEL_DO_TARGET)) | |||
2717 | goto cleanup; | |||
2718 | ||||
2719 | new_st.label1 = label; | |||
2720 | ||||
2721 | if (new_st.op == EXEC_DO_WHILE) | |||
2722 | new_st.expr1 = iter.end; | |||
2723 | else | |||
2724 | { | |||
2725 | new_st.ext.iterator = ip = gfc_get_iterator ()((gfc_iterator *) xcalloc (1, sizeof (gfc_iterator))); | |||
2726 | *ip = iter; | |||
2727 | } | |||
2728 | ||||
2729 | return MATCH_YES; | |||
2730 | ||||
2731 | cleanup: | |||
2732 | gfc_free_iterator (&iter, 0); | |||
2733 | ||||
2734 | return MATCH_ERROR; | |||
2735 | } | |||
2736 | ||||
2737 | ||||
2738 | /* Match an EXIT or CYCLE statement. */ | |||
2739 | ||||
2740 | static match | |||
2741 | match_exit_cycle (gfc_statement st, gfc_exec_op op) | |||
2742 | { | |||
2743 | gfc_state_data *p, *o; | |||
2744 | gfc_symbol *sym; | |||
2745 | match m; | |||
2746 | int cnt; | |||
2747 | ||||
2748 | if (gfc_match_eos () == MATCH_YES) | |||
2749 | sym = NULL__null; | |||
2750 | else | |||
2751 | { | |||
2752 | char name[GFC_MAX_SYMBOL_LEN63 + 1]; | |||
2753 | gfc_symtree* stree; | |||
2754 | ||||
2755 | m = gfc_match ("% %n%t", name); | |||
2756 | if (m == MATCH_ERROR) | |||
2757 | return MATCH_ERROR; | |||
2758 | if (m == MATCH_NO) | |||
2759 | { | |||
2760 | gfc_syntax_error (st)gfc_error ("Syntax error in %s statement at %C", gfc_ascii_statement (st));; | |||
2761 | return MATCH_ERROR; | |||
2762 | } | |||
2763 | ||||
2764 | /* Find the corresponding symbol. If there's a BLOCK statement | |||
2765 | between here and the label, it is not in gfc_current_ns but a parent | |||
2766 | namespace! */ | |||
2767 | stree = gfc_find_symtree_in_proc (name, gfc_current_ns); | |||
2768 | if (!stree) | |||
2769 | { | |||
2770 | gfc_error ("Name %qs in %s statement at %C is unknown", | |||
2771 | name, gfc_ascii_statement (st)); | |||
2772 | return MATCH_ERROR; | |||
2773 | } | |||
2774 | ||||
2775 | sym = stree->n.sym; | |||
2776 | if (sym->attr.flavor != FL_LABEL) | |||
2777 | { | |||
2778 | gfc_error ("Name %qs in %s statement at %C is not a construct name", | |||
2779 | name, gfc_ascii_statement (st)); | |||
2780 | return MATCH_ERROR; | |||
2781 | } | |||
2782 | } | |||
2783 | ||||
2784 | /* Find the loop specified by the label (or lack of a label). */ | |||
2785 | for (o = NULL__null, p = gfc_state_stack; p; p = p->previous) | |||
2786 | if (o == NULL__null && p->state == COMP_OMP_STRUCTURED_BLOCK) | |||
2787 | o = p; | |||
2788 | else if (p->state == COMP_CRITICAL) | |||
2789 | { | |||
2790 | gfc_error("%s statement at %C leaves CRITICAL construct", | |||
2791 | gfc_ascii_statement (st)); | |||
2792 | return MATCH_ERROR; | |||
2793 | } | |||
2794 | else if (p->state == COMP_DO_CONCURRENT | |||
2795 | && (op == EXEC_EXIT || (sym && sym != p->sym))) | |||
2796 | { | |||
2797 | /* F2008, C821 & C845. */ | |||
2798 | gfc_error("%s statement at %C leaves DO CONCURRENT construct", | |||
2799 | gfc_ascii_statement (st)); | |||
2800 | return MATCH_ERROR; | |||
2801 | } | |||
2802 | else if ((sym && sym == p->sym) | |||
2803 | || (!sym && (p->state == COMP_DO | |||
2804 | || p->state == COMP_DO_CONCURRENT))) | |||
2805 | break; | |||
2806 | ||||
2807 | if (p == NULL__null) | |||
2808 | { | |||
2809 | if (sym == NULL__null) | |||
2810 | gfc_error ("%s statement at %C is not within a construct", | |||
2811 | gfc_ascii_statement (st)); | |||
2812 | else | |||
2813 | gfc_error ("%s statement at %C is not within construct %qs", | |||
2814 | gfc_ascii_statement (st), sym->name); | |||
2815 | ||||
2816 | return MATCH_ERROR; | |||
2817 | } | |||
2818 | ||||
2819 | /* Special checks for EXIT from non-loop constructs. */ | |||
2820 | switch (p->state) | |||
2821 | { | |||
2822 | case COMP_DO: | |||
2823 | case COMP_DO_CONCURRENT: | |||
2824 | break; | |||
2825 | ||||
2826 | case COMP_CRITICAL: | |||
2827 | /* This is already handled above. */ | |||
2828 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/match.cc" , 2828, __FUNCTION__)); | |||
2829 | ||||
2830 | case COMP_ASSOCIATE: | |||
2831 | case COMP_BLOCK: | |||
2832 | case COMP_IF: | |||
2833 | case COMP_SELECT: | |||
2834 | case COMP_SELECT_TYPE: | |||
2835 | case COMP_SELECT_RANK: | |||
2836 | gcc_assert (sym)((void)(!(sym) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/match.cc" , 2836, __FUNCTION__), 0 : 0)); | |||
2837 | if (op == EXEC_CYCLE) | |||
2838 | { | |||
2839 | gfc_error ("CYCLE statement at %C is not applicable to non-loop" | |||
2840 | " construct %qs", sym->name); | |||
2841 | return MATCH_ERROR; | |||
2842 | } | |||
2843 | gcc_assert (op == EXEC_EXIT)((void)(!(op == EXEC_EXIT) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/match.cc" , 2843, __FUNCTION__), 0 : 0)); | |||
2844 | if (!gfc_notify_std (GFC_STD_F2008(1<<7), "EXIT statement with no" | |||
2845 | " do-construct-name at %C")) | |||
2846 | return MATCH_ERROR; | |||
2847 | break; | |||
2848 | ||||
2849 | default: | |||
2850 | gfc_error ("%s statement at %C is not applicable to construct %qs", | |||
2851 | gfc_ascii_statement (st), sym->name); | |||
2852 | return MATCH_ERROR; | |||
2853 | } | |||
2854 | ||||
2855 | if (o != NULL__null) | |||
2856 | { | |||
2857 | gfc_error (is_oacc (p) | |||
2858 | ? G_("%s statement at %C leaving OpenACC structured block")"%s statement at %C leaving OpenACC structured block" | |||
2859 | : G_("%s statement at %C leaving OpenMP structured block")"%s statement at %C leaving OpenMP structured block", | |||
2860 | gfc_ascii_statement (st)); | |||
2861 | return MATCH_ERROR; | |||
2862 | } | |||
2863 | ||||
2864 | for (o = p, cnt = 0; o->state == COMP_DO && o->previous != NULL__null; cnt++) | |||
2865 | o = o->previous; | |||
2866 | ||||
2867 | int count = 1; | |||
2868 | if (cnt > 0 | |||
2869 | && o != NULL__null | |||
2870 | && o->state == COMP_OMP_STRUCTURED_BLOCK) | |||
2871 | switch (o->head->op) | |||
2872 | { | |||
2873 | case EXEC_OACC_LOOP: | |||
2874 | case EXEC_OACC_KERNELS_LOOP: | |||
2875 | case EXEC_OACC_PARALLEL_LOOP: | |||
2876 | case EXEC_OACC_SERIAL_LOOP: | |||
2877 | gcc_assert (o->head->next != NULL((void)(!(o->head->next != __null && (o->head ->next->op == EXEC_DO || o->head->next->op == EXEC_DO_WHILE ) && o->previous != __null && o->previous ->tail->op == o->head->op) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/match.cc" , 2881, __FUNCTION__), 0 : 0)) | |||
2878 | && (o->head->next->op == EXEC_DO((void)(!(o->head->next != __null && (o->head ->next->op == EXEC_DO || o->head->next->op == EXEC_DO_WHILE ) && o->previous != __null && o->previous ->tail->op == o->head->op) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/match.cc" , 2881, __FUNCTION__), 0 : 0)) | |||
2879 | || o->head->next->op == EXEC_DO_WHILE)((void)(!(o->head->next != __null && (o->head ->next->op == EXEC_DO || o->head->next->op == EXEC_DO_WHILE ) && o->previous != __null && o->previous ->tail->op == o->head->op) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/match.cc" , 2881, __FUNCTION__), 0 : 0)) | |||
2880 | && o->previous != NULL((void)(!(o->head->next != __null && (o->head ->next->op == EXEC_DO || o->head->next->op == EXEC_DO_WHILE ) && o->previous != __null && o->previous ->tail->op == o->head->op) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/match.cc" , 2881, __FUNCTION__), 0 : 0)) | |||
2881 | && o->previous->tail->op == o->head->op)((void)(!(o->head->next != __null && (o->head ->next->op == EXEC_DO || o->head->next->op == EXEC_DO_WHILE ) && o->previous != __null && o->previous ->tail->op == o->head->op) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/match.cc" , 2881, __FUNCTION__), 0 : 0)); | |||
2882 | if (o->previous->tail->ext.omp_clauses != NULL__null) | |||
2883 | { | |||
2884 | /* Both collapsed and tiled loops are lowered the same way, but are | |||
2885 | not compatible. In gfc_trans_omp_do, the tile is prioritized. */ | |||
2886 | if (o->previous->tail->ext.omp_clauses->tile_list) | |||
2887 | { | |||
2888 | count = 0; | |||
2889 | gfc_expr_list *el | |||
2890 | = o->previous->tail->ext.omp_clauses->tile_list; | |||
2891 | for ( ; el; el = el->next) | |||
2892 | ++count; | |||
2893 | } | |||
2894 | else if (o->previous->tail->ext.omp_clauses->collapse > 1) | |||
2895 | count = o->previous->tail->ext.omp_clauses->collapse; | |||
2896 | } | |||
2897 | if (st == ST_EXIT && cnt <= count) | |||
2898 | { | |||
2899 | gfc_error ("EXIT statement at %C terminating !$ACC LOOP loop"); | |||
2900 | return MATCH_ERROR; | |||
2901 | } | |||
2902 | if (st == ST_CYCLE && cnt < count) | |||
2903 | { | |||
2904 | gfc_error (o->previous->tail->ext.omp_clauses->tile_list | |||
2905 | ? G_("CYCLE statement at %C to non-innermost tiled ""CYCLE statement at %C to non-innermost tiled " "!$ACC LOOP loop" | |||
2906 | "!$ACC LOOP loop")"CYCLE statement at %C to non-innermost tiled " "!$ACC LOOP loop" | |||
2907 | : G_("CYCLE statement at %C to non-innermost collapsed ""CYCLE statement at %C to non-innermost collapsed " "!$ACC LOOP loop" | |||
2908 | "!$ACC LOOP loop")"CYCLE statement at %C to non-innermost collapsed " "!$ACC LOOP loop"); | |||
2909 | return MATCH_ERROR; | |||
2910 | } | |||
2911 | break; | |||
2912 | case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD: | |||
2913 | case EXEC_OMP_TARGET_PARALLEL_DO_SIMD: | |||
2914 | case EXEC_OMP_TARGET_SIMD: | |||
2915 | case EXEC_OMP_TASKLOOP_SIMD: | |||
2916 | case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD: | |||
2917 | case EXEC_OMP_MASTER_TASKLOOP_SIMD: | |||
2918 | case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD: | |||
2919 | case EXEC_OMP_MASKED_TASKLOOP_SIMD: | |||
2920 | case EXEC_OMP_PARALLEL_DO_SIMD: | |||
2921 | case EXEC_OMP_DISTRIBUTE_SIMD: | |||
2922 | case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD: | |||
2923 | case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD: | |||
2924 | case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD: | |||
2925 | case EXEC_OMP_LOOP: | |||
2926 | case EXEC_OMP_PARALLEL_LOOP: | |||
2927 | case EXEC_OMP_TEAMS_LOOP: | |||
2928 | case EXEC_OMP_TARGET_PARALLEL_LOOP: | |||
2929 | case EXEC_OMP_TARGET_TEAMS_LOOP: | |||
2930 | case EXEC_OMP_DO: | |||
2931 | case EXEC_OMP_PARALLEL_DO: | |||
2932 | case EXEC_OMP_SIMD: | |||
2933 | case EXEC_OMP_DO_SIMD: | |||
2934 | case EXEC_OMP_DISTRIBUTE_PARALLEL_DO: | |||
2935 | case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO: | |||
2936 | case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO: | |||
2937 | case EXEC_OMP_TARGET_PARALLEL_DO: | |||
2938 | case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD: | |||
2939 | ||||
2940 | gcc_assert (o->head->next != NULL((void)(!(o->head->next != __null && (o->head ->next->op == EXEC_DO || o->head->next->op == EXEC_DO_WHILE ) && o->previous != __null && o->previous ->tail->op == o->head->op) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/match.cc" , 2944, __FUNCTION__), 0 : 0)) | |||
2941 | && (o->head->next->op == EXEC_DO((void)(!(o->head->next != __null && (o->head ->next->op == EXEC_DO || o->head->next->op == EXEC_DO_WHILE ) && o->previous != __null && o->previous ->tail->op == o->head->op) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/match.cc" , 2944, __FUNCTION__), 0 : 0)) | |||
2942 | || o->head->next->op == EXEC_DO_WHILE)((void)(!(o->head->next != __null && (o->head ->next->op == EXEC_DO || o->head->next->op == EXEC_DO_WHILE ) && o->previous != __null && o->previous ->tail->op == o->head->op) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/match.cc" , 2944, __FUNCTION__), 0 : 0)) | |||
2943 | && o->previous != NULL((void)(!(o->head->next != __null && (o->head ->next->op == EXEC_DO || o->head->next->op == EXEC_DO_WHILE ) && o->previous != __null && o->previous ->tail->op == o->head->op) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/match.cc" , 2944, __FUNCTION__), 0 : 0)) | |||
2944 | && o->previous->tail->op == o->head->op)((void)(!(o->head->next != __null && (o->head ->next->op == EXEC_DO || o->head->next->op == EXEC_DO_WHILE ) && o->previous != __null && o->previous ->tail->op == o->head->op) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/match.cc" , 2944, __FUNCTION__), 0 : 0)); | |||
2945 | if (o->previous->tail->ext.omp_clauses != NULL__null) | |||
2946 | { | |||
2947 | if (o->previous->tail->ext.omp_clauses->collapse > 1) | |||
2948 | count = o->previous->tail->ext.omp_clauses->collapse; | |||
2949 | if (o->previous->tail->ext.omp_clauses->orderedc) | |||
2950 | count = o->previous->tail->ext.omp_clauses->orderedc; | |||
2951 | } | |||
2952 | if (st == ST_EXIT && cnt <= count) | |||
2953 | { | |||
2954 | gfc_error ("EXIT statement at %C terminating !$OMP DO loop"); | |||
2955 | return MATCH_ERROR; | |||
2956 | } | |||
2957 | if (st == ST_CYCLE && cnt < count) | |||
2958 | { | |||
2959 | gfc_error ("CYCLE statement at %C to non-innermost collapsed " | |||
2960 | "!$OMP DO loop"); | |||
2961 | return MATCH_ERROR; | |||
2962 | } | |||
2963 | break; | |||
2964 | default: | |||
2965 | break; | |||
2966 | } | |||
2967 | ||||
2968 | /* Save the first statement in the construct - needed by the backend. */ | |||
2969 | new_st.ext.which_construct = p->construct; | |||
2970 | ||||
2971 | new_st.op = op; | |||
2972 | ||||
2973 | return MATCH_YES; | |||
2974 | } | |||
2975 | ||||
2976 | ||||
2977 | /* Match the EXIT statement. */ | |||
2978 | ||||
2979 | match | |||
2980 | gfc_match_exit (void) | |||
2981 | { | |||
2982 | return match_exit_cycle (ST_EXIT, EXEC_EXIT); | |||
2983 | } | |||
2984 | ||||
2985 | ||||
2986 | /* Match the CYCLE statement. */ | |||
2987 | ||||
2988 | match | |||
2989 | gfc_match_cycle (void) | |||
2990 | { | |||
2991 | return match_exit_cycle (ST_CYCLE, EXEC_CYCLE); | |||
2992 | } | |||
2993 | ||||
2994 | ||||
2995 | /* Match a stop-code after an (ERROR) STOP or PAUSE statement. The | |||
2996 | requirements for a stop-code differ in the standards. | |||
2997 | ||||
2998 | Fortran 95 has | |||
2999 | ||||
3000 | R840 stop-stmt is STOP [ stop-code ] | |||
3001 | R841 stop-code is scalar-char-constant | |||
3002 | or digit [ digit [ digit [ digit [ digit ] ] ] ] | |||
3003 | ||||
3004 | Fortran 2003 matches Fortran 95 except R840 and R841 are now R849 and R850. | |||
3005 | Fortran 2008 has | |||
3006 | ||||
3007 | R855 stop-stmt is STOP [ stop-code ] | |||
3008 | R856 allstop-stmt is ALL STOP [ stop-code ] | |||
3009 | R857 stop-code is scalar-default-char-constant-expr | |||
3010 | or scalar-int-constant-expr | |||
3011 | Fortran 2018 has | |||
3012 | ||||
3013 | R1160 stop-stmt is STOP [ stop-code ] [ , QUIET = scalar-logical-expr] | |||
3014 | R1161 error-stop-stmt is | |||
3015 | ERROR STOP [ stop-code ] [ , QUIET = scalar-logical-expr] | |||
3016 | R1162 stop-code is scalar-default-char-expr | |||
3017 | or scalar-int-expr | |||
3018 | ||||
3019 | For free-form source code, all standards contain a statement of the form: | |||
3020 | ||||
3021 | A blank shall be used to separate names, constants, or labels from | |||
3022 | adjacent keywords, names, constants, or labels. | |||
3023 | ||||
3024 | A stop-code is not a name, constant, or label. So, under Fortran 95 and 2003, | |||
3025 | ||||
3026 | STOP123 | |||
3027 | ||||
3028 | is valid, but it is invalid Fortran 2008. */ | |||
3029 | ||||
3030 | static match | |||
3031 | gfc_match_stopcode (gfc_statement st) | |||
3032 | { | |||
3033 | gfc_expr *e = NULL__null; | |||
3034 | gfc_expr *quiet = NULL__null; | |||
3035 | match m; | |||
3036 | bool f95, f03, f08; | |||
3037 | char c; | |||
3038 | ||||
3039 | /* Set f95 for -std=f95. */ | |||
3040 | f95 = (gfc_option.allow_std == GFC_STD_OPT_F95((1<<0) | (1<<3) | (1<<1) | (1<<8) | ( 1<<10) | (1<<11))); | |||
3041 | ||||
3042 | /* Set f03 for -std=f2003. */ | |||
3043 | f03 = (gfc_option.allow_std == GFC_STD_OPT_F03(((1<<0) | (1<<3) | (1<<1) | (1<<8) | (1<<10) | (1<<11)) | (1<<4))); | |||
3044 | ||||
3045 | /* Set f08 for -std=f2008. */ | |||
3046 | f08 = (gfc_option.allow_std == GFC_STD_OPT_F08((((1<<0) | (1<<3) | (1<<1) | (1<<8) | (1<<10) | (1<<11)) | (1<<4)) | (1<<7 ))); | |||
3047 | ||||
3048 | /* Plain STOP statement? */ | |||
3049 | if (gfc_match_eos () == MATCH_YES) | |||
3050 | goto checks; | |||
3051 | ||||
3052 | /* Look for a blank between STOP and the stop-code for F2008 or later. | |||
3053 | But allow for F2018's ,QUIET= specifier. */ | |||
3054 | c = gfc_peek_ascii_char (); | |||
3055 | ||||
3056 | if (gfc_current_form != FORM_FIXED && !(f95 || f03) && c != ',') | |||
3057 | { | |||
3058 | /* Look for end-of-statement. There is no stop-code. */ | |||
3059 | if (c == '\n' || c == '!' || c == ';') | |||
3060 | goto done; | |||
3061 | ||||
3062 | if (c != ' ') | |||
3063 | { | |||
3064 | gfc_error ("Blank required in %s statement near %C", | |||
3065 | gfc_ascii_statement (st)); | |||
3066 | return MATCH_ERROR; | |||
3067 | } | |||
3068 | } | |||
3069 | ||||
3070 | if (c == ' ') | |||
3071 | { | |||
3072 | gfc_gobble_whitespace (); | |||
3073 | c = gfc_peek_ascii_char (); | |||
3074 | } | |||
3075 | if (c != ',') | |||
3076 | { | |||
3077 | int stopcode; | |||
3078 | locus old_locus; | |||
3079 | ||||
3080 | /* First look for the F95 or F2003 digit [...] construct. */ | |||
3081 | old_locus = gfc_current_locus; | |||
3082 | m = gfc_match_small_int (&stopcode); | |||
3083 | if (m == MATCH_YES && (f95 || f03)) | |||
3084 | { | |||
3085 | if (stopcode < 0) | |||
3086 | { | |||
3087 | gfc_error ("STOP code at %C cannot be negative"); | |||
3088 | return MATCH_ERROR; | |||
3089 | } | |||
3090 | ||||
3091 | if (stopcode > 99999) | |||
3092 | { | |||
3093 | gfc_error ("STOP code at %C contains too many digits"); | |||
3094 | return MATCH_ERROR; | |||
3095 | } | |||
3096 | } | |||
3097 | ||||
3098 | /* Reset the locus and now load gfc_expr. */ | |||
3099 | gfc_current_locus = old_locus; | |||
3100 | m = gfc_match_expr (&e); | |||
3101 | if (m == MATCH_ERROR) | |||
3102 | goto cleanup; | |||
3103 | if (m == MATCH_NO) | |||
3104 | goto syntax; | |||
3105 | } | |||
3106 | ||||
3107 | if (gfc_match (" , quiet = %e", &quiet) == MATCH_YES) | |||
3108 | { | |||
3109 | if (!gfc_notify_std (GFC_STD_F2018(1<<9), "QUIET= specifier for %s at %L", | |||
3110 | gfc_ascii_statement (st), &quiet->where)) | |||
3111 | goto cleanup; | |||
3112 | } | |||
3113 | ||||
3114 | if (gfc_match_eos () != MATCH_YES) | |||
3115 | goto syntax; | |||
3116 | ||||
3117 | checks: | |||
3118 | ||||
3119 | if (gfc_pure (NULL__null)) | |||
3120 | { | |||
3121 | if (st == ST_ERROR_STOP) | |||
3122 | { | |||
3123 | if (!gfc_notify_std (GFC_STD_F2018(1<<9), "%s statement at %C in PURE " | |||
3124 | "procedure", gfc_ascii_statement (st))) | |||
3125 | goto cleanup; | |||
3126 | } | |||
3127 | else | |||
3128 | { | |||
3129 | gfc_error ("%s statement not allowed in PURE procedure at %C", | |||
3130 | gfc_ascii_statement (st)); | |||
3131 | goto cleanup; | |||
3132 | } | |||
3133 | } | |||
3134 | ||||
3135 | gfc_unset_implicit_pure (NULL__null); | |||
3136 | ||||
3137 | if (st == ST_STOP && gfc_find_state (COMP_CRITICAL)) | |||
3138 | { | |||
3139 | gfc_error ("Image control statement STOP at %C in CRITICAL block"); | |||
3140 | goto cleanup; | |||
3141 | } | |||
3142 | if (st == ST_STOP && gfc_find_state (COMP_DO_CONCURRENT)) | |||
3143 | { | |||
3144 | gfc_error ("Image control statement STOP at %C in DO CONCURRENT block"); | |||
3145 | goto cleanup; | |||
3146 | } | |||
3147 | ||||
3148 | if (e != NULL__null) | |||
3149 | { | |||
3150 | if (!gfc_simplify_expr (e, 0)) | |||
3151 | goto cleanup; | |||
3152 | ||||
3153 | /* Test for F95 and F2003 style STOP stop-code. */ | |||
3154 | if (e->expr_type != EXPR_CONSTANT && (f95 || f03)) | |||
3155 | { | |||
3156 | gfc_error ("STOP code at %L must be a scalar CHARACTER constant " | |||
3157 | "or digit[digit[digit[digit[digit]]]]", &e->where); | |||
3158 | goto cleanup; | |||
3159 | } | |||
3160 | ||||
3161 | /* Use the machinery for an initialization expression to reduce the | |||
3162 | stop-code to a constant. */ | |||
3163 | gfc_reduce_init_expr (e); | |||
3164 | ||||
3165 | /* Test for F2008 style STOP stop-code. */ | |||
3166 | if (e->expr_type != EXPR_CONSTANT && f08) | |||
3167 | { | |||
3168 | gfc_error ("STOP code at %L must be a scalar default CHARACTER or " | |||
3169 | "INTEGER constant expression", &e->where); | |||
3170 | goto cleanup; | |||
3171 | } | |||
3172 | ||||
3173 | if (!(e->ts.type == BT_CHARACTER || e->ts.type == BT_INTEGER)) | |||
3174 | { | |||
3175 | gfc_error ("STOP code at %L must be either INTEGER or CHARACTER type", | |||
3176 | &e->where); | |||
3177 | goto cleanup; | |||
3178 | } | |||
3179 | ||||
3180 | if (e->rank != 0) | |||
3181 | { | |||
3182 | gfc_error ("STOP code at %L must be scalar", &e->where); | |||
3183 | goto cleanup; | |||
3184 | } | |||
3185 | ||||
3186 | if (e->ts.type == BT_CHARACTER | |||
3187 | && e->ts.kind != gfc_default_character_kind) | |||
3188 | { | |||
3189 | gfc_error ("STOP code at %L must be default character KIND=%d", | |||
3190 | &e->where, (int) gfc_default_character_kind); | |||
3191 | goto cleanup; | |||
3192 | } | |||
3193 | ||||
3194 | if (e->ts.type == BT_INTEGER && e->ts.kind != gfc_default_integer_kind | |||
3195 | && !gfc_notify_std (GFC_STD_F2018(1<<9), | |||
3196 | "STOP code at %L must be default integer KIND=%d", | |||
3197 | &e->where, (int) gfc_default_integer_kind)) | |||
3198 | goto cleanup; | |||
3199 | } | |||
3200 | ||||
3201 | if (quiet != NULL__null) | |||
3202 | { | |||
3203 | if (!gfc_simplify_expr (quiet, 0)) | |||
3204 | goto cleanup; | |||
3205 | ||||
3206 | if (quiet->rank != 0) | |||
3207 | { | |||
3208 | gfc_error ("QUIET specifier at %L must be a scalar LOGICAL", | |||
3209 | &quiet->where); | |||
3210 | goto cleanup; | |||
3211 | } | |||
3212 | } | |||
3213 | ||||
3214 | done: | |||
3215 | ||||
3216 | switch (st) | |||
3217 | { | |||
3218 | case ST_STOP: | |||
3219 | new_st.op = EXEC_STOP; | |||
3220 | break; | |||
3221 | case ST_ERROR_STOP: | |||
3222 | new_st.op = EXEC_ERROR_STOP; | |||
3223 | break; | |||
3224 | case ST_PAUSE: | |||
3225 | new_st.op = EXEC_PAUSE; | |||
3226 | break; | |||
3227 | default: | |||
3228 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/match.cc" , 3228, __FUNCTION__)); | |||
3229 | } | |||
3230 | ||||
3231 | new_st.expr1 = e; | |||
3232 | new_st.expr2 = quiet; | |||
3233 | new_st.ext.stop_code = -1; | |||
3234 | ||||
3235 | return MATCH_YES; | |||
3236 | ||||
3237 | syntax: | |||
3238 | gfc_syntax_error (st)gfc_error ("Syntax error in %s statement at %C", gfc_ascii_statement (st));; | |||
3239 | ||||
3240 | cleanup: | |||
3241 | ||||
3242 | gfc_free_expr (e); | |||
3243 | gfc_free_expr (quiet); | |||
3244 | return MATCH_ERROR; | |||
3245 | } | |||
3246 | ||||
3247 | ||||
3248 | /* Match the (deprecated) PAUSE statement. */ | |||
3249 | ||||
3250 | match | |||
3251 | gfc_match_pause (void) | |||
3252 | { | |||
3253 | match m; | |||
3254 | ||||
3255 | m = gfc_match_stopcode (ST_PAUSE); | |||
3256 | if (m == MATCH_YES) | |||
3257 | { | |||
3258 | if (!gfc_notify_std (GFC_STD_F95_DEL(1<<2), "PAUSE statement at %C")) | |||
3259 | m = MATCH_ERROR; | |||
3260 | } | |||
3261 | return m; | |||
3262 | } | |||
3263 | ||||
3264 | ||||
3265 | /* Match the STOP statement. */ | |||
3266 | ||||
3267 | match | |||
3268 | gfc_match_stop (void) | |||
3269 | { | |||
3270 | return gfc_match_stopcode (ST_STOP); | |||
3271 | } | |||
3272 | ||||
3273 | ||||
3274 | /* Match the ERROR STOP statement. */ | |||
3275 | ||||
3276 | match | |||
3277 | gfc_match_error_stop (void) | |||
3278 | { | |||
3279 | if (!gfc_notify_std (GFC_STD_F2008(1<<7), "ERROR STOP statement at %C")) | |||
3280 | return MATCH_ERROR; | |||
3281 | ||||
3282 | return gfc_match_stopcode (ST_ERROR_STOP); | |||
3283 | } | |||
3284 | ||||
3285 | /* Match EVENT POST/WAIT statement. Syntax: | |||
3286 | EVENT POST ( event-variable [, sync-stat-list] ) | |||
3287 | EVENT WAIT ( event-variable [, wait-spec-list] ) | |||
3288 | with | |||
3289 | wait-spec-list is sync-stat-list or until-spec | |||
3290 | until-spec is UNTIL_COUNT = scalar-int-expr | |||
3291 | sync-stat is STAT= or ERRMSG=. */ | |||
3292 | ||||
3293 | static match | |||
3294 | event_statement (gfc_statement st) | |||
3295 | { | |||
3296 | match m; | |||
3297 | gfc_expr *tmp, *eventvar, *until_count, *stat, *errmsg; | |||
3298 | bool saw_until_count, saw_stat, saw_errmsg; | |||
3299 | ||||
3300 | tmp = eventvar = until_count = stat = errmsg = NULL__null; | |||
3301 | saw_until_count = saw_stat = saw_errmsg = false; | |||
3302 | ||||
3303 | if (gfc_pure (NULL__null)) | |||
3304 | { | |||
3305 | gfc_error ("Image control statement EVENT %s at %C in PURE procedure", | |||
3306 | st == ST_EVENT_POST ? "POST" : "WAIT"); | |||
3307 | return MATCH_ERROR; | |||
3308 | } | |||
3309 | ||||
3310 | gfc_unset_implicit_pure (NULL__null); | |||
3311 | ||||
3312 | if (flag_coarrayglobal_options.x_flag_coarray == GFC_FCOARRAY_NONE) | |||
3313 | { | |||
3314 | gfc_fatal_error ("Coarrays disabled at %C, use %<-fcoarray=%> to enable"); | |||
3315 | return MATCH_ERROR; | |||
3316 | } | |||
3317 | ||||
3318 | if (gfc_find_state (COMP_CRITICAL)) | |||
3319 | { | |||
3320 | gfc_error ("Image control statement EVENT %s at %C in CRITICAL block", | |||
3321 | st == ST_EVENT_POST ? "POST" : "WAIT"); | |||
3322 | return MATCH_ERROR; | |||
3323 | } | |||
3324 | ||||
3325 | if (gfc_find_state (COMP_DO_CONCURRENT)) | |||
3326 | { | |||
3327 | gfc_error ("Image control statement EVENT %s at %C in DO CONCURRENT " | |||
3328 | "block", st == ST_EVENT_POST ? "POST" : "WAIT"); | |||
3329 | return MATCH_ERROR; | |||
3330 | } | |||
3331 | ||||
3332 | if (gfc_match_char ('(') != MATCH_YES) | |||
3333 | goto syntax; | |||
3334 | ||||
3335 | if (gfc_match ("%e", &eventvar) != MATCH_YES) | |||
3336 | goto syntax; | |||
3337 | m = gfc_match_char (','); | |||
3338 | if (m == MATCH_ERROR) | |||
3339 | goto syntax; | |||
3340 | if (m == MATCH_NO) | |||
3341 | { | |||
3342 | m = gfc_match_char (')'); | |||
3343 | if (m == MATCH_YES) | |||
3344 | goto done; | |||
3345 | goto syntax; | |||
3346 | } | |||
3347 | ||||
3348 | for (;;) | |||
3349 | { | |||
3350 | m = gfc_match (" stat = %v", &tmp); | |||
3351 | if (m == MATCH_ERROR) | |||
3352 | goto syntax; | |||
3353 | if (m == MATCH_YES) | |||
3354 | { | |||
3355 | if (saw_stat) | |||
3356 | { | |||
3357 | gfc_error ("Redundant STAT tag found at %L", &tmp->where); | |||
3358 | goto cleanup; | |||
3359 | } | |||
3360 | stat = tmp; | |||
3361 | saw_stat = true; | |||
3362 | ||||
3363 | m = gfc_match_char (','); | |||
3364 | if (m == MATCH_YES) | |||
3365 | continue; | |||
3366 | ||||
3367 | tmp = NULL__null; | |||
3368 | break; | |||
3369 | } | |||
3370 | ||||
3371 | m = gfc_match (" errmsg = %v", &tmp); | |||
3372 | if (m == MATCH_ERROR) | |||
3373 | goto syntax; | |||
3374 | if (m == MATCH_YES) | |||
3375 | { | |||
3376 | if (saw_errmsg) | |||
3377 | { | |||
3378 | gfc_error ("Redundant ERRMSG tag found at %L", &tmp->where); | |||
3379 | goto cleanup; | |||
3380 | } | |||
3381 | errmsg = tmp; | |||
3382 | saw_errmsg = true; | |||
3383 | ||||
3384 | m = gfc_match_char (','); | |||
3385 | if (m == MATCH_YES) | |||
3386 | continue; | |||
3387 | ||||
3388 | tmp = NULL__null; | |||
3389 | break; | |||
3390 | } | |||
3391 | ||||
3392 | m = gfc_match (" until_count = %e", &tmp); | |||
3393 | if (m == MATCH_ERROR || st == ST_EVENT_POST) | |||
3394 | goto syntax; | |||
3395 | if (m == MATCH_YES) | |||
3396 | { | |||
3397 | if (saw_until_count) | |||
3398 | { | |||
3399 | gfc_error ("Redundant UNTIL_COUNT tag found at %L", | |||
3400 | &tmp->where); | |||
3401 | goto cleanup; | |||
3402 | } | |||
3403 | until_count = tmp; | |||
3404 | saw_until_count = true; | |||
3405 | ||||
3406 | m = gfc_match_char (','); | |||
3407 | if (m == MATCH_YES) | |||
3408 | continue; | |||
3409 | ||||
3410 | tmp = NULL__null; | |||
3411 | break; | |||
3412 | } | |||
3413 | ||||
3414 | break; | |||
3415 | } | |||
3416 | ||||
3417 | if (m == MATCH_ERROR) | |||
3418 | goto syntax; | |||
3419 | ||||
3420 | if (gfc_match (" )%t") != MATCH_YES) | |||
3421 | goto syntax; | |||
3422 | ||||
3423 | done: | |||
3424 | switch (st) | |||
3425 | { | |||
3426 | case ST_EVENT_POST: | |||
3427 | new_st.op = EXEC_EVENT_POST; | |||
3428 | break; | |||
3429 | case ST_EVENT_WAIT: | |||
3430 | new_st.op = EXEC_EVENT_WAIT; | |||
3431 | break; | |||
3432 | default: | |||
3433 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/match.cc" , 3433, __FUNCTION__)); | |||
3434 | } | |||
3435 | ||||
3436 | new_st.expr1 = eventvar; | |||
3437 | new_st.expr2 = stat; | |||
3438 | new_st.expr3 = errmsg; | |||
3439 | new_st.expr4 = until_count; | |||
3440 | ||||
3441 | return MATCH_YES; | |||
3442 | ||||
3443 | syntax: | |||
3444 | gfc_syntax_error (st)gfc_error ("Syntax error in %s statement at %C", gfc_ascii_statement (st));; | |||
3445 | ||||
3446 | cleanup: | |||
3447 | if (until_count != tmp) | |||
3448 | gfc_free_expr (until_count); | |||
3449 | if (errmsg != tmp) | |||
3450 | gfc_free_expr (errmsg); | |||
3451 | if (stat != tmp) | |||
3452 | gfc_free_expr (stat); | |||
3453 | ||||
3454 | gfc_free_expr (tmp); | |||
3455 | gfc_free_expr (eventvar); | |||
3456 | ||||
3457 | return MATCH_ERROR; | |||
3458 | ||||
3459 | } | |||
3460 | ||||
3461 | ||||
3462 | match | |||
3463 | gfc_match_event_post (void) | |||
3464 | { | |||
3465 | if (!gfc_notify_std (GFC_STD_F2018(1<<9), "EVENT POST statement at %C")) | |||
3466 | return MATCH_ERROR; | |||
3467 | ||||
3468 | return event_statement (ST_EVENT_POST); | |||
3469 | } | |||
3470 | ||||
3471 | ||||
3472 | match | |||
3473 | gfc_match_event_wait (void) | |||
3474 | { | |||
3475 | if (!gfc_notify_std (GFC_STD_F2018(1<<9), "EVENT WAIT statement at %C")) | |||
3476 | return MATCH_ERROR; | |||
3477 | ||||
3478 | return event_statement (ST_EVENT_WAIT); | |||
3479 | } | |||
3480 | ||||
3481 | ||||
3482 | /* Match a FAIL IMAGE statement. */ | |||
3483 | ||||
3484 | match | |||
3485 | gfc_match_fail_image (void) | |||
3486 | { | |||
3487 | if (!gfc_notify_std (GFC_STD_F2018(1<<9), "FAIL IMAGE statement at %C")) | |||
3488 | return MATCH_ERROR; | |||
3489 | ||||
3490 | if (gfc_match_char ('(') == MATCH_YES) | |||
3491 | goto syntax; | |||
3492 | ||||
3493 | new_st.op = EXEC_FAIL_IMAGE; | |||
3494 | ||||
3495 | return MATCH_YES; | |||
3496 | ||||
3497 | syntax: | |||
3498 | gfc_syntax_error (ST_FAIL_IMAGE)gfc_error ("Syntax error in %s statement at %C", gfc_ascii_statement (ST_FAIL_IMAGE));; | |||
3499 | ||||
3500 | return MATCH_ERROR; | |||
3501 | } | |||
3502 | ||||
3503 | /* Match a FORM TEAM statement. */ | |||
3504 | ||||
3505 | match | |||
3506 | gfc_match_form_team (void) | |||
3507 | { | |||
3508 | match m; | |||
3509 | gfc_expr *teamid,*team; | |||
3510 | ||||
3511 | if (!gfc_notify_std (GFC_STD_F2018(1<<9), "FORM TEAM statement at %C")) | |||
3512 | return MATCH_ERROR; | |||
3513 | ||||
3514 | if (gfc_match_char ('(') == MATCH_NO) | |||
3515 | goto syntax; | |||
3516 | ||||
3517 | new_st.op = EXEC_FORM_TEAM; | |||
3518 | ||||
3519 | if (gfc_match ("%e", &teamid) != MATCH_YES) | |||
3520 | goto syntax; | |||
3521 | m = gfc_match_char (','); | |||
3522 | if (m == MATCH_ERROR) | |||
3523 | goto syntax; | |||
3524 | if (gfc_match ("%e", &team) != MATCH_YES) | |||
3525 | goto syntax; | |||
3526 | ||||
3527 | m = gfc_match_char (')'); | |||
3528 | if (m == MATCH_NO) | |||
3529 | goto syntax; | |||
3530 | ||||
3531 | new_st.expr1 = teamid; | |||
3532 | new_st.expr2 = team; | |||
3533 | ||||
3534 | return MATCH_YES; | |||
3535 | ||||
3536 | syntax: | |||
3537 | gfc_syntax_error (ST_FORM_TEAM)gfc_error ("Syntax error in %s statement at %C", gfc_ascii_statement (ST_FORM_TEAM));; | |||
3538 | ||||
3539 | return MATCH_ERROR; | |||
3540 | } | |||
3541 | ||||
3542 | /* Match a CHANGE TEAM statement. */ | |||
3543 | ||||
3544 | match | |||
3545 | gfc_match_change_team (void) | |||
3546 | { | |||
3547 | match m; | |||
3548 | gfc_expr *team; | |||
3549 | ||||
3550 | if (!gfc_notify_std (GFC_STD_F2018(1<<9), "CHANGE TEAM statement at %C")) | |||
3551 | return MATCH_ERROR; | |||
3552 | ||||
3553 | if (gfc_match_char ('(') == MATCH_NO) | |||
3554 | goto syntax; | |||
3555 | ||||
3556 | new_st.op = EXEC_CHANGE_TEAM; | |||
3557 | ||||
3558 | if (gfc_match ("%e", &team) != MATCH_YES) | |||
3559 | goto syntax; | |||
3560 | ||||
3561 | m = gfc_match_char (')'); | |||
3562 | if (m == MATCH_NO) | |||
3563 | goto syntax; | |||
3564 | ||||
3565 | new_st.expr1 = team; | |||
3566 | ||||
3567 | return MATCH_YES; | |||
3568 | ||||
3569 | syntax: | |||
3570 | gfc_syntax_error (ST_CHANGE_TEAM)gfc_error ("Syntax error in %s statement at %C", gfc_ascii_statement (ST_CHANGE_TEAM));; | |||
3571 | ||||
3572 | return MATCH_ERROR; | |||
3573 | } | |||
3574 | ||||
3575 | /* Match a END TEAM statement. */ | |||
3576 | ||||
3577 | match | |||
3578 | gfc_match_end_team (void) | |||
3579 | { | |||
3580 | if (!gfc_notify_std (GFC_STD_F2018(1<<9), "END TEAM statement at %C")) | |||
3581 | return MATCH_ERROR; | |||
3582 | ||||
3583 | if (gfc_match_char ('(') == MATCH_YES) | |||
3584 | goto syntax; | |||
3585 | ||||
3586 | new_st.op = EXEC_END_TEAM; | |||
3587 | ||||
3588 | return MATCH_YES; | |||
3589 | ||||
3590 | syntax: | |||
3591 | gfc_syntax_error (ST_END_TEAM)gfc_error ("Syntax error in %s statement at %C", gfc_ascii_statement (ST_END_TEAM));; | |||
3592 | ||||
3593 | return MATCH_ERROR; | |||
3594 | } | |||
3595 | ||||
3596 | /* Match a SYNC TEAM statement. */ | |||
3597 | ||||
3598 | match | |||
3599 | gfc_match_sync_team (void) | |||
3600 | { | |||
3601 | match m; | |||
3602 | gfc_expr *team; | |||
3603 | ||||
3604 | if (!gfc_notify_std (GFC_STD_F2018(1<<9), "SYNC TEAM statement at %C")) | |||
3605 | return MATCH_ERROR; | |||
3606 | ||||
3607 | if (gfc_match_char ('(') == MATCH_NO) | |||
3608 | goto syntax; | |||
3609 | ||||
3610 | new_st.op = EXEC_SYNC_TEAM; | |||
3611 | ||||
3612 | if (gfc_match ("%e", &team) != MATCH_YES) | |||
3613 | goto syntax; | |||
3614 | ||||
3615 | m = gfc_match_char (')'); | |||
3616 | if (m == MATCH_NO) | |||
3617 | goto syntax; | |||
3618 | ||||
3619 | new_st.expr1 = team; | |||
3620 | ||||
3621 | return MATCH_YES; | |||
3622 | ||||
3623 | syntax: | |||
3624 | gfc_syntax_error (ST_SYNC_TEAM)gfc_error ("Syntax error in %s statement at %C", gfc_ascii_statement (ST_SYNC_TEAM));; | |||
3625 | ||||
3626 | return MATCH_ERROR; | |||
3627 | } | |||
3628 | ||||
3629 | /* Match LOCK/UNLOCK statement. Syntax: | |||
3630 | LOCK ( lock-variable [ , lock-stat-list ] ) | |||
3631 | UNLOCK ( lock-variable [ , sync-stat-list ] ) | |||
3632 | where lock-stat is ACQUIRED_LOCK or sync-stat | |||
3633 | and sync-stat is STAT= or ERRMSG=. */ | |||
3634 | ||||
3635 | static match | |||
3636 | lock_unlock_statement (gfc_statement st) | |||
3637 | { | |||
3638 | match m; | |||
3639 | gfc_expr *tmp, *lockvar, *acq_lock, *stat, *errmsg; | |||
3640 | bool saw_acq_lock, saw_stat, saw_errmsg; | |||
3641 | ||||
3642 | tmp = lockvar = acq_lock = stat = errmsg = NULL__null; | |||
3643 | saw_acq_lock = saw_stat = saw_errmsg = false; | |||
3644 | ||||
3645 | if (gfc_pure (NULL__null)) | |||
3646 | { | |||
3647 | gfc_error ("Image control statement %s at %C in PURE procedure", | |||
3648 | st == ST_LOCK ? "LOCK" : "UNLOCK"); | |||
3649 | return MATCH_ERROR; | |||
3650 | } | |||
3651 | ||||
3652 | gfc_unset_implicit_pure (NULL__null); | |||
3653 | ||||
3654 | if (flag_coarrayglobal_options.x_flag_coarray == GFC_FCOARRAY_NONE) | |||
3655 | { | |||
3656 | gfc_fatal_error ("Coarrays disabled at %C, use %<-fcoarray=%> to enable"); | |||
3657 | return MATCH_ERROR; | |||
3658 | } | |||
3659 | ||||
3660 | if (gfc_find_state (COMP_CRITICAL)) | |||
3661 | { | |||
3662 | gfc_error ("Image control statement %s at %C in CRITICAL block", | |||
3663 | st == ST_LOCK ? "LOCK" : "UNLOCK"); | |||
3664 | return MATCH_ERROR; | |||
3665 | } | |||
3666 | ||||
3667 | if (gfc_find_state (COMP_DO_CONCURRENT)) | |||
3668 | { | |||
3669 | gfc_error ("Image control statement %s at %C in DO CONCURRENT block", | |||
3670 | st == ST_LOCK ? "LOCK" : "UNLOCK"); | |||
3671 | return MATCH_ERROR; | |||
3672 | } | |||
3673 | ||||
3674 | if (gfc_match_char ('(') != MATCH_YES) | |||
3675 | goto syntax; | |||
3676 | ||||
3677 | if (gfc_match ("%e", &lockvar) != MATCH_YES) | |||
3678 | goto syntax; | |||
3679 | m = gfc_match_char (','); | |||
3680 | if (m == MATCH_ERROR) | |||
3681 | goto syntax; | |||
3682 | if (m == MATCH_NO) | |||
3683 | { | |||
3684 | m = gfc_match_char (')'); | |||
3685 | if (m == MATCH_YES) | |||
3686 | goto done; | |||
3687 | goto syntax; | |||
3688 | } | |||
3689 | ||||
3690 | for (;;) | |||
3691 | { | |||
3692 | m = gfc_match (" stat = %v", &tmp); | |||
3693 | if (m == MATCH_ERROR) | |||
3694 | goto syntax; | |||
3695 | if (m == MATCH_YES) | |||
3696 | { | |||
3697 | if (saw_stat) | |||
3698 | { | |||
3699 | gfc_error ("Redundant STAT tag found at %L", &tmp->where); | |||
3700 | goto cleanup; | |||
3701 | } | |||
3702 | stat = tmp; | |||
3703 | saw_stat = true; | |||
3704 | ||||
3705 | m = gfc_match_char (','); | |||
3706 | if (m == MATCH_YES) | |||
3707 | continue; | |||
3708 | ||||
3709 | tmp = NULL__null; | |||
3710 | break; | |||
3711 | } | |||
3712 | ||||
3713 | m = gfc_match (" errmsg = %v", &tmp); | |||
3714 | if (m == MATCH_ERROR) | |||
3715 | goto syntax; | |||
3716 | if (m == MATCH_YES) | |||
3717 | { | |||
3718 | if (saw_errmsg) | |||
3719 | { | |||
3720 | gfc_error ("Redundant ERRMSG tag found at %L", &tmp->where); | |||
3721 | goto cleanup; | |||
3722 | } | |||
3723 | errmsg = tmp; | |||
3724 | saw_errmsg = true; | |||
3725 | ||||
3726 | m = gfc_match_char (','); | |||
3727 | if (m == MATCH_YES) | |||
3728 | continue; | |||
3729 | ||||
3730 | tmp = NULL__null; | |||
3731 | break; | |||
3732 | } | |||
3733 | ||||
3734 | m = gfc_match (" acquired_lock = %v", &tmp); | |||
3735 | if (m == MATCH_ERROR || st == ST_UNLOCK) | |||
3736 | goto syntax; | |||
3737 | if (m == MATCH_YES) | |||
3738 | { | |||
3739 | if (saw_acq_lock) | |||
3740 | { | |||
3741 | gfc_error ("Redundant ACQUIRED_LOCK tag found at %L", | |||
3742 | &tmp->where); | |||
3743 | goto cleanup; | |||
3744 | } | |||
3745 | acq_lock = tmp; | |||
3746 | saw_acq_lock = true; | |||
3747 | ||||
3748 | m = gfc_match_char (','); | |||
3749 | if (m == MATCH_YES) | |||
3750 | continue; | |||
3751 | ||||
3752 | tmp = NULL__null; | |||
3753 | break; | |||
3754 | } | |||
3755 | ||||
3756 | break; | |||
3757 | } | |||
3758 | ||||
3759 | if (m == MATCH_ERROR) | |||
3760 | goto syntax; | |||
3761 | ||||
3762 | if (gfc_match (" )%t") != MATCH_YES) | |||
3763 | goto syntax; | |||
3764 | ||||
3765 | done: | |||
3766 | switch (st) | |||
3767 | { | |||
3768 | case ST_LOCK: | |||
3769 | new_st.op = EXEC_LOCK; | |||
3770 | break; | |||
3771 | case ST_UNLOCK: | |||
3772 | new_st.op = EXEC_UNLOCK; | |||
3773 | break; | |||
3774 | default: | |||
3775 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/match.cc" , 3775, __FUNCTION__)); | |||
3776 | } | |||
3777 | ||||
3778 | new_st.expr1 = lockvar; | |||
3779 | new_st.expr2 = stat; | |||
3780 | new_st.expr3 = errmsg; | |||
3781 | new_st.expr4 = acq_lock; | |||
3782 | ||||
3783 | return MATCH_YES; | |||
3784 | ||||
3785 | syntax: | |||
3786 | gfc_syntax_error (st)gfc_error ("Syntax error in %s statement at %C", gfc_ascii_statement (st));; | |||
3787 | ||||
3788 | cleanup: | |||
3789 | if (acq_lock != tmp) | |||
3790 | gfc_free_expr (acq_lock); | |||
3791 | if (errmsg != tmp) | |||
3792 | gfc_free_expr (errmsg); | |||
3793 | if (stat != tmp) | |||
3794 | gfc_free_expr (stat); | |||
3795 | ||||
3796 | gfc_free_expr (tmp); | |||
3797 | gfc_free_expr (lockvar); | |||
3798 | ||||
3799 | return MATCH_ERROR; | |||
3800 | } | |||
3801 | ||||
3802 | ||||
3803 | match | |||
3804 | gfc_match_lock (void) | |||
3805 | { | |||
3806 | if (!gfc_notify_std (GFC_STD_F2008(1<<7), "LOCK statement at %C")) | |||
3807 | return MATCH_ERROR; | |||
3808 | ||||
3809 | return lock_unlock_statement (ST_LOCK); | |||
3810 | } | |||
3811 | ||||
3812 | ||||
3813 | match | |||
3814 | gfc_match_unlock (void) | |||
3815 | { | |||
3816 | if (!gfc_notify_std (GFC_STD_F2008(1<<7), "UNLOCK statement at %C")) | |||
3817 | return MATCH_ERROR; | |||
3818 | ||||
3819 | return lock_unlock_statement (ST_UNLOCK); | |||
3820 | } | |||
3821 | ||||
3822 | ||||
3823 | /* Match SYNC ALL/IMAGES/MEMORY statement. Syntax: | |||
3824 | SYNC ALL [(sync-stat-list)] | |||
3825 | SYNC MEMORY [(sync-stat-list)] | |||
3826 | SYNC IMAGES (image-set [, sync-stat-list] ) | |||
3827 | with sync-stat is int-expr or *. */ | |||
3828 | ||||
3829 | static match | |||
3830 | sync_statement (gfc_statement st) | |||
3831 | { | |||
3832 | match m; | |||
3833 | gfc_expr *tmp, *imageset, *stat, *errmsg; | |||
3834 | bool saw_stat, saw_errmsg; | |||
3835 | ||||
3836 | tmp = imageset = stat = errmsg = NULL__null; | |||
3837 | saw_stat = saw_errmsg = false; | |||
3838 | ||||
3839 | if (gfc_pure (NULL__null)) | |||
3840 | { | |||
3841 | gfc_error ("Image control statement SYNC at %C in PURE procedure"); | |||
3842 | return MATCH_ERROR; | |||
3843 | } | |||
3844 | ||||
3845 | gfc_unset_implicit_pure (NULL__null); | |||
3846 | ||||
3847 | if (!gfc_notify_std (GFC_STD_F2008(1<<7), "SYNC statement at %C")) | |||
3848 | return MATCH_ERROR; | |||
3849 | ||||
3850 | if (flag_coarrayglobal_options.x_flag_coarray == GFC_FCOARRAY_NONE) | |||
3851 | { | |||
3852 | gfc_fatal_error ("Coarrays disabled at %C, use %<-fcoarray=%> to " | |||
3853 | "enable"); | |||
3854 | return MATCH_ERROR; | |||
3855 | } | |||
3856 | ||||
3857 | if (gfc_find_state (COMP_CRITICAL)) | |||
3858 | { | |||
3859 | gfc_error ("Image control statement SYNC at %C in CRITICAL block"); | |||
3860 | return MATCH_ERROR; | |||
3861 | } | |||
3862 | ||||
3863 | if (gfc_find_state (COMP_DO_CONCURRENT)) | |||
3864 | { | |||
3865 | gfc_error ("Image control statement SYNC at %C in DO CONCURRENT block"); | |||
3866 | return MATCH_ERROR; | |||
3867 | } | |||
3868 | ||||
3869 | if (gfc_match_eos () == MATCH_YES) | |||
3870 | { | |||
3871 | if (st == ST_SYNC_IMAGES) | |||
3872 | goto syntax; | |||
3873 | goto done; | |||
3874 | } | |||
3875 | ||||
3876 | if (gfc_match_char ('(') != MATCH_YES) | |||
3877 | goto syntax; | |||
3878 | ||||
3879 | if (st == ST_SYNC_IMAGES) | |||
3880 | { | |||
3881 | /* Denote '*' as imageset == NULL. */ | |||
3882 | m = gfc_match_char ('*'); | |||
3883 | if (m == MATCH_ERROR) | |||
3884 | goto syntax; | |||
3885 | if (m == MATCH_NO) | |||
3886 | { | |||
3887 | if (gfc_match ("%e", &imageset) != MATCH_YES) | |||
3888 | goto syntax; | |||
3889 | } | |||
3890 | m = gfc_match_char (','); | |||
3891 | if (m == MATCH_ERROR) | |||
3892 | goto syntax; | |||
3893 | if (m == MATCH_NO) | |||
3894 | { | |||
3895 | m = gfc_match_char (')'); | |||
3896 | if (m == MATCH_YES) | |||
3897 | goto done; | |||
3898 | goto syntax; | |||
3899 | } | |||
3900 | } | |||
3901 | ||||
3902 | for (;;) | |||
3903 | { | |||
3904 | m = gfc_match (" stat = %e", &tmp); | |||
3905 | if (m == MATCH_ERROR) | |||
3906 | goto syntax; | |||
3907 | if (m == MATCH_YES) | |||
3908 | { | |||
3909 | if (saw_stat) | |||
3910 | { | |||
3911 | gfc_error ("Redundant STAT tag found at %L", &tmp->where); | |||
3912 | goto cleanup; | |||
3913 | } | |||
3914 | stat = tmp; | |||
3915 | saw_stat = true; | |||
3916 | ||||
3917 | if (gfc_match_char (',') == MATCH_YES) | |||
3918 | continue; | |||
3919 | ||||
3920 | tmp = NULL__null; | |||
3921 | break; | |||
3922 | } | |||
3923 | ||||
3924 | m = gfc_match (" errmsg = %e", &tmp); | |||
3925 | if (m == MATCH_ERROR) | |||
3926 | goto syntax; | |||
3927 | if (m == MATCH_YES) | |||
3928 | { | |||
3929 | if (saw_errmsg) | |||
3930 | { | |||
3931 | gfc_error ("Redundant ERRMSG tag found at %L", &tmp->where); | |||
3932 | goto cleanup; | |||
3933 | } | |||
3934 | errmsg = tmp; | |||
3935 | saw_errmsg = true; | |||
3936 | ||||
3937 | if (gfc_match_char (',') == MATCH_YES) | |||
3938 | continue; | |||
3939 | ||||
3940 | tmp = NULL__null; | |||
3941 | break; | |||
3942 | } | |||
3943 | ||||
3944 | break; | |||
3945 | } | |||
3946 | ||||
3947 | if (gfc_match (" )%t") != MATCH_YES) | |||
3948 | goto syntax; | |||
3949 | ||||
3950 | done: | |||
3951 | switch (st) | |||
3952 | { | |||
3953 | case ST_SYNC_ALL: | |||
3954 | new_st.op = EXEC_SYNC_ALL; | |||
3955 | break; | |||
3956 | case ST_SYNC_IMAGES: | |||
3957 | new_st.op = EXEC_SYNC_IMAGES; | |||
3958 | break; | |||
3959 | case ST_SYNC_MEMORY: | |||
3960 | new_st.op = EXEC_SYNC_MEMORY; | |||
3961 | break; | |||
3962 | default: | |||
3963 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/match.cc" , 3963, __FUNCTION__)); | |||
3964 | } | |||
3965 | ||||
3966 | new_st.expr1 = imageset; | |||
3967 | new_st.expr2 = stat; | |||
3968 | new_st.expr3 = errmsg; | |||
3969 | ||||
3970 | return MATCH_YES; | |||
3971 | ||||
3972 | syntax: | |||
3973 | gfc_syntax_error (st)gfc_error ("Syntax error in %s statement at %C", gfc_ascii_statement (st));; | |||
3974 | ||||
3975 | cleanup: | |||
3976 | if (stat != tmp) | |||
3977 | gfc_free_expr (stat); | |||
3978 | if (errmsg != tmp) | |||
3979 | gfc_free_expr (errmsg); | |||
3980 | ||||
3981 | gfc_free_expr (tmp); | |||
3982 | gfc_free_expr (imageset); | |||
3983 | ||||
3984 | return MATCH_ERROR; | |||
3985 | } | |||
3986 | ||||
3987 | ||||
3988 | /* Match SYNC ALL statement. */ | |||
3989 | ||||
3990 | match | |||
3991 | gfc_match_sync_all (void) | |||
3992 | { | |||
3993 | return sync_statement (ST_SYNC_ALL); | |||
3994 | } | |||
3995 | ||||
3996 | ||||
3997 | /* Match SYNC IMAGES statement. */ | |||
3998 | ||||
3999 | match | |||
4000 | gfc_match_sync_images (void) | |||
4001 | { | |||
4002 | return sync_statement (ST_SYNC_IMAGES); | |||
4003 | } | |||
4004 | ||||
4005 | ||||
4006 | /* Match SYNC MEMORY statement. */ | |||
4007 | ||||
4008 | match | |||
4009 | gfc_match_sync_memory (void) | |||
4010 | { | |||
4011 | return sync_statement (ST_SYNC_MEMORY); | |||
4012 | } | |||
4013 | ||||
4014 | ||||
4015 | /* Match a CONTINUE statement. */ | |||
4016 | ||||
4017 | match | |||
4018 | gfc_match_continue (void) | |||
4019 | { | |||
4020 | if (gfc_match_eos () != MATCH_YES) | |||
4021 | { | |||
4022 | gfc_syntax_error (ST_CONTINUE)gfc_error ("Syntax error in %s statement at %C", gfc_ascii_statement (ST_CONTINUE));; | |||
4023 | return MATCH_ERROR; | |||
4024 | } | |||
4025 | ||||
4026 | new_st.op = EXEC_CONTINUE; | |||
4027 | return MATCH_YES; | |||
4028 | } | |||
4029 | ||||
4030 | ||||
4031 | /* Match the (deprecated) ASSIGN statement. */ | |||
4032 | ||||
4033 | match | |||
4034 | gfc_match_assign (void) | |||
4035 | { | |||
4036 | gfc_expr *expr; | |||
4037 | gfc_st_label *label; | |||
4038 | ||||
4039 | if (gfc_match (" %l", &label) == MATCH_YES) | |||
4040 | { | |||
4041 | if (!gfc_reference_st_label (label, ST_LABEL_UNKNOWN)) | |||
4042 | return MATCH_ERROR; | |||
4043 | if (gfc_match (" to %v%t", &expr) == MATCH_YES) | |||
4044 | { | |||
4045 | if (!gfc_notify_std (GFC_STD_F95_DEL(1<<2), "ASSIGN statement at %C")) | |||
4046 | return MATCH_ERROR; | |||
4047 | ||||
4048 | expr->symtree->n.sym->attr.assign = 1; | |||
4049 | ||||
4050 | new_st.op = EXEC_LABEL_ASSIGN; | |||
4051 | new_st.label1 = label; | |||
4052 | new_st.expr1 = expr; | |||
4053 | return MATCH_YES; | |||
4054 | } | |||
4055 | } | |||
4056 | return MATCH_NO; | |||
4057 | } | |||
4058 | ||||
4059 | ||||
4060 | /* Match the GO TO statement. As a computed GOTO statement is | |||
4061 | matched, it is transformed into an equivalent SELECT block. No | |||
4062 | tree is necessary, and the resulting jumps-to-jumps are | |||
4063 | specifically optimized away by the back end. */ | |||
4064 | ||||
4065 | match | |||
4066 | gfc_match_goto (void) | |||
4067 | { | |||
4068 | gfc_code *head, *tail; | |||
4069 | gfc_expr *expr; | |||
4070 | gfc_case *cp; | |||
4071 | gfc_st_label *label; | |||
4072 | int i; | |||
4073 | match m; | |||
4074 | ||||
4075 | if (gfc_match (" %l%t", &label) == MATCH_YES) | |||
4076 | { | |||
4077 | if (!gfc_reference_st_label (label, ST_LABEL_TARGET)) | |||
4078 | return MATCH_ERROR; | |||
4079 | ||||
4080 | new_st.op = EXEC_GOTO; | |||
4081 | new_st.label1 = label; | |||
4082 | return MATCH_YES; | |||
4083 | } | |||
4084 | ||||
4085 | /* The assigned GO TO statement. */ | |||
4086 | ||||
4087 | if (gfc_match_variable (&expr, 0) == MATCH_YES) | |||
4088 | { | |||
4089 | if (!gfc_notify_std (GFC_STD_F95_DEL(1<<2), "Assigned GOTO statement at %C")) | |||
4090 | return MATCH_ERROR; | |||
4091 | ||||
4092 | new_st.op = EXEC_GOTO; | |||
4093 | new_st.expr1 = expr; | |||
4094 | ||||
4095 | if (gfc_match_eos () == MATCH_YES) | |||
4096 | return MATCH_YES; | |||
4097 | ||||
4098 | /* Match label list. */ | |||
4099 | gfc_match_char (','); | |||
4100 | if (gfc_match_char ('(') != MATCH_YES) | |||
4101 | { | |||
4102 | gfc_syntax_error (ST_GOTO)gfc_error ("Syntax error in %s statement at %C", gfc_ascii_statement (ST_GOTO));; | |||
4103 | return MATCH_ERROR; | |||
4104 | } | |||
4105 | head = tail = NULL__null; | |||
4106 | ||||
4107 | do | |||
4108 | { | |||
4109 | m = gfc_match_st_label (&label); | |||
4110 | if (m != MATCH_YES) | |||
4111 | goto syntax; | |||
4112 | ||||
4113 | if (!gfc_reference_st_label (label, ST_LABEL_TARGET)) | |||
4114 | goto cleanup; | |||
4115 | ||||
4116 | if (head == NULL__null) | |||
4117 | head = tail = gfc_get_code (EXEC_GOTO); | |||
4118 | else | |||
4119 | { | |||
4120 | tail->block = gfc_get_code (EXEC_GOTO); | |||
4121 | tail = tail->block; | |||
4122 | } | |||
4123 | ||||
4124 | tail->label1 = label; | |||
4125 | } | |||
4126 | while (gfc_match_char (',') == MATCH_YES); | |||
4127 | ||||
4128 | if (gfc_match (" )%t") != MATCH_YES) | |||
4129 | goto syntax; | |||
4130 | ||||
4131 | if (head == NULL__null) | |||
4132 | { | |||
4133 | gfc_error ("Statement label list in GOTO at %C cannot be empty"); | |||
4134 | goto syntax; | |||
4135 | } | |||
4136 | new_st.block = head; | |||
4137 | ||||
4138 | return MATCH_YES; | |||
4139 | } | |||
4140 | ||||
4141 | /* Last chance is a computed GO TO statement. */ | |||
4142 | if (gfc_match_char ('(') != MATCH_YES) | |||
4143 | { | |||
4144 | gfc_syntax_error (ST_GOTO)gfc_error ("Syntax error in %s statement at %C", gfc_ascii_statement (ST_GOTO));; | |||
4145 | return MATCH_ERROR; | |||
4146 | } | |||
4147 | ||||
4148 | head = tail = NULL__null; | |||
4149 | i = 1; | |||
4150 | ||||
4151 | do | |||
4152 | { | |||
4153 | m = gfc_match_st_label (&label); | |||
4154 | if (m != MATCH_YES) | |||
4155 | goto syntax; | |||
4156 | ||||
4157 | if (!gfc_reference_st_label (label, ST_LABEL_TARGET)) | |||
4158 | goto cleanup; | |||
4159 | ||||
4160 | if (head == NULL__null) | |||
4161 | head = tail = gfc_get_code (EXEC_SELECT); | |||
4162 | else | |||
4163 | { | |||
4164 | tail->block = gfc_get_code (EXEC_SELECT); | |||
4165 | tail = tail->block; | |||
4166 | } | |||
4167 | ||||
4168 | cp = gfc_get_case ()((gfc_case *) xcalloc (1, sizeof (gfc_case))); | |||
4169 | cp->low = cp->high = gfc_get_int_expr (gfc_default_integer_kind, | |||
4170 | NULL__null, i++); | |||
4171 | ||||
4172 | tail->ext.block.case_list = cp; | |||
4173 | ||||
4174 | tail->next = gfc_get_code (EXEC_GOTO); | |||
4175 | tail->next->label1 = label; | |||
4176 | } | |||
4177 | while (gfc_match_char (',') == MATCH_YES); | |||
4178 | ||||
4179 | if (gfc_match_char (')') != MATCH_YES) | |||
4180 | goto syntax; | |||
4181 | ||||
4182 | if (head == NULL__null) | |||
4183 | { | |||
4184 | gfc_error ("Statement label list in GOTO at %C cannot be empty"); | |||
4185 | goto syntax; | |||
4186 | } | |||
4187 | ||||
4188 | /* Get the rest of the statement. */ | |||
4189 | gfc_match_char (','); | |||
4190 | ||||
4191 | if (gfc_match (" %e%t", &expr) != MATCH_YES) | |||
4192 | goto syntax; | |||
4193 | ||||
4194 | if (!gfc_notify_std (GFC_STD_F95_OBS(1<<1), "Computed GOTO at %C")) | |||
4195 | return MATCH_ERROR; | |||
4196 | ||||
4197 | /* At this point, a computed GOTO has been fully matched and an | |||
4198 | equivalent SELECT statement constructed. */ | |||
4199 | ||||
4200 | new_st.op = EXEC_SELECT; | |||
4201 | new_st.expr1 = NULL__null; | |||
4202 | ||||
4203 | /* Hack: For a "real" SELECT, the expression is in expr. We put | |||
4204 | it in expr2 so we can distinguish then and produce the correct | |||
4205 | diagnostics. */ | |||
4206 | new_st.expr2 = expr; | |||
4207 | new_st.block = head; | |||
4208 | return MATCH_YES; | |||
4209 | ||||
4210 | syntax: | |||
4211 | gfc_syntax_error (ST_GOTO)gfc_error ("Syntax error in %s statement at %C", gfc_ascii_statement (ST_GOTO));; | |||
4212 | cleanup: | |||
4213 | gfc_free_statements (head); | |||
4214 | return MATCH_ERROR; | |||
4215 | } | |||
4216 | ||||
4217 | ||||
4218 | /* Frees a list of gfc_alloc structures. */ | |||
4219 | ||||
4220 | void | |||
4221 | gfc_free_alloc_list (gfc_alloc *p) | |||
4222 | { | |||
4223 | gfc_alloc *q; | |||
4224 | ||||
4225 | for (; p; p = q) | |||
4226 | { | |||
4227 | q = p->next; | |||
4228 | gfc_free_expr (p->expr); | |||
4229 | free (p); | |||
4230 | } | |||
4231 | } | |||
4232 | ||||
4233 | ||||
4234 | /* Match an ALLOCATE statement. */ | |||
4235 | ||||
4236 | match | |||
4237 | gfc_match_allocate (void) | |||
4238 | { | |||
4239 | gfc_alloc *head, *tail; | |||
4240 | gfc_expr *stat, *errmsg, *tmp, *source, *mold; | |||
4241 | gfc_typespec ts; | |||
4242 | gfc_symbol *sym; | |||
4243 | match m; | |||
4244 | locus old_locus, deferred_locus, assumed_locus; | |||
4245 | bool saw_stat, saw_errmsg, saw_source, saw_mold, saw_deferred, b1, b2, b3; | |||
4246 | bool saw_unlimited = false, saw_assumed = false; | |||
4247 | ||||
4248 | head = tail = NULL__null; | |||
4249 | stat = errmsg = source = mold = tmp = NULL__null; | |||
4250 | saw_stat = saw_errmsg = saw_source = saw_mold = saw_deferred = false; | |||
4251 | ||||
4252 | if (gfc_match_char ('(') != MATCH_YES) | |||
4253 | { | |||
4254 | gfc_syntax_error (ST_ALLOCATE)gfc_error ("Syntax error in %s statement at %C", gfc_ascii_statement (ST_ALLOCATE));; | |||
4255 | return MATCH_ERROR; | |||
4256 | } | |||
4257 | ||||
4258 | /* Match an optional type-spec. */ | |||
4259 | old_locus = gfc_current_locus; | |||
4260 | m = gfc_match_type_spec (&ts); | |||
4261 | if (m == MATCH_ERROR) | |||
4262 | goto cleanup; | |||
4263 | else if (m == MATCH_NO) | |||
4264 | { | |||
4265 | char name[GFC_MAX_SYMBOL_LEN63 + 3]; | |||
4266 | ||||
4267 | if (gfc_match ("%n :: ", name) == MATCH_YES) | |||
4268 | { | |||
4269 | gfc_error ("Error in type-spec at %L", &old_locus); | |||
4270 | goto cleanup; | |||
4271 | } | |||
4272 | ||||
4273 | ts.type = BT_UNKNOWN; | |||
4274 | } | |||
4275 | else | |||
4276 | { | |||
4277 | /* Needed for the F2008:C631 check below. */ | |||
4278 | assumed_locus = gfc_current_locus; | |||
4279 | ||||
4280 | if (gfc_match (" :: ") == MATCH_YES) | |||
4281 | { | |||
4282 | if (!gfc_notify_std (GFC_STD_F2003(1<<4), "typespec in ALLOCATE at %L", | |||
4283 | &old_locus)) | |||
4284 | goto cleanup; | |||
4285 | ||||
4286 | if (ts.deferred) | |||
4287 | { | |||
4288 | gfc_error ("Type-spec at %L cannot contain a deferred " | |||
4289 | "type parameter", &old_locus); | |||
4290 | goto cleanup; | |||
4291 | } | |||
4292 | ||||
4293 | if (ts.type == BT_CHARACTER) | |||
4294 | { | |||
4295 | if (!ts.u.cl->length) | |||
4296 | saw_assumed = true; | |||
4297 | else | |||
4298 | ts.u.cl->length_from_typespec = true; | |||
4299 | } | |||
4300 | ||||
4301 | if (type_param_spec_list | |||
4302 | && gfc_spec_list_type (type_param_spec_list, NULL__null) | |||
4303 | == SPEC_DEFERRED) | |||
4304 | { | |||
4305 | gfc_error ("The type parameter spec list in the type-spec at " | |||
4306 | "%L cannot contain DEFERRED parameters", &old_locus); | |||
4307 | goto cleanup; | |||
4308 | } | |||
4309 | } | |||
4310 | else | |||
4311 | { | |||
4312 | ts.type = BT_UNKNOWN; | |||
4313 | gfc_current_locus = old_locus; | |||
4314 | } | |||
4315 | } | |||
4316 | ||||
4317 | for (;;) | |||
4318 | { | |||
4319 | if (head == NULL__null) | |||
4320 | head = tail = gfc_get_alloc ()((gfc_alloc *) xcalloc (1, sizeof (gfc_alloc))); | |||
4321 | else | |||
4322 | { | |||
4323 | tail->next = gfc_get_alloc ()((gfc_alloc *) xcalloc (1, sizeof (gfc_alloc))); | |||
4324 | tail = tail->next; | |||
4325 | } | |||
4326 | ||||
4327 | m = gfc_match_variable (&tail->expr, 0); | |||
4328 | if (m == MATCH_NO) | |||
4329 | goto syntax; | |||
4330 | if (m == MATCH_ERROR) | |||
4331 | goto cleanup; | |||
4332 | ||||
4333 | if (tail->expr->expr_type == EXPR_CONSTANT) | |||
4334 | { | |||
4335 | gfc_error ("Unexpected constant at %C"); | |||
4336 | goto cleanup; | |||
4337 | } | |||
4338 | ||||
4339 | if (gfc_check_do_variable (tail->expr->symtree)) | |||
4340 | goto cleanup; | |||
4341 | ||||
4342 | bool impure = gfc_impure_variable (tail->expr->symtree->n.sym); | |||
4343 | if (impure && gfc_pure (NULL__null)) | |||
4344 | { | |||
4345 | gfc_error ("Bad allocate-object at %C for a PURE procedure"); | |||
4346 | goto cleanup; | |||
4347 | } | |||
4348 | ||||
4349 | if (impure) | |||
4350 | gfc_unset_implicit_pure (NULL__null); | |||
4351 | ||||
4352 | /* F2008:C631 (R626) A type-param-value in a type-spec shall be an | |||
4353 | asterisk if and only if each allocate-object is a dummy argument | |||
4354 | for which the corresponding type parameter is assumed. */ | |||
4355 | if (saw_assumed | |||
4356 | && (tail->expr->ts.deferred | |||
4357 | || (tail->expr->ts.u.cl && tail->expr->ts.u.cl->length) | |||
4358 | || tail->expr->symtree->n.sym->attr.dummy == 0)) | |||
4359 | { | |||
4360 | gfc_error ("Incompatible allocate-object at %C for CHARACTER " | |||
4361 | "type-spec at %L", &assumed_locus); | |||
4362 | goto cleanup; | |||
4363 | } | |||
4364 | ||||
4365 | if (tail->expr->ts.deferred) | |||
4366 | { | |||
4367 | saw_deferred = true; | |||
4368 | deferred_locus = tail->expr->where; | |||
4369 | } | |||
4370 | ||||
4371 | if (gfc_find_state (COMP_DO_CONCURRENT) | |||
4372 | || gfc_find_state (COMP_CRITICAL)) | |||
4373 | { | |||
4374 | gfc_ref *ref; | |||
4375 | bool coarray = tail->expr->symtree->n.sym->attr.codimension; | |||
4376 | for (ref = tail->expr->ref; ref; ref = ref->next) | |||
4377 | if (ref->type == REF_COMPONENT) | |||
4378 | coarray = ref->u.c.component->attr.codimension; | |||
4379 | ||||
4380 | if (coarray && gfc_find_state (COMP_DO_CONCURRENT)) | |||
4381 | { | |||
4382 | gfc_error ("ALLOCATE of coarray at %C in DO CONCURRENT block"); | |||
4383 | goto cleanup; | |||
4384 | } | |||
4385 | if (coarray && gfc_find_state (COMP_CRITICAL)) | |||
4386 | { | |||
4387 | gfc_error ("ALLOCATE of coarray at %C in CRITICAL block"); | |||
4388 | goto cleanup; | |||
4389 | } | |||
4390 | } | |||
4391 | ||||
4392 | /* Check for F08:C628. */ | |||
4393 | sym = tail->expr->symtree->n.sym; | |||
4394 | b1 = !(tail->expr->ref | |||
4395 | && (tail->expr->ref->type == REF_COMPONENT | |||
4396 | || tail->expr->ref->type == REF_ARRAY)); | |||
4397 | if (sym && sym->ts.type == BT_CLASS && sym->attr.class_ok) | |||
4398 | b2 = !(CLASS_DATA (sym)sym->ts.u.derived->components->attr.allocatable | |||
4399 | || CLASS_DATA (sym)sym->ts.u.derived->components->attr.class_pointer); | |||
4400 | else | |||
4401 | b2 = sym && !(sym->attr.allocatable || sym->attr.pointer | |||
4402 | || sym->attr.proc_pointer); | |||
4403 | b3 = sym && sym->ns && sym->ns->proc_name | |||
4404 | && (sym->ns->proc_name->attr.allocatable | |||
4405 | || sym->ns->proc_name->attr.pointer | |||
4406 | || sym->ns->proc_name->attr.proc_pointer); | |||
4407 | if (b1 && b2 && !b3) | |||
4408 | { | |||
4409 | gfc_error ("Allocate-object at %L is neither a data pointer " | |||
4410 | "nor an allocatable variable", &tail->expr->where); | |||
4411 | goto cleanup; | |||
4412 | } | |||
4413 | ||||
4414 | /* The ALLOCATE statement had an optional typespec. Check the | |||
4415 | constraints. */ | |||
4416 | if (ts.type != BT_UNKNOWN) | |||
4417 | { | |||
4418 | /* Enforce F03:C624. */ | |||
4419 | if (!gfc_type_compatible (&tail->expr->ts, &ts)) | |||
4420 | { | |||
4421 | gfc_error ("Type of entity at %L is type incompatible with " | |||
4422 | "typespec", &tail->expr->where); | |||
4423 | goto cleanup; | |||
4424 | } | |||
4425 | ||||
4426 | /* Enforce F03:C627. */ | |||
4427 | if (ts.kind != tail->expr->ts.kind && !UNLIMITED_POLY (tail->expr)(tail->expr != __null && tail->expr->ts.type == BT_CLASS && tail->expr->ts.u.derived->components && tail->expr->ts.u.derived->components-> ts.u.derived && tail->expr->ts.u.derived->components ->ts.u.derived->attr.unlimited_polymorphic)) | |||
4428 | { | |||
4429 | gfc_error ("Kind type parameter for entity at %L differs from " | |||
4430 | "the kind type parameter of the typespec", | |||
4431 | &tail->expr->where); | |||
4432 | goto cleanup; | |||
4433 | } | |||
4434 | } | |||
4435 | ||||
4436 | if (tail->expr->ts.type == BT_DERIVED) | |||
4437 | tail->expr->ts.u.derived = gfc_use_derived (tail->expr->ts.u.derived); | |||
4438 | ||||
4439 | if (type_param_spec_list) | |||
4440 | tail->expr->param_list = gfc_copy_actual_arglist (type_param_spec_list); | |||
4441 | ||||
4442 | saw_unlimited = saw_unlimited | UNLIMITED_POLY (tail->expr)(tail->expr != __null && tail->expr->ts.type == BT_CLASS && tail->expr->ts.u.derived->components && tail->expr->ts.u.derived->components-> ts.u.derived && tail->expr->ts.u.derived->components ->ts.u.derived->attr.unlimited_polymorphic); | |||
4443 | ||||
4444 | if (gfc_peek_ascii_char () == '(' && !sym->attr.dimension) | |||
4445 | { | |||
4446 | gfc_error ("Shape specification for allocatable scalar at %C"); | |||
4447 | goto cleanup; | |||
4448 | } | |||
4449 | ||||
4450 | if (gfc_match_char (',') != MATCH_YES) | |||
4451 | break; | |||
4452 | ||||
4453 | alloc_opt_list: | |||
4454 | ||||
4455 | m = gfc_match (" stat = %e", &tmp); | |||
4456 | if (m == MATCH_ERROR) | |||
4457 | goto cleanup; | |||
4458 | if (m == MATCH_YES) | |||
4459 | { | |||
4460 | /* Enforce C630. */ | |||
4461 | if (saw_stat) | |||
4462 | { | |||
4463 | gfc_error ("Redundant STAT tag found at %L", &tmp->where); | |||
4464 | goto cleanup; | |||
4465 | } | |||
4466 | ||||
4467 | stat = tmp; | |||
4468 | tmp = NULL__null; | |||
4469 | saw_stat = true; | |||
4470 | ||||
4471 | if (stat->expr_type == EXPR_CONSTANT) | |||
4472 | { | |||
4473 | gfc_error ("STAT tag at %L cannot be a constant", &stat->where); | |||
4474 | goto cleanup; | |||
4475 | } | |||
4476 | ||||
4477 | if (gfc_check_do_variable (stat->symtree)) | |||
4478 | goto cleanup; | |||
4479 | ||||
4480 | if (gfc_match_char (',') == MATCH_YES) | |||
4481 | goto alloc_opt_list; | |||
4482 | } | |||
4483 | ||||
4484 | m = gfc_match (" errmsg = %e", &tmp); | |||
4485 | if (m == MATCH_ERROR) | |||
4486 | goto cleanup; | |||
4487 | if (m == MATCH_YES) | |||
4488 | { | |||
4489 | if (!gfc_notify_std (GFC_STD_F2003(1<<4), "ERRMSG tag at %L", &tmp->where)) | |||
4490 | goto cleanup; | |||
4491 | ||||
4492 | /* Enforce C630. */ | |||
4493 | if (saw_errmsg) | |||
4494 | { | |||
4495 | gfc_error ("Redundant ERRMSG tag found at %L", &tmp->where); | |||
4496 | goto cleanup; | |||
4497 | } | |||
4498 | ||||
4499 | errmsg = tmp; | |||
4500 | tmp = NULL__null; | |||
4501 | saw_errmsg = true; | |||
4502 | ||||
4503 | if (gfc_match_char (',') == MATCH_YES) | |||
4504 | goto alloc_opt_list; | |||
4505 | } | |||
4506 | ||||
4507 | m = gfc_match (" source = %e", &tmp); | |||
4508 | if (m == MATCH_ERROR) | |||
4509 | goto cleanup; | |||
4510 | if (m == MATCH_YES) | |||
4511 | { | |||
4512 | if (!gfc_notify_std (GFC_STD_F2003(1<<4), "SOURCE tag at %L", &tmp->where)) | |||
4513 | goto cleanup; | |||
4514 | ||||
4515 | /* Enforce C630. */ | |||
4516 | if (saw_source) | |||
4517 | { | |||
4518 | gfc_error ("Redundant SOURCE tag found at %L", &tmp->where); | |||
4519 | goto cleanup; | |||
4520 | } | |||
4521 | ||||
4522 | /* The next 2 conditionals check C631. */ | |||
4523 | if (ts.type != BT_UNKNOWN) | |||
4524 | { | |||
4525 | gfc_error ("SOURCE tag at %L conflicts with the typespec at %L", | |||
4526 | &tmp->where, &old_locus); | |||
4527 | goto cleanup; | |||
4528 | } | |||
4529 | ||||
4530 | if (head->next | |||
4531 | && !gfc_notify_std (GFC_STD_F2008(1<<7), "SOURCE tag at %L" | |||
4532 | " with more than a single allocate object", | |||
4533 | &tmp->where)) | |||
4534 | goto cleanup; | |||
4535 | ||||
4536 | source = tmp; | |||
4537 | tmp = NULL__null; | |||
4538 | saw_source = true; | |||
4539 | ||||
4540 | if (gfc_match_char (',') == MATCH_YES) | |||
4541 | goto alloc_opt_list; | |||
4542 | } | |||
4543 | ||||
4544 | m = gfc_match (" mold = %e", &tmp); | |||
4545 | if (m == MATCH_ERROR) | |||
4546 | goto cleanup; | |||
4547 | if (m == MATCH_YES) | |||
4548 | { | |||
4549 | if (!gfc_notify_std (GFC_STD_F2008(1<<7), "MOLD tag at %L", &tmp->where)) | |||
4550 | goto cleanup; | |||
4551 | ||||
4552 | /* Check F08:C636. */ | |||
4553 | if (saw_mold) | |||
4554 | { | |||
4555 | gfc_error ("Redundant MOLD tag found at %L", &tmp->where); | |||
4556 | goto cleanup; | |||
4557 | } | |||
4558 | ||||
4559 | /* Check F08:C637. */ | |||
4560 | if (ts.type != BT_UNKNOWN) | |||
4561 | { | |||
4562 | gfc_error ("MOLD tag at %L conflicts with the typespec at %L", | |||
4563 | &tmp->where, &old_locus); | |||
4564 | goto cleanup; | |||
4565 | } | |||
4566 | ||||
4567 | mold = tmp; | |||
4568 | tmp = NULL__null; | |||
4569 | saw_mold = true; | |||
4570 | mold->mold = 1; | |||
4571 | ||||
4572 | if (gfc_match_char (',') == MATCH_YES) | |||
4573 | goto alloc_opt_list; | |||
4574 | } | |||
4575 | ||||
4576 | gfc_gobble_whitespace (); | |||
4577 | ||||
4578 | if (gfc_peek_char () == ')') | |||
4579 | break; | |||
4580 | } | |||
4581 | ||||
4582 | if (gfc_match (" )%t") != MATCH_YES) | |||
4583 | goto syntax; | |||
4584 | ||||
4585 | /* Check F08:C637. */ | |||
4586 | if (source && mold) | |||
4587 | { | |||
4588 | gfc_error ("MOLD tag at %L conflicts with SOURCE tag at %L", | |||
4589 | &mold->where, &source->where); | |||
4590 | goto cleanup; | |||
4591 | } | |||
4592 | ||||
4593 | /* Check F03:C623, */ | |||
4594 | if (saw_deferred && ts.type == BT_UNKNOWN && !source && !mold) | |||
4595 | { | |||
4596 | gfc_error ("Allocate-object at %L with a deferred type parameter " | |||
4597 | "requires either a type-spec or SOURCE tag or a MOLD tag", | |||
4598 | &deferred_locus); | |||
4599 | goto cleanup; | |||
4600 | } | |||
4601 | ||||
4602 | /* Check F03:C625, */ | |||
4603 | if (saw_unlimited && ts.type == BT_UNKNOWN && !source && !mold) | |||
4604 | { | |||
4605 | for (tail = head; tail; tail = tail->next) | |||
4606 | { | |||
4607 | if (UNLIMITED_POLY (tail->expr)(tail->expr != __null && tail->expr->ts.type == BT_CLASS && tail->expr->ts.u.derived->components && tail->expr->ts.u.derived->components-> ts.u.derived && tail->expr->ts.u.derived->components ->ts.u.derived->attr.unlimited_polymorphic)) | |||
4608 | gfc_error ("Unlimited polymorphic allocate-object at %L " | |||
4609 | "requires either a type-spec or SOURCE tag " | |||
4610 | "or a MOLD tag", &tail->expr->where); | |||
4611 | } | |||
4612 | goto cleanup; | |||
4613 | } | |||
4614 | ||||
4615 | new_st.op = EXEC_ALLOCATE; | |||
4616 | new_st.expr1 = stat; | |||
4617 | new_st.expr2 = errmsg; | |||
4618 | if (source) | |||
4619 | new_st.expr3 = source; | |||
4620 | else | |||
4621 | new_st.expr3 = mold; | |||
4622 | new_st.ext.alloc.list = head; | |||
4623 | new_st.ext.alloc.ts = ts; | |||
4624 | ||||
4625 | if (type_param_spec_list) | |||
4626 | gfc_free_actual_arglist (type_param_spec_list); | |||
4627 | ||||
4628 | return MATCH_YES; | |||
4629 | ||||
4630 | syntax: | |||
4631 | gfc_syntax_error (ST_ALLOCATE)gfc_error ("Syntax error in %s statement at %C", gfc_ascii_statement (ST_ALLOCATE));; | |||
4632 | ||||
4633 | cleanup: | |||
4634 | gfc_free_expr (errmsg); | |||
4635 | gfc_free_expr (source); | |||
4636 | gfc_free_expr (stat); | |||
4637 | gfc_free_expr (mold); | |||
4638 | if (tmp && tmp->expr_type) gfc_free_expr (tmp); | |||
4639 | gfc_free_alloc_list (head); | |||
4640 | if (type_param_spec_list) | |||
4641 | gfc_free_actual_arglist (type_param_spec_list); | |||
4642 | return MATCH_ERROR; | |||
4643 | } | |||
4644 | ||||
4645 | ||||
4646 | /* Match a NULLIFY statement. A NULLIFY statement is transformed into | |||
4647 | a set of pointer assignments to intrinsic NULL(). */ | |||
4648 | ||||
4649 | match | |||
4650 | gfc_match_nullify (void) | |||
4651 | { | |||
4652 | gfc_code *tail; | |||
4653 | gfc_expr *e, *p; | |||
4654 | match m; | |||
4655 | ||||
4656 | tail = NULL__null; | |||
4657 | ||||
4658 | if (gfc_match_char ('(') != MATCH_YES) | |||
4659 | goto syntax; | |||
4660 | ||||
4661 | for (;;) | |||
4662 | { | |||
4663 | m = gfc_match_variable (&p, 0); | |||
4664 | if (m == MATCH_ERROR) | |||
4665 | goto cleanup; | |||
4666 | if (m == MATCH_NO) | |||
4667 | goto syntax; | |||
4668 | ||||
4669 | if (gfc_check_do_variable (p->symtree)) | |||
4670 | goto cleanup; | |||
4671 | ||||
4672 | /* F2008, C1242. */ | |||
4673 | if (gfc_is_coindexed (p)) | |||
4674 | { | |||
4675 | gfc_error ("Pointer object at %C shall not be coindexed"); | |||
4676 | goto cleanup; | |||
4677 | } | |||
4678 | ||||
4679 | /* Check for valid array pointer object. Bounds remapping is not | |||
4680 | allowed with NULLIFY. */ | |||
4681 | if (p->ref) | |||
4682 | { | |||
4683 | gfc_ref *remap = p->ref; | |||
4684 | for (; remap; remap = remap->next) | |||
4685 | if (!remap->next && remap->type == REF_ARRAY | |||
4686 | && remap->u.ar.type != AR_FULL) | |||
4687 | break; | |||
4688 | if (remap) | |||
4689 | { | |||
4690 | gfc_error ("NULLIFY does not allow bounds remapping for " | |||
4691 | "pointer object at %C"); | |||
4692 | goto cleanup; | |||
4693 | } | |||
4694 | } | |||
4695 | ||||
4696 | /* build ' => NULL() '. */ | |||
4697 | e = gfc_get_null_expr (&gfc_current_locus); | |||
4698 | ||||
4699 | /* Chain to list. */ | |||
4700 | if (tail == NULL__null) | |||
4701 | { | |||
4702 | tail = &new_st; | |||
4703 | tail->op = EXEC_POINTER_ASSIGN; | |||
4704 | } | |||
4705 | else | |||
4706 | { | |||
4707 | tail->next = gfc_get_code (EXEC_POINTER_ASSIGN); | |||
4708 | tail = tail->next; | |||
4709 | } | |||
4710 | ||||
4711 | tail->expr1 = p; | |||
4712 | tail->expr2 = e; | |||
4713 | ||||
4714 | if (gfc_match (" )%t") == MATCH_YES) | |||
4715 | break; | |||
4716 | if (gfc_match_char (',') != MATCH_YES) | |||
4717 | goto syntax; | |||
4718 | } | |||
4719 | ||||
4720 | return MATCH_YES; | |||
4721 | ||||
4722 | syntax: | |||
4723 | gfc_syntax_error (ST_NULLIFY)gfc_error ("Syntax error in %s statement at %C", gfc_ascii_statement (ST_NULLIFY));; | |||
4724 | ||||
4725 | cleanup: | |||
4726 | gfc_free_statements (new_st.next); | |||
4727 | new_st.next = NULL__null; | |||
4728 | gfc_free_expr (new_st.expr1); | |||
4729 | new_st.expr1 = NULL__null; | |||
4730 | gfc_free_expr (new_st.expr2); | |||
4731 | new_st.expr2 = NULL__null; | |||
4732 | return MATCH_ERROR; | |||
4733 | } | |||
4734 | ||||
4735 | ||||
4736 | /* Match a DEALLOCATE statement. */ | |||
4737 | ||||
4738 | match | |||
4739 | gfc_match_deallocate (void) | |||
4740 | { | |||
4741 | gfc_alloc *head, *tail; | |||
4742 | gfc_expr *stat, *errmsg, *tmp; | |||
4743 | gfc_symbol *sym; | |||
4744 | match m; | |||
4745 | bool saw_stat, saw_errmsg, b1, b2; | |||
4746 | ||||
4747 | head = tail = NULL__null; | |||
4748 | stat = errmsg = tmp = NULL__null; | |||
4749 | saw_stat = saw_errmsg = false; | |||
4750 | ||||
4751 | if (gfc_match_char ('(') != MATCH_YES) | |||
4752 | goto syntax; | |||
4753 | ||||
4754 | for (;;) | |||
4755 | { | |||
4756 | if (head == NULL__null) | |||
4757 | head = tail = gfc_get_alloc ()((gfc_alloc *) xcalloc (1, sizeof (gfc_alloc))); | |||
4758 | else | |||
4759 | { | |||
4760 | tail->next = gfc_get_alloc ()((gfc_alloc *) xcalloc (1, sizeof (gfc_alloc))); | |||
4761 | tail = tail->next; | |||
4762 | } | |||
4763 | ||||
4764 | m = gfc_match_variable (&tail->expr, 0); | |||
4765 | if (m == MATCH_ERROR) | |||
4766 | goto cleanup; | |||
4767 | if (m == MATCH_NO) | |||
4768 | goto syntax; | |||
4769 | ||||
4770 | if (tail->expr->expr_type == EXPR_CONSTANT) | |||
4771 | { | |||
4772 | gfc_error ("Unexpected constant at %C"); | |||
4773 | goto cleanup; | |||
4774 | } | |||
4775 | ||||
4776 | if (gfc_check_do_variable (tail->expr->symtree)) | |||
4777 | goto cleanup; | |||
4778 | ||||
4779 | sym = tail->expr->symtree->n.sym; | |||
4780 | ||||
4781 | bool impure = gfc_impure_variable (sym); | |||
4782 | if (impure && gfc_pure (NULL__null)) | |||
4783 | { | |||
4784 | gfc_error ("Illegal allocate-object at %C for a PURE procedure"); | |||
4785 | goto cleanup; | |||
4786 | } | |||
4787 | ||||
4788 | if (impure) | |||
4789 | gfc_unset_implicit_pure (NULL__null); | |||
4790 | ||||
4791 | if (gfc_is_coarray (tail->expr) | |||
4792 | && gfc_find_state (COMP_DO_CONCURRENT)) | |||
4793 | { | |||
4794 | gfc_error ("DEALLOCATE of coarray at %C in DO CONCURRENT block"); | |||
4795 | goto cleanup; | |||
4796 | } | |||
4797 | ||||
4798 | if (gfc_is_coarray (tail->expr) | |||
4799 | && gfc_find_state (COMP_CRITICAL)) | |||
4800 | { | |||
4801 | gfc_error ("DEALLOCATE of coarray at %C in CRITICAL block"); | |||
4802 | goto cleanup; | |||
4803 | } | |||
4804 | ||||
4805 | /* FIXME: disable the checking on derived types. */ | |||
4806 | b1 = !(tail->expr->ref | |||
4807 | && (tail->expr->ref->type == REF_COMPONENT | |||
4808 | || tail->expr->ref->type == REF_ARRAY)); | |||
4809 | if (sym && sym->ts.type == BT_CLASS) | |||
4810 | b2 = !(CLASS_DATA (sym)sym->ts.u.derived->components && (CLASS_DATA (sym)sym->ts.u.derived->components->attr.allocatable | |||
4811 | || CLASS_DATA (sym)sym->ts.u.derived->components->attr.class_pointer)); | |||
4812 | else | |||
4813 | b2 = sym && !(sym->attr.allocatable || sym->attr.pointer | |||
4814 | || sym->attr.proc_pointer); | |||
4815 | if (b1 && b2) | |||
4816 | { | |||
4817 | gfc_error ("Allocate-object at %C is not a nonprocedure pointer " | |||
4818 | "nor an allocatable variable"); | |||
4819 | goto cleanup; | |||
4820 | } | |||
4821 | ||||
4822 | if (gfc_match_char (',') != MATCH_YES) | |||
4823 | break; | |||
4824 | ||||
4825 | dealloc_opt_list: | |||
4826 | ||||
4827 | m = gfc_match (" stat = %e", &tmp); | |||
4828 | if (m == MATCH_ERROR) | |||
4829 | goto cleanup; | |||
4830 | if (m == MATCH_YES) | |||
4831 | { | |||
4832 | if (saw_stat) | |||
4833 | { | |||
4834 | gfc_error ("Redundant STAT tag found at %L", &tmp->where); | |||
4835 | gfc_free_expr (tmp); | |||
4836 | goto cleanup; | |||
4837 | } | |||
4838 | ||||
4839 | stat = tmp; | |||
4840 | saw_stat = true; | |||
4841 | ||||
4842 | if (gfc_check_do_variable (stat->symtree)) | |||
4843 | goto cleanup; | |||
4844 | ||||
4845 | if (gfc_match_char (',') == MATCH_YES) | |||
4846 | goto dealloc_opt_list; | |||
4847 | } | |||
4848 | ||||
4849 | m = gfc_match (" errmsg = %e", &tmp); | |||
4850 | if (m == MATCH_ERROR) | |||
4851 | goto cleanup; | |||
4852 | if (m == MATCH_YES) | |||
4853 | { | |||
4854 | if (!gfc_notify_std (GFC_STD_F2003(1<<4), "ERRMSG at %L", &tmp->where)) | |||
4855 | goto cleanup; | |||
4856 | ||||
4857 | if (saw_errmsg) | |||
4858 | { | |||
4859 | gfc_error ("Redundant ERRMSG tag found at %L", &tmp->where); | |||
4860 | gfc_free_expr (tmp); | |||
4861 | goto cleanup; | |||
4862 | } | |||
4863 | ||||
4864 | errmsg = tmp; | |||
4865 | saw_errmsg = true; | |||
4866 | ||||
4867 | if (gfc_match_char (',') == MATCH_YES) | |||
4868 | goto dealloc_opt_list; | |||
4869 | } | |||
4870 | ||||
4871 | gfc_gobble_whitespace (); | |||
4872 | ||||
4873 | if (gfc_peek_char () == ')') | |||
4874 | break; | |||
4875 | } | |||
4876 | ||||
4877 | if (gfc_match (" )%t") != MATCH_YES) | |||
4878 | goto syntax; | |||
4879 | ||||
4880 | new_st.op = EXEC_DEALLOCATE; | |||
4881 | new_st.expr1 = stat; | |||
4882 | new_st.expr2 = errmsg; | |||
4883 | new_st.ext.alloc.list = head; | |||
4884 | ||||
4885 | return MATCH_YES; | |||
4886 | ||||
4887 | syntax: | |||
4888 | gfc_syntax_error (ST_DEALLOCATE)gfc_error ("Syntax error in %s statement at %C", gfc_ascii_statement (ST_DEALLOCATE));; | |||
4889 | ||||
4890 | cleanup: | |||
4891 | gfc_free_expr (errmsg); | |||
4892 | gfc_free_expr (stat); | |||
4893 | gfc_free_alloc_list (head); | |||
4894 | return MATCH_ERROR; | |||
4895 | } | |||
4896 | ||||
4897 | ||||
4898 | /* Match a RETURN statement. */ | |||
4899 | ||||
4900 | match | |||
4901 | gfc_match_return (void) | |||
4902 | { | |||
4903 | gfc_expr *e; | |||
4904 | match m; | |||
4905 | gfc_compile_state s; | |||
4906 | ||||
4907 | e = NULL__null; | |||
4908 | ||||
4909 | if (gfc_find_state (COMP_CRITICAL)) | |||
4910 | { | |||
4911 | gfc_error ("Image control statement RETURN at %C in CRITICAL block"); | |||
4912 | return MATCH_ERROR; | |||
4913 | } | |||
4914 | ||||
4915 | if (gfc_find_state (COMP_DO_CONCURRENT)) | |||
4916 | { | |||
4917 | gfc_error ("Image control statement RETURN at %C in DO CONCURRENT block"); | |||
4918 | return MATCH_ERROR; | |||
4919 | } | |||
4920 | ||||
4921 | if (gfc_match_eos () == MATCH_YES) | |||
4922 | goto done; | |||
4923 | ||||
4924 | if (!gfc_find_state (COMP_SUBROUTINE)) | |||
4925 | { | |||
4926 | gfc_error ("Alternate RETURN statement at %C is only allowed within " | |||
4927 | "a SUBROUTINE"); | |||
4928 | goto cleanup; | |||
4929 | } | |||
4930 | ||||
4931 | if (gfc_current_form == FORM_FREE) | |||
4932 | { | |||
4933 | /* The following are valid, so we can't require a blank after the | |||
4934 | RETURN keyword: | |||
4935 | return+1 | |||
4936 | return(1) */ | |||
4937 | char c = gfc_peek_ascii_char (); | |||
4938 | if (ISALPHA (c)(_sch_istable[(c) & 0xff] & (unsigned short)(_sch_isalpha )) || ISDIGIT (c)(_sch_istable[(c) & 0xff] & (unsigned short)(_sch_isdigit ))) | |||
4939 | return MATCH_NO; | |||
4940 | } | |||
4941 | ||||
4942 | m = gfc_match (" %e%t", &e); | |||
4943 | if (m == MATCH_YES) | |||
4944 | goto done; | |||
4945 | if (m == MATCH_ERROR) | |||
4946 | goto cleanup; | |||
4947 | ||||
4948 | gfc_syntax_error (ST_RETURN)gfc_error ("Syntax error in %s statement at %C", gfc_ascii_statement (ST_RETURN));; | |||
4949 | ||||
4950 | cleanup: | |||
4951 | gfc_free_expr (e); | |||
4952 | return MATCH_ERROR; | |||
4953 | ||||
4954 | done: | |||
4955 | gfc_enclosing_unit (&s); | |||
4956 | if (s == COMP_PROGRAM | |||
4957 | && !gfc_notify_std (GFC_STD_GNU(1<<5), "RETURN statement in " | |||
4958 | "main program at %C")) | |||
4959 | return MATCH_ERROR; | |||
4960 | ||||
4961 | new_st.op = EXEC_RETURN; | |||
4962 | new_st.expr1 = e; | |||
4963 | ||||
4964 | return MATCH_YES; | |||
4965 | } | |||
4966 | ||||
4967 | ||||
4968 | /* Match the call of a type-bound procedure, if CALL%var has already been | |||
4969 | matched and var found to be a derived-type variable. */ | |||
4970 | ||||
4971 | static match | |||
4972 | match_typebound_call (gfc_symtree* varst) | |||
4973 | { | |||
4974 | gfc_expr* base; | |||
4975 | match m; | |||
4976 | ||||
4977 | base = gfc_get_expr (); | |||
4978 | base->expr_type = EXPR_VARIABLE; | |||
4979 | base->symtree = varst; | |||
4980 | base->where = gfc_current_locus; | |||
4981 | gfc_set_sym_referenced (varst->n.sym); | |||
4982 | ||||
4983 | m = gfc_match_varspec (base, 0, true, true); | |||
4984 | if (m == MATCH_NO) | |||
4985 | gfc_error ("Expected component reference at %C"); | |||
4986 | if (m != MATCH_YES) | |||
4987 | { | |||
4988 | gfc_free_expr (base); | |||
4989 | return MATCH_ERROR; | |||
4990 | } | |||
4991 | ||||
4992 | if (gfc_match_eos () != MATCH_YES) | |||
4993 | { | |||
4994 | gfc_error ("Junk after CALL at %C"); | |||
4995 | gfc_free_expr (base); | |||
4996 | return MATCH_ERROR; | |||
4997 | } | |||
4998 | ||||
4999 | if (base->expr_type == EXPR_COMPCALL) | |||
5000 | new_st.op = EXEC_COMPCALL; | |||
5001 | else if (base->expr_type == EXPR_PPC) | |||
5002 | new_st.op = EXEC_CALL_PPC; | |||
5003 | else | |||
5004 | { | |||
5005 | gfc_error ("Expected type-bound procedure or procedure pointer component " | |||
5006 | "at %C"); | |||
5007 | gfc_free_expr (base); | |||
5008 | return MATCH_ERROR; | |||
5009 | } | |||
5010 | new_st.expr1 = base; | |||
5011 | ||||
5012 | return MATCH_YES; | |||
5013 | } | |||
5014 | ||||
5015 | ||||
5016 | /* Match a CALL statement. The tricky part here are possible | |||
5017 | alternate return specifiers. We handle these by having all | |||
5018 | "subroutines" actually return an integer via a register that gives | |||
5019 | the return number. If the call specifies alternate returns, we | |||
5020 | generate code for a SELECT statement whose case clauses contain | |||
5021 | GOTOs to the various labels. */ | |||
5022 | ||||
5023 | match | |||
5024 | gfc_match_call (void) | |||
5025 | { | |||
5026 | char name[GFC_MAX_SYMBOL_LEN63 + 1]; | |||
5027 | gfc_actual_arglist *a, *arglist; | |||
5028 | gfc_case *new_case; | |||
5029 | gfc_symbol *sym; | |||
5030 | gfc_symtree *st; | |||
5031 | gfc_code *c; | |||
5032 | match m; | |||
5033 | int i; | |||
5034 | ||||
5035 | arglist = NULL__null; | |||
5036 | ||||
5037 | m = gfc_match ("% %n", name); | |||
5038 | if (m == MATCH_NO) | |||
5039 | goto syntax; | |||
5040 | if (m != MATCH_YES) | |||
5041 | return m; | |||
5042 | ||||
5043 | if (gfc_get_ha_sym_tree (name, &st)) | |||
5044 | return MATCH_ERROR; | |||
5045 | ||||
5046 | sym = st->n.sym; | |||
5047 | ||||
5048 | /* If this is a variable of derived-type, it probably starts a type-bound | |||
5049 | procedure call. Associate variable targets have to be resolved for the | |||
5050 | target type. */ | |||
5051 | if (((sym->attr.flavor != FL_PROCEDURE | |||
5052 | || gfc_is_function_return_value (sym, gfc_current_ns)) | |||
5053 | && (sym->ts.type == BT_DERIVED || sym->ts.type == BT_CLASS)) | |||
5054 | || | |||
5055 | (sym->assoc && sym->assoc->target | |||
5056 | && gfc_resolve_expr (sym->assoc->target) | |||
5057 | && (sym->assoc->target->ts.type == BT_DERIVED | |||
5058 | || sym->assoc->target->ts.type == BT_CLASS))) | |||
5059 | return match_typebound_call (st); | |||
5060 | ||||
5061 | /* If it does not seem to be callable (include functions so that the | |||
5062 | right association is made. They are thrown out in resolution.) | |||
5063 | ... */ | |||
5064 | if (!sym->attr.generic | |||
5065 | && !sym->attr.subroutine | |||
5066 | && !sym->attr.function) | |||
5067 | { | |||
5068 | if (!(sym->attr.external && !sym->attr.referenced)) | |||
5069 | { | |||
5070 | /* ...create a symbol in this scope... */ | |||
5071 | if (sym->ns != gfc_current_ns | |||
5072 | && gfc_get_sym_tree (name, NULL__null, &st, false) == 1) | |||
5073 | return MATCH_ERROR; | |||
5074 | ||||
5075 | if (sym != st->n.sym) | |||
5076 | sym = st->n.sym; | |||
5077 | } | |||
5078 | ||||
5079 | /* ...and then to try to make the symbol into a subroutine. */ | |||
5080 | if (!gfc_add_subroutine (&sym->attr, sym->name, NULL__null)) | |||
5081 | return MATCH_ERROR; | |||
5082 | } | |||
5083 | ||||
5084 | gfc_set_sym_referenced (sym); | |||
5085 | ||||
5086 | if (gfc_match_eos () != MATCH_YES) | |||
5087 | { | |||
5088 | m = gfc_match_actual_arglist (1, &arglist); | |||
5089 | if (m == MATCH_NO) | |||
5090 | goto syntax; | |||
5091 | if (m == MATCH_ERROR) | |||
5092 | goto cleanup; | |||
5093 | ||||
5094 | if (gfc_match_eos () != MATCH_YES) | |||
5095 | goto syntax; | |||
5096 | } | |||
5097 | ||||
5098 | /* Walk the argument list looking for invalid BOZ. */ | |||
5099 | for (a = arglist; a; a = a->next) | |||
5100 | if (a->expr && a->expr->ts.type == BT_BOZ) | |||
5101 | { | |||
5102 | gfc_error ("A BOZ literal constant at %L cannot appear as an actual " | |||
5103 | "argument in a subroutine reference", &a->expr->where); | |||
5104 | goto cleanup; | |||
5105 | } | |||
5106 | ||||
5107 | ||||
5108 | /* If any alternate return labels were found, construct a SELECT | |||
5109 | statement that will jump to the right place. */ | |||
5110 | ||||
5111 | i = 0; | |||
5112 | for (a = arglist; a; a = a->next) | |||
5113 | if (a->expr == NULL__null) | |||
5114 | { | |||
5115 | i = 1; | |||
5116 | break; | |||
5117 | } | |||
5118 | ||||
5119 | if (i) | |||
5120 | { | |||
5121 | gfc_symtree *select_st; | |||
5122 | gfc_symbol *select_sym; | |||
5123 | char name[GFC_MAX_SYMBOL_LEN63 + 1]; | |||
5124 | ||||
5125 | new_st.next = c = gfc_get_code (EXEC_SELECT); | |||
5126 | sprintf (name, "_result_%s", sym->name); | |||
5127 | gfc_get_ha_sym_tree (name, &select_st); /* Can't fail. */ | |||
5128 | ||||
5129 | select_sym = select_st->n.sym; | |||
5130 | select_sym->ts.type = BT_INTEGER; | |||
5131 | select_sym->ts.kind = gfc_default_integer_kind; | |||
5132 | gfc_set_sym_referenced (select_sym); | |||
5133 | c->expr1 = gfc_get_expr (); | |||
5134 | c->expr1->expr_type = EXPR_VARIABLE; | |||
5135 | c->expr1->symtree = select_st; | |||
5136 | c->expr1->ts = select_sym->ts; | |||
5137 | c->expr1->where = gfc_current_locus; | |||
5138 | ||||
5139 | i = 0; | |||
5140 | for (a = arglist; a; a = a->next) | |||
5141 | { | |||
5142 | if (a->expr != NULL__null) | |||
5143 | continue; | |||
5144 | ||||
5145 | if (!gfc_reference_st_label (a->label, ST_LABEL_TARGET)) | |||
5146 | continue; | |||
5147 | ||||
5148 | i++; | |||
5149 | ||||
5150 | c->block = gfc_get_code (EXEC_SELECT); | |||
5151 | c = c->block; | |||
5152 | ||||
5153 | new_case = gfc_get_case ()((gfc_case *) xcalloc (1, sizeof (gfc_case))); | |||
5154 | new_case->high = gfc_get_int_expr (gfc_default_integer_kind, NULL__null, i); | |||
5155 | new_case->low = new_case->high; | |||
5156 | c->ext.block.case_list = new_case; | |||
5157 | ||||
5158 | c->next = gfc_get_code (EXEC_GOTO); | |||
5159 | c->next->label1 = a->label; | |||
5160 | } | |||
5161 | } | |||
5162 | ||||
5163 | new_st.op = EXEC_CALL; | |||
5164 | new_st.symtree = st; | |||
5165 | new_st.ext.actual = arglist; | |||
5166 | ||||
5167 | return MATCH_YES; | |||
5168 | ||||
5169 | syntax: | |||
5170 | gfc_syntax_error (ST_CALL)gfc_error ("Syntax error in %s statement at %C", gfc_ascii_statement (ST_CALL));; | |||
5171 | ||||
5172 | cleanup: | |||
5173 | gfc_free_actual_arglist (arglist); | |||
5174 | return MATCH_ERROR; | |||
5175 | } | |||
5176 | ||||
5177 | ||||
5178 | /* Given a name, return a pointer to the common head structure, | |||
5179 | creating it if it does not exist. If FROM_MODULE is nonzero, we | |||
5180 | mangle the name so that it doesn't interfere with commons defined | |||
5181 | in the using namespace. | |||
5182 | TODO: Add to global symbol tree. */ | |||
5183 | ||||
5184 | gfc_common_head * | |||
5185 | gfc_get_common (const char *name, int from_module) | |||
5186 | { | |||
5187 | gfc_symtree *st; | |||
5188 | static int serial = 0; | |||
5189 | char mangled_name[GFC_MAX_SYMBOL_LEN63 + 1]; | |||
5190 | ||||
5191 | if (from_module) | |||
5192 | { | |||
5193 | /* A use associated common block is only needed to correctly layout | |||
5194 | the variables it contains. */ | |||
5195 | snprintf (mangled_name, GFC_MAX_SYMBOL_LEN63, "_%d_%s", serial++, name); | |||
5196 | st = gfc_new_symtree (&gfc_current_ns->common_root, mangled_name); | |||
5197 | } | |||
5198 | else | |||
5199 | { | |||
5200 | st = gfc_find_symtree (gfc_current_ns->common_root, name); | |||
5201 | ||||
5202 | if (st == NULL__null) | |||
5203 | st = gfc_new_symtree (&gfc_current_ns->common_root, name); | |||
5204 | } | |||
5205 | ||||
5206 | if (st->n.common == NULL__null) | |||
5207 | { | |||
5208 | st->n.common = gfc_get_common_head ()((gfc_common_head *) xcalloc (1, sizeof (gfc_common_head))); | |||
5209 | st->n.common->where = gfc_current_locus; | |||
5210 | strcpy (st->n.common->name, name); | |||
5211 | } | |||
5212 | ||||
5213 | return st->n.common; | |||
5214 | } | |||
5215 | ||||
5216 | ||||
5217 | /* Match a common block name. */ | |||
5218 | ||||
5219 | match | |||
5220 | gfc_match_common_name (char *name) | |||
5221 | { | |||
5222 | match m; | |||
5223 | ||||
5224 | if (gfc_match_char ('/') == MATCH_NO) | |||
5225 | { | |||
5226 | name[0] = '\0'; | |||
5227 | return MATCH_YES; | |||
5228 | } | |||
5229 | ||||
5230 | if (gfc_match_char ('/') == MATCH_YES) | |||
5231 | { | |||
5232 | name[0] = '\0'; | |||
5233 | return MATCH_YES; | |||
5234 | } | |||
5235 | ||||
5236 | m = gfc_match_name (name); | |||
5237 | ||||
5238 | if (m == MATCH_ERROR) | |||
5239 | return MATCH_ERROR; | |||
5240 | if (m == MATCH_YES && gfc_match_char ('/') == MATCH_YES) | |||
5241 | return MATCH_YES; | |||
5242 | ||||
5243 | gfc_error ("Syntax error in common block name at %C"); | |||
5244 | return MATCH_ERROR; | |||
5245 | } | |||
5246 | ||||
5247 | ||||
5248 | /* Match a COMMON statement. */ | |||
5249 | ||||
5250 | match | |||
5251 | gfc_match_common (void) | |||
5252 | { | |||
5253 | gfc_symbol *sym, **head, *tail, *other; | |||
5254 | char name[GFC_MAX_SYMBOL_LEN63 + 1]; | |||
5255 | gfc_common_head *t; | |||
5256 | gfc_array_spec *as; | |||
5257 | gfc_equiv *e1, *e2; | |||
5258 | match m; | |||
5259 | char c; | |||
5260 | ||||
5261 | /* COMMON has been matched. In free form source code, the next character | |||
5262 | needs to be whitespace or '/'. Check that here. Fixed form source | |||
5263 | code needs to be checked below. */ | |||
5264 | c = gfc_peek_ascii_char (); | |||
5265 | if (gfc_current_form == FORM_FREE && !gfc_is_whitespace (c)((c==' ') || (c=='\t') || (c=='\f')) && c != '/') | |||
5266 | return MATCH_NO; | |||
5267 | ||||
5268 | as = NULL__null; | |||
5269 | ||||
5270 | for (;;) | |||
5271 | { | |||
5272 | m = gfc_match_common_name (name); | |||
5273 | if (m == MATCH_ERROR) | |||
5274 | goto cleanup; | |||
5275 | ||||
5276 | if (name[0] == '\0') | |||
5277 | { | |||
5278 | t = &gfc_current_ns->blank_common; | |||
5279 | if (t->head == NULL__null) | |||
5280 | t->where = gfc_current_locus; | |||
5281 | } | |||
5282 | else | |||
5283 | { | |||
5284 | t = gfc_get_common (name, 0); | |||
5285 | } | |||
5286 | head = &t->head; | |||
5287 | ||||
5288 | if (*head == NULL__null) | |||
5289 | tail = NULL__null; | |||
5290 | else | |||
5291 | { | |||
5292 | tail = *head; | |||
5293 | while (tail->common_next) | |||
5294 | tail = tail->common_next; | |||
5295 | } | |||
5296 | ||||
5297 | /* Grab the list of symbols. */ | |||
5298 | for (;;) | |||
5299 | { | |||
5300 | m = gfc_match_symbol (&sym, 0); | |||
5301 | if (m == MATCH_ERROR) | |||
5302 | goto cleanup; | |||
5303 | if (m == MATCH_NO) | |||
5304 | goto syntax; | |||
5305 | ||||
5306 | /* See if we know the current common block is bind(c), and if | |||
5307 | so, then see if we can check if the symbol is (which it'll | |||
5308 | need to be). This can happen if the bind(c) attr stmt was | |||
5309 | applied to the common block, and the variable(s) already | |||
5310 | defined, before declaring the common block. */ | |||
5311 | if (t->is_bind_c == 1) | |||
5312 | { | |||
5313 | if (sym->ts.type != BT_UNKNOWN && sym->ts.is_c_interop != 1) | |||
5314 | { | |||
5315 | /* If we find an error, just print it and continue, | |||
5316 | cause it's just semantic, and we can see if there | |||
5317 | are more errors. */ | |||
5318 | gfc_error_now ("Variable %qs at %L in common block %qs " | |||
5319 | "at %C must be declared with a C " | |||
5320 | "interoperable kind since common block " | |||
5321 | "%qs is bind(c)", | |||
5322 | sym->name, &(sym->declared_at), t->name, | |||
5323 | t->name); | |||
5324 | } | |||
5325 | ||||
5326 | if (sym->attr.is_bind_c == 1) | |||
5327 | gfc_error_now ("Variable %qs in common block %qs at %C cannot " | |||
5328 | "be bind(c) since it is not global", sym->name, | |||
5329 | t->name); | |||
5330 | } | |||
5331 | ||||
5332 | if (sym->attr.in_common) | |||
5333 | { | |||
5334 | gfc_error ("Symbol %qs at %C is already in a COMMON block", | |||
5335 | sym->name); | |||
5336 | goto cleanup; | |||
5337 | } | |||
5338 | ||||
5339 | if (((sym->value != NULL__null && sym->value->expr_type != EXPR_NULL) | |||
5340 | || sym->attr.data) && gfc_current_state ()(gfc_state_stack->state) != COMP_BLOCK_DATA) | |||
5341 | { | |||
5342 | if (!gfc_notify_std (GFC_STD_GNU(1<<5), "Initialized symbol %qs at " | |||
5343 | "%C can only be COMMON in BLOCK DATA", | |||
5344 | sym->name)) | |||
5345 | goto cleanup; | |||
5346 | } | |||
5347 | ||||
5348 | /* F2018:R874: common-block-object is variable-name [ (array-spec) ] | |||
5349 | F2018:C8121: A variable-name shall not be a name made accessible | |||
5350 | by use association. */ | |||
5351 | if (sym->attr.use_assoc) | |||
5352 | { | |||
5353 | gfc_error ("Symbol %qs at %C is USE associated from module %qs " | |||
5354 | "and cannot occur in COMMON", sym->name, sym->module); | |||
5355 | goto cleanup; | |||
5356 | } | |||
5357 | ||||
5358 | /* Deal with an optional array specification after the | |||
5359 | symbol name. */ | |||
5360 | m = gfc_match_array_spec (&as, true, true); | |||
5361 | if (m == MATCH_ERROR) | |||
5362 | goto cleanup; | |||
5363 | ||||
5364 | if (m == MATCH_YES) | |||
5365 | { | |||
5366 | if (as->type != AS_EXPLICIT) | |||
5367 | { | |||
5368 | gfc_error ("Array specification for symbol %qs in COMMON " | |||
5369 | "at %C must be explicit", sym->name); | |||
5370 | goto cleanup; | |||
5371 | } | |||
5372 | ||||
5373 | if (as->corank) | |||
5374 | { | |||
5375 | gfc_error ("Symbol %qs in COMMON at %C cannot be a " | |||
5376 | "coarray", sym->name); | |||
5377 | goto cleanup; | |||
5378 | } | |||
5379 | ||||
5380 | if (!gfc_add_dimension (&sym->attr, sym->name, NULL__null)) | |||
5381 | goto cleanup; | |||
5382 | ||||
5383 | if (sym->attr.pointer) | |||
5384 | { | |||
5385 | gfc_error ("Symbol %qs in COMMON at %C cannot be a " | |||
5386 | "POINTER array", sym->name); | |||
5387 | goto cleanup; | |||
5388 | } | |||
5389 | ||||
5390 | sym->as = as; | |||
5391 | as = NULL__null; | |||
5392 | ||||
5393 | } | |||
5394 | ||||
5395 | /* Add the in_common attribute, but ignore the reported errors | |||
5396 | if any, and continue matching. */ | |||
5397 | gfc_add_in_common (&sym->attr, sym->name, NULL__null); | |||
5398 | ||||
5399 | sym->common_block = t; | |||
5400 | sym->common_block->refs++; | |||
5401 | ||||
5402 | if (tail != NULL__null) | |||
5403 | tail->common_next = sym; | |||
5404 | else | |||
5405 | *head = sym; | |||
5406 | ||||
5407 | tail = sym; | |||
5408 | ||||
5409 | sym->common_head = t; | |||
5410 | ||||
5411 | /* Check to see if the symbol is already in an equivalence group. | |||
5412 | If it is, set the other members as being in common. */ | |||
5413 | if (sym->attr.in_equivalence) | |||
5414 | { | |||
5415 | for (e1 = gfc_current_ns->equiv; e1; e1 = e1->next) | |||
5416 | { | |||
5417 | for (e2 = e1; e2; e2 = e2->eq) | |||
5418 | if (e2->expr->symtree->n.sym == sym) | |||
5419 | goto equiv_found; | |||
5420 | ||||
5421 | continue; | |||
5422 | ||||
5423 | equiv_found: | |||
5424 | ||||
5425 | for (e2 = e1; e2; e2 = e2->eq) | |||
5426 | { | |||
5427 | other = e2->expr->symtree->n.sym; | |||
5428 | if (other->common_head | |||
5429 | && other->common_head != sym->common_head) | |||
5430 | { | |||
5431 | gfc_error ("Symbol %qs, in COMMON block %qs at " | |||
5432 | "%C is being indirectly equivalenced to " | |||
5433 | "another COMMON block %qs", | |||
5434 | sym->name, sym->common_head->name, | |||
5435 | other->common_head->name); | |||
5436 | goto cleanup; | |||
5437 | } | |||
5438 | other->attr.in_common = 1; | |||
5439 | other->common_head = t; | |||
5440 | } | |||
5441 | } | |||
5442 | } | |||
5443 | ||||
5444 | ||||
5445 | gfc_gobble_whitespace (); | |||
5446 | if (gfc_match_eos () == MATCH_YES) | |||
5447 | goto done; | |||
5448 | c = gfc_peek_ascii_char (); | |||
5449 | if (c == '/') | |||
5450 | break; | |||
5451 | if (c != ',') | |||
5452 | { | |||
5453 | /* In Fixed form source code, gfortran can end up here for an | |||
5454 | expression of the form COMMONI = RHS. This may not be an | |||
5455 | error, so return MATCH_NO. */ | |||
5456 | if (gfc_current_form == FORM_FIXED && c == '=') | |||
5457 | { | |||
5458 | gfc_free_array_spec (as); | |||
5459 | return MATCH_NO; | |||
5460 | } | |||
5461 | goto syntax; | |||
5462 | } | |||
5463 | else | |||
5464 | gfc_match_char (','); | |||
5465 | ||||
5466 | gfc_gobble_whitespace (); | |||
5467 | if (gfc_peek_ascii_char () == '/') | |||
5468 | break; | |||
5469 | } | |||
5470 | } | |||
5471 | ||||
5472 | done: | |||
5473 | return MATCH_YES; | |||
5474 | ||||
5475 | syntax: | |||
5476 | gfc_syntax_error (ST_COMMON)gfc_error ("Syntax error in %s statement at %C", gfc_ascii_statement (ST_COMMON));; | |||
5477 | ||||
5478 | cleanup: | |||
5479 | gfc_free_array_spec (as); | |||
5480 | return MATCH_ERROR; | |||
5481 | } | |||
5482 | ||||
5483 | ||||
5484 | /* Match a BLOCK DATA program unit. */ | |||
5485 | ||||
5486 | match | |||
5487 | gfc_match_block_data (void) | |||
5488 | { | |||
5489 | char name[GFC_MAX_SYMBOL_LEN63 + 1]; | |||
5490 | gfc_symbol *sym; | |||
5491 | match m; | |||
5492 | ||||
5493 | if (!gfc_notify_std (GFC_STD_F2018_OBS(1<<10), "BLOCK DATA construct at %L", | |||
5494 | &gfc_current_locus)) | |||
5495 | return MATCH_ERROR; | |||
5496 | ||||
5497 | if (gfc_match_eos () == MATCH_YES) | |||
5498 | { | |||
5499 | gfc_new_block = NULL__null; | |||
5500 | return MATCH_YES; | |||
5501 | } | |||
5502 | ||||
5503 | m = gfc_match ("% %n%t", name); | |||
5504 | if (m != MATCH_YES) | |||
5505 | return MATCH_ERROR; | |||
5506 | ||||
5507 | if (gfc_get_symbol (name, NULL__null, &sym)) | |||
5508 | return MATCH_ERROR; | |||
5509 | ||||
5510 | if (!gfc_add_flavor (&sym->attr, FL_BLOCK_DATA, sym->name, NULL__null)) | |||
5511 | return MATCH_ERROR; | |||
5512 | ||||
5513 | gfc_new_block = sym; | |||
5514 | ||||
5515 | return MATCH_YES; | |||
5516 | } | |||
5517 | ||||
5518 | ||||
5519 | /* Free a namelist structure. */ | |||
5520 | ||||
5521 | void | |||
5522 | gfc_free_namelist (gfc_namelist *name) | |||
5523 | { | |||
5524 | gfc_namelist *n; | |||
5525 | ||||
5526 | for (; name; name = n) | |||
5527 | { | |||
5528 | n = name->next; | |||
5529 | free (name); | |||
5530 | } | |||
5531 | } | |||
5532 | ||||
5533 | ||||
5534 | /* Free an OpenMP namelist structure. */ | |||
5535 | ||||
5536 | void | |||
5537 | gfc_free_omp_namelist (gfc_omp_namelist *name, bool free_ns, bool free_align) | |||
5538 | { | |||
5539 | gfc_omp_namelist *n; | |||
5540 | ||||
5541 | for (; name; name = n) | |||
5542 | { | |||
5543 | gfc_free_expr (name->expr); | |||
5544 | if (free_align) | |||
5545 | gfc_free_expr (name->u.align); | |||
5546 | if (free_ns) | |||
5547 | gfc_free_namespace (name->u2.ns); | |||
5548 | else if (name->u2.udr) | |||
5549 | { | |||
5550 | if (name->u2.udr->combiner) | |||
5551 | gfc_free_statement (name->u2.udr->combiner); | |||
5552 | if (name->u2.udr->initializer) | |||
5553 | gfc_free_statement (name->u2.udr->initializer); | |||
5554 | free (name->u2.udr); | |||
5555 | } | |||
5556 | n = name->next; | |||
5557 | free (name); | |||
5558 | } | |||
5559 | } | |||
5560 | ||||
5561 | ||||
5562 | /* Match a NAMELIST statement. */ | |||
5563 | ||||
5564 | match | |||
5565 | gfc_match_namelist (void) | |||
5566 | { | |||
5567 | gfc_symbol *group_name, *sym; | |||
5568 | gfc_namelist *nl; | |||
5569 | match m, m2; | |||
5570 | ||||
5571 | m = gfc_match (" / %s /", &group_name); | |||
5572 | if (m == MATCH_NO) | |||
5573 | goto syntax; | |||
5574 | if (m == MATCH_ERROR) | |||
5575 | goto error; | |||
5576 | ||||
5577 | for (;;) | |||
5578 | { | |||
5579 | if (group_name->ts.type != BT_UNKNOWN) | |||
5580 | { | |||
5581 | gfc_error ("Namelist group name %qs at %C already has a basic " | |||
5582 | "type of %s", group_name->name, | |||
5583 | gfc_typename (&group_name->ts)); | |||
5584 | return MATCH_ERROR; | |||
5585 | } | |||
5586 | ||||
5587 | if (group_name->attr.flavor == FL_NAMELIST | |||
5588 | && group_name->attr.use_assoc | |||
5589 | && !gfc_notify_std (GFC_STD_GNU(1<<5), "Namelist group name %qs " | |||
5590 | "at %C already is USE associated and can" | |||
5591 | "not be respecified.", group_name->name)) | |||
5592 | return MATCH_ERROR; | |||
5593 | ||||
5594 | if (group_name->attr.flavor != FL_NAMELIST | |||
5595 | && !gfc_add_flavor (&group_name->attr, FL_NAMELIST, | |||
5596 | group_name->name, NULL__null)) | |||
5597 | return MATCH_ERROR; | |||
5598 | ||||
5599 | for (;;) | |||
5600 | { | |||
5601 | m = gfc_match_symbol (&sym, 1); | |||
5602 | if (m == MATCH_NO) | |||
5603 | goto syntax; | |||
5604 | if (m == MATCH_ERROR) | |||
5605 | goto error; | |||
5606 | ||||
5607 | if (sym->ts.type == BT_UNKNOWN) | |||
5608 | { | |||
5609 | if (gfc_current_ns->seen_implicit_none) | |||
5610 | { | |||
5611 | /* It is required that members of a namelist be declared | |||
5612 | before the namelist. We check this by checking if the | |||
5613 | symbol has a defined type for IMPLICIT NONE. */ | |||
5614 | gfc_error ("Symbol %qs in namelist %qs at %C must be " | |||
5615 | "declared before the namelist is declared.", | |||
5616 | sym->name, group_name->name); | |||
5617 | gfc_error_check (); | |||
5618 | } | |||
5619 | else | |||
5620 | /* If the type is not set already, we set it here to the | |||
5621 | implicit default type. It is not allowed to set it | |||
5622 | later to any other type. */ | |||
5623 | gfc_set_default_type (sym, 0, gfc_current_ns); | |||
5624 | } | |||
5625 | if (sym->attr.in_namelist == 0 | |||
5626 | && !gfc_add_in_namelist (&sym->attr, sym->name, NULL__null)) | |||
5627 | goto error; | |||
5628 | ||||
5629 | /* Use gfc_error_check here, rather than goto error, so that | |||
5630 | these are the only errors for the next two lines. */ | |||
5631 | if (sym->as && sym->as->type == AS_ASSUMED_SIZE) | |||
5632 | { | |||
5633 | gfc_error ("Assumed size array %qs in namelist %qs at " | |||
5634 | "%C is not allowed", sym->name, group_name->name); | |||
5635 | gfc_error_check (); | |||
5636 | } | |||
5637 | ||||
5638 | nl = gfc_get_namelist ()((gfc_namelist *) xcalloc (1, sizeof (gfc_namelist))); | |||
5639 | nl->sym = sym; | |||
5640 | sym->refs++; | |||
5641 | ||||
5642 | if (group_name->namelist == NULL__null) | |||
5643 | group_name->namelist = group_name->namelist_tail = nl; | |||
5644 | else | |||
5645 | { | |||
5646 | group_name->namelist_tail->next = nl; | |||
5647 | group_name->namelist_tail = nl; | |||
5648 | } | |||
5649 | ||||
5650 | if (gfc_match_eos () == MATCH_YES) | |||
5651 | goto done; | |||
5652 | ||||
5653 | m = gfc_match_char (','); | |||
5654 | ||||
5655 | if (gfc_match_char ('/') == MATCH_YES) | |||
5656 | { | |||
5657 | m2 = gfc_match (" %s /", &group_name); | |||
5658 | if (m2 == MATCH_YES) | |||
5659 | break; | |||
5660 | if (m2 == MATCH_ERROR) | |||
5661 | goto error; | |||
5662 | goto syntax; | |||
5663 | } | |||
5664 | ||||
5665 | if (m != MATCH_YES) | |||
5666 | goto syntax; | |||
5667 | } | |||
5668 | } | |||
5669 | ||||
5670 | done: | |||
5671 | return MATCH_YES; | |||
5672 | ||||
5673 | syntax: | |||
5674 | gfc_syntax_error (ST_NAMELIST)gfc_error ("Syntax error in %s statement at %C", gfc_ascii_statement (ST_NAMELIST));; | |||
5675 | ||||
5676 | error: | |||
5677 | return MATCH_ERROR; | |||
5678 | } | |||
5679 | ||||
5680 | ||||
5681 | /* Match a MODULE statement. */ | |||
5682 | ||||
5683 | match | |||
5684 | gfc_match_module (void) | |||
5685 | { | |||
5686 | match m; | |||
5687 | ||||
5688 | m = gfc_match (" %s%t", &gfc_new_block); | |||
5689 | if (m != MATCH_YES) | |||
5690 | return m; | |||
5691 | ||||
5692 | if (!gfc_add_flavor (&gfc_new_block->attr, FL_MODULE, | |||
5693 | gfc_new_block->name, NULL__null)) | |||
5694 | return MATCH_ERROR; | |||
5695 | ||||
5696 | return MATCH_YES; | |||
5697 | } | |||
5698 | ||||
5699 | ||||
5700 | /* Free equivalence sets and lists. Recursively is the easiest way to | |||
5701 | do this. */ | |||
5702 | ||||
5703 | void | |||
5704 | gfc_free_equiv_until (gfc_equiv *eq, gfc_equiv *stop) | |||
5705 | { | |||
5706 | if (eq == stop) | |||
5707 | return; | |||
5708 | ||||
5709 | gfc_free_equiv (eq->eq); | |||
5710 | gfc_free_equiv_until (eq->next, stop); | |||
5711 | gfc_free_expr (eq->expr); | |||
5712 | free (eq); | |||
5713 | } | |||
5714 | ||||
5715 | ||||
5716 | void | |||
5717 | gfc_free_equiv (gfc_equiv *eq) | |||
5718 | { | |||
5719 | gfc_free_equiv_until (eq, NULL__null); | |||
5720 | } | |||
5721 | ||||
5722 | ||||
5723 | /* Match an EQUIVALENCE statement. */ | |||
5724 | ||||
5725 | match | |||
5726 | gfc_match_equivalence (void) | |||
5727 | { | |||
5728 | gfc_equiv *eq, *set, *tail; | |||
5729 | gfc_ref *ref; | |||
5730 | gfc_symbol *sym; | |||
5731 | match m; | |||
5732 | gfc_common_head *common_head = NULL__null; | |||
5733 | bool common_flag; | |||
5734 | int cnt; | |||
5735 | char c; | |||
5736 | ||||
5737 | /* EQUIVALENCE has been matched. After gobbling any possible whitespace, | |||
5738 | the next character needs to be '('. Check that here, and return | |||
5739 | MATCH_NO for a variable of the form equivalencej. */ | |||
5740 | gfc_gobble_whitespace (); | |||
5741 | c = gfc_peek_ascii_char (); | |||
5742 | if (c != '(') | |||
5743 | return MATCH_NO; | |||
5744 | ||||
5745 | tail = NULL__null; | |||
5746 | ||||
5747 | for (;;) | |||
5748 | { | |||
5749 | eq = gfc_get_equiv ()((gfc_equiv *) xcalloc (1, sizeof (gfc_equiv))); | |||
5750 | if (tail == NULL__null) | |||
5751 | tail = eq; | |||
5752 | ||||
5753 | eq->next = gfc_current_ns->equiv; | |||
5754 | gfc_current_ns->equiv = eq; | |||
5755 | ||||
5756 | if (gfc_match_char ('(') != MATCH_YES) | |||
5757 | goto syntax; | |||
5758 | ||||
5759 | set = eq; | |||
5760 | common_flag = FALSEfalse; | |||
5761 | cnt = 0; | |||
5762 | ||||
5763 | for (;;) | |||
5764 | { | |||
5765 | m = gfc_match_equiv_variable (&set->expr); | |||
5766 | if (m == MATCH_ERROR) | |||
5767 | goto cleanup; | |||
5768 | if (m == MATCH_NO) | |||
5769 | goto syntax; | |||
5770 | ||||
5771 | /* count the number of objects. */ | |||
5772 | cnt++; | |||
5773 | ||||
5774 | if (gfc_match_char ('%') == MATCH_YES) | |||
5775 | { | |||
5776 | gfc_error ("Derived type component %C is not a " | |||
5777 | "permitted EQUIVALENCE member"); | |||
5778 | goto cleanup; | |||
5779 | } | |||
5780 | ||||
5781 | for (ref = set->expr->ref; ref; ref = ref->next) | |||
5782 | if (ref->type == REF_ARRAY && ref->u.ar.type == AR_SECTION) | |||
5783 | { | |||
5784 | gfc_error ("Array reference in EQUIVALENCE at %C cannot " | |||
5785 | "be an array section"); | |||
5786 | goto cleanup; | |||
5787 | } | |||
5788 | ||||
5789 | sym = set->expr->symtree->n.sym; | |||
5790 | ||||
5791 | if (!gfc_add_in_equivalence (&sym->attr, sym->name, NULL__null)) | |||
5792 | goto cleanup; | |||
5793 | if (sym->ts.type == BT_CLASS | |||
5794 | && CLASS_DATA (sym)sym->ts.u.derived->components | |||
5795 | && !gfc_add_in_equivalence (&CLASS_DATA (sym)sym->ts.u.derived->components->attr, | |||
5796 | sym->name, NULL__null)) | |||
5797 | goto cleanup; | |||
5798 | ||||
5799 | if (sym->attr.in_common) | |||
5800 | { | |||
5801 | common_flag = TRUEtrue; | |||
5802 | common_head = sym->common_head; | |||
5803 | } | |||
5804 | ||||
5805 | if (gfc_match_char (')') == MATCH_YES) | |||
5806 | break; | |||
5807 | ||||
5808 | if (gfc_match_char (',') != MATCH_YES) | |||
5809 | goto syntax; | |||
5810 | ||||
5811 | set->eq = gfc_get_equiv ()((gfc_equiv *) xcalloc (1, sizeof (gfc_equiv))); | |||
5812 | set = set->eq; | |||
5813 | } | |||
5814 | ||||
5815 | if (cnt < 2) | |||
5816 | { | |||
5817 | gfc_error ("EQUIVALENCE at %C requires two or more objects"); | |||
5818 | goto cleanup; | |||
5819 | } | |||
5820 | ||||
5821 | /* If one of the members of an equivalence is in common, then | |||
5822 | mark them all as being in common. Before doing this, check | |||
5823 | that members of the equivalence group are not in different | |||
5824 | common blocks. */ | |||
5825 | if (common_flag) | |||
5826 | for (set = eq; set; set = set->eq) | |||
5827 | { | |||
5828 | sym = set->expr->symtree->n.sym; | |||
5829 | if (sym->common_head && sym->common_head != common_head) | |||
5830 | { | |||
5831 | gfc_error ("Attempt to indirectly overlap COMMON " | |||
5832 | "blocks %s and %s by EQUIVALENCE at %C", | |||
5833 | sym->common_head->name, common_head->name); | |||
5834 | goto cleanup; | |||
5835 | } | |||
5836 | sym->attr.in_common = 1; | |||
5837 | sym->common_head = common_head; | |||
5838 | } | |||
5839 | ||||
5840 | if (gfc_match_eos () == MATCH_YES) | |||
5841 | break; | |||
5842 | if (gfc_match_char (',') != MATCH_YES) | |||
5843 | { | |||
5844 | gfc_error ("Expecting a comma in EQUIVALENCE at %C"); | |||
5845 | goto cleanup; | |||
5846 | } | |||
5847 | } | |||
5848 | ||||
5849 | if (!gfc_notify_std (GFC_STD_F2018_OBS(1<<10), "EQUIVALENCE statement at %C")) | |||
5850 | return MATCH_ERROR; | |||
5851 | ||||
5852 | return MATCH_YES; | |||
5853 | ||||
5854 | syntax: | |||
5855 | gfc_syntax_error (ST_EQUIVALENCE)gfc_error ("Syntax error in %s statement at %C", gfc_ascii_statement (ST_EQUIVALENCE));; | |||
5856 | ||||
5857 | cleanup: | |||
5858 | eq = tail->next; | |||
5859 | tail->next = NULL__null; | |||
5860 | ||||
5861 | gfc_free_equiv (gfc_current_ns->equiv); | |||
5862 | gfc_current_ns->equiv = eq; | |||
5863 | ||||
5864 | return MATCH_ERROR; | |||
5865 | } | |||
5866 | ||||
5867 | ||||
5868 | /* Check that a statement function is not recursive. This is done by looking | |||
5869 | for the statement function symbol(sym) by looking recursively through its | |||
5870 | expression(e). If a reference to sym is found, true is returned. | |||
5871 | 12.5.4 requires that any variable of function that is implicitly typed | |||
5872 | shall have that type confirmed by any subsequent type declaration. The | |||
5873 | implicit typing is conveniently done here. */ | |||
5874 | static bool | |||
5875 | recursive_stmt_fcn (gfc_expr *, gfc_symbol *); | |||
5876 | ||||
5877 | static bool | |||
5878 | check_stmt_fcn (gfc_expr *e, gfc_symbol *sym, int *f ATTRIBUTE_UNUSED__attribute__ ((__unused__))) | |||
5879 | { | |||
5880 | ||||
5881 | if (e == NULL__null) | |||
5882 | return false; | |||
5883 | ||||
5884 | switch (e->expr_type) | |||
5885 | { | |||
5886 | case EXPR_FUNCTION: | |||
5887 | if (e->symtree == NULL__null) | |||
5888 | return false; | |||
5889 | ||||
5890 | /* Check the name before testing for nested recursion! */ | |||
5891 | if (sym->name == e->symtree->n.sym->name) | |||
5892 | return true; | |||
5893 | ||||
5894 | /* Catch recursion via other statement functions. */ | |||
5895 | if (e->symtree->n.sym->attr.proc == PROC_ST_FUNCTION | |||
5896 | && e->symtree->n.sym->value | |||
5897 | && recursive_stmt_fcn (e->symtree->n.sym->value, sym)) | |||
5898 | return true; | |||
5899 | ||||
5900 | if (e->symtree->n.sym->ts.type == BT_UNKNOWN) | |||
5901 | gfc_set_default_type (e->symtree->n.sym, 0, NULL__null); | |||
5902 | ||||
5903 | break; | |||
5904 | ||||
5905 | case EXPR_VARIABLE: | |||
5906 | if (e->symtree && sym->name == e->symtree->n.sym->name) | |||
5907 | return true; | |||
5908 | ||||
5909 | if (e->symtree->n.sym->ts.type == BT_UNKNOWN) | |||
5910 | gfc_set_default_type (e->symtree->n.sym, 0, NULL__null); | |||
5911 | break; | |||
5912 | ||||
5913 | default: | |||
5914 | break; | |||
5915 | } | |||
5916 | ||||
5917 | return false; | |||
5918 | } | |||
5919 | ||||
5920 | ||||
5921 | static bool | |||
5922 | recursive_stmt_fcn (gfc_expr *e, gfc_symbol *sym) | |||
5923 | { | |||
5924 | return gfc_traverse_expr (e, sym, check_stmt_fcn, 0); | |||
5925 | } | |||
5926 | ||||
5927 | ||||
5928 | /* Check for invalid uses of statement function dummy arguments in body. */ | |||
5929 | ||||
5930 | static bool | |||
5931 | chk_stmt_fcn_body (gfc_expr *e, gfc_symbol *sym, int *f ATTRIBUTE_UNUSED__attribute__ ((__unused__))) | |||
5932 | { | |||
5933 | gfc_formal_arglist *formal; | |||
5934 | ||||
5935 | if (e == NULL__null || e->symtree == NULL__null || e->expr_type != EXPR_FUNCTION) | |||
5936 | return false; | |||
5937 | ||||
5938 | for (formal = sym->formal; formal; formal = formal->next) | |||
5939 | { | |||
5940 | if (formal->sym == e->symtree->n.sym) | |||
5941 | { | |||
5942 | gfc_error ("Invalid use of statement function argument at %L", | |||
5943 | &e->where); | |||
5944 | return true; | |||
5945 | } | |||
5946 | } | |||
5947 | ||||
5948 | return false; | |||
5949 | } | |||
5950 | ||||
5951 | ||||
5952 | /* Match a statement function declaration. It is so easy to match | |||
5953 | non-statement function statements with a MATCH_ERROR as opposed to | |||
5954 | MATCH_NO that we suppress error message in most cases. */ | |||
5955 | ||||
5956 | match | |||
5957 | gfc_match_st_function (void) | |||
5958 | { | |||
5959 | gfc_error_buffer old_error; | |||
5960 | gfc_symbol *sym; | |||
5961 | gfc_expr *expr; | |||
5962 | match m; | |||
5963 | char name[GFC_MAX_SYMBOL_LEN63 + 1]; | |||
5964 | locus old_locus; | |||
5965 | bool fcn; | |||
5966 | gfc_formal_arglist *ptr; | |||
5967 | ||||
5968 | /* Read the possible statement function name, and then check to see if | |||
5969 | a symbol is already present in the namespace. Record if it is a | |||
5970 | function and whether it has been referenced. */ | |||
5971 | fcn = false; | |||
5972 | ptr = NULL__null; | |||
5973 | old_locus = gfc_current_locus; | |||
5974 | m = gfc_match_name (name); | |||
5975 | if (m == MATCH_YES) | |||
5976 | { | |||
5977 | gfc_find_symbol (name, NULL__null, 1, &sym); | |||
5978 | if (sym && sym->attr.function && !sym->attr.referenced) | |||
5979 | { | |||
5980 | fcn = true; | |||
5981 | ptr = sym->formal; | |||
5982 | } | |||
5983 | } | |||
5984 | ||||
5985 | gfc_current_locus = old_locus; | |||
5986 | m = gfc_match_symbol (&sym, 0); | |||
5987 | if (m != MATCH_YES) | |||
5988 | return m; | |||
5989 | ||||
5990 | gfc_push_error (&old_error); | |||
5991 | ||||
5992 | if (!gfc_add_procedure (&sym->attr, PROC_ST_FUNCTION, sym->name, NULL__null)) | |||
5993 | goto undo_error; | |||
5994 | ||||
5995 | if (gfc_match_formal_arglist (sym, 1, 0) != MATCH_YES) | |||
5996 | goto undo_error; | |||
5997 | ||||
5998 | m = gfc_match (" = %e%t", &expr); | |||
5999 | if (m == MATCH_NO) | |||
6000 | goto undo_error; | |||
6001 | ||||
6002 | gfc_free_error (&old_error); | |||
6003 | ||||
6004 | if (m == MATCH_ERROR) | |||
6005 | return m; | |||
6006 | ||||
6007 | if (recursive_stmt_fcn (expr, sym)) | |||
6008 | { | |||
6009 | gfc_error ("Statement function at %L is recursive", &expr->where); | |||
6010 | return MATCH_ERROR; | |||
6011 | } | |||
6012 | ||||
6013 | if (fcn && ptr != sym->formal) | |||
6014 | { | |||
6015 | gfc_error ("Statement function %qs at %L conflicts with function name", | |||
6016 | sym->name, &expr->where); | |||
6017 | return MATCH_ERROR; | |||
6018 | } | |||
6019 | ||||
6020 | if (gfc_traverse_expr (expr, sym, chk_stmt_fcn_body, 0)) | |||
6021 | return MATCH_ERROR; | |||
6022 | ||||
6023 | sym->value = expr; | |||
6024 | ||||
6025 | if ((gfc_current_state ()(gfc_state_stack->state) == COMP_FUNCTION | |||
6026 | || gfc_current_state ()(gfc_state_stack->state) == COMP_SUBROUTINE) | |||
6027 | && gfc_state_stack->previous->state == COMP_INTERFACE) | |||
6028 | { | |||
6029 | gfc_error ("Statement function at %L cannot appear within an INTERFACE", | |||
6030 | &expr->where); | |||
6031 | return MATCH_ERROR; | |||
6032 | } | |||
6033 | ||||
6034 | if (!gfc_notify_std (GFC_STD_F95_OBS(1<<1), "Statement function at %C")) | |||
6035 | return MATCH_ERROR; | |||
6036 | ||||
6037 | return MATCH_YES; | |||
6038 | ||||
6039 | undo_error: | |||
6040 | gfc_pop_error (&old_error); | |||
6041 | return MATCH_NO; | |||
6042 | } | |||
6043 | ||||
6044 | ||||
6045 | /* Match an assignment to a pointer function (F2008). This could, in | |||
6046 | general be ambiguous with a statement function. In this implementation | |||
6047 | it remains so if it is the first statement after the specification | |||
6048 | block. */ | |||
6049 | ||||
6050 | match | |||
6051 | gfc_match_ptr_fcn_assign (void) | |||
6052 | { | |||
6053 | gfc_error_buffer old_error; | |||
6054 | locus old_loc; | |||
6055 | gfc_symbol *sym; | |||
6056 | gfc_expr *expr; | |||
6057 | match m; | |||
6058 | char name[GFC_MAX_SYMBOL_LEN63 + 1]; | |||
6059 | ||||
6060 | old_loc = gfc_current_locus; | |||
6061 | m = gfc_match_name (name); | |||
6062 | if (m != MATCH_YES) | |||
6063 | return m; | |||
6064 | ||||
6065 | gfc_find_symbol (name, NULL__null, 1, &sym); | |||
6066 | if (sym && sym->attr.flavor != FL_PROCEDURE) | |||
6067 | return MATCH_NO; | |||
6068 | ||||
6069 | gfc_push_error (&old_error); | |||
6070 | ||||
6071 | if (sym && sym->attr.function) | |||
6072 | goto match_actual_arglist; | |||
6073 | ||||
6074 | gfc_current_locus = old_loc; | |||
6075 | m = gfc_match_symbol (&sym, 0); | |||
6076 | if (m != MATCH_YES) | |||
6077 | return m; | |||
6078 | ||||
6079 | if (!gfc_add_procedure (&sym->attr, PROC_UNKNOWN, sym->name, NULL__null)) | |||
6080 | goto undo_error; | |||
6081 | ||||
6082 | match_actual_arglist: | |||
6083 | gfc_current_locus = old_loc; | |||
6084 | m = gfc_match (" %e", &expr); | |||
6085 | if (m != MATCH_YES) | |||
6086 | goto undo_error; | |||
6087 | ||||
6088 | new_st.op = EXEC_ASSIGN; | |||
6089 | new_st.expr1 = expr; | |||
6090 | expr = NULL__null; | |||
6091 | ||||
6092 | m = gfc_match (" = %e%t", &expr); | |||
6093 | if (m != MATCH_YES) | |||
6094 | goto undo_error; | |||
6095 | ||||
6096 | new_st.expr2 = expr; | |||
6097 | return MATCH_YES; | |||
6098 | ||||
6099 | undo_error: | |||
6100 | gfc_pop_error (&old_error); | |||
6101 | return MATCH_NO; | |||
6102 | } | |||
6103 | ||||
6104 | ||||
6105 | /***************** SELECT CASE subroutines ******************/ | |||
6106 | ||||
6107 | /* Free a single case structure. */ | |||
6108 | ||||
6109 | static void | |||
6110 | free_case (gfc_case *p) | |||
6111 | { | |||
6112 | if (p->low == p->high) | |||
6113 | p->high = NULL__null; | |||
6114 | gfc_free_expr (p->low); | |||
6115 | gfc_free_expr (p->high); | |||
6116 | free (p); | |||
6117 | } | |||
6118 | ||||
6119 | ||||
6120 | /* Free a list of case structures. */ | |||
6121 | ||||
6122 | void | |||
6123 | gfc_free_case_list (gfc_case *p) | |||
6124 | { | |||
6125 | gfc_case *q; | |||
6126 | ||||
6127 | for (; p; p = q) | |||
6128 | { | |||
6129 | q = p->next; | |||
6130 | free_case (p); | |||
6131 | } | |||
6132 | } | |||
6133 | ||||
6134 | ||||
6135 | /* Match a single case selector. Combining the requirements of F08:C830 | |||
6136 | and F08:C832 (R838) means that the case-value must have either CHARACTER, | |||
6137 | INTEGER, or LOGICAL type. */ | |||
6138 | ||||
6139 | static match | |||
6140 | match_case_selector (gfc_case **cp) | |||
6141 | { | |||
6142 | gfc_case *c; | |||
6143 | match m; | |||
6144 | ||||
6145 | c = gfc_get_case ()((gfc_case *) xcalloc (1, sizeof (gfc_case))); | |||
6146 | c->where = gfc_current_locus; | |||
6147 | ||||
6148 | if (gfc_match_char (':') == MATCH_YES) | |||
6149 | { | |||
6150 | m = gfc_match_init_expr (&c->high); | |||
6151 | if (m == MATCH_NO) | |||
6152 | goto need_expr; | |||
6153 | if (m == MATCH_ERROR) | |||
6154 | goto cleanup; | |||
6155 | ||||
6156 | if (c->high->ts.type != BT_LOGICAL && c->high->ts.type != BT_INTEGER | |||
6157 | && c->high->ts.type != BT_CHARACTER) | |||
6158 | { | |||
6159 | gfc_error ("Expression in CASE selector at %L cannot be %s", | |||
6160 | &c->high->where, gfc_typename (&c->high->ts)); | |||
6161 | goto cleanup; | |||
6162 | } | |||
6163 | } | |||
6164 | else | |||
6165 | { | |||
6166 | m = gfc_match_init_expr (&c->low); | |||
6167 | if (m == MATCH_ERROR) | |||
6168 | goto cleanup; | |||
6169 | if (m == MATCH_NO) | |||
6170 | goto need_expr; | |||
6171 | ||||
6172 | if (c->low->ts.type != BT_LOGICAL && c->low->ts.type != BT_INTEGER | |||
6173 | && c->low->ts.type != BT_CHARACTER) | |||
6174 | { | |||
6175 | gfc_error ("Expression in CASE selector at %L cannot be %s", | |||
6176 | &c->low->where, gfc_typename (&c->low->ts)); | |||
6177 | goto cleanup; | |||
6178 | } | |||
6179 | ||||
6180 | /* If we're not looking at a ':' now, make a range out of a single | |||
6181 | target. Else get the upper bound for the case range. */ | |||
6182 | if (gfc_match_char (':') != MATCH_YES) | |||
6183 | c->high = c->low; | |||
6184 | else | |||
6185 | { | |||
6186 | m = gfc_match_init_expr (&c->high); | |||
6187 | if (m == MATCH_ERROR) | |||
6188 | goto cleanup; | |||
6189 | if (m == MATCH_YES | |||
6190 | && c->high->ts.type != BT_LOGICAL | |||
6191 | && c->high->ts.type != BT_INTEGER | |||
6192 | && c->high->ts.type != BT_CHARACTER) | |||
6193 | { | |||
6194 | gfc_error ("Expression in CASE selector at %L cannot be %s", | |||
6195 | &c->high->where, gfc_typename (c->high)); | |||
6196 | goto cleanup; | |||
6197 | } | |||
6198 | /* MATCH_NO is fine. It's OK if nothing is there! */ | |||
6199 | } | |||
6200 | } | |||
6201 | ||||
6202 | if (c->low && c->low->rank != 0) | |||
6203 | { | |||
6204 | gfc_error ("Expression in CASE selector at %L must be scalar", | |||
6205 | &c->low->where); | |||
6206 | goto cleanup; | |||
6207 | } | |||
6208 | if (c->high && c->high->rank != 0) | |||
6209 | { | |||
6210 | gfc_error ("Expression in CASE selector at %L must be scalar", | |||
6211 | &c->high->where); | |||
6212 | goto cleanup; | |||
6213 | } | |||
6214 | ||||
6215 | *cp = c; | |||
6216 | return MATCH_YES; | |||
6217 | ||||
6218 | need_expr: | |||
6219 | gfc_error ("Expected initialization expression in CASE at %C"); | |||
6220 | ||||
6221 | cleanup: | |||
6222 | free_case (c); | |||
6223 | return MATCH_ERROR; | |||
6224 | } | |||
6225 | ||||
6226 | ||||
6227 | /* Match the end of a case statement. */ | |||
6228 | ||||
6229 | static match | |||
6230 | match_case_eos (void) | |||
6231 | { | |||
6232 | char name[GFC_MAX_SYMBOL_LEN63 + 1]; | |||
6233 | match m; | |||
6234 | ||||
6235 | if (gfc_match_eos () == MATCH_YES) | |||
6236 | return MATCH_YES; | |||
6237 | ||||
6238 | /* If the case construct doesn't have a case-construct-name, we | |||
6239 | should have matched the EOS. */ | |||
6240 | if (!gfc_current_block ()(gfc_state_stack->sym)) | |||
6241 | return MATCH_NO; | |||
6242 | ||||
6243 | gfc_gobble_whitespace (); | |||
6244 | ||||
6245 | m = gfc_match_name (name); | |||
6246 | if (m != MATCH_YES) | |||
6247 | return m; | |||
6248 | ||||
6249 | if (strcmp (name, gfc_current_block ()(gfc_state_stack->sym)->name) != 0) | |||
6250 | { | |||
6251 | gfc_error ("Expected block name %qs of SELECT construct at %C", | |||
6252 | gfc_current_block ()(gfc_state_stack->sym)->name); | |||
6253 | return MATCH_ERROR; | |||
6254 | } | |||
6255 | ||||
6256 | return gfc_match_eos (); | |||
6257 | } | |||
6258 | ||||
6259 | ||||
6260 | /* Match a SELECT statement. */ | |||
6261 | ||||
6262 | match | |||
6263 | gfc_match_select (void) | |||
6264 | { | |||
6265 | gfc_expr *expr; | |||
6266 | match m; | |||
6267 | ||||
6268 | m = gfc_match_label (); | |||
6269 | if (m == MATCH_ERROR) | |||
6270 | return m; | |||
6271 | ||||
6272 | m = gfc_match (" select case ( %e )%t", &expr); | |||
6273 | if (m != MATCH_YES) | |||
6274 | return m; | |||
6275 | ||||
6276 | new_st.op = EXEC_SELECT; | |||
6277 | new_st.expr1 = expr; | |||
6278 | ||||
6279 | return MATCH_YES; | |||
6280 | } | |||
6281 | ||||
6282 | ||||
6283 | /* Transfer the selector typespec to the associate name. */ | |||
6284 | ||||
6285 | static void | |||
6286 | copy_ts_from_selector_to_associate (gfc_expr *associate, gfc_expr *selector) | |||
6287 | { | |||
6288 | gfc_ref *ref; | |||
6289 | gfc_symbol *assoc_sym; | |||
6290 | int rank = 0; | |||
6291 | ||||
6292 | assoc_sym = associate->symtree->n.sym; | |||
6293 | ||||
6294 | /* At this stage the expression rank and arrayspec dimensions have | |||
6295 | not been completely sorted out. We must get the expr2->rank | |||
6296 | right here, so that the correct class container is obtained. */ | |||
6297 | ref = selector->ref; | |||
6298 | while (ref && ref->next) | |||
6299 | ref = ref->next; | |||
6300 | ||||
6301 | if (selector->ts.type == BT_CLASS | |||
6302 | && CLASS_DATA (selector)selector->ts.u.derived->components | |||
6303 | && CLASS_DATA (selector)selector->ts.u.derived->components->as | |||
6304 | && CLASS_DATA (selector)selector->ts.u.derived->components->as->type == AS_ASSUMED_RANK) | |||
6305 | { | |||
6306 | assoc_sym->attr.dimension = 1; | |||
6307 | assoc_sym->as = gfc_copy_array_spec (CLASS_DATA (selector)selector->ts.u.derived->components->as); | |||
6308 | goto build_class_sym; | |||
6309 | } | |||
6310 | else if (selector->ts.type == BT_CLASS | |||
6311 | && CLASS_DATA (selector)selector->ts.u.derived->components | |||
6312 | && CLASS_DATA (selector)selector->ts.u.derived->components->as | |||
6313 | && ref && ref->type == REF_ARRAY) | |||
6314 | { | |||
6315 | /* Ensure that the array reference type is set. We cannot use | |||
6316 | gfc_resolve_expr at this point, so the usable parts of | |||
6317 | resolve.cc(resolve_array_ref) are employed to do it. */ | |||
6318 | if (ref->u.ar.type == AR_UNKNOWN) | |||
6319 | { | |||
6320 | ref->u.ar.type = AR_ELEMENT; | |||
6321 | for (int i = 0; i < ref->u.ar.dimen + ref->u.ar.codimen; i++) | |||
6322 | if (ref->u.ar.dimen_type[i] == DIMEN_RANGE | |||
6323 | || ref->u.ar.dimen_type[i] == DIMEN_VECTOR | |||
6324 | || (ref->u.ar.dimen_type[i] == DIMEN_UNKNOWN | |||
6325 | && ref->u.ar.start[i] && ref->u.ar.start[i]->rank)) | |||
6326 | { | |||
6327 | ref->u.ar.type = AR_SECTION; | |||
6328 | break; | |||
6329 | } | |||
6330 | } | |||
6331 | ||||
6332 | if (ref->u.ar.type == AR_FULL) | |||
6333 | selector->rank = CLASS_DATA (selector)selector->ts.u.derived->components->as->rank; | |||
6334 | else if (ref->u.ar.type == AR_SECTION) | |||
6335 | selector->rank = ref->u.ar.dimen; | |||
6336 | else | |||
6337 | selector->rank = 0; | |||
6338 | ||||
6339 | rank = selector->rank; | |||
6340 | } | |||
6341 | ||||
6342 | if (rank) | |||
6343 | { | |||
6344 | for (int i = 0; i < ref->u.ar.dimen + ref->u.ar.codimen; i++) | |||
6345 | if (ref->u.ar.dimen_type[i] == DIMEN_ELEMENT | |||
6346 | || (ref->u.ar.dimen_type[i] == DIMEN_UNKNOWN | |||
6347 | && ref->u.ar.end[i] == NULL__null | |||
6348 | && ref->u.ar.stride[i] == NULL__null)) | |||
6349 | rank--; | |||
6350 | ||||
6351 | if (rank) | |||
6352 | { | |||
6353 | assoc_sym->attr.dimension = 1; | |||
6354 | assoc_sym->as = gfc_get_array_spec ()((gfc_array_spec *) xcalloc (1, sizeof (gfc_array_spec))); | |||
6355 | assoc_sym->as->rank = rank; | |||
6356 | assoc_sym->as->type = AS_DEFERRED; | |||
6357 | } | |||
6358 | else | |||
6359 | assoc_sym->as = NULL__null; | |||
6360 | } | |||
6361 | else | |||
6362 | assoc_sym->as = NULL__null; | |||
6363 | ||||
6364 | build_class_sym: | |||
6365 | if (selector->ts.type == BT_CLASS) | |||
6366 | { | |||
6367 | /* The correct class container has to be available. */ | |||
6368 | assoc_sym->ts.type = BT_CLASS; | |||
6369 | assoc_sym->ts.u.derived = CLASS_DATA (selector)selector->ts.u.derived->components | |||
6370 | ? CLASS_DATA (selector)selector->ts.u.derived->components->ts.u.derived : selector->ts.u.derived; | |||
6371 | assoc_sym->attr.pointer = 1; | |||
6372 | gfc_build_class_symbol (&assoc_sym->ts, &assoc_sym->attr, &assoc_sym->as); | |||
6373 | } | |||
6374 | } | |||
6375 | ||||
6376 | ||||
6377 | /* Push the current selector onto the SELECT TYPE stack. */ | |||
6378 | ||||
6379 | static void | |||
6380 | select_type_push (gfc_symbol *sel) | |||
6381 | { | |||
6382 | gfc_select_type_stack *top = gfc_get_select_type_stack ()((gfc_select_type_stack *) xcalloc (1, sizeof (gfc_select_type_stack ))); | |||
6383 | top->selector = sel; | |||
6384 | top->tmp = NULL__null; | |||
6385 | top->prev = select_type_stack; | |||
6386 | ||||
6387 | select_type_stack = top; | |||
6388 | } | |||
6389 | ||||
6390 | ||||
6391 | /* Set the temporary for the current intrinsic SELECT TYPE selector. */ | |||
6392 | ||||
6393 | static gfc_symtree * | |||
6394 | select_intrinsic_set_tmp (gfc_typespec *ts) | |||
6395 | { | |||
6396 | char name[GFC_MAX_SYMBOL_LEN63]; | |||
6397 | gfc_symtree *tmp; | |||
6398 | HOST_WIDE_INTlong charlen = 0; | |||
6399 | gfc_symbol *selector = select_type_stack->selector; | |||
6400 | gfc_symbol *sym; | |||
6401 | ||||
6402 | if (ts->type == BT_CLASS || ts->type == BT_DERIVED) | |||
6403 | return NULL__null; | |||
6404 | ||||
6405 | if (selector->ts.type == BT_CLASS && !selector->attr.class_ok) | |||
6406 | return NULL__null; | |||
6407 | ||||
6408 | /* Case value == NULL corresponds to SELECT TYPE cases otherwise | |||
6409 | the values correspond to SELECT rank cases. */ | |||
6410 | if (ts->type == BT_CHARACTER && ts->u.cl && ts->u.cl->length | |||
6411 | && ts->u.cl->length->expr_type == EXPR_CONSTANT) | |||
6412 | charlen = gfc_mpz_get_hwi (ts->u.cl->length->value.integer); | |||
6413 | ||||
6414 | if (ts->type != BT_CHARACTER) | |||
6415 | sprintf (name, "__tmp_%s_%d", gfc_basic_typename (ts->type), | |||
6416 | ts->kind); | |||
6417 | else | |||
6418 | snprintf (name, sizeof (name), | |||
6419 | "__tmp_%s_" HOST_WIDE_INT_PRINT_DEC"%" "l" "d" "_%d", | |||
6420 | gfc_basic_typename (ts->type), charlen, ts->kind); | |||
6421 | ||||
6422 | gfc_get_sym_tree (name, gfc_current_ns, &tmp, false); | |||
6423 | sym = tmp->n.sym; | |||
6424 | gfc_add_type (sym, ts, NULL__null); | |||
6425 | ||||
6426 | /* Copy across the array spec to the selector. */ | |||
6427 | if (selector->ts.type == BT_CLASS | |||
6428 | && (CLASS_DATA (selector)selector->ts.u.derived->components->attr.dimension | |||
6429 | || CLASS_DATA (selector)selector->ts.u.derived->components->attr.codimension)) | |||
6430 | { | |||
6431 | sym->attr.pointer = 1; | |||
6432 | sym->attr.dimension = CLASS_DATA (selector)selector->ts.u.derived->components->attr.dimension; | |||
6433 | sym->attr.codimension = CLASS_DATA (selector)selector->ts.u.derived->components->attr.codimension; | |||
6434 | sym->as = gfc_copy_array_spec (CLASS_DATA (selector)selector->ts.u.derived->components->as); | |||
6435 | } | |||
6436 | ||||
6437 | gfc_set_sym_referenced (sym); | |||
6438 | gfc_add_flavor (&sym->attr, FL_VARIABLE, name, NULL__null); | |||
6439 | sym->attr.select_type_temporary = 1; | |||
6440 | ||||
6441 | return tmp; | |||
6442 | } | |||
6443 | ||||
6444 | ||||
6445 | /* Set up a temporary for the current TYPE IS / CLASS IS branch . */ | |||
6446 | ||||
6447 | static void | |||
6448 | select_type_set_tmp (gfc_typespec *ts) | |||
6449 | { | |||
6450 | char name[GFC_MAX_SYMBOL_LEN63 + 12 + 1]; | |||
6451 | gfc_symtree *tmp = NULL__null; | |||
6452 | gfc_symbol *selector = select_type_stack->selector; | |||
6453 | gfc_symbol *sym; | |||
6454 | ||||
6455 | if (!ts) | |||
6456 | { | |||
6457 | select_type_stack->tmp = NULL__null; | |||
6458 | return; | |||
6459 | } | |||
6460 | ||||
6461 | tmp = select_intrinsic_set_tmp (ts); | |||
6462 | ||||
6463 | if (tmp == NULL__null) | |||
6464 | { | |||
6465 | if (!ts->u.derived) | |||
6466 | return; | |||
6467 | ||||
6468 | if (ts->type == BT_CLASS) | |||
6469 | sprintf (name, "__tmp_class_%s", ts->u.derived->name); | |||
6470 | else | |||
6471 | sprintf (name, "__tmp_type_%s", ts->u.derived->name); | |||
6472 | ||||
6473 | gfc_get_sym_tree (name, gfc_current_ns, &tmp, false); | |||
6474 | sym = tmp->n.sym; | |||
6475 | gfc_add_type (sym, ts, NULL__null); | |||
6476 | ||||
6477 | if (selector->ts.type == BT_CLASS && selector->attr.class_ok | |||
6478 | && selector->ts.u.derived && CLASS_DATA (selector)selector->ts.u.derived->components) | |||
6479 | { | |||
6480 | sym->attr.pointer | |||
6481 | = CLASS_DATA (selector)selector->ts.u.derived->components->attr.class_pointer; | |||
6482 | ||||
6483 | /* Copy across the array spec to the selector. */ | |||
6484 | if (CLASS_DATA (selector)selector->ts.u.derived->components->attr.dimension | |||
6485 | || CLASS_DATA (selector)selector->ts.u.derived->components->attr.codimension) | |||
6486 | { | |||
6487 | sym->attr.dimension | |||
6488 | = CLASS_DATA (selector)selector->ts.u.derived->components->attr.dimension; | |||
6489 | sym->attr.codimension | |||
6490 | = CLASS_DATA (selector)selector->ts.u.derived->components->attr.codimension; | |||
6491 | if (CLASS_DATA (selector)selector->ts.u.derived->components->as->type != AS_EXPLICIT) | |||
6492 | sym->as = gfc_copy_array_spec (CLASS_DATA (selector)selector->ts.u.derived->components->as); | |||
6493 | else | |||
6494 | { | |||
6495 | sym->as = gfc_get_array_spec()((gfc_array_spec *) xcalloc (1, sizeof (gfc_array_spec))); | |||
6496 | sym->as->rank = CLASS_DATA (selector)selector->ts.u.derived->components->as->rank; | |||
6497 | sym->as->type = AS_DEFERRED; | |||
6498 | } | |||
6499 | } | |||
6500 | } | |||
6501 | ||||
6502 | gfc_set_sym_referenced (sym); | |||
6503 | gfc_add_flavor (&sym->attr, FL_VARIABLE, name, NULL__null); | |||
6504 | sym->attr.select_type_temporary = 1; | |||
6505 | ||||
6506 | if (ts->type == BT_CLASS) | |||
6507 | gfc_build_class_symbol (&sym->ts, &sym->attr, &sym->as); | |||
6508 | } | |||
6509 | else | |||
6510 | sym = tmp->n.sym; | |||
6511 | ||||
6512 | ||||
6513 | /* Add an association for it, so the rest of the parser knows it is | |||
6514 | an associate-name. The target will be set during resolution. */ | |||
6515 | sym->assoc = gfc_get_association_list ()((gfc_association_list *) xcalloc (1, sizeof (gfc_association_list ))); | |||
6516 | sym->assoc->dangling = 1; | |||
6517 | sym->assoc->st = tmp; | |||
6518 | ||||
6519 | select_type_stack->tmp = tmp; | |||
6520 | } | |||
6521 | ||||
6522 | ||||
6523 | /* Match a SELECT TYPE statement. */ | |||
6524 | ||||
6525 | match | |||
6526 | gfc_match_select_type (void) | |||
6527 | { | |||
6528 | gfc_expr *expr1, *expr2 = NULL__null; | |||
6529 | match m; | |||
6530 | char name[GFC_MAX_SYMBOL_LEN63 + 1]; | |||
6531 | bool class_array; | |||
6532 | gfc_symbol *sym; | |||
6533 | gfc_namespace *ns = gfc_current_ns; | |||
6534 | ||||
6535 | m = gfc_match_label (); | |||
6536 | if (m == MATCH_ERROR) | |||
6537 | return m; | |||
6538 | ||||
6539 | m = gfc_match (" select type ( "); | |||
6540 | if (m != MATCH_YES) | |||
6541 | return m; | |||
6542 | ||||
6543 | if (gfc_current_state()(gfc_state_stack->state) == COMP_MODULE | |||
6544 | || gfc_current_state()(gfc_state_stack->state) == COMP_SUBMODULE) | |||
6545 | { | |||
6546 | gfc_error ("SELECT TYPE at %C cannot appear in this scope"); | |||
6547 | return MATCH_ERROR; | |||
6548 | } | |||
6549 | ||||
6550 | gfc_current_ns = gfc_build_block_ns (ns); | |||
6551 | m = gfc_match (" %n => %e", name, &expr2); | |||
6552 | if (m == MATCH_YES) | |||
6553 | { | |||
6554 | expr1 = gfc_get_expr (); | |||
6555 | expr1->expr_type = EXPR_VARIABLE; | |||
6556 | expr1->where = expr2->where; | |||
6557 | if (gfc_get_sym_tree (name, NULL__null, &expr1->symtree, false)) | |||
6558 | { | |||
6559 | m = MATCH_ERROR; | |||
6560 | goto cleanup; | |||
6561 | } | |||
6562 | ||||
6563 | sym = expr1->symtree->n.sym; | |||
6564 | if (expr2->ts.type == BT_UNKNOWN) | |||
6565 | sym->attr.untyped = 1; | |||
6566 | else | |||
6567 | copy_ts_from_selector_to_associate (expr1, expr2); | |||
6568 | ||||
6569 | sym->attr.flavor = FL_VARIABLE; | |||
6570 | sym->attr.referenced = 1; | |||
6571 | sym->attr.class_ok = 1; | |||
6572 | } | |||
6573 | else | |||
6574 | { | |||
6575 | m = gfc_match (" %e ", &expr1); | |||
6576 | if (m != MATCH_YES) | |||
6577 | { | |||
6578 | std::swap (ns, gfc_current_ns); | |||
6579 | gfc_free_namespace (ns); | |||
6580 | return m; | |||
6581 | } | |||
6582 | } | |||
6583 | ||||
6584 | m = gfc_match (" )%t"); | |||
6585 | if (m != MATCH_YES) | |||
6586 | { | |||
6587 | gfc_error ("parse error in SELECT TYPE statement at %C"); | |||
6588 | goto cleanup; | |||
6589 | } | |||
6590 | ||||
6591 | /* This ghastly expression seems to be needed to distinguish a CLASS | |||
6592 | array, which can have a reference, from other expressions that | |||
6593 | have references, such as derived type components, and are not | |||
6594 | allowed by the standard. | |||
6595 | TODO: see if it is sufficient to exclude component and substring | |||
6596 | references. */ | |||
6597 | class_array = (expr1->expr_type == EXPR_VARIABLE | |||
6598 | && expr1->ts.type == BT_CLASS | |||
6599 | && CLASS_DATA (expr1)expr1->ts.u.derived->components | |||
6600 | && (strcmp (CLASS_DATA (expr1)expr1->ts.u.derived->components->name, "_data") == 0) | |||
6601 | && (CLASS_DATA (expr1)expr1->ts.u.derived->components->attr.dimension | |||
6602 | || CLASS_DATA (expr1)expr1->ts.u.derived->components->attr.codimension) | |||
6603 | && expr1->ref | |||
6604 | && expr1->ref->type == REF_ARRAY | |||
6605 | && expr1->ref->u.ar.type == AR_FULL | |||
6606 | && expr1->ref->next == NULL__null); | |||
6607 | ||||
6608 | /* Check for F03:C811 (F08:C835). */ | |||
6609 | if (!expr2 && (expr1->expr_type != EXPR_VARIABLE | |||
6610 | || (!class_array && expr1->ref != NULL__null))) | |||
6611 | { | |||
6612 | gfc_error ("Selector in SELECT TYPE at %C is not a named variable; " | |||
6613 | "use associate-name=>"); | |||
6614 | m = MATCH_ERROR; | |||
6615 | goto cleanup; | |||
6616 | } | |||
6617 | ||||
6618 | new_st.op = EXEC_SELECT_TYPE; | |||
6619 | new_st.expr1 = expr1; | |||
6620 | new_st.expr2 = expr2; | |||
6621 | new_st.ext.block.ns = gfc_current_ns; | |||
6622 | ||||
6623 | select_type_push (expr1->symtree->n.sym); | |||
6624 | gfc_current_ns = ns; | |||
6625 | ||||
6626 | return MATCH_YES; | |||
6627 | ||||
6628 | cleanup: | |||
6629 | gfc_free_expr (expr1); | |||
6630 | gfc_free_expr (expr2); | |||
6631 | gfc_undo_symbols (); | |||
6632 | std::swap (ns, gfc_current_ns); | |||
6633 | gfc_free_namespace (ns); | |||
6634 | return m; | |||
6635 | } | |||
6636 | ||||
6637 | ||||
6638 | /* Set the temporary for the current intrinsic SELECT RANK selector. */ | |||
6639 | ||||
6640 | static void | |||
6641 | select_rank_set_tmp (gfc_typespec *ts, int *case_value) | |||
6642 | { | |||
6643 | char name[2 * GFC_MAX_SYMBOL_LEN63]; | |||
6644 | char tname[GFC_MAX_SYMBOL_LEN63 + 7]; | |||
6645 | gfc_symtree *tmp; | |||
6646 | gfc_symbol *selector = select_type_stack->selector; | |||
6647 | gfc_symbol *sym; | |||
6648 | gfc_symtree *st; | |||
6649 | HOST_WIDE_INTlong charlen = 0; | |||
6650 | ||||
6651 | if (case_value == NULL__null) | |||
6652 | return; | |||
6653 | ||||
6654 | if (ts->type == BT_CHARACTER && ts->u.cl && ts->u.cl->length | |||
6655 | && ts->u.cl->length->expr_type == EXPR_CONSTANT) | |||
6656 | charlen = gfc_mpz_get_hwi (ts->u.cl->length->value.integer); | |||
6657 | ||||
6658 | if (ts->type == BT_CLASS) | |||
6659 | sprintf (tname, "class_%s", ts->u.derived->name); | |||
6660 | else if (ts->type == BT_DERIVED) | |||
6661 | sprintf (tname, "type_%s", ts->u.derived->name); | |||
6662 | else if (ts->type != BT_CHARACTER) | |||
6663 | sprintf (tname, "%s_%d", gfc_basic_typename (ts->type), ts->kind); | |||
6664 | else | |||
6665 | sprintf (tname, "%s_" HOST_WIDE_INT_PRINT_DEC"%" "l" "d" "_%d", | |||
6666 | gfc_basic_typename (ts->type), charlen, ts->kind); | |||
6667 | ||||
6668 | /* Case value == NULL corresponds to SELECT TYPE cases otherwise | |||
6669 | the values correspond to SELECT rank cases. */ | |||
6670 | if (*case_value >=0) | |||
6671 | sprintf (name, "__tmp_%s_rank_%d", tname, *case_value); | |||
6672 | else | |||
6673 | sprintf (name, "__tmp_%s_rank_m%d", tname, -*case_value); | |||
6674 | ||||
6675 | gfc_find_sym_tree (name, gfc_current_ns, 0, &st); | |||
6676 | if (st) | |||
6677 | return; | |||
6678 | ||||
6679 | gfc_get_sym_tree (name, gfc_current_ns, &tmp, false); | |||
6680 | sym = tmp->n.sym; | |||
6681 | gfc_add_type (sym, ts, NULL__null); | |||
6682 | ||||
6683 | /* Copy across the array spec to the selector. */ | |||
6684 | if (selector->ts.type == BT_CLASS) | |||
6685 | { | |||
6686 | sym->ts.u.derived = CLASS_DATA (selector)selector->ts.u.derived->components->ts.u.derived; | |||
6687 | sym->attr.pointer = CLASS_DATA (selector)selector->ts.u.derived->components->attr.pointer; | |||