Line data Source code
1 : /* OpenMP directive matching and resolving.
2 : Copyright (C) 2005-2026 Free Software Foundation, Inc.
3 : Contributed by Jakub Jelinek
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 : #define INCLUDE_VECTOR
22 : #define INCLUDE_STRING
23 : #include "config.h"
24 : #include "system.h"
25 : #include "coretypes.h"
26 : #include "options.h"
27 : #include "gfortran.h"
28 : #include "arith.h"
29 : #include "match.h"
30 : #include "parse.h"
31 : #include "constructor.h"
32 : #include "diagnostic.h"
33 : #include "gomp-constants.h"
34 : #include "target-memory.h" /* For gfc_encode_character. */
35 : #include "bitmap.h"
36 : #include "omp-api.h" /* For omp_runtime_api_procname. */
37 :
38 : location_t gfc_get_location (locus *);
39 :
40 : static gfc_statement omp_code_to_statement (gfc_code *);
41 :
42 : enum gfc_omp_directive_kind {
43 : GFC_OMP_DIR_DECLARATIVE,
44 : GFC_OMP_DIR_EXECUTABLE,
45 : GFC_OMP_DIR_INFORMATIONAL,
46 : GFC_OMP_DIR_META,
47 : GFC_OMP_DIR_SUBSIDIARY,
48 : GFC_OMP_DIR_UTILITY
49 : };
50 :
51 : struct gfc_omp_directive {
52 : const char *name;
53 : enum gfc_omp_directive_kind kind;
54 : gfc_statement st;
55 : };
56 :
57 : /* Alphabetically sorted OpenMP clauses, except that longer strings are before
58 : substrings; excludes combined/composite directives. See note for "ordered"
59 : and "nothing". */
60 :
61 : static const struct gfc_omp_directive gfc_omp_directives[] = {
62 : /* allocate as alias for allocators is also executive. */
63 : {"allocate", GFC_OMP_DIR_DECLARATIVE, ST_OMP_ALLOCATE},
64 : {"allocators", GFC_OMP_DIR_EXECUTABLE, ST_OMP_ALLOCATORS},
65 : {"assumes", GFC_OMP_DIR_INFORMATIONAL, ST_OMP_ASSUMES},
66 : {"assume", GFC_OMP_DIR_INFORMATIONAL, ST_OMP_ASSUME},
67 : {"atomic", GFC_OMP_DIR_EXECUTABLE, ST_OMP_ATOMIC},
68 : {"barrier", GFC_OMP_DIR_EXECUTABLE, ST_OMP_BARRIER},
69 : {"cancellation point", GFC_OMP_DIR_EXECUTABLE, ST_OMP_CANCELLATION_POINT},
70 : {"cancel", GFC_OMP_DIR_EXECUTABLE, ST_OMP_CANCEL},
71 : {"critical", GFC_OMP_DIR_EXECUTABLE, ST_OMP_CRITICAL},
72 : /* {"declare induction", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_INDUCTION}, */
73 : {"declare mapper", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_MAPPER},
74 : {"declare reduction", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_REDUCTION},
75 : {"declare simd", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_SIMD},
76 : {"declare target", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_TARGET},
77 : {"declare variant", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_VARIANT},
78 : {"depobj", GFC_OMP_DIR_EXECUTABLE, ST_OMP_DEPOBJ},
79 : {"dispatch", GFC_OMP_DIR_EXECUTABLE, ST_OMP_DISPATCH},
80 : {"distribute", GFC_OMP_DIR_EXECUTABLE, ST_OMP_DISTRIBUTE},
81 : {"do", GFC_OMP_DIR_EXECUTABLE, ST_OMP_DO},
82 : /* "error" becomes GFC_OMP_DIR_EXECUTABLE with at(execution) */
83 : {"error", GFC_OMP_DIR_UTILITY, ST_OMP_ERROR},
84 : /* {"flatten", GFC_OMP_DIR_EXECUTABLE, ST_OMP_FLATTEN}, */
85 : {"flush", GFC_OMP_DIR_EXECUTABLE, ST_OMP_FLUSH},
86 : /* {"fuse", GFC_OMP_DIR_EXECUTABLE, ST_OMP_FLUSE}, */
87 : {"groupprivate", GFC_OMP_DIR_DECLARATIVE, ST_OMP_GROUPPRIVATE},
88 : /* {"interchange", GFC_OMP_DIR_EXECUTABLE, ST_OMP_INTERCHANGE}, */
89 : {"interop", GFC_OMP_DIR_EXECUTABLE, ST_OMP_INTEROP},
90 : {"loop", GFC_OMP_DIR_EXECUTABLE, ST_OMP_LOOP},
91 : {"masked", GFC_OMP_DIR_EXECUTABLE, ST_OMP_MASKED},
92 : {"metadirective", GFC_OMP_DIR_META, ST_OMP_METADIRECTIVE},
93 : /* Note: gfc_match_omp_nothing returns ST_NONE. */
94 : {"nothing", GFC_OMP_DIR_UTILITY, ST_OMP_NOTHING},
95 : /* Special case; for now map to the first one.
96 : ordered-blockassoc = ST_OMP_ORDERED
97 : ordered-standalone = ST_OMP_ORDERED_DEPEND + depend/doacross. */
98 : {"ordered", GFC_OMP_DIR_EXECUTABLE, ST_OMP_ORDERED},
99 : {"parallel", GFC_OMP_DIR_EXECUTABLE, ST_OMP_PARALLEL},
100 : {"requires", GFC_OMP_DIR_INFORMATIONAL, ST_OMP_REQUIRES},
101 : {"scan", GFC_OMP_DIR_SUBSIDIARY, ST_OMP_SCAN},
102 : {"scope", GFC_OMP_DIR_EXECUTABLE, ST_OMP_SCOPE},
103 : {"sections", GFC_OMP_DIR_EXECUTABLE, ST_OMP_SECTIONS},
104 : {"section", GFC_OMP_DIR_SUBSIDIARY, ST_OMP_SECTION},
105 : {"simd", GFC_OMP_DIR_EXECUTABLE, ST_OMP_SIMD},
106 : {"single", GFC_OMP_DIR_EXECUTABLE, ST_OMP_SINGLE},
107 : /* {"split", GFC_OMP_DIR_EXECUTABLE, ST_OMP_SPLIT}, */
108 : /* {"strip", GFC_OMP_DIR_EXECUTABLE, ST_OMP_STRIP}, */
109 : {"target data", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TARGET_DATA},
110 : {"target enter data", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TARGET_ENTER_DATA},
111 : {"target exit data", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TARGET_EXIT_DATA},
112 : {"target update", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TARGET_UPDATE},
113 : {"target", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TARGET},
114 : /* {"taskgraph", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TASKGRAPH}, */
115 : /* {"task iteration", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TASK_ITERATION}, */
116 : {"taskloop", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TASKLOOP},
117 : {"taskwait", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TASKWAIT},
118 : {"taskyield", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TASKYIELD},
119 : {"task", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TASK},
120 : {"teams", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TEAMS},
121 : {"threadprivate", GFC_OMP_DIR_DECLARATIVE, ST_OMP_THREADPRIVATE},
122 : {"tile", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TILE},
123 : {"unroll", GFC_OMP_DIR_EXECUTABLE, ST_OMP_UNROLL},
124 : /* {"workdistribute", GFC_OMP_DIR_EXECUTABLE, ST_OMP_WORKDISTRIBUTE}, */
125 : {"workshare", GFC_OMP_DIR_EXECUTABLE, ST_OMP_WORKSHARE},
126 : };
127 :
128 :
129 : /* Match an end of OpenMP directive. End of OpenMP directive is optional
130 : whitespace, followed by '\n' or comment '!'. In the special case where a
131 : context selector is being matched, match against ')' instead. */
132 :
133 : static match
134 55508 : gfc_match_omp_eos (void)
135 : {
136 55508 : locus old_loc;
137 55508 : char c;
138 :
139 55508 : old_loc = gfc_current_locus;
140 55508 : gfc_gobble_whitespace ();
141 :
142 55508 : if (gfc_matching_omp_context_selector)
143 : {
144 269 : if (gfc_peek_ascii_char () == ')')
145 : return MATCH_YES;
146 : }
147 : else
148 : {
149 55239 : c = gfc_next_ascii_char ();
150 55239 : switch (c)
151 : {
152 0 : case '!':
153 0 : do
154 0 : c = gfc_next_ascii_char ();
155 0 : while (c != '\n');
156 : /* Fall through */
157 :
158 53511 : case '\n':
159 53511 : return MATCH_YES;
160 : }
161 : }
162 :
163 1729 : gfc_current_locus = old_loc;
164 1729 : return MATCH_NO;
165 : }
166 :
167 : match
168 13179 : gfc_match_omp_eos_error (void)
169 : {
170 13179 : if (gfc_match_omp_eos() == MATCH_YES)
171 : return MATCH_YES;
172 :
173 35 : gfc_error ("Unexpected junk at %C");
174 35 : return MATCH_ERROR;
175 : }
176 :
177 :
178 : /* Free an omp_clauses structure. */
179 :
180 : void
181 61452 : gfc_free_omp_clauses (gfc_omp_clauses *c)
182 : {
183 61452 : if (c == NULL)
184 : return;
185 :
186 34612 : gfc_free_expr (c->if_expr);
187 380732 : for (int i = 0; i < OMP_IF_LAST; i++)
188 346120 : gfc_free_expr (c->if_exprs[i]);
189 34612 : gfc_free_expr (c->self_expr);
190 34612 : gfc_free_expr (c->final_expr);
191 34612 : gfc_free_expr (c->num_threads);
192 34612 : gfc_free_expr (c->chunk_size);
193 34612 : gfc_free_expr (c->safelen_expr);
194 34612 : gfc_free_expr (c->simdlen_expr);
195 34612 : gfc_free_expr (c->num_teams_lower);
196 34612 : gfc_free_expr (c->num_teams_upper);
197 34612 : gfc_free_expr (c->device);
198 34612 : gfc_free_expr (c->dyn_groupprivate);
199 34612 : gfc_free_expr (c->thread_limit);
200 34612 : gfc_free_expr (c->dist_chunk_size);
201 34612 : gfc_free_expr (c->grainsize);
202 34612 : gfc_free_expr (c->hint);
203 34612 : gfc_free_expr (c->num_tasks);
204 34612 : gfc_free_expr (c->priority);
205 34612 : gfc_free_expr (c->detach);
206 34612 : gfc_free_expr (c->novariants);
207 34612 : gfc_free_expr (c->nocontext);
208 34612 : gfc_free_expr (c->async_expr);
209 34612 : gfc_free_expr (c->gang_num_expr);
210 34612 : gfc_free_expr (c->gang_static_expr);
211 34612 : gfc_free_expr (c->worker_expr);
212 34612 : gfc_free_expr (c->vector_expr);
213 34612 : gfc_free_expr (c->num_gangs_expr);
214 34612 : gfc_free_expr (c->num_workers_expr);
215 34612 : gfc_free_expr (c->vector_length_expr);
216 1384480 : for (enum gfc_omp_list_type t = OMP_LIST_FIRST; t < OMP_LIST_NUM;
217 1349868 : t = gfc_omp_list_type (t + 1))
218 1349868 : gfc_free_omp_namelist (c->lists[t], t);
219 34612 : gfc_free_expr_list (c->wait_list);
220 34612 : gfc_free_expr_list (c->tile_list);
221 34612 : gfc_free_expr_list (c->sizes_list);
222 34612 : free (const_cast<char *> (c->critical_name));
223 34612 : if (c->assume)
224 : {
225 24 : free (c->assume->absent);
226 24 : free (c->assume->contains);
227 24 : gfc_free_expr_list (c->assume->holds);
228 24 : free (c->assume);
229 : }
230 34612 : free (c);
231 : }
232 :
233 : /* Free oacc_declare structures. */
234 :
235 : void
236 76 : gfc_free_oacc_declare_clauses (struct gfc_oacc_declare *oc)
237 : {
238 76 : struct gfc_oacc_declare *decl = oc;
239 :
240 76 : do
241 : {
242 76 : struct gfc_oacc_declare *next;
243 :
244 76 : next = decl->next;
245 76 : gfc_free_omp_clauses (decl->clauses);
246 76 : free (decl);
247 76 : decl = next;
248 : }
249 76 : while (decl);
250 76 : }
251 :
252 : /* Free expression list. */
253 : void
254 104839 : gfc_free_expr_list (gfc_expr_list *list)
255 : {
256 104839 : gfc_expr_list *n;
257 :
258 106246 : for (; list; list = n)
259 : {
260 1407 : n = list->next;
261 1407 : free (list);
262 : }
263 104839 : }
264 :
265 : /* Free an !$omp declare simd construct list. */
266 :
267 : void
268 236 : gfc_free_omp_declare_simd (gfc_omp_declare_simd *ods)
269 : {
270 236 : if (ods)
271 : {
272 236 : gfc_free_omp_clauses (ods->clauses);
273 236 : free (ods);
274 : }
275 236 : }
276 :
277 : void
278 534998 : gfc_free_omp_declare_simd_list (gfc_omp_declare_simd *list)
279 : {
280 535234 : while (list)
281 : {
282 236 : gfc_omp_declare_simd *current = list;
283 236 : list = list->next;
284 236 : gfc_free_omp_declare_simd (current);
285 : }
286 534998 : }
287 :
288 : static void
289 721 : gfc_free_omp_trait_property_list (gfc_omp_trait_property *list)
290 : {
291 1128 : while (list)
292 : {
293 407 : gfc_omp_trait_property *current = list;
294 407 : list = list->next;
295 407 : switch (current->property_kind)
296 : {
297 24 : case OMP_TRAIT_PROPERTY_ID:
298 24 : free (current->name);
299 24 : break;
300 261 : case OMP_TRAIT_PROPERTY_NAME_LIST:
301 261 : if (current->is_name)
302 168 : free (current->name);
303 : break;
304 15 : case OMP_TRAIT_PROPERTY_CLAUSE_LIST:
305 15 : gfc_free_omp_clauses (current->clauses);
306 15 : break;
307 : default:
308 : break;
309 : }
310 407 : free (current);
311 : }
312 721 : }
313 :
314 : static void
315 593 : gfc_free_omp_selector_list (gfc_omp_selector *list)
316 : {
317 1314 : while (list)
318 : {
319 721 : gfc_omp_selector *current = list;
320 721 : list = list->next;
321 721 : gfc_free_omp_trait_property_list (current->properties);
322 721 : free (current);
323 : }
324 593 : }
325 :
326 : static void
327 662 : gfc_free_omp_set_selector_list (gfc_omp_set_selector *list)
328 : {
329 1255 : while (list)
330 : {
331 593 : gfc_omp_set_selector *current = list;
332 593 : list = list->next;
333 593 : gfc_free_omp_selector_list (current->trait_selectors);
334 593 : free (current);
335 : }
336 662 : }
337 :
338 : /* Free an !$omp declare variant construct list. */
339 :
340 : void
341 534998 : gfc_free_omp_declare_variant_list (gfc_omp_declare_variant *list)
342 : {
343 535446 : while (list)
344 : {
345 448 : gfc_omp_declare_variant *current = list;
346 448 : list = list->next;
347 448 : gfc_free_omp_set_selector_list (current->set_selectors);
348 448 : gfc_free_omp_namelist (current->adjust_args_list, OMP_LIST_NONE);
349 448 : free (current);
350 : }
351 534998 : }
352 :
353 : /* Free an !$omp declare reduction. */
354 :
355 : void
356 1271 : gfc_free_omp_udr (gfc_omp_udr *omp_udr)
357 : {
358 1271 : if (omp_udr)
359 : {
360 685 : gfc_free_omp_udr (omp_udr->next);
361 685 : gfc_free_namespace (omp_udr->combiner_ns);
362 685 : if (omp_udr->initializer_ns)
363 386 : gfc_free_namespace (omp_udr->initializer_ns);
364 685 : free (omp_udr);
365 : }
366 1271 : }
367 :
368 : /* Free variants of an !$omp metadirective construct. */
369 :
370 : void
371 93 : gfc_free_omp_variants (gfc_omp_variant *variant)
372 : {
373 284 : while (variant)
374 : {
375 191 : gfc_omp_variant *next_variant = variant->next;
376 191 : gfc_free_omp_set_selector_list (variant->selectors);
377 191 : free (variant);
378 191 : variant = next_variant;
379 : }
380 93 : }
381 :
382 : /* Free an !$omp declare mapper. */
383 :
384 : void
385 46 : gfc_free_omp_udm (gfc_omp_udm *omp_udm)
386 : {
387 46 : if (omp_udm)
388 : {
389 23 : gfc_free_omp_udm (omp_udm->next);
390 23 : gfc_free_namespace (omp_udm->mapper_ns);
391 23 : free (omp_udm);
392 : }
393 46 : }
394 :
395 : static gfc_omp_udr *
396 4716 : gfc_find_omp_udr (gfc_namespace *ns, const char *name, gfc_typespec *ts)
397 : {
398 4716 : gfc_symtree *st;
399 :
400 4716 : if (ns == NULL)
401 470 : ns = gfc_current_ns;
402 5664 : do
403 : {
404 5664 : gfc_omp_udr *omp_udr;
405 :
406 5664 : st = gfc_find_symtree (ns->omp_udr_root, name);
407 5664 : if (st != NULL)
408 : {
409 941 : for (omp_udr = st->n.omp_udr; omp_udr; omp_udr = omp_udr->next)
410 941 : if (ts == NULL)
411 : return omp_udr;
412 571 : else if (gfc_compare_types (&omp_udr->ts, ts))
413 : {
414 482 : if (ts->type == BT_CHARACTER)
415 : {
416 60 : if (omp_udr->ts.u.cl->length == NULL)
417 : return omp_udr;
418 36 : if (ts->u.cl->length == NULL)
419 0 : continue;
420 36 : if (gfc_compare_expr (omp_udr->ts.u.cl->length,
421 : ts->u.cl->length,
422 : INTRINSIC_EQ) != 0)
423 12 : continue;
424 : }
425 446 : return omp_udr;
426 : }
427 : }
428 :
429 : /* Don't escape an interface block. */
430 4824 : if (ns && !ns->has_import_set
431 4824 : && ns->proc_name && ns->proc_name->attr.if_source == IFSRC_IFBODY)
432 : break;
433 :
434 4824 : ns = ns->parent;
435 : }
436 4824 : while (ns != NULL);
437 :
438 : return NULL;
439 : }
440 :
441 :
442 : /* Match a variable/common block list and construct a namelist from it;
443 : if has_all_memory != NULL, *has_all_memory is set and omp_all_memory
444 : yields a list->sym NULL entry. */
445 :
446 : static match
447 31737 : gfc_match_omp_variable_list (const char *str, gfc_omp_namelist **list,
448 : bool allow_common, bool *end_colon = NULL,
449 : gfc_omp_namelist ***headp = NULL,
450 : bool allow_sections = false,
451 : bool allow_derived = false,
452 : bool *has_all_memory = NULL,
453 : bool reject_common_vars = false,
454 : bool reverse_order = false)
455 : {
456 31737 : gfc_omp_namelist *head, *tail, *p;
457 31737 : locus old_loc, cur_loc;
458 31737 : char n[GFC_MAX_SYMBOL_LEN+1];
459 31737 : gfc_symbol *sym;
460 31737 : match m;
461 31737 : gfc_symtree *st;
462 :
463 31737 : head = tail = NULL;
464 :
465 31737 : old_loc = gfc_current_locus;
466 31737 : if (has_all_memory)
467 708 : *has_all_memory = false;
468 31737 : m = gfc_match (str);
469 31737 : if (m != MATCH_YES)
470 : return m;
471 :
472 38493 : for (;;)
473 : {
474 38493 : gfc_gobble_whitespace ();
475 38493 : cur_loc = gfc_current_locus;
476 :
477 38493 : m = gfc_match_name (n);
478 38493 : if (m == MATCH_YES && strcmp (n, "omp_all_memory") == 0)
479 : {
480 23 : locus loc = gfc_get_location_range (NULL, 0, &cur_loc, 1,
481 : &gfc_current_locus);
482 23 : if (!has_all_memory)
483 : {
484 2 : gfc_error ("%<omp_all_memory%> at %L not permitted in this "
485 : "clause", &loc);
486 2 : goto cleanup;
487 : }
488 21 : *has_all_memory = true;
489 21 : p = gfc_get_omp_namelist ();
490 21 : if (head == NULL)
491 : head = tail = p;
492 : else
493 : {
494 3 : tail->next = p;
495 3 : tail = tail->next;
496 : }
497 21 : tail->where = loc;
498 21 : goto next_item;
499 : }
500 38214 : if (m == MATCH_YES)
501 : {
502 38214 : gfc_symtree *st;
503 38214 : if ((m = gfc_get_ha_sym_tree (n, &st) ? MATCH_ERROR : MATCH_YES)
504 : == MATCH_YES)
505 38214 : sym = st->n.sym;
506 : }
507 38470 : switch (m)
508 : {
509 38214 : case MATCH_YES:
510 38214 : gfc_expr *expr;
511 38214 : expr = NULL;
512 38214 : gfc_gobble_whitespace ();
513 23527 : if ((allow_sections && gfc_peek_ascii_char () == '(')
514 57379 : || (allow_derived && gfc_peek_ascii_char () == '%'))
515 : {
516 6602 : gfc_current_locus = cur_loc;
517 6602 : m = gfc_match_variable (&expr, 0);
518 6602 : switch (m)
519 : {
520 4 : case MATCH_ERROR:
521 12 : goto cleanup;
522 0 : case MATCH_NO:
523 0 : goto syntax;
524 6598 : default:
525 6598 : break;
526 : }
527 6598 : if (gfc_is_coindexed (expr))
528 : {
529 5 : gfc_error ("List item shall not be coindexed at %L",
530 5 : &expr->where);
531 5 : goto cleanup;
532 : }
533 : }
534 38205 : gfc_set_sym_referenced (sym);
535 38205 : p = gfc_get_omp_namelist ();
536 38205 : if (head == NULL)
537 : head = tail = p;
538 10165 : else if (reverse_order)
539 : {
540 57 : p->next = head;
541 57 : head = p;
542 : }
543 : else
544 : {
545 10108 : tail->next = p;
546 10108 : tail = tail->next;
547 : }
548 38205 : p->sym = sym;
549 38205 : p->expr = expr;
550 38205 : p->where = gfc_get_location_range (NULL, 0, &cur_loc, 1,
551 : &gfc_current_locus);
552 38205 : if (reject_common_vars && sym->attr.in_common)
553 : {
554 3 : gcc_assert (allow_common);
555 3 : gfc_error ("%qs at %L is part of the common block %</%s/%> and "
556 : "may only be specified implicitly via the named "
557 : "common block", sym->name, &cur_loc,
558 3 : sym->common_head->name);
559 3 : goto cleanup;
560 : }
561 38202 : goto next_item;
562 256 : case MATCH_NO:
563 256 : break;
564 0 : case MATCH_ERROR:
565 0 : goto cleanup;
566 : }
567 :
568 256 : if (!allow_common)
569 12 : goto syntax;
570 :
571 244 : m = gfc_match ("/ %n /", n);
572 244 : if (m == MATCH_ERROR)
573 0 : goto cleanup;
574 244 : if (m == MATCH_NO)
575 19 : goto syntax;
576 :
577 225 : cur_loc = gfc_get_location_range (NULL, 0, &cur_loc, 1,
578 : &gfc_current_locus);
579 225 : st = gfc_find_symtree (gfc_current_ns->common_root, n);
580 225 : if (st == NULL)
581 : {
582 2 : gfc_error ("COMMON block %</%s/%> not found at %L", n, &cur_loc);
583 2 : goto cleanup;
584 : }
585 724 : for (sym = st->n.common->head; sym; sym = sym->common_next)
586 : {
587 501 : gfc_set_sym_referenced (sym);
588 501 : p = gfc_get_omp_namelist ();
589 501 : if (head == NULL)
590 : head = tail = p;
591 325 : else if (reverse_order)
592 : {
593 0 : p->next = head;
594 0 : head = p;
595 : }
596 : else
597 : {
598 325 : tail->next = p;
599 325 : tail = tail->next;
600 : }
601 501 : p->sym = sym;
602 501 : p->where = cur_loc;
603 : }
604 :
605 223 : next_item:
606 38446 : if (end_colon && gfc_match_char (':') == MATCH_YES)
607 : {
608 793 : *end_colon = true;
609 793 : break;
610 : }
611 37653 : if (gfc_match_char (')') == MATCH_YES)
612 : break;
613 10236 : if (gfc_match_char (',') != MATCH_YES)
614 21 : goto syntax;
615 : }
616 :
617 38248 : while (*list)
618 10038 : list = &(*list)->next;
619 :
620 28210 : *list = head;
621 28210 : if (headp)
622 22317 : *headp = list;
623 : return MATCH_YES;
624 :
625 52 : syntax:
626 52 : gfc_error ("Syntax error in OpenMP variable list at %C");
627 :
628 68 : cleanup:
629 68 : gfc_free_omp_namelist (head, OMP_LIST_NONE);
630 68 : gfc_current_locus = old_loc;
631 68 : return MATCH_ERROR;
632 : }
633 :
634 : /* Match a variable/procedure/common block list and construct a namelist
635 : from it. */
636 :
637 : static match
638 363 : gfc_match_omp_to_link (const char *str, gfc_omp_namelist **list)
639 : {
640 363 : gfc_omp_namelist *head, *tail, *p;
641 363 : locus old_loc, cur_loc;
642 363 : char n[GFC_MAX_SYMBOL_LEN+1];
643 363 : gfc_symbol *sym;
644 363 : match m;
645 363 : gfc_symtree *st;
646 :
647 363 : head = tail = NULL;
648 :
649 363 : old_loc = gfc_current_locus;
650 :
651 363 : m = gfc_match (str);
652 363 : if (m != MATCH_YES)
653 : return m;
654 :
655 549 : for (;;)
656 : {
657 549 : cur_loc = gfc_current_locus;
658 549 : m = gfc_match_symbol (&sym, 1);
659 549 : switch (m)
660 : {
661 508 : case MATCH_YES:
662 508 : p = gfc_get_omp_namelist ();
663 508 : if (head == NULL)
664 : head = tail = p;
665 : else
666 : {
667 194 : tail->next = p;
668 194 : tail = tail->next;
669 : }
670 508 : tail->sym = sym;
671 508 : tail->where = cur_loc;
672 508 : goto next_item;
673 : case MATCH_NO:
674 : break;
675 0 : case MATCH_ERROR:
676 0 : goto cleanup;
677 : }
678 :
679 41 : m = gfc_match (" / %n /", n);
680 41 : if (m == MATCH_ERROR)
681 0 : goto cleanup;
682 41 : if (m == MATCH_NO)
683 0 : goto syntax;
684 :
685 41 : st = gfc_find_symtree (gfc_current_ns->common_root, n);
686 41 : if (st == NULL)
687 : {
688 0 : gfc_error ("COMMON block /%s/ not found at %C", n);
689 0 : goto cleanup;
690 : }
691 41 : p = gfc_get_omp_namelist ();
692 41 : if (head == NULL)
693 : head = tail = p;
694 : else
695 : {
696 4 : tail->next = p;
697 4 : tail = tail->next;
698 : }
699 41 : tail->u.common = st->n.common;
700 41 : tail->where = cur_loc;
701 :
702 549 : next_item:
703 549 : if (gfc_match_char (')') == MATCH_YES)
704 : break;
705 198 : if (gfc_match_char (',') != MATCH_YES)
706 0 : goto syntax;
707 : }
708 :
709 362 : while (*list)
710 11 : list = &(*list)->next;
711 :
712 351 : *list = head;
713 351 : return MATCH_YES;
714 :
715 0 : syntax:
716 0 : gfc_error ("Syntax error in OpenMP variable list at %C");
717 :
718 0 : cleanup:
719 0 : gfc_free_omp_namelist (head, OMP_LIST_NONE);
720 0 : gfc_current_locus = old_loc;
721 0 : return MATCH_ERROR;
722 : }
723 :
724 : /* Match detach(event-handle). */
725 :
726 : static match
727 126 : gfc_match_omp_detach (gfc_expr **expr)
728 : {
729 126 : locus old_loc = gfc_current_locus;
730 :
731 126 : if (gfc_match ("detach ( ") != MATCH_YES)
732 0 : goto syntax_error;
733 :
734 126 : if (gfc_match_variable (expr, 0) != MATCH_YES)
735 0 : goto syntax_error;
736 :
737 126 : if (gfc_match_char (')') != MATCH_YES)
738 0 : goto syntax_error;
739 :
740 : return MATCH_YES;
741 :
742 0 : syntax_error:
743 0 : gfc_error ("Syntax error in OpenMP detach clause at %C");
744 0 : gfc_current_locus = old_loc;
745 0 : return MATCH_ERROR;
746 :
747 : }
748 :
749 : /* Match doacross(sink : ...) construct a namelist from it;
750 : if depend is true, match legacy 'depend(sink : ...)'. */
751 :
752 : static match
753 241 : gfc_match_omp_doacross_sink (gfc_omp_namelist **list, bool depend)
754 : {
755 241 : char n[GFC_MAX_SYMBOL_LEN+1];
756 241 : gfc_omp_namelist *head, *tail, *p;
757 241 : locus old_loc, cur_loc;
758 241 : gfc_symbol *sym;
759 :
760 241 : head = tail = NULL;
761 :
762 241 : old_loc = gfc_current_locus;
763 :
764 2231 : for (;;)
765 : {
766 1236 : gfc_gobble_whitespace ();
767 1236 : cur_loc = gfc_current_locus;
768 :
769 1236 : if (gfc_match_name (n) != MATCH_YES)
770 1 : goto syntax;
771 1235 : locus loc = gfc_get_location_range (NULL, 0, &cur_loc, 1,
772 : &gfc_current_locus);
773 1235 : if (UNLIKELY (strcmp (n, "omp_all_memory") == 0))
774 : {
775 1 : gfc_error ("%<omp_all_memory%> used with dependence-type "
776 : "other than OUT or INOUT at %L", &loc);
777 1 : goto cleanup;
778 : }
779 1234 : sym = NULL;
780 1234 : if (!(strcmp (n, "omp_cur_iteration") == 0))
781 : {
782 1229 : gfc_symtree *st;
783 1229 : if (gfc_get_ha_sym_tree (n, &st))
784 0 : goto syntax;
785 1229 : sym = st->n.sym;
786 1229 : gfc_set_sym_referenced (sym);
787 : }
788 1234 : p = gfc_get_omp_namelist ();
789 1234 : if (head == NULL)
790 : {
791 239 : head = tail = p;
792 253 : head->u.depend_doacross_op = (depend ? OMP_DEPEND_SINK_FIRST
793 : : OMP_DOACROSS_SINK_FIRST);
794 : }
795 : else
796 : {
797 995 : tail->next = p;
798 995 : tail = tail->next;
799 995 : tail->u.depend_doacross_op = OMP_DOACROSS_SINK;
800 : }
801 1234 : tail->sym = sym;
802 1234 : tail->expr = NULL;
803 1234 : tail->where = loc;
804 1234 : if (gfc_match_char ('+') == MATCH_YES)
805 : {
806 154 : if (gfc_match_literal_constant (&tail->expr, 0) != MATCH_YES)
807 0 : goto syntax;
808 : }
809 1080 : else if (gfc_match_char ('-') == MATCH_YES)
810 : {
811 418 : if (gfc_match_literal_constant (&tail->expr, 0) != MATCH_YES)
812 1 : goto syntax;
813 417 : tail->expr = gfc_uminus (tail->expr);
814 : }
815 1233 : if (gfc_match_char (')') == MATCH_YES)
816 : break;
817 995 : if (gfc_match_char (',') != MATCH_YES)
818 0 : goto syntax;
819 995 : }
820 :
821 1030 : while (*list)
822 792 : list = &(*list)->next;
823 :
824 238 : *list = head;
825 238 : return MATCH_YES;
826 :
827 2 : syntax:
828 2 : gfc_error ("Syntax error in OpenMP SINK dependence-type list at %C");
829 :
830 3 : cleanup:
831 3 : gfc_free_omp_namelist (head, OMP_LIST_DEPEND);
832 3 : gfc_current_locus = old_loc;
833 3 : return MATCH_ERROR;
834 : }
835 :
836 : static match
837 818 : match_omp_oacc_expr_list (const char *str, gfc_expr_list **list,
838 : bool allow_asterisk, bool is_omp)
839 : {
840 818 : gfc_expr_list *head, *tail, *p;
841 818 : locus old_loc;
842 818 : gfc_expr *expr;
843 818 : match m;
844 :
845 818 : head = tail = NULL;
846 :
847 818 : old_loc = gfc_current_locus;
848 :
849 818 : m = gfc_match (str);
850 818 : if (m != MATCH_YES)
851 : return m;
852 :
853 1030 : for (;;)
854 : {
855 1030 : m = gfc_match_expr (&expr);
856 1030 : if (m == MATCH_YES || allow_asterisk)
857 : {
858 1018 : p = gfc_get_expr_list ();
859 1018 : if (head == NULL)
860 : head = tail = p;
861 : else
862 : {
863 335 : tail->next = p;
864 335 : tail = tail->next;
865 : }
866 1018 : if (m == MATCH_YES)
867 885 : tail->expr = expr;
868 133 : else if (gfc_match (" *") != MATCH_YES)
869 18 : goto syntax;
870 1000 : goto next_item;
871 : }
872 12 : if (m == MATCH_ERROR)
873 0 : goto cleanup;
874 12 : goto syntax;
875 :
876 1000 : next_item:
877 1000 : if (gfc_match_char (')') == MATCH_YES)
878 : break;
879 346 : if (gfc_match_char (',') != MATCH_YES)
880 6 : goto syntax;
881 : }
882 :
883 660 : while (*list)
884 6 : list = &(*list)->next;
885 :
886 654 : *list = head;
887 654 : return MATCH_YES;
888 :
889 36 : syntax:
890 36 : if (is_omp)
891 7 : gfc_error ("Syntax error in OpenMP expression list at %C");
892 : else
893 29 : gfc_error ("Syntax error in OpenACC expression list at %C");
894 :
895 36 : cleanup:
896 36 : gfc_free_expr_list (head);
897 36 : gfc_current_locus = old_loc;
898 36 : return MATCH_ERROR;
899 : }
900 :
901 : static match
902 3056 : match_oacc_clause_gwv (gfc_omp_clauses *cp, unsigned gwv)
903 : {
904 3056 : match ret = MATCH_YES;
905 :
906 3056 : if (gfc_match (" ( ") != MATCH_YES)
907 : return MATCH_NO;
908 :
909 470 : if (gwv == GOMP_DIM_GANG)
910 : {
911 : /* The gang clause accepts two optional arguments, num and static.
912 : The num argument may either be explicit (num: <val>) or
913 : implicit without (<val> without num:). */
914 :
915 457 : while (ret == MATCH_YES)
916 : {
917 236 : if (gfc_match (" static :") == MATCH_YES)
918 : {
919 114 : if (cp->gang_static)
920 : return MATCH_ERROR;
921 : else
922 113 : cp->gang_static = true;
923 113 : if (gfc_match_char ('*') == MATCH_YES)
924 18 : cp->gang_static_expr = NULL;
925 95 : else if (gfc_match (" %e ", &cp->gang_static_expr) != MATCH_YES)
926 : return MATCH_ERROR;
927 : }
928 : else
929 : {
930 122 : if (cp->gang_num_expr)
931 : return MATCH_ERROR;
932 :
933 : /* The 'num' argument is optional. */
934 121 : gfc_match (" num :");
935 :
936 121 : if (gfc_match (" %e ", &cp->gang_num_expr) != MATCH_YES)
937 : return MATCH_ERROR;
938 : }
939 :
940 231 : ret = gfc_match (" , ");
941 : }
942 : }
943 244 : else if (gwv == GOMP_DIM_WORKER)
944 : {
945 : /* The 'num' argument is optional. */
946 107 : gfc_match (" num :");
947 :
948 107 : if (gfc_match (" %e ", &cp->worker_expr) != MATCH_YES)
949 : return MATCH_ERROR;
950 : }
951 137 : else if (gwv == GOMP_DIM_VECTOR)
952 : {
953 : /* The 'length' argument is optional. */
954 137 : gfc_match (" length :");
955 :
956 137 : if (gfc_match (" %e ", &cp->vector_expr) != MATCH_YES)
957 : return MATCH_ERROR;
958 : }
959 : else
960 0 : gfc_fatal_error ("Unexpected OpenACC parallelism.");
961 :
962 459 : return gfc_match (" )");
963 : }
964 :
965 : static match
966 8 : gfc_match_oacc_clause_link (const char *str, gfc_omp_namelist **list)
967 : {
968 8 : gfc_omp_namelist *head = NULL;
969 8 : gfc_omp_namelist *tail, *p;
970 8 : locus old_loc;
971 8 : char n[GFC_MAX_SYMBOL_LEN+1];
972 8 : gfc_symbol *sym;
973 8 : match m;
974 8 : gfc_symtree *st;
975 :
976 8 : old_loc = gfc_current_locus;
977 :
978 8 : m = gfc_match (str);
979 8 : if (m != MATCH_YES)
980 : return m;
981 :
982 8 : m = gfc_match (" (");
983 :
984 14 : for (;;)
985 : {
986 14 : m = gfc_match_symbol (&sym, 0);
987 14 : switch (m)
988 : {
989 8 : case MATCH_YES:
990 8 : if (sym->attr.in_common)
991 : {
992 2 : gfc_error_now ("Variable at %C is an element of a COMMON block");
993 2 : goto cleanup;
994 : }
995 6 : gfc_set_sym_referenced (sym);
996 6 : p = gfc_get_omp_namelist ();
997 6 : if (head == NULL)
998 : head = tail = p;
999 : else
1000 : {
1001 4 : tail->next = p;
1002 4 : tail = tail->next;
1003 : }
1004 6 : tail->sym = sym;
1005 6 : tail->expr = NULL;
1006 6 : tail->where = gfc_current_locus;
1007 6 : goto next_item;
1008 : case MATCH_NO:
1009 : break;
1010 :
1011 0 : case MATCH_ERROR:
1012 0 : goto cleanup;
1013 : }
1014 :
1015 6 : m = gfc_match (" / %n /", n);
1016 6 : if (m == MATCH_ERROR)
1017 0 : goto cleanup;
1018 6 : if (m == MATCH_NO || n[0] == '\0')
1019 0 : goto syntax;
1020 :
1021 6 : st = gfc_find_symtree (gfc_current_ns->common_root, n);
1022 6 : if (st == NULL)
1023 : {
1024 1 : gfc_error ("COMMON block /%s/ not found at %C", n);
1025 1 : goto cleanup;
1026 : }
1027 :
1028 20 : for (sym = st->n.common->head; sym; sym = sym->common_next)
1029 : {
1030 15 : gfc_set_sym_referenced (sym);
1031 15 : p = gfc_get_omp_namelist ();
1032 15 : if (head == NULL)
1033 : head = tail = p;
1034 : else
1035 : {
1036 12 : tail->next = p;
1037 12 : tail = tail->next;
1038 : }
1039 15 : tail->sym = sym;
1040 15 : tail->where = gfc_current_locus;
1041 : }
1042 :
1043 5 : next_item:
1044 11 : if (gfc_match_char (')') == MATCH_YES)
1045 : break;
1046 6 : if (gfc_match_char (',') != MATCH_YES)
1047 0 : goto syntax;
1048 : }
1049 :
1050 5 : if (gfc_match_omp_eos () != MATCH_YES)
1051 : {
1052 1 : gfc_error ("Unexpected junk after !$ACC DECLARE at %C");
1053 1 : goto cleanup;
1054 : }
1055 :
1056 4 : while (*list)
1057 0 : list = &(*list)->next;
1058 4 : *list = head;
1059 4 : return MATCH_YES;
1060 :
1061 0 : syntax:
1062 0 : gfc_error ("Syntax error in !$ACC DECLARE list at %C");
1063 :
1064 4 : cleanup:
1065 4 : gfc_current_locus = old_loc;
1066 4 : return MATCH_ERROR;
1067 : }
1068 :
1069 : /* OpenMP clauses. */
1070 : enum omp_mask1
1071 : {
1072 : OMP_CLAUSE_PRIVATE,
1073 : OMP_CLAUSE_FIRSTPRIVATE,
1074 : OMP_CLAUSE_LASTPRIVATE,
1075 : OMP_CLAUSE_COPYPRIVATE,
1076 : OMP_CLAUSE_SHARED,
1077 : OMP_CLAUSE_COPYIN,
1078 : OMP_CLAUSE_REDUCTION,
1079 : OMP_CLAUSE_IN_REDUCTION,
1080 : OMP_CLAUSE_TASK_REDUCTION,
1081 : OMP_CLAUSE_IF,
1082 : OMP_CLAUSE_NUM_THREADS,
1083 : OMP_CLAUSE_SCHEDULE,
1084 : OMP_CLAUSE_DEFAULT,
1085 : OMP_CLAUSE_ORDER,
1086 : OMP_CLAUSE_ORDERED,
1087 : OMP_CLAUSE_COLLAPSE,
1088 : OMP_CLAUSE_UNTIED,
1089 : OMP_CLAUSE_FINAL,
1090 : OMP_CLAUSE_MERGEABLE,
1091 : OMP_CLAUSE_ALIGNED,
1092 : OMP_CLAUSE_DEPEND,
1093 : OMP_CLAUSE_INBRANCH,
1094 : OMP_CLAUSE_LINEAR,
1095 : OMP_CLAUSE_NOTINBRANCH,
1096 : OMP_CLAUSE_PROC_BIND,
1097 : OMP_CLAUSE_SAFELEN,
1098 : OMP_CLAUSE_SIMDLEN,
1099 : OMP_CLAUSE_UNIFORM,
1100 : OMP_CLAUSE_DEVICE,
1101 : OMP_CLAUSE_MAP,
1102 : OMP_CLAUSE_TO,
1103 : OMP_CLAUSE_FROM,
1104 : OMP_CLAUSE_NUM_TEAMS,
1105 : OMP_CLAUSE_THREAD_LIMIT,
1106 : OMP_CLAUSE_DIST_SCHEDULE,
1107 : OMP_CLAUSE_DEFAULTMAP,
1108 : OMP_CLAUSE_GRAINSIZE,
1109 : OMP_CLAUSE_HINT,
1110 : OMP_CLAUSE_IS_DEVICE_PTR,
1111 : OMP_CLAUSE_LINK,
1112 : OMP_CLAUSE_NOGROUP,
1113 : OMP_CLAUSE_NOTEMPORAL,
1114 : OMP_CLAUSE_NUM_TASKS,
1115 : OMP_CLAUSE_PRIORITY,
1116 : OMP_CLAUSE_SIMD,
1117 : OMP_CLAUSE_THREADS,
1118 : OMP_CLAUSE_USE_DEVICE_PTR,
1119 : OMP_CLAUSE_USE_DEVICE_ADDR, /* OpenMP 5.0. */
1120 : OMP_CLAUSE_DEVICE_TYPE, /* OpenMP 5.0. */
1121 : OMP_CLAUSE_ATOMIC, /* OpenMP 5.0. */
1122 : OMP_CLAUSE_CAPTURE, /* OpenMP 5.0. */
1123 : OMP_CLAUSE_MEMORDER, /* OpenMP 5.0. */
1124 : OMP_CLAUSE_DETACH, /* OpenMP 5.0. */
1125 : OMP_CLAUSE_AFFINITY, /* OpenMP 5.0. */
1126 : OMP_CLAUSE_ALLOCATE, /* OpenMP 5.0. */
1127 : OMP_CLAUSE_BIND, /* OpenMP 5.0. */
1128 : OMP_CLAUSE_FILTER, /* OpenMP 5.1. */
1129 : OMP_CLAUSE_AT, /* OpenMP 5.1. */
1130 : OMP_CLAUSE_MESSAGE, /* OpenMP 5.1. */
1131 : OMP_CLAUSE_SEVERITY, /* OpenMP 5.1. */
1132 : OMP_CLAUSE_COMPARE, /* OpenMP 5.1. */
1133 : OMP_CLAUSE_FAIL, /* OpenMP 5.1. */
1134 : OMP_CLAUSE_WEAK, /* OpenMP 5.1. */
1135 : OMP_CLAUSE_NOWAIT,
1136 : /* This must come last. */
1137 : OMP_MASK1_LAST
1138 : };
1139 :
1140 : /* More OpenMP clauses and OpenACC 2.0+ specific clauses. */
1141 : enum omp_mask2
1142 : {
1143 : OMP_CLAUSE_ASYNC,
1144 : OMP_CLAUSE_NUM_GANGS,
1145 : OMP_CLAUSE_NUM_WORKERS,
1146 : OMP_CLAUSE_VECTOR_LENGTH,
1147 : OMP_CLAUSE_COPY,
1148 : OMP_CLAUSE_COPYOUT,
1149 : OMP_CLAUSE_CREATE,
1150 : OMP_CLAUSE_NO_CREATE,
1151 : OMP_CLAUSE_PRESENT,
1152 : OMP_CLAUSE_DEVICEPTR,
1153 : OMP_CLAUSE_GANG,
1154 : OMP_CLAUSE_WORKER,
1155 : OMP_CLAUSE_VECTOR,
1156 : OMP_CLAUSE_SEQ,
1157 : OMP_CLAUSE_INDEPENDENT,
1158 : OMP_CLAUSE_USE_DEVICE,
1159 : OMP_CLAUSE_DEVICE_RESIDENT,
1160 : OMP_CLAUSE_SELF,
1161 : OMP_CLAUSE_HOST,
1162 : OMP_CLAUSE_WAIT,
1163 : OMP_CLAUSE_DELETE,
1164 : OMP_CLAUSE_AUTO,
1165 : OMP_CLAUSE_TILE,
1166 : OMP_CLAUSE_IF_PRESENT,
1167 : OMP_CLAUSE_FINALIZE,
1168 : OMP_CLAUSE_ATTACH,
1169 : OMP_CLAUSE_NOHOST,
1170 : OMP_CLAUSE_HAS_DEVICE_ADDR, /* OpenMP 5.1 */
1171 : OMP_CLAUSE_ENTER, /* OpenMP 5.2 */
1172 : OMP_CLAUSE_DOACROSS, /* OpenMP 5.2 */
1173 : OMP_CLAUSE_ASSUMPTIONS, /* OpenMP 5.1. */
1174 : OMP_CLAUSE_USES_ALLOCATORS, /* OpenMP 5.0 */
1175 : OMP_CLAUSE_INDIRECT, /* OpenMP 5.1 */
1176 : OMP_CLAUSE_FULL, /* OpenMP 5.1. */
1177 : OMP_CLAUSE_PARTIAL, /* OpenMP 5.1. */
1178 : OMP_CLAUSE_SIZES, /* OpenMP 5.1. */
1179 : OMP_CLAUSE_INIT, /* OpenMP 5.1. */
1180 : OMP_CLAUSE_DESTROY, /* OpenMP 5.1. */
1181 : OMP_CLAUSE_USE, /* OpenMP 5.1. */
1182 : OMP_CLAUSE_NOVARIANTS, /* OpenMP 5.1 */
1183 : OMP_CLAUSE_NOCONTEXT, /* OpenMP 5.1 */
1184 : OMP_CLAUSE_INTEROP, /* OpenMP 5.1 */
1185 : OMP_CLAUSE_LOCAL, /* OpenMP 6.0 */
1186 : OMP_CLAUSE_DYN_GROUPPRIVATE, /* OpenMP 6.1 */
1187 : /* This must come last. */
1188 : OMP_MASK2_LAST
1189 : };
1190 :
1191 : struct omp_inv_mask;
1192 :
1193 : /* Customized bitset for up to 128-bits.
1194 : The two enums above provide bit numbers to use, and which of the
1195 : two enums it is determines which of the two mask fields is used.
1196 : Supported operations are defining a mask, like:
1197 : #define XXX_CLAUSES \
1198 : (omp_mask (OMP_CLAUSE_XXX) | OMP_CLAUSE_YYY | OMP_CLAUSE_ZZZ)
1199 : oring such bitsets together or removing selected bits:
1200 : (XXX_CLAUSES | YYY_CLAUSES) & ~(omp_mask (OMP_CLAUSE_VVV))
1201 : and testing individual bits:
1202 : if (mask & OMP_CLAUSE_UUU) */
1203 :
1204 : struct omp_mask {
1205 : const uint64_t mask1;
1206 : const uint64_t mask2;
1207 : inline omp_mask ();
1208 : inline omp_mask (omp_mask1);
1209 : inline omp_mask (omp_mask2);
1210 : inline omp_mask (uint64_t, uint64_t);
1211 : inline omp_mask operator| (omp_mask1) const;
1212 : inline omp_mask operator| (omp_mask2) const;
1213 : inline omp_mask operator| (omp_mask) const;
1214 : inline omp_mask operator& (const omp_inv_mask &) const;
1215 : inline bool operator& (omp_mask1) const;
1216 : inline bool operator& (omp_mask2) const;
1217 : inline omp_inv_mask operator~ () const;
1218 : };
1219 :
1220 : struct omp_inv_mask : public omp_mask {
1221 : inline omp_inv_mask (const omp_mask &);
1222 : };
1223 :
1224 : omp_mask::omp_mask () : mask1 (0), mask2 (0)
1225 : {
1226 : }
1227 :
1228 32352 : omp_mask::omp_mask (omp_mask1 m) : mask1 (((uint64_t) 1) << m), mask2 (0)
1229 : {
1230 : }
1231 :
1232 2205 : omp_mask::omp_mask (omp_mask2 m) : mask1 (0), mask2 (((uint64_t) 1) << m)
1233 : {
1234 : }
1235 :
1236 33234 : omp_mask::omp_mask (uint64_t m1, uint64_t m2) : mask1 (m1), mask2 (m2)
1237 : {
1238 : }
1239 :
1240 : omp_mask
1241 32283 : omp_mask::operator| (omp_mask1 m) const
1242 : {
1243 32283 : return omp_mask (mask1 | (((uint64_t) 1) << m), mask2);
1244 : }
1245 :
1246 : omp_mask
1247 16861 : omp_mask::operator| (omp_mask2 m) const
1248 : {
1249 16861 : return omp_mask (mask1, mask2 | (((uint64_t) 1) << m));
1250 : }
1251 :
1252 : omp_mask
1253 4365 : omp_mask::operator| (omp_mask m) const
1254 : {
1255 4365 : return omp_mask (mask1 | m.mask1, mask2 | m.mask2);
1256 : }
1257 :
1258 : omp_mask
1259 2024 : omp_mask::operator& (const omp_inv_mask &m) const
1260 : {
1261 2024 : return omp_mask (mask1 & ~m.mask1, mask2 & ~m.mask2);
1262 : }
1263 :
1264 : bool
1265 125913 : omp_mask::operator& (omp_mask1 m) const
1266 : {
1267 125913 : return (mask1 & (((uint64_t) 1) << m)) != 0;
1268 : }
1269 :
1270 : bool
1271 88420 : omp_mask::operator& (omp_mask2 m) const
1272 : {
1273 88420 : return (mask2 & (((uint64_t) 1) << m)) != 0;
1274 : }
1275 :
1276 : omp_inv_mask
1277 2024 : omp_mask::operator~ () const
1278 : {
1279 2024 : return omp_inv_mask (*this);
1280 : }
1281 :
1282 2024 : omp_inv_mask::omp_inv_mask (const omp_mask &m) : omp_mask (m)
1283 : {
1284 : }
1285 :
1286 : /* Helper function for OpenACC and OpenMP clauses involving memory
1287 : mapping. */
1288 :
1289 : static bool
1290 5544 : gfc_match_omp_map_clause (gfc_omp_namelist **list, gfc_omp_map_op map_op,
1291 : bool allow_common, bool allow_derived)
1292 : {
1293 5544 : gfc_omp_namelist **head = NULL;
1294 5544 : if (gfc_match_omp_variable_list ("", list, allow_common, NULL, &head, true,
1295 : allow_derived)
1296 : == MATCH_YES)
1297 : {
1298 5535 : gfc_omp_namelist *n;
1299 13409 : for (n = *head; n; n = n->next)
1300 7874 : n->u.map.op = map_op;
1301 : return true;
1302 : }
1303 :
1304 : return false;
1305 : }
1306 :
1307 : static match
1308 8729 : gfc_match_iterator (gfc_namespace **ns, bool permit_var)
1309 : {
1310 8729 : locus old_loc = gfc_current_locus;
1311 :
1312 8729 : if (gfc_match ("iterator ( ") != MATCH_YES)
1313 : return MATCH_NO;
1314 :
1315 142 : gfc_typespec ts;
1316 142 : gfc_symbol *last = NULL;
1317 142 : gfc_expr *begin, *end, *step;
1318 142 : *ns = gfc_build_block_ns (gfc_current_ns);
1319 161 : char name[GFC_MAX_SYMBOL_LEN + 1];
1320 180 : while (true)
1321 : {
1322 161 : locus prev_loc = gfc_current_locus;
1323 161 : if (gfc_match_type_spec (&ts) == MATCH_YES
1324 161 : && gfc_match (" :: ") == MATCH_YES)
1325 : {
1326 5 : if (ts.type != BT_INTEGER)
1327 : {
1328 2 : gfc_error ("Expected INTEGER type at %L", &prev_loc);
1329 5 : return MATCH_ERROR;
1330 : }
1331 : permit_var = false;
1332 : }
1333 : else
1334 : {
1335 156 : ts.type = BT_INTEGER;
1336 156 : ts.kind = gfc_default_integer_kind;
1337 156 : gfc_current_locus = prev_loc;
1338 : }
1339 159 : prev_loc = gfc_current_locus;
1340 159 : if (gfc_match_name (name) != MATCH_YES)
1341 : {
1342 4 : gfc_error ("Expected identifier at %C");
1343 4 : goto failed;
1344 : }
1345 155 : if (gfc_find_symtree ((*ns)->sym_root, name))
1346 : {
1347 2 : gfc_error ("Same identifier %qs specified again at %C", name);
1348 2 : goto failed;
1349 : }
1350 :
1351 153 : gfc_symbol *sym = gfc_new_symbol (name, *ns);
1352 153 : if (last)
1353 17 : last->tlink = sym;
1354 : else
1355 136 : (*ns)->omp_affinity_iterators = sym;
1356 153 : last = sym;
1357 153 : sym->declared_at = prev_loc;
1358 153 : sym->ts = ts;
1359 153 : sym->attr.flavor = FL_VARIABLE;
1360 153 : sym->attr.artificial = 1;
1361 153 : sym->attr.referenced = 1;
1362 153 : sym->refs++;
1363 153 : gfc_symtree *st = gfc_new_symtree (&(*ns)->sym_root, name);
1364 153 : st->n.sym = sym;
1365 :
1366 153 : prev_loc = gfc_current_locus;
1367 153 : if (gfc_match (" = ") != MATCH_YES)
1368 3 : goto failed;
1369 150 : permit_var = false;
1370 150 : begin = end = step = NULL;
1371 150 : if (gfc_match ("%e : ", &begin) != MATCH_YES
1372 150 : || gfc_match ("%e ", &end) != MATCH_YES)
1373 : {
1374 3 : gfc_error ("Expected range-specification at %C");
1375 3 : gfc_free_expr (begin);
1376 3 : gfc_free_expr (end);
1377 3 : return MATCH_ERROR;
1378 : }
1379 147 : if (':' == gfc_peek_ascii_char ())
1380 : {
1381 23 : if (gfc_match (": %e ", &step) != MATCH_YES)
1382 : {
1383 5 : gfc_free_expr (begin);
1384 5 : gfc_free_expr (end);
1385 5 : gfc_free_expr (step);
1386 5 : goto failed;
1387 : }
1388 : }
1389 :
1390 142 : gfc_expr *e = gfc_get_expr ();
1391 142 : e->where = prev_loc;
1392 142 : e->expr_type = EXPR_ARRAY;
1393 142 : e->ts = ts;
1394 142 : e->rank = 1;
1395 142 : e->shape = gfc_get_shape (1);
1396 266 : mpz_init_set_ui (e->shape[0], step ? 3 : 2);
1397 142 : gfc_constructor_append_expr (&e->value.constructor, begin, &begin->where);
1398 142 : gfc_constructor_append_expr (&e->value.constructor, end, &end->where);
1399 142 : if (step)
1400 18 : gfc_constructor_append_expr (&e->value.constructor, step, &step->where);
1401 142 : sym->value = e;
1402 :
1403 142 : if (gfc_match (") ") == MATCH_YES)
1404 : break;
1405 19 : if (gfc_match (", ") != MATCH_YES)
1406 0 : goto failed;
1407 19 : }
1408 123 : return MATCH_YES;
1409 :
1410 14 : failed:
1411 14 : gfc_namespace *prev_ns = NULL;
1412 14 : for (gfc_namespace *it = gfc_current_ns->contained; it; it = it->sibling)
1413 : {
1414 0 : if (it == *ns)
1415 : {
1416 0 : if (prev_ns)
1417 0 : prev_ns->sibling = it->sibling;
1418 : else
1419 0 : gfc_current_ns->contained = it->sibling;
1420 0 : gfc_free_namespace (it);
1421 0 : break;
1422 : }
1423 0 : prev_ns = it;
1424 : }
1425 14 : *ns = NULL;
1426 14 : if (!permit_var)
1427 : return MATCH_ERROR;
1428 4 : gfc_current_locus = old_loc;
1429 4 : return MATCH_NO;
1430 : }
1431 :
1432 : /* Match target update's to/from( [present:] var-list). */
1433 :
1434 : static match
1435 1736 : gfc_match_motion_var_list (const char *str, gfc_omp_namelist **list,
1436 : gfc_omp_namelist ***headp)
1437 : {
1438 1736 : match m = gfc_match (str);
1439 1736 : if (m != MATCH_YES)
1440 : return m;
1441 :
1442 1736 : gfc_namespace *ns_iter = NULL, *ns_curr = gfc_current_ns;
1443 1736 : locus old_loc = gfc_current_locus;
1444 1736 : int present_modifier = 0;
1445 1736 : int iterator_modifier = 0;
1446 1736 : locus second_present_locus = old_loc;
1447 1736 : locus second_iterator_locus = old_loc;
1448 1736 : bool saw_modifier = false;
1449 :
1450 1748 : for (;;)
1451 : {
1452 1742 : locus current_locus = gfc_current_locus;
1453 1742 : if (gfc_match ("present ") == MATCH_YES)
1454 : {
1455 8 : if (present_modifier++ == 1)
1456 0 : second_present_locus = current_locus;
1457 : }
1458 1734 : else if (gfc_match_iterator (&ns_iter, true) == MATCH_YES)
1459 : {
1460 20 : if (iterator_modifier++ == 1)
1461 1 : second_iterator_locus = current_locus;
1462 : }
1463 1714 : else if (!saw_modifier)
1464 : break;
1465 : else
1466 : {
1467 2 : gfc_error ("Expected clause modifier at %C");
1468 4 : return MATCH_ERROR;
1469 : }
1470 :
1471 : /* OpenMP 5.1 syntax mistakenly allowed commas to be optional
1472 : between and after modifiers in a clause. This was corrected
1473 : in 5.2 and later specifications: they're now required between
1474 : modifiers and a trailing comma is not permitted. We implement
1475 : the 5.2 syntax here. */
1476 28 : saw_modifier = true;
1477 28 : if (gfc_match (" : ") == MATCH_YES)
1478 : break;
1479 8 : else if (gfc_match (", ") == MATCH_YES)
1480 6 : continue;
1481 : else
1482 : {
1483 2 : gfc_error ("Expected %<,%> or %<:%> after clause modifier at %C");
1484 2 : return MATCH_ERROR;
1485 : }
1486 : }
1487 :
1488 1732 : if (!saw_modifier)
1489 : {
1490 1712 : gfc_current_locus = old_loc;
1491 1712 : present_modifier = 0;
1492 1712 : iterator_modifier = 0;
1493 : }
1494 :
1495 1732 : if (present_modifier > 1)
1496 : {
1497 0 : gfc_error ("Too many %<present%> modifiers at %L", &second_present_locus);
1498 0 : return MATCH_ERROR;
1499 : }
1500 1732 : if (iterator_modifier > 1)
1501 : {
1502 1 : gfc_error ("Too many %<iterator%> modifiers at %L",
1503 : &second_iterator_locus);
1504 1 : return MATCH_ERROR;
1505 : }
1506 :
1507 1731 : if (ns_iter)
1508 14 : gfc_current_ns = ns_iter;
1509 :
1510 1731 : m = gfc_match_omp_variable_list ("", list, false, NULL, headp, true, true);
1511 1731 : gfc_current_ns = ns_curr;
1512 1731 : if (m != MATCH_YES)
1513 : return m;
1514 1729 : gfc_omp_namelist *n;
1515 3532 : for (n = **headp; n; n = n->next)
1516 : {
1517 1803 : if (present_modifier)
1518 6 : n->u.present_modifier = true;
1519 1803 : if (iterator_modifier)
1520 : {
1521 18 : n->u2.ns = ns_iter;
1522 18 : ns_iter->refs++;
1523 : }
1524 : }
1525 : return MATCH_YES;
1526 : }
1527 :
1528 : /* reduction ( reduction-modifier, reduction-operator : variable-list )
1529 : in_reduction ( reduction-operator : variable-list )
1530 : task_reduction ( reduction-operator : variable-list ) */
1531 :
1532 : static match
1533 4360 : gfc_match_omp_clause_reduction (char pc, gfc_omp_clauses *c, bool openacc,
1534 : bool allow_derived, bool openmp_target = false)
1535 : {
1536 4360 : if (pc == 'r' && gfc_match ("reduction ( ") != MATCH_YES)
1537 : return MATCH_NO;
1538 4360 : else if (pc == 'i' && gfc_match ("in_reduction ( ") != MATCH_YES)
1539 : return MATCH_NO;
1540 4248 : else if (pc == 't' && gfc_match ("task_reduction ( ") != MATCH_YES)
1541 : return MATCH_NO;
1542 :
1543 4248 : locus old_loc = gfc_current_locus;
1544 4248 : enum gfc_omp_list_type list_idx = OMP_LIST_NONE;
1545 :
1546 4248 : if (pc == 'r' && !openacc)
1547 : {
1548 2121 : if (gfc_match ("inscan") == MATCH_YES)
1549 : list_idx = OMP_LIST_REDUCTION_INSCAN;
1550 2051 : else if (gfc_match ("task") == MATCH_YES)
1551 : list_idx = OMP_LIST_REDUCTION_TASK;
1552 1946 : else if (gfc_match ("default") == MATCH_YES)
1553 : list_idx = OMP_LIST_REDUCTION;
1554 231 : if (list_idx != OMP_LIST_NONE && gfc_match (", ") != MATCH_YES)
1555 : {
1556 1 : gfc_error ("Comma expected at %C");
1557 1 : gfc_current_locus = old_loc;
1558 1 : return MATCH_NO;
1559 : }
1560 2120 : if (list_idx == OMP_LIST_NONE)
1561 3834 : list_idx = OMP_LIST_REDUCTION;
1562 : }
1563 2127 : else if (pc == 'i')
1564 : list_idx = OMP_LIST_IN_REDUCTION;
1565 2009 : else if (pc == 't')
1566 : list_idx = OMP_LIST_TASK_REDUCTION;
1567 : else
1568 3834 : list_idx = OMP_LIST_REDUCTION;
1569 :
1570 4247 : gfc_omp_reduction_op rop = OMP_REDUCTION_NONE;
1571 4247 : char buffer[GFC_MAX_SYMBOL_LEN + 3];
1572 4247 : if (gfc_match_char ('+') == MATCH_YES)
1573 : rop = OMP_REDUCTION_PLUS;
1574 2223 : else if (gfc_match_char ('*') == MATCH_YES)
1575 : rop = OMP_REDUCTION_TIMES;
1576 1991 : else if (gfc_match_char ('-') == MATCH_YES)
1577 : {
1578 171 : if (!openacc)
1579 16 : gfc_warning (OPT_Wdeprecated_openmp,
1580 : "%<-%> operator at %C for reductions deprecated in "
1581 : "OpenMP 5.2");
1582 : rop = OMP_REDUCTION_MINUS;
1583 : }
1584 1820 : else if (gfc_match (".and.") == MATCH_YES)
1585 : rop = OMP_REDUCTION_AND;
1586 1714 : else if (gfc_match (".or.") == MATCH_YES)
1587 : rop = OMP_REDUCTION_OR;
1588 929 : else if (gfc_match (".eqv.") == MATCH_YES)
1589 : rop = OMP_REDUCTION_EQV;
1590 831 : else if (gfc_match (".neqv.") == MATCH_YES)
1591 : rop = OMP_REDUCTION_NEQV;
1592 736 : if (rop != OMP_REDUCTION_NONE)
1593 3511 : snprintf (buffer, sizeof buffer, "operator %s",
1594 : gfc_op2string ((gfc_intrinsic_op) rop));
1595 736 : else if (gfc_match_defined_op_name (buffer + 1, 1) == MATCH_YES)
1596 : {
1597 38 : buffer[0] = '.';
1598 38 : strcat (buffer, ".");
1599 : }
1600 698 : else if (gfc_match_name (buffer) == MATCH_YES)
1601 : {
1602 697 : gfc_symbol *sym;
1603 697 : const char *n = buffer;
1604 :
1605 697 : gfc_find_symbol (buffer, NULL, 1, &sym);
1606 697 : if (sym != NULL)
1607 : {
1608 216 : if (sym->attr.intrinsic)
1609 139 : n = sym->name;
1610 77 : else if ((sym->attr.flavor != FL_UNKNOWN
1611 75 : && sym->attr.flavor != FL_PROCEDURE)
1612 75 : || sym->attr.external
1613 64 : || sym->attr.generic
1614 64 : || sym->attr.entry
1615 64 : || sym->attr.result
1616 64 : || sym->attr.dummy
1617 64 : || sym->attr.subroutine
1618 63 : || sym->attr.pointer
1619 63 : || sym->attr.target
1620 63 : || sym->attr.cray_pointer
1621 63 : || sym->attr.cray_pointee
1622 63 : || (sym->attr.proc != PROC_UNKNOWN
1623 1 : && sym->attr.proc != PROC_INTRINSIC)
1624 62 : || sym->attr.if_source != IFSRC_UNKNOWN
1625 62 : || sym == sym->ns->proc_name)
1626 : {
1627 : sym = NULL;
1628 : n = NULL;
1629 : }
1630 : else
1631 62 : n = sym->name;
1632 : }
1633 201 : if (n == NULL)
1634 : rop = OMP_REDUCTION_NONE;
1635 682 : else if (strcmp (n, "max") == 0)
1636 : rop = OMP_REDUCTION_MAX;
1637 517 : else if (strcmp (n, "min") == 0)
1638 : rop = OMP_REDUCTION_MIN;
1639 376 : else if (strcmp (n, "iand") == 0)
1640 : rop = OMP_REDUCTION_IAND;
1641 321 : else if (strcmp (n, "ior") == 0)
1642 : rop = OMP_REDUCTION_IOR;
1643 255 : else if (strcmp (n, "ieor") == 0)
1644 : rop = OMP_REDUCTION_IEOR;
1645 : if (rop != OMP_REDUCTION_NONE
1646 477 : && sym != NULL
1647 200 : && ! sym->attr.intrinsic
1648 61 : && ! sym->attr.use_assoc
1649 61 : && ((sym->attr.flavor == FL_UNKNOWN
1650 2 : && !gfc_add_flavor (&sym->attr, FL_PROCEDURE,
1651 : sym->name, NULL))
1652 61 : || !gfc_add_intrinsic (&sym->attr, NULL)))
1653 : rop = OMP_REDUCTION_NONE;
1654 : }
1655 : else
1656 1 : buffer[0] = '\0';
1657 4247 : gfc_omp_udr *udr = (buffer[0] ? gfc_find_omp_udr (gfc_current_ns, buffer, NULL)
1658 : : NULL);
1659 4247 : gfc_omp_namelist **head = NULL;
1660 4247 : if (rop == OMP_REDUCTION_NONE && udr)
1661 250 : rop = OMP_REDUCTION_USER;
1662 :
1663 4247 : if (gfc_match_omp_variable_list (" :", &c->lists[list_idx], false, NULL,
1664 : &head, openacc, allow_derived) != MATCH_YES)
1665 : {
1666 9 : gfc_current_locus = old_loc;
1667 9 : return MATCH_NO;
1668 : }
1669 4238 : gfc_omp_namelist *n;
1670 4238 : if (rop == OMP_REDUCTION_NONE)
1671 : {
1672 6 : n = *head;
1673 6 : *head = NULL;
1674 6 : gfc_error_now ("!$OMP DECLARE REDUCTION %s not found at %L",
1675 : buffer, &old_loc);
1676 6 : gfc_free_omp_namelist (n, OMP_LIST_NONE);
1677 : }
1678 : else
1679 9116 : for (n = *head; n; n = n->next)
1680 : {
1681 4884 : n->u.reduction_op = rop;
1682 4884 : if (udr)
1683 : {
1684 476 : n->u2.udr = gfc_get_omp_namelist_udr ();
1685 476 : n->u2.udr->udr = udr;
1686 : }
1687 4884 : if (openmp_target && list_idx == OMP_LIST_IN_REDUCTION)
1688 : {
1689 40 : gfc_omp_namelist *p = gfc_get_omp_namelist (), **tl;
1690 40 : p->sym = n->sym;
1691 40 : p->where = n->where;
1692 40 : p->u.map.op = OMP_MAP_ALWAYS_TOFROM;
1693 :
1694 40 : tl = &c->lists[OMP_LIST_MAP];
1695 52 : while (*tl)
1696 12 : tl = &((*tl)->next);
1697 40 : *tl = p;
1698 40 : p->next = NULL;
1699 : }
1700 : }
1701 : return MATCH_YES;
1702 : }
1703 :
1704 : static match
1705 40 : gfc_omp_absent_contains_clause (gfc_omp_assumptions **assume, bool is_absent)
1706 : {
1707 40 : if (*assume == NULL)
1708 15 : *assume = gfc_get_omp_assumptions ();
1709 62 : do
1710 : {
1711 51 : gfc_statement st = ST_NONE;
1712 51 : gfc_gobble_whitespace ();
1713 51 : locus old_loc = gfc_current_locus;
1714 51 : char c = gfc_peek_ascii_char ();
1715 51 : enum gfc_omp_directive_kind kind
1716 : = GFC_OMP_DIR_DECLARATIVE; /* Silence warning. */
1717 1585 : for (size_t i = 0; i < ARRAY_SIZE (gfc_omp_directives); i++)
1718 : {
1719 1585 : if (gfc_omp_directives[i].name[0] > c)
1720 : break;
1721 1534 : if (gfc_omp_directives[i].name[0] != c)
1722 1182 : continue;
1723 352 : if (gfc_match (gfc_omp_directives[i].name) == MATCH_YES)
1724 : {
1725 51 : st = gfc_omp_directives[i].st;
1726 51 : kind = gfc_omp_directives[i].kind;
1727 : }
1728 : }
1729 51 : gfc_gobble_whitespace ();
1730 51 : c = gfc_peek_ascii_char ();
1731 51 : if (st == ST_NONE || (c != ',' && c != ')'))
1732 : {
1733 0 : if (st == ST_NONE)
1734 0 : gfc_error ("Unknown directive at %L", &old_loc);
1735 : else
1736 0 : gfc_error ("Invalid combined or composite directive at %L",
1737 : &old_loc);
1738 4 : return MATCH_ERROR;
1739 : }
1740 51 : if (kind == GFC_OMP_DIR_DECLARATIVE
1741 51 : || kind == GFC_OMP_DIR_INFORMATIONAL
1742 : || kind == GFC_OMP_DIR_META)
1743 : {
1744 5 : gfc_error ("Invalid %qs directive at %L in %s clause: declarative, "
1745 : "informational, and meta directives not permitted",
1746 : gfc_ascii_statement (st, true), &old_loc,
1747 : is_absent ? "ABSENT" : "CONTAINS");
1748 4 : return MATCH_ERROR;
1749 : }
1750 47 : if (is_absent)
1751 : {
1752 : /* Use exponential allocation; equivalent to pow2p(x). */
1753 33 : int i = (*assume)->n_absent;
1754 33 : int size = ((i == 0) ? 4
1755 10 : : pow2p_hwi (i) == 1 ? i*2 : 0);
1756 8 : if (size != 0)
1757 31 : (*assume)->absent = XRESIZEVEC (gfc_statement,
1758 : (*assume)->absent, size);
1759 33 : (*assume)->absent[(*assume)->n_absent++] = st;
1760 : }
1761 : else
1762 : {
1763 14 : int i = (*assume)->n_contains;
1764 14 : int size = ((i == 0) ? 4
1765 4 : : pow2p_hwi (i) == 1 ? i*2 : 0);
1766 4 : if (size != 0)
1767 14 : (*assume)->contains = XRESIZEVEC (gfc_statement,
1768 : (*assume)->contains, size);
1769 14 : (*assume)->contains[(*assume)->n_contains++] = st;
1770 : }
1771 47 : gfc_gobble_whitespace ();
1772 47 : if (gfc_match(",") == MATCH_YES)
1773 11 : continue;
1774 36 : if (gfc_match(")") == MATCH_YES)
1775 : break;
1776 0 : gfc_error ("Expected %<,%> or %<)%> at %C");
1777 0 : return MATCH_ERROR;
1778 : }
1779 : while (true);
1780 :
1781 36 : return MATCH_YES;
1782 : }
1783 :
1784 : /* Check 'check' argument for duplicated statements in absent and/or contains
1785 : clauses. If 'merge', merge them from check to 'merge'. */
1786 :
1787 : static match
1788 43 : omp_verify_merge_absent_contains (gfc_statement st, gfc_omp_assumptions *check,
1789 : gfc_omp_assumptions *merge, locus *loc)
1790 : {
1791 43 : if (check == NULL)
1792 : return MATCH_YES;
1793 43 : bitmap_head absent_head, contains_head;
1794 43 : bitmap_obstack_initialize (NULL);
1795 43 : bitmap_initialize (&absent_head, &bitmap_default_obstack);
1796 43 : bitmap_initialize (&contains_head, &bitmap_default_obstack);
1797 :
1798 43 : match m = MATCH_YES;
1799 76 : for (int i = 0; i < check->n_absent; i++)
1800 33 : if (!bitmap_set_bit (&absent_head, check->absent[i]))
1801 : {
1802 2 : gfc_error ("%qs directive mentioned multiple times in %s clause in %s "
1803 : "directive at %L",
1804 2 : gfc_ascii_statement (check->absent[i], true),
1805 : "ABSENT", gfc_ascii_statement (st), loc);
1806 2 : m = MATCH_ERROR;
1807 : }
1808 57 : for (int i = 0; i < check->n_contains; i++)
1809 : {
1810 14 : if (!bitmap_set_bit (&contains_head, check->contains[i]))
1811 : {
1812 2 : gfc_error ("%qs directive mentioned multiple times in %s clause in %s "
1813 : "directive at %L",
1814 2 : gfc_ascii_statement (check->contains[i], true),
1815 : "CONTAINS", gfc_ascii_statement (st), loc);
1816 2 : m = MATCH_ERROR;
1817 : }
1818 14 : if (bitmap_bit_p (&absent_head, check->contains[i]))
1819 : {
1820 2 : gfc_error ("%qs directive mentioned both times in ABSENT and CONTAINS "
1821 : "clauses in %s directive at %L",
1822 2 : gfc_ascii_statement (check->absent[i], true),
1823 : gfc_ascii_statement (st), loc);
1824 2 : m = MATCH_ERROR;
1825 : }
1826 : }
1827 :
1828 43 : if (m == MATCH_ERROR)
1829 : return MATCH_ERROR;
1830 37 : if (merge == NULL)
1831 : return MATCH_YES;
1832 2 : if (merge->absent == NULL && check->absent)
1833 : {
1834 1 : merge->n_absent = check->n_absent;
1835 1 : merge->absent = check->absent;
1836 1 : check->absent = NULL;
1837 : }
1838 1 : else if (merge->absent && check->absent)
1839 : {
1840 0 : check->absent = XRESIZEVEC (gfc_statement, check->absent,
1841 : merge->n_absent + check->n_absent);
1842 0 : for (int i = 0; i < merge->n_absent; i++)
1843 0 : if (!bitmap_bit_p (&absent_head, merge->absent[i]))
1844 0 : check->absent[check->n_absent++] = merge->absent[i];
1845 0 : free (merge->absent);
1846 0 : merge->absent = check->absent;
1847 0 : merge->n_absent = check->n_absent;
1848 0 : check->absent = NULL;
1849 : }
1850 2 : if (merge->contains == NULL && check->contains)
1851 : {
1852 0 : merge->n_contains = check->n_contains;
1853 0 : merge->contains = check->contains;
1854 0 : check->contains = NULL;
1855 : }
1856 2 : else if (merge->contains && check->contains)
1857 : {
1858 0 : check->contains = XRESIZEVEC (gfc_statement, check->contains,
1859 : merge->n_contains + check->n_contains);
1860 0 : for (int i = 0; i < merge->n_contains; i++)
1861 0 : if (!bitmap_bit_p (&contains_head, merge->contains[i]))
1862 0 : check->contains[check->n_contains++] = merge->contains[i];
1863 0 : free (merge->contains);
1864 0 : merge->contains = check->contains;
1865 0 : merge->n_contains = check->n_contains;
1866 0 : check->contains = NULL;
1867 : }
1868 : return MATCH_YES;
1869 : }
1870 :
1871 : /* OpenMP 5.0
1872 : uses_allocators ( allocator-list )
1873 :
1874 : allocator:
1875 : predefined-allocator
1876 : variable ( traits-array )
1877 :
1878 : OpenMP 5.2 deprecated, 6.0 deleted: 'variable ( traits-array )'
1879 :
1880 : OpenMP 5.2:
1881 : uses_allocators ( [modifier-list :] allocator-list )
1882 :
1883 : OpenMP 6.0:
1884 : uses_allocators ( [modifier-list :] allocator-list [; ...])
1885 :
1886 : allocator:
1887 : variable or predefined-allocator
1888 : modifier:
1889 : traits ( traits-array )
1890 : memspace ( mem-space-handle ) */
1891 :
1892 : static match
1893 78 : gfc_match_omp_clause_uses_allocators (gfc_omp_clauses *c)
1894 : {
1895 82 : parse_next:
1896 82 : gfc_symbol *memspace_sym = NULL;
1897 82 : gfc_symbol *traits_sym = NULL;
1898 82 : gfc_omp_namelist *head = NULL;
1899 82 : gfc_omp_namelist *p, *tail, **list;
1900 82 : int ntraits, nmemspace;
1901 82 : bool has_modifiers;
1902 82 : locus old_loc, cur_loc;
1903 :
1904 82 : gfc_gobble_whitespace ();
1905 82 : old_loc = gfc_current_locus;
1906 82 : ntraits = nmemspace = 0;
1907 126 : do
1908 : {
1909 104 : cur_loc = gfc_current_locus;
1910 104 : if (gfc_match ("traits ( %S ) ", &traits_sym) == MATCH_YES)
1911 34 : ntraits++;
1912 70 : else if (gfc_match ("memspace ( %S ) ", &memspace_sym) == MATCH_YES)
1913 33 : nmemspace++;
1914 104 : if (ntraits > 1 || nmemspace > 1)
1915 : {
1916 5 : gfc_error ("Duplicate %s modifier at %L in USES_ALLOCATORS clause",
1917 : ntraits > 1 ? "TRAITS" : "MEMSPACE", &cur_loc);
1918 5 : return MATCH_ERROR;
1919 : }
1920 99 : if (gfc_match (", ") == MATCH_YES)
1921 22 : continue;
1922 77 : if (gfc_match (": ") != MATCH_YES)
1923 : {
1924 : /* Assume no modifier. */
1925 39 : memspace_sym = traits_sym = NULL;
1926 39 : gfc_current_locus = old_loc;
1927 39 : break;
1928 : }
1929 : break;
1930 : } while (true);
1931 :
1932 115 : has_modifiers = traits_sym != NULL || memspace_sym != NULL;
1933 179 : do
1934 : {
1935 128 : p = gfc_get_omp_namelist ();
1936 128 : p->where = gfc_current_locus;
1937 128 : if (head == NULL)
1938 : head = tail = p;
1939 : else
1940 : {
1941 51 : tail->next = p;
1942 51 : tail = tail->next;
1943 : }
1944 128 : if (gfc_match ("%S ", &p->sym) != MATCH_YES)
1945 1 : goto error;
1946 127 : if (!has_modifiers)
1947 : {
1948 83 : if (gfc_match ("( %S ) ", &p->u2.traits_sym) == MATCH_YES)
1949 22 : gfc_warning (OPT_Wdeprecated_openmp,
1950 : "The specification of arguments to "
1951 : "%<uses_allocators%> at %L where each item is of "
1952 : "the form %<allocator(traits)%> is deprecated since "
1953 : "OpenMP 5.2; instead use %<uses_allocators(traits(%s"
1954 22 : "): %s)%>", &p->where, p->u2.traits_sym->name,
1955 22 : p->sym->name);
1956 : }
1957 44 : else if (gfc_peek_ascii_char () == '(')
1958 : {
1959 1 : gfc_error ("Unexpected %<(%> at %C");
1960 1 : goto error;
1961 : }
1962 : else
1963 : {
1964 43 : p->u.memspace_sym = memspace_sym;
1965 43 : p->u2.traits_sym = traits_sym;
1966 : }
1967 126 : gfc_gobble_whitespace ();
1968 126 : const char c = gfc_peek_ascii_char ();
1969 126 : if (c == ';' || c == ')')
1970 : break;
1971 53 : if (c != ',')
1972 : {
1973 2 : gfc_error ("Expected %<,%>, %<)%> or %<;%> at %C");
1974 2 : goto error;
1975 : }
1976 51 : gfc_match_char (',');
1977 51 : gfc_gobble_whitespace ();
1978 51 : } while (true);
1979 :
1980 73 : list = &c->lists[OMP_LIST_USES_ALLOCATORS];
1981 91 : while (*list)
1982 18 : list = &(*list)->next;
1983 73 : *list = head;
1984 :
1985 73 : if (gfc_match_char (';') == MATCH_YES)
1986 4 : goto parse_next;
1987 :
1988 69 : gfc_match_char (')');
1989 69 : return MATCH_YES;
1990 :
1991 4 : error:
1992 4 : gfc_free_omp_namelist (head, OMP_LIST_USES_ALLOCATORS);
1993 4 : return MATCH_ERROR;
1994 : }
1995 :
1996 :
1997 : /* Match the 'prefer_type' modifier of the interop 'init' clause:
1998 : with either OpenMP 5.1's
1999 : prefer_type ( <const-int-expr|string literal> [, ...]
2000 : or
2001 : prefer_type ( '{' <fr(...) | attr (...)>, ...] '}' [, '{' ... '}' ] )
2002 : where 'fr' takes a constant expression or a string literal
2003 : and 'attr takes a list of string literals, starting with 'ompx_')
2004 :
2005 : For the foreign runtime identifiers, string values are converted to
2006 : their integer value; unknown string or integer values are set to
2007 : GOMP_INTEROP_IFR_KNOWN.
2008 :
2009 : Data format:
2010 : For the foreign runtime identifiers, string values are converted to
2011 : their integer value; unknown string or integer values are set to 0.
2012 :
2013 : Each item (a) GOMP_INTEROP_IFR_SEPARATOR
2014 : (b) for any 'fr', its integer value.
2015 : Note: Spec only permits 1 'fr' entry (6.0; changed after TR13)
2016 : (c) GOMP_INTEROP_IFR_SEPARATOR
2017 : (d) list of \0-terminated non-empty strings for 'attr'
2018 : (e) '\0'
2019 : Tailing '\0'. */
2020 :
2021 : static match
2022 82 : gfc_match_omp_prefer_type (char **type_str, int *type_str_len)
2023 : {
2024 82 : gfc_expr *e;
2025 82 : std::string type_string, attr_string;
2026 : /* New syntax. */
2027 82 : if (gfc_peek_ascii_char () == '{')
2028 115 : do
2029 : {
2030 85 : attr_string.clear ();
2031 85 : type_string += (char) GOMP_INTEROP_IFR_SEPARATOR;
2032 85 : if (gfc_match ("{ ") != MATCH_YES)
2033 : {
2034 1 : gfc_error ("Expected %<{%> at %C");
2035 1 : return MATCH_ERROR;
2036 : }
2037 : bool fr_found = false;
2038 148 : do
2039 : {
2040 116 : if (gfc_match ("fr ( ") == MATCH_YES)
2041 : {
2042 62 : if (fr_found)
2043 : {
2044 1 : gfc_error ("Duplicated %<fr%> preference-selector-name "
2045 : "at %C");
2046 1 : return MATCH_ERROR;
2047 : }
2048 61 : fr_found = true;
2049 61 : do
2050 : {
2051 61 : bool found_literal = false;
2052 61 : match m = MATCH_YES;
2053 61 : if (gfc_match_literal_constant (&e, false) == MATCH_YES)
2054 : found_literal = true;
2055 : else
2056 12 : m = gfc_match_expr (&e);
2057 12 : if (m != MATCH_YES
2058 61 : || !gfc_resolve_expr (e)
2059 61 : || e->rank != 0
2060 60 : || e->expr_type != EXPR_CONSTANT
2061 59 : || (e->ts.type != BT_INTEGER
2062 43 : && (!found_literal || e->ts.type != BT_CHARACTER))
2063 58 : || (e->ts.type == BT_INTEGER
2064 16 : && !mpz_fits_sint_p (e->value.integer))
2065 70 : || (e->ts.type == BT_CHARACTER
2066 42 : && (e->ts.kind != gfc_default_character_kind
2067 41 : || e->value.character.length == 0)))
2068 : {
2069 5 : gfc_error ("Expected constant scalar integer expression"
2070 : " or non-empty default-kind character "
2071 5 : "literal at %L", &e->where);
2072 5 : gfc_free_expr (e);
2073 5 : return MATCH_ERROR;
2074 : }
2075 56 : gfc_gobble_whitespace ();
2076 56 : int val;
2077 56 : if (e->ts.type == BT_INTEGER)
2078 : {
2079 16 : val = mpz_get_si (e->value.integer);
2080 16 : if (val < 1 || val > GOMP_INTEROP_IFR_LAST)
2081 : {
2082 0 : gfc_warning_now (OPT_Wopenmp,
2083 : "Unknown foreign runtime "
2084 : "identifier %qd at %L",
2085 : val, &e->where);
2086 0 : val = GOMP_INTEROP_IFR_UNKNOWN;
2087 : }
2088 : }
2089 : else
2090 : {
2091 40 : char *str = XALLOCAVEC (char,
2092 : e->value.character.length+1);
2093 229 : for (int i = 0; i < e->value.character.length + 1; i++)
2094 189 : str[i] = e->value.character.string[i];
2095 40 : if (memchr (str, '\0', e->value.character.length) != 0)
2096 : {
2097 0 : gfc_error ("Unexpected null character in character "
2098 : "literal at %L", &e->where);
2099 0 : return MATCH_ERROR;
2100 : }
2101 40 : val = omp_get_fr_id_from_name (str);
2102 40 : if (val == GOMP_INTEROP_IFR_UNKNOWN)
2103 2 : gfc_warning_now (OPT_Wopenmp,
2104 : "Unknown foreign runtime identifier "
2105 2 : "%qs at %L", str, &e->where);
2106 : }
2107 :
2108 56 : type_string += (char) val;
2109 56 : if (gfc_match (") ") == MATCH_YES)
2110 : break;
2111 4 : gfc_error ("Expected %<)%> at %C");
2112 4 : return MATCH_ERROR;
2113 : }
2114 : while (true);
2115 : }
2116 54 : else if (gfc_match ("attr ( ") == MATCH_YES)
2117 : {
2118 60 : do
2119 : {
2120 57 : if (gfc_match_literal_constant (&e, false) != MATCH_YES
2121 56 : || !gfc_resolve_expr (e)
2122 56 : || e->expr_type != EXPR_CONSTANT
2123 56 : || e->rank != 0
2124 56 : || e->ts.type != BT_CHARACTER
2125 113 : || e->ts.kind != gfc_default_character_kind)
2126 : {
2127 1 : gfc_error ("Expected default-kind character literal "
2128 1 : "at %L", &e->where);
2129 1 : gfc_free_expr (e);
2130 1 : return MATCH_ERROR;
2131 : }
2132 56 : gfc_gobble_whitespace ();
2133 56 : char *str = XALLOCAVEC (char, e->value.character.length+1);
2134 564 : for (int i = 0; i < e->value.character.length + 1; i++)
2135 508 : str[i] = e->value.character.string[i];
2136 56 : if (!startswith (str, "ompx_"))
2137 : {
2138 1 : gfc_error ("Character literal at %L must start with "
2139 : "%<ompx_%>", &e->where);
2140 1 : gfc_free_expr (e);
2141 1 : return MATCH_ERROR;
2142 : }
2143 55 : if (memchr (str, '\0', e->value.character.length) != 0
2144 55 : || memchr (str, ',', e->value.character.length) != 0)
2145 : {
2146 1 : gfc_error ("Unexpected null or %<,%> character in "
2147 : "character literal at %L", &e->where);
2148 1 : return MATCH_ERROR;
2149 : }
2150 54 : attr_string += str;
2151 54 : attr_string += '\0';
2152 54 : if (gfc_match (", ") == MATCH_YES)
2153 3 : continue;
2154 51 : if (gfc_match (") ") == MATCH_YES)
2155 : break;
2156 0 : gfc_error ("Expected %<,%> or %<)%> at %C");
2157 0 : return MATCH_ERROR;
2158 3 : }
2159 : while (true);
2160 : }
2161 : else
2162 : {
2163 0 : gfc_error ("Expected %<fr(%> or %<attr(%> at %C");
2164 0 : return MATCH_ERROR;
2165 : }
2166 103 : if (gfc_match (", ") == MATCH_YES)
2167 32 : continue;
2168 71 : if (gfc_match ("} ") == MATCH_YES)
2169 : break;
2170 2 : gfc_error ("Expected %<,%> or %<}%> at %C");
2171 2 : return MATCH_ERROR;
2172 32 : }
2173 : while (true);
2174 69 : type_string += (char) GOMP_INTEROP_IFR_SEPARATOR;
2175 69 : type_string += attr_string;
2176 69 : type_string += '\0';
2177 69 : if (gfc_match (", ") == MATCH_YES)
2178 30 : continue;
2179 39 : if (gfc_match (") ") == MATCH_YES)
2180 : break;
2181 1 : gfc_error ("Expected %<,%> or %<)%> at %C");
2182 1 : return MATCH_ERROR;
2183 30 : }
2184 : while (true);
2185 : else
2186 75 : do
2187 : {
2188 51 : type_string += (char) GOMP_INTEROP_IFR_SEPARATOR;
2189 51 : bool found_literal = false;
2190 51 : match m = MATCH_YES;
2191 51 : if (gfc_match_literal_constant (&e, false) == MATCH_YES)
2192 : found_literal = true;
2193 : else
2194 19 : m = gfc_match_expr (&e);
2195 19 : if (m != MATCH_YES
2196 51 : || !gfc_resolve_expr (e)
2197 51 : || e->rank != 0
2198 50 : || e->expr_type != EXPR_CONSTANT
2199 49 : || (e->ts.type != BT_INTEGER
2200 28 : && (!found_literal || e->ts.type != BT_CHARACTER))
2201 48 : || (e->ts.type == BT_INTEGER
2202 21 : && !mpz_fits_sint_p (e->value.integer))
2203 67 : || (e->ts.type == BT_CHARACTER
2204 27 : && (e->ts.kind != gfc_default_character_kind
2205 27 : || e->value.character.length == 0)))
2206 : {
2207 3 : gfc_error ("Expected constant scalar integer expression or "
2208 3 : "non-empty default-kind character literal at %L", &e->where);
2209 3 : gfc_free_expr (e);
2210 3 : return MATCH_ERROR;
2211 : }
2212 48 : gfc_gobble_whitespace ();
2213 48 : int val;
2214 48 : if (e->ts.type == BT_INTEGER)
2215 : {
2216 21 : val = mpz_get_si (e->value.integer);
2217 21 : if (val < 1 || val > GOMP_INTEROP_IFR_LAST)
2218 : {
2219 3 : gfc_warning_now (OPT_Wopenmp,
2220 : "Unknown foreign runtime identifier %qd at %L",
2221 : val, &e->where);
2222 3 : val = 0;
2223 : }
2224 : }
2225 : else
2226 : {
2227 27 : char *str = XALLOCAVEC (char, e->value.character.length+1);
2228 169 : for (int i = 0; i < e->value.character.length + 1; i++)
2229 142 : str[i] = e->value.character.string[i];
2230 27 : if (memchr (str, '\0', e->value.character.length) != 0)
2231 : {
2232 0 : gfc_error ("Unexpected null character in character "
2233 : "literal at %L", &e->where);
2234 0 : return MATCH_ERROR;
2235 : }
2236 27 : val = omp_get_fr_id_from_name (str);
2237 27 : if (val == GOMP_INTEROP_IFR_UNKNOWN)
2238 5 : gfc_warning_now (OPT_Wopenmp,
2239 : "Unknown foreign runtime identifier %qs at %L",
2240 5 : str, &e->where);
2241 : }
2242 48 : type_string += (char) val;
2243 48 : type_string += (char) GOMP_INTEROP_IFR_SEPARATOR;
2244 48 : type_string += '\0';
2245 48 : gfc_free_expr (e);
2246 48 : if (gfc_match (", ") == MATCH_YES)
2247 24 : continue;
2248 24 : if (gfc_match (") ") == MATCH_YES)
2249 : break;
2250 2 : gfc_error ("Expected %<,%> or %<)%> at %C");
2251 2 : return MATCH_ERROR;
2252 24 : }
2253 : while (true);
2254 60 : type_string += '\0';
2255 60 : *type_str_len = type_string.length();
2256 60 : *type_str = XNEWVEC (char, type_string.length ());
2257 60 : memcpy (*type_str, type_string.data (), type_string.length ());
2258 60 : return MATCH_YES;
2259 82 : }
2260 :
2261 :
2262 : /* Match OpenMP 5.1's 'init'-clause modifiers, used by the 'init' clause of
2263 : the 'interop' directive and the 'append_args' directive of 'declare variant'.
2264 : [prefer_type(...)][,][<target|targetsync>, ...])
2265 :
2266 : If is_init_clause, the modifier parsing ends with a ':'.
2267 : If not is_init_clause (i.e. append_args), the parsing ends with ')'. */
2268 :
2269 : static match
2270 164 : gfc_parser_omp_clause_init_modifiers (bool &target, bool &targetsync,
2271 : char **type_str, int &type_str_len,
2272 : bool is_init_clause)
2273 : {
2274 164 : target = false;
2275 164 : targetsync = false;
2276 164 : *type_str = NULL;
2277 164 : type_str_len = 0;
2278 286 : match m;
2279 :
2280 286 : do
2281 : {
2282 286 : if (gfc_match ("prefer_type ( ") == MATCH_YES)
2283 : {
2284 83 : if (*type_str)
2285 : {
2286 1 : gfc_error ("Duplicate %<prefer_type%> modifier at %C");
2287 1 : return MATCH_ERROR;
2288 : }
2289 82 : m = gfc_match_omp_prefer_type (type_str, &type_str_len);
2290 82 : if (m != MATCH_YES)
2291 : return m;
2292 60 : if (gfc_match (", ") == MATCH_YES)
2293 14 : continue;
2294 46 : if (is_init_clause)
2295 : {
2296 24 : if (gfc_match (": ") == MATCH_YES)
2297 : break;
2298 0 : gfc_error ("Expected %<,%> or %<:%> at %C");
2299 : }
2300 : else
2301 : {
2302 22 : if (gfc_match (") ") == MATCH_YES)
2303 : break;
2304 0 : gfc_error ("Expected %<,%> or %<)%> at %C");
2305 : }
2306 0 : return MATCH_ERROR;
2307 : }
2308 :
2309 203 : if (gfc_match ("prefer_type ") == MATCH_YES)
2310 : {
2311 2 : gfc_error ("Expected %<(%> after %<prefer_type%> at %C");
2312 2 : return MATCH_ERROR;
2313 : }
2314 :
2315 201 : if (gfc_match ("targetsync ") == MATCH_YES)
2316 : {
2317 57 : if (targetsync)
2318 : {
2319 3 : gfc_error ("Duplicate %<targetsync%> at %C");
2320 3 : return MATCH_ERROR;
2321 : }
2322 54 : targetsync = true;
2323 54 : if (gfc_match (", ") == MATCH_YES)
2324 13 : continue;
2325 41 : if (!is_init_clause)
2326 : {
2327 23 : if (gfc_match (") ") == MATCH_YES)
2328 : break;
2329 0 : gfc_error ("Expected %<,%> or %<)%> at %C");
2330 0 : return MATCH_ERROR;
2331 : }
2332 18 : if (gfc_match (": ") == MATCH_YES)
2333 : break;
2334 1 : gfc_error ("Expected %<,%> or %<:%> at %C");
2335 1 : return MATCH_ERROR;
2336 : }
2337 144 : if (gfc_match ("target ") == MATCH_YES)
2338 : {
2339 135 : if (target)
2340 : {
2341 3 : gfc_error ("Duplicate %<target%> at %C");
2342 3 : return MATCH_ERROR;
2343 : }
2344 132 : target = true;
2345 132 : if (gfc_match (", ") == MATCH_YES)
2346 95 : continue;
2347 37 : if (!is_init_clause)
2348 : {
2349 11 : if (gfc_match (") ") == MATCH_YES)
2350 : break;
2351 0 : gfc_error ("Expected %<,%> or %<)%> at %C");
2352 0 : return MATCH_ERROR;
2353 : }
2354 26 : if (gfc_match (": ") == MATCH_YES)
2355 : break;
2356 1 : gfc_error ("Expected %<,%> or %<:%> at %C");
2357 1 : return MATCH_ERROR;
2358 : }
2359 9 : gfc_error ("Expected %<prefer_type%>, %<target%>, or %<targetsync%> "
2360 : "at %C");
2361 9 : return MATCH_ERROR;
2362 : }
2363 : while (true);
2364 :
2365 122 : if (!target && !targetsync)
2366 : {
2367 4 : gfc_error ("Missing required %<target%> and/or %<targetsync%> "
2368 : "modifier at %C");
2369 4 : return MATCH_ERROR;
2370 : }
2371 : return MATCH_YES;
2372 : }
2373 :
2374 : /* Match OpenMP 5.1's 'init' clause for 'interop' objects:
2375 : init([prefer_type(...)][,][<target|targetsync>, ...] :] interop-obj-list) */
2376 :
2377 : static match
2378 108 : gfc_match_omp_init (gfc_omp_namelist **list)
2379 : {
2380 108 : bool target, targetsync;
2381 108 : char *type_str = NULL;
2382 108 : int type_str_len;
2383 108 : if (gfc_parser_omp_clause_init_modifiers (target, targetsync, &type_str,
2384 : type_str_len, true) == MATCH_ERROR)
2385 : return MATCH_ERROR;
2386 :
2387 64 : gfc_omp_namelist **head = NULL;
2388 64 : if (gfc_match_omp_variable_list ("", list, false, NULL, &head) != MATCH_YES)
2389 : return MATCH_ERROR;
2390 147 : for (gfc_omp_namelist *n = *head; n; n = n->next)
2391 : {
2392 84 : n->u.init.target = target;
2393 84 : n->u.init.targetsync = targetsync;
2394 84 : n->u.init.len = type_str_len;
2395 84 : n->u2.init_interop = type_str;
2396 : }
2397 : return MATCH_YES;
2398 : }
2399 :
2400 :
2401 : /* Match with duplicate check. Matches 'name'. If expr != NULL, it
2402 : then matches '(expr)', otherwise, if open_parens is true,
2403 : it matches a ' ( ' after 'name'.
2404 : dupl_message requires '%qs %L' - and is used by
2405 : gfc_match_dupl_memorder and gfc_match_dupl_atomic. */
2406 :
2407 : static match
2408 22400 : gfc_match_dupl_check (bool not_dupl, const char *name, bool open_parens = false,
2409 : gfc_expr **expr = NULL, const char *dupl_msg = NULL)
2410 : {
2411 22400 : match m;
2412 22400 : char c;
2413 22400 : locus old_loc = gfc_current_locus;
2414 22400 : if ((m = gfc_match (name)) != MATCH_YES)
2415 : return m;
2416 : /* Ensure that no partial string is matched. */
2417 17431 : if (gfc_current_form == FORM_FREE
2418 16933 : && gfc_match_eos () != MATCH_YES
2419 30228 : && ((c = gfc_peek_ascii_char ()) == '_' || ISALNUM (c)))
2420 : {
2421 8 : gfc_current_locus = old_loc;
2422 8 : return MATCH_NO;
2423 : }
2424 17423 : if (!not_dupl)
2425 : {
2426 44 : if (dupl_msg)
2427 2 : gfc_error (dupl_msg, name, &old_loc);
2428 : else
2429 42 : gfc_error ("Duplicated %qs clause at %L", name, &old_loc);
2430 44 : return MATCH_ERROR;
2431 : }
2432 17379 : if (open_parens || expr)
2433 : {
2434 9489 : if (gfc_match (" ( ") != MATCH_YES)
2435 : {
2436 22 : gfc_error ("Expected %<(%> after %qs at %C", name);
2437 22 : return MATCH_ERROR;
2438 : }
2439 9467 : if (expr)
2440 : {
2441 4423 : if (gfc_match ("%e )", expr) != MATCH_YES)
2442 : {
2443 9 : gfc_error ("Invalid expression after %<%s(%> at %C", name);
2444 9 : return MATCH_ERROR;
2445 : }
2446 : }
2447 : }
2448 : return MATCH_YES;
2449 : }
2450 :
2451 : static match
2452 211 : gfc_match_dupl_memorder (bool not_dupl, const char *name)
2453 : {
2454 0 : return gfc_match_dupl_check (not_dupl, name, false, NULL,
2455 : "Duplicated memory-order clause: unexpected %s "
2456 0 : "clause at %L");
2457 : }
2458 :
2459 : static match
2460 1175 : gfc_match_dupl_atomic (bool not_dupl, const char *name)
2461 : {
2462 0 : return gfc_match_dupl_check (not_dupl, name, false, NULL,
2463 : "Duplicated atomic clause: unexpected %s "
2464 0 : "clause at %L");
2465 : }
2466 :
2467 :
2468 : /* Search upwards though namespace NS and its parents to find an
2469 : !$omp declare mapper named MAPPER_ID, for typespec TS. The default
2470 : mapper has mapper_id == "". */
2471 :
2472 : gfc_omp_udm *
2473 999 : gfc_find_omp_udm (gfc_namespace *ns, const char *mapper_id, gfc_typespec *ts)
2474 : {
2475 999 : gfc_symtree *st;
2476 :
2477 999 : if (ns == NULL)
2478 0 : ns = gfc_current_ns;
2479 :
2480 1177 : do
2481 : {
2482 1177 : gfc_omp_udm *omp_udm;
2483 :
2484 1177 : st = gfc_find_symtree (ns->omp_udm_root, mapper_id);
2485 :
2486 1177 : if (st != NULL)
2487 : {
2488 28 : for (omp_udm = st->n.omp_udm; omp_udm; omp_udm = omp_udm->next)
2489 28 : if (gfc_compare_types (&omp_udm->ts, ts))
2490 : return omp_udm;
2491 : }
2492 :
2493 : /* Don't escape an interface block. */
2494 1151 : if (ns && !ns->has_import_set
2495 1151 : && ns->proc_name && ns->proc_name->attr.if_source == IFSRC_IFBODY)
2496 : break;
2497 :
2498 1151 : ns = ns->parent;
2499 : }
2500 1151 : while (ns != NULL);
2501 :
2502 : return NULL;
2503 : }
2504 :
2505 :
2506 : /* Match OpenMP and OpenACC directive clauses. MASK is a bitmask of
2507 : clauses that are allowed for a particular directive. */
2508 :
2509 : static match
2510 34557 : gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
2511 : bool first = true, bool needs_space = true,
2512 : bool openacc = false, bool openmp_target = false,
2513 : gfc_omp_map_op default_map_op = OMP_MAP_TOFROM)
2514 : {
2515 34557 : bool error = false;
2516 34557 : gfc_omp_clauses *c = gfc_get_omp_clauses ();
2517 34557 : locus old_loc;
2518 : /* Determine whether we're dealing with an OpenACC directive that permits
2519 : derived type member accesses. This in particular disallows
2520 : "!$acc declare" from using such accesses, because it's not clear if/how
2521 : that should work. */
2522 34557 : bool allow_derived = (openacc
2523 34557 : && ((mask & OMP_CLAUSE_ATTACH)
2524 5932 : || (mask & OMP_CLAUSE_DETACH)));
2525 :
2526 34557 : gcc_checking_assert (OMP_MASK1_LAST <= 64 && OMP_MASK2_LAST <= 64);
2527 34557 : *cp = NULL;
2528 127045 : while (1)
2529 : {
2530 80801 : match m = MATCH_NO;
2531 60014 : if ((first || (m = gfc_match_char (',')) != MATCH_YES)
2532 140459 : && (needs_space && gfc_match_space () != MATCH_YES))
2533 : break;
2534 76235 : needs_space = false;
2535 76235 : first = false;
2536 76235 : gfc_gobble_whitespace ();
2537 76235 : bool end_colon;
2538 76235 : gfc_omp_namelist **head;
2539 76235 : old_loc = gfc_current_locus;
2540 76235 : char pc = gfc_peek_ascii_char ();
2541 76235 : if (pc == '\n' && m == MATCH_YES)
2542 : {
2543 1 : gfc_error ("Clause expected at %C after trailing comma");
2544 1 : goto error;
2545 : }
2546 76234 : switch (pc)
2547 : {
2548 1314 : case 'a':
2549 1314 : end_colon = false;
2550 1314 : head = NULL;
2551 1338 : if ((mask & OMP_CLAUSE_ASSUMPTIONS)
2552 1314 : && gfc_match ("absent ( ") == MATCH_YES)
2553 : {
2554 27 : if (gfc_omp_absent_contains_clause (&c->assume, true)
2555 : != MATCH_YES)
2556 3 : goto error;
2557 24 : continue;
2558 : }
2559 1287 : if ((mask & OMP_CLAUSE_ALIGNED)
2560 1287 : && gfc_match_omp_variable_list ("aligned (",
2561 : &c->lists[OMP_LIST_ALIGNED],
2562 : false, &end_colon,
2563 : &head) == MATCH_YES)
2564 : {
2565 112 : gfc_expr *alignment = NULL;
2566 112 : gfc_omp_namelist *n;
2567 :
2568 112 : if (end_colon && gfc_match (" %e )", &alignment) != MATCH_YES)
2569 : {
2570 0 : gfc_free_omp_namelist (*head, OMP_LIST_ALIGNED);
2571 0 : gfc_current_locus = old_loc;
2572 0 : *head = NULL;
2573 0 : break;
2574 : }
2575 268 : for (n = *head; n; n = n->next)
2576 156 : if (n->next && alignment)
2577 42 : n->expr = gfc_copy_expr (alignment);
2578 : else
2579 114 : n->expr = alignment;
2580 112 : continue;
2581 112 : }
2582 1185 : if ((mask & OMP_CLAUSE_MEMORDER)
2583 1192 : && (m = gfc_match_dupl_memorder ((c->memorder
2584 17 : == OMP_MEMORDER_UNSET),
2585 : "acq_rel")) != MATCH_NO)
2586 : {
2587 10 : if (m == MATCH_ERROR)
2588 0 : goto error;
2589 10 : c->memorder = OMP_MEMORDER_ACQ_REL;
2590 10 : continue;
2591 : }
2592 1172 : if ((mask & OMP_CLAUSE_MEMORDER)
2593 1172 : && (m = gfc_match_dupl_memorder ((c->memorder
2594 7 : == OMP_MEMORDER_UNSET),
2595 : "acquire")) != MATCH_NO)
2596 : {
2597 7 : if (m == MATCH_ERROR)
2598 0 : goto error;
2599 7 : c->memorder = OMP_MEMORDER_ACQUIRE;
2600 7 : continue;
2601 : }
2602 1158 : if ((mask & OMP_CLAUSE_AFFINITY)
2603 1158 : && gfc_match ("affinity ( ") == MATCH_YES)
2604 : {
2605 41 : gfc_namespace *ns_iter = NULL, *ns_curr = gfc_current_ns;
2606 41 : m = gfc_match_iterator (&ns_iter, true);
2607 41 : if (m == MATCH_ERROR)
2608 : break;
2609 31 : if (m == MATCH_YES && gfc_match (" : ") != MATCH_YES)
2610 : {
2611 1 : gfc_error ("Expected %<:%> at %C");
2612 1 : break;
2613 : }
2614 30 : if (ns_iter)
2615 18 : gfc_current_ns = ns_iter;
2616 30 : head = NULL;
2617 30 : m = gfc_match_omp_variable_list ("", &c->lists[OMP_LIST_AFFINITY],
2618 : false, NULL, &head, true);
2619 30 : gfc_current_ns = ns_curr;
2620 30 : if (m == MATCH_ERROR)
2621 : break;
2622 27 : if (ns_iter)
2623 : {
2624 45 : for (gfc_omp_namelist *n = *head; n; n = n->next)
2625 : {
2626 27 : n->u2.ns = ns_iter;
2627 27 : ns_iter->refs++;
2628 : }
2629 : }
2630 27 : continue;
2631 27 : }
2632 1117 : if ((mask & OMP_CLAUSE_ALLOCATE)
2633 1117 : && gfc_match ("allocate ( ") == MATCH_YES)
2634 : {
2635 281 : gfc_expr *allocator = NULL;
2636 281 : gfc_expr *align = NULL;
2637 281 : old_loc = gfc_current_locus;
2638 281 : if ((m = gfc_match ("allocator ( %e )", &allocator)) == MATCH_YES)
2639 50 : gfc_match (" , align ( %e )", &align);
2640 231 : else if ((m = gfc_match ("align ( %e )", &align)) == MATCH_YES)
2641 29 : gfc_match (" , allocator ( %e )", &allocator);
2642 :
2643 281 : if (m == MATCH_YES)
2644 : {
2645 79 : if (gfc_match (" : ") != MATCH_YES)
2646 : {
2647 5 : gfc_error ("Expected %<:%> at %C");
2648 8 : goto error;
2649 : }
2650 : }
2651 : else
2652 : {
2653 202 : m = gfc_match_expr (&allocator);
2654 202 : if (m == MATCH_YES && gfc_match (" : ") != MATCH_YES)
2655 : {
2656 : /* If no ":" then there is no allocator, we backtrack
2657 : and read the variable list. */
2658 101 : gfc_free_expr (allocator);
2659 101 : allocator = NULL;
2660 101 : gfc_current_locus = old_loc;
2661 : }
2662 : }
2663 276 : gfc_omp_namelist **head = NULL;
2664 276 : m = gfc_match_omp_variable_list ("", &c->lists[OMP_LIST_ALLOCATE],
2665 : true, NULL, &head);
2666 :
2667 276 : if (m != MATCH_YES)
2668 : {
2669 3 : gfc_free_expr (allocator);
2670 3 : gfc_free_expr (align);
2671 3 : gfc_error ("Expected variable list at %C");
2672 3 : goto error;
2673 : }
2674 :
2675 729 : for (gfc_omp_namelist *n = *head; n; n = n->next)
2676 : {
2677 456 : n->u2.allocator = allocator;
2678 456 : n->u.align = (align) ? gfc_copy_expr (align) : NULL;
2679 : }
2680 273 : gfc_free_expr (align);
2681 273 : continue;
2682 273 : }
2683 896 : if ((mask & OMP_CLAUSE_AT)
2684 836 : && (m = gfc_match_dupl_check (c->at == OMP_AT_UNSET, "at", true))
2685 : != MATCH_NO)
2686 : {
2687 66 : if (m == MATCH_ERROR)
2688 2 : goto error;
2689 64 : if (gfc_match ("compilation )") == MATCH_YES)
2690 15 : c->at = OMP_AT_COMPILATION;
2691 49 : else if (gfc_match ("execution )") == MATCH_YES)
2692 45 : c->at = OMP_AT_EXECUTION;
2693 : else
2694 : {
2695 4 : gfc_error ("Expected COMPILATION or EXECUTION in AT clause "
2696 : "at %C");
2697 4 : goto error;
2698 : }
2699 60 : continue;
2700 : }
2701 1413 : if ((mask & OMP_CLAUSE_ASYNC)
2702 770 : && (m = gfc_match_dupl_check (!c->async, "async")) != MATCH_NO)
2703 : {
2704 643 : if (m == MATCH_ERROR)
2705 0 : goto error;
2706 643 : c->async = true;
2707 643 : m = gfc_match (" ( %e )", &c->async_expr);
2708 643 : if (m == MATCH_ERROR)
2709 : {
2710 0 : gfc_current_locus = old_loc;
2711 0 : break;
2712 : }
2713 643 : else if (m == MATCH_NO)
2714 : {
2715 133 : c->async_expr
2716 133 : = gfc_get_constant_expr (BT_INTEGER,
2717 : gfc_default_integer_kind,
2718 : &gfc_current_locus);
2719 133 : mpz_set_si (c->async_expr->value.integer, GOMP_ASYNC_NOVAL);
2720 : }
2721 643 : continue;
2722 : }
2723 190 : if ((mask & OMP_CLAUSE_AUTO)
2724 127 : && (m = gfc_match_dupl_check (!c->par_auto, "auto"))
2725 : != MATCH_NO)
2726 : {
2727 63 : if (m == MATCH_ERROR)
2728 0 : goto error;
2729 63 : c->par_auto = true;
2730 63 : continue;
2731 : }
2732 125 : if ((mask & OMP_CLAUSE_ATTACH)
2733 62 : && gfc_match ("attach ( ") == MATCH_YES
2734 125 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
2735 : OMP_MAP_ATTACH, false,
2736 : allow_derived))
2737 61 : continue;
2738 : break;
2739 36 : case 'b':
2740 70 : if ((mask & OMP_CLAUSE_BIND)
2741 36 : && (m = gfc_match_dupl_check (c->bind == OMP_BIND_UNSET, "bind",
2742 : true)) != MATCH_NO)
2743 : {
2744 36 : if (m == MATCH_ERROR)
2745 1 : goto error;
2746 35 : if (gfc_match ("teams )") == MATCH_YES)
2747 11 : c->bind = OMP_BIND_TEAMS;
2748 24 : else if (gfc_match ("parallel )") == MATCH_YES)
2749 15 : c->bind = OMP_BIND_PARALLEL;
2750 9 : else if (gfc_match ("thread )") == MATCH_YES)
2751 8 : c->bind = OMP_BIND_THREAD;
2752 : else
2753 : {
2754 1 : gfc_error ("Expected TEAMS, PARALLEL or THREAD as binding in "
2755 : "BIND at %C");
2756 1 : break;
2757 : }
2758 34 : continue;
2759 : }
2760 : break;
2761 7110 : case 'c':
2762 7383 : if ((mask & OMP_CLAUSE_CAPTURE)
2763 7110 : && (m = gfc_match_dupl_check (!c->capture, "capture"))
2764 : != MATCH_NO)
2765 : {
2766 274 : if (m == MATCH_ERROR)
2767 1 : goto error;
2768 273 : c->capture = true;
2769 273 : continue;
2770 : }
2771 6836 : if (mask & OMP_CLAUSE_COLLAPSE)
2772 : {
2773 1996 : gfc_expr *cexpr = NULL;
2774 1996 : if ((m = gfc_match_dupl_check (!c->collapse, "collapse", true,
2775 : &cexpr)) != MATCH_NO)
2776 : {
2777 1506 : int collapse;
2778 1506 : if (m == MATCH_ERROR)
2779 0 : goto error;
2780 1506 : if (gfc_extract_int (cexpr, &collapse, -1))
2781 4 : collapse = 1;
2782 1502 : else if (collapse <= 0)
2783 : {
2784 8 : gfc_error_now ("COLLAPSE clause argument not constant "
2785 : "positive integer at %C");
2786 8 : collapse = 1;
2787 : }
2788 1506 : gfc_free_expr (cexpr);
2789 1506 : c->collapse = collapse;
2790 1506 : continue;
2791 1506 : }
2792 : }
2793 5496 : if ((mask & OMP_CLAUSE_COMPARE)
2794 5330 : && (m = gfc_match_dupl_check (!c->compare, "compare"))
2795 : != MATCH_NO)
2796 : {
2797 167 : if (m == MATCH_ERROR)
2798 1 : goto error;
2799 166 : c->compare = true;
2800 166 : continue;
2801 : }
2802 5175 : if ((mask & OMP_CLAUSE_ASSUMPTIONS)
2803 5163 : && gfc_match ("contains ( ") == MATCH_YES)
2804 : {
2805 13 : if (gfc_omp_absent_contains_clause (&c->assume, false)
2806 : != MATCH_YES)
2807 1 : goto error;
2808 12 : continue;
2809 : }
2810 7266 : if ((mask & OMP_CLAUSE_COPY)
2811 3723 : && gfc_match ("copy ( ") == MATCH_YES
2812 7267 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
2813 : OMP_MAP_TOFROM, true,
2814 : allow_derived))
2815 2116 : continue;
2816 3034 : if (mask & OMP_CLAUSE_COPYIN)
2817 : {
2818 2628 : if (openacc)
2819 : {
2820 2529 : if (gfc_match ("copyin ( ") == MATCH_YES)
2821 : {
2822 1458 : bool readonly = gfc_match ("readonly : ") == MATCH_YES;
2823 1458 : head = NULL;
2824 1458 : if (gfc_match_omp_variable_list ("",
2825 : &c->lists[OMP_LIST_MAP],
2826 : true, NULL, &head, true,
2827 : allow_derived)
2828 : == MATCH_YES)
2829 : {
2830 1452 : gfc_omp_namelist *n;
2831 3349 : for (n = *head; n; n = n->next)
2832 : {
2833 1897 : n->u.map.op = OMP_MAP_TO;
2834 1897 : n->u.map.readonly = readonly;
2835 : }
2836 1452 : continue;
2837 1452 : }
2838 : }
2839 : }
2840 99 : else if (gfc_match_omp_variable_list ("copyin (",
2841 : &c->lists[OMP_LIST_COPYIN],
2842 : true) == MATCH_YES)
2843 97 : continue;
2844 : }
2845 2556 : if ((mask & OMP_CLAUSE_COPYOUT)
2846 1216 : && gfc_match ("copyout ( ") == MATCH_YES
2847 2556 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
2848 : OMP_MAP_FROM, true, allow_derived))
2849 1071 : continue;
2850 498 : if ((mask & OMP_CLAUSE_COPYPRIVATE)
2851 414 : && gfc_match_omp_variable_list ("copyprivate (",
2852 : &c->lists[OMP_LIST_COPYPRIVATE],
2853 : true) == MATCH_YES)
2854 84 : continue;
2855 651 : if ((mask & OMP_CLAUSE_CREATE)
2856 328 : && gfc_match ("create ( ") == MATCH_YES
2857 651 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
2858 : OMP_MAP_ALLOC, true, allow_derived))
2859 321 : continue;
2860 : break;
2861 3742 : case 'd':
2862 3742 : if ((mask & OMP_CLAUSE_DEFAULTMAP)
2863 3742 : && gfc_match ("defaultmap ( ") == MATCH_YES)
2864 : {
2865 181 : enum gfc_omp_defaultmap behavior;
2866 181 : gfc_omp_defaultmap_category category
2867 : = OMP_DEFAULTMAP_CAT_UNCATEGORIZED;
2868 181 : if (gfc_match ("alloc ") == MATCH_YES)
2869 : behavior = OMP_DEFAULTMAP_ALLOC;
2870 175 : else if (gfc_match ("tofrom ") == MATCH_YES)
2871 : behavior = OMP_DEFAULTMAP_TOFROM;
2872 143 : else if (gfc_match ("to ") == MATCH_YES)
2873 : behavior = OMP_DEFAULTMAP_TO;
2874 133 : else if (gfc_match ("from ") == MATCH_YES)
2875 : behavior = OMP_DEFAULTMAP_FROM;
2876 130 : else if (gfc_match ("firstprivate ") == MATCH_YES)
2877 : behavior = OMP_DEFAULTMAP_FIRSTPRIVATE;
2878 95 : else if (gfc_match ("present ") == MATCH_YES)
2879 : behavior = OMP_DEFAULTMAP_PRESENT;
2880 91 : else if (gfc_match ("none ") == MATCH_YES)
2881 : behavior = OMP_DEFAULTMAP_NONE;
2882 10 : else if (gfc_match ("default ") == MATCH_YES)
2883 : behavior = OMP_DEFAULTMAP_DEFAULT;
2884 : else
2885 : {
2886 1 : gfc_error ("Expected ALLOC, TO, FROM, TOFROM, FIRSTPRIVATE, "
2887 : "PRESENT, NONE or DEFAULT at %C");
2888 1 : break;
2889 : }
2890 180 : if (')' == gfc_peek_ascii_char ())
2891 : ;
2892 102 : else if (gfc_match (": ") != MATCH_YES)
2893 : break;
2894 : else
2895 : {
2896 102 : if (gfc_match ("scalar ") == MATCH_YES)
2897 : category = OMP_DEFAULTMAP_CAT_SCALAR;
2898 67 : else if (gfc_match ("aggregate ") == MATCH_YES)
2899 : category = OMP_DEFAULTMAP_CAT_AGGREGATE;
2900 43 : else if (gfc_match ("allocatable ") == MATCH_YES)
2901 : category = OMP_DEFAULTMAP_CAT_ALLOCATABLE;
2902 31 : else if (gfc_match ("pointer ") == MATCH_YES)
2903 : category = OMP_DEFAULTMAP_CAT_POINTER;
2904 14 : else if (gfc_match ("all ") == MATCH_YES)
2905 : category = OMP_DEFAULTMAP_CAT_ALL;
2906 : else
2907 : {
2908 1 : gfc_error ("Expected SCALAR, AGGREGATE, ALLOCATABLE, "
2909 : "POINTER or ALL at %C");
2910 1 : break;
2911 : }
2912 : }
2913 1200 : for (int i = 0; i < OMP_DEFAULTMAP_CAT_NUM; ++i)
2914 : {
2915 1034 : if (i != category
2916 1034 : && category != OMP_DEFAULTMAP_CAT_UNCATEGORIZED
2917 486 : && category != OMP_DEFAULTMAP_CAT_ALL
2918 486 : && i != OMP_DEFAULTMAP_CAT_UNCATEGORIZED
2919 341 : && i != OMP_DEFAULTMAP_CAT_ALL)
2920 254 : continue;
2921 780 : if (c->defaultmap[i] != OMP_DEFAULTMAP_UNSET)
2922 : {
2923 13 : const char *pcategory = NULL;
2924 13 : switch (i)
2925 : {
2926 : case OMP_DEFAULTMAP_CAT_UNCATEGORIZED: break;
2927 : case OMP_DEFAULTMAP_CAT_ALL: pcategory = "ALL"; break;
2928 1 : case OMP_DEFAULTMAP_CAT_SCALAR: pcategory = "SCALAR"; break;
2929 2 : case OMP_DEFAULTMAP_CAT_AGGREGATE:
2930 2 : pcategory = "AGGREGATE";
2931 2 : break;
2932 1 : case OMP_DEFAULTMAP_CAT_ALLOCATABLE:
2933 1 : pcategory = "ALLOCATABLE";
2934 1 : break;
2935 2 : case OMP_DEFAULTMAP_CAT_POINTER:
2936 2 : pcategory = "POINTER";
2937 2 : break;
2938 : default: gcc_unreachable ();
2939 : }
2940 6 : if (i == OMP_DEFAULTMAP_CAT_UNCATEGORIZED)
2941 4 : gfc_error ("DEFAULTMAP at %C but prior DEFAULTMAP with "
2942 : "unspecified category");
2943 : else
2944 9 : gfc_error ("DEFAULTMAP at %C but prior DEFAULTMAP for "
2945 : "category %s", pcategory);
2946 13 : goto error;
2947 : }
2948 : }
2949 166 : c->defaultmap[category] = behavior;
2950 166 : if (gfc_match (")") != MATCH_YES)
2951 : break;
2952 166 : continue;
2953 166 : }
2954 4528 : if ((mask & OMP_CLAUSE_DEFAULT)
2955 3561 : && (m = gfc_match_dupl_check (c->default_sharing
2956 : == OMP_DEFAULT_UNKNOWN, "default",
2957 : true)) != MATCH_NO)
2958 : {
2959 1012 : if (m == MATCH_ERROR)
2960 6 : goto error;
2961 1006 : if (gfc_match ("none") == MATCH_YES)
2962 596 : c->default_sharing = OMP_DEFAULT_NONE;
2963 410 : else if (openacc)
2964 : {
2965 225 : if (gfc_match ("present") == MATCH_YES)
2966 195 : c->default_sharing = OMP_DEFAULT_PRESENT;
2967 : }
2968 : else
2969 : {
2970 185 : if (gfc_match ("firstprivate") == MATCH_YES)
2971 8 : c->default_sharing = OMP_DEFAULT_FIRSTPRIVATE;
2972 177 : else if (gfc_match ("private") == MATCH_YES)
2973 24 : c->default_sharing = OMP_DEFAULT_PRIVATE;
2974 153 : else if (gfc_match ("shared") == MATCH_YES)
2975 153 : c->default_sharing = OMP_DEFAULT_SHARED;
2976 : }
2977 1006 : if (c->default_sharing == OMP_DEFAULT_UNKNOWN)
2978 : {
2979 30 : if (openacc)
2980 30 : gfc_error ("Expected NONE or PRESENT in DEFAULT clause "
2981 : "at %C");
2982 : else
2983 0 : gfc_error ("Expected NONE, FIRSTPRIVATE, PRIVATE or SHARED "
2984 : "in DEFAULT clause at %C");
2985 30 : goto error;
2986 : }
2987 976 : if (gfc_match (" )") != MATCH_YES)
2988 9 : goto error;
2989 967 : continue;
2990 : }
2991 2857 : if ((mask & OMP_CLAUSE_DELETE)
2992 345 : && gfc_match ("delete ( ") == MATCH_YES
2993 2857 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
2994 : OMP_MAP_RELEASE, true,
2995 : allow_derived))
2996 308 : continue;
2997 : /* DOACROSS: match 'doacross' and 'depend' with sink/source.
2998 : DEPEND: match 'depend' but not sink/source. */
2999 2241 : m = MATCH_NO;
3000 2241 : if (((mask & OMP_CLAUSE_DOACROSS)
3001 383 : && gfc_match ("doacross ( ") == MATCH_YES)
3002 2597 : || (((mask & OMP_CLAUSE_DEPEND) || (mask & OMP_CLAUSE_DOACROSS))
3003 1600 : && (m = gfc_match ("depend ( ")) == MATCH_YES))
3004 : {
3005 1100 : bool has_omp_all_memory;
3006 1100 : bool is_depend = m == MATCH_YES;
3007 1100 : gfc_namespace *ns_iter = NULL, *ns_curr = gfc_current_ns;
3008 1100 : match m_it = MATCH_NO;
3009 1100 : if (is_depend)
3010 1073 : m_it = gfc_match_iterator (&ns_iter, false);
3011 1073 : if (m_it == MATCH_ERROR)
3012 : break;
3013 1095 : if (m_it == MATCH_YES && gfc_match (" , ") != MATCH_YES)
3014 : break;
3015 1095 : m = MATCH_YES;
3016 1095 : gfc_omp_depend_doacross_op depend_op = OMP_DEPEND_OUT;
3017 1095 : if (gfc_match ("inoutset") == MATCH_YES)
3018 : depend_op = OMP_DEPEND_INOUTSET;
3019 1083 : else if (gfc_match ("inout") == MATCH_YES)
3020 : depend_op = OMP_DEPEND_INOUT;
3021 991 : else if (gfc_match ("in") == MATCH_YES)
3022 : depend_op = OMP_DEPEND_IN;
3023 704 : else if (gfc_match ("out") == MATCH_YES)
3024 : depend_op = OMP_DEPEND_OUT;
3025 442 : else if (gfc_match ("mutexinoutset") == MATCH_YES)
3026 : depend_op = OMP_DEPEND_MUTEXINOUTSET;
3027 424 : else if (gfc_match ("depobj") == MATCH_YES)
3028 : depend_op = OMP_DEPEND_DEPOBJ;
3029 387 : else if (gfc_match ("source") == MATCH_YES)
3030 : {
3031 143 : if (m_it == MATCH_YES)
3032 : {
3033 1 : gfc_error ("ITERATOR may not be combined with SOURCE "
3034 : "at %C");
3035 17 : goto error;
3036 : }
3037 142 : if (!(mask & OMP_CLAUSE_DOACROSS))
3038 : {
3039 1 : gfc_error ("SOURCE at %C not permitted as dependence-type"
3040 : " for this directive");
3041 1 : goto error;
3042 : }
3043 141 : if (c->doacross_source)
3044 : {
3045 0 : gfc_error ("Duplicated clause with SOURCE dependence-type"
3046 : " at %C");
3047 0 : goto error;
3048 : }
3049 141 : gfc_gobble_whitespace ();
3050 141 : m = gfc_match (": ");
3051 141 : if (m != MATCH_YES && !is_depend)
3052 : {
3053 1 : gfc_error ("Expected %<:%> at %C");
3054 1 : goto error;
3055 : }
3056 140 : if (gfc_match (")") != MATCH_YES
3057 146 : && !(m == MATCH_YES
3058 6 : && gfc_match ("omp_cur_iteration )") == MATCH_YES))
3059 : {
3060 2 : gfc_error ("Expected %<)%> or %<omp_cur_iteration)%> "
3061 : "at %C");
3062 2 : goto error;
3063 : }
3064 138 : if (is_depend)
3065 130 : gfc_warning (OPT_Wdeprecated_openmp,
3066 : "%<source%> modifier with %<depend%> clause "
3067 : "at %L deprecated since OpenMP 5.2, use with "
3068 : "%<doacross%>", &old_loc);
3069 138 : c->doacross_source = true;
3070 138 : c->depend_source = is_depend;
3071 1078 : continue;
3072 : }
3073 244 : else if (gfc_match ("sink ") == MATCH_YES)
3074 : {
3075 244 : if (!(mask & OMP_CLAUSE_DOACROSS))
3076 : {
3077 2 : gfc_error ("SINK at %C not permitted as dependence-type "
3078 : "for this directive");
3079 2 : goto error;
3080 : }
3081 242 : if (gfc_match (": ") != MATCH_YES)
3082 : {
3083 1 : gfc_error ("Expected %<:%> at %C");
3084 1 : goto error;
3085 : }
3086 241 : if (m_it == MATCH_YES)
3087 : {
3088 0 : gfc_error ("ITERATOR may not be combined with SINK "
3089 : "at %C");
3090 0 : goto error;
3091 : }
3092 241 : if (is_depend)
3093 226 : gfc_warning (OPT_Wdeprecated_openmp,
3094 : "%<sink%> modifier with %<depend%> clause at "
3095 : "%L deprecated since OpenMP 5.2, use with "
3096 : "%<doacross%>", &old_loc);
3097 241 : m = gfc_match_omp_doacross_sink (&c->lists[OMP_LIST_DEPEND],
3098 : is_depend);
3099 241 : if (m == MATCH_YES)
3100 238 : continue;
3101 3 : goto error;
3102 : }
3103 : else
3104 : m = MATCH_NO;
3105 708 : if (!(mask & OMP_CLAUSE_DEPEND))
3106 : {
3107 0 : gfc_error ("Expected dependence-type SINK or SOURCE at %C");
3108 0 : goto error;
3109 : }
3110 708 : head = NULL;
3111 708 : if (ns_iter)
3112 40 : gfc_current_ns = ns_iter;
3113 708 : if (m == MATCH_YES)
3114 708 : m = gfc_match_omp_variable_list (" : ",
3115 : &c->lists[OMP_LIST_DEPEND],
3116 : false, NULL, &head, true,
3117 : false, &has_omp_all_memory);
3118 708 : if (m != MATCH_YES)
3119 2 : goto error;
3120 706 : gfc_current_ns = ns_curr;
3121 706 : if (has_omp_all_memory && depend_op != OMP_DEPEND_INOUT
3122 21 : && depend_op != OMP_DEPEND_OUT)
3123 : {
3124 4 : gfc_error ("%<omp_all_memory%> used with DEPEND kind "
3125 : "other than OUT or INOUT at %C");
3126 4 : goto error;
3127 : }
3128 702 : gfc_omp_namelist *n;
3129 1435 : for (n = *head; n; n = n->next)
3130 : {
3131 733 : n->u.depend_doacross_op = depend_op;
3132 733 : n->u2.ns = ns_iter;
3133 733 : if (ns_iter)
3134 39 : ns_iter->refs++;
3135 : }
3136 702 : continue;
3137 702 : }
3138 1162 : if ((mask & OMP_CLAUSE_DESTROY)
3139 1141 : && gfc_match_omp_variable_list ("destroy (",
3140 : &c->lists[OMP_LIST_DESTROY],
3141 : true) == MATCH_YES)
3142 21 : continue;
3143 1246 : if ((mask & OMP_CLAUSE_DETACH)
3144 164 : && !openacc
3145 127 : && !c->detach
3146 1246 : && gfc_match_omp_detach (&c->detach) == MATCH_YES)
3147 126 : continue;
3148 1031 : if ((mask & OMP_CLAUSE_DETACH)
3149 38 : && openacc
3150 37 : && gfc_match ("detach ( ") == MATCH_YES
3151 1031 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
3152 : OMP_MAP_DETACH, false,
3153 : allow_derived))
3154 37 : continue;
3155 993 : if ((mask & OMP_CLAUSE_DEVICEPTR)
3156 87 : && gfc_match ("deviceptr ( ") == MATCH_YES
3157 995 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
3158 : OMP_MAP_FORCE_DEVICEPTR, false,
3159 : allow_derived))
3160 36 : continue;
3161 1012 : if ((mask & OMP_CLAUSE_DEVICE_TYPE)
3162 921 : && gfc_match_dupl_check (c->device_type == OMP_DEVICE_TYPE_UNSET,
3163 : "device_type", true) == MATCH_YES)
3164 : {
3165 92 : if (gfc_match ("host") == MATCH_YES)
3166 32 : c->device_type = OMP_DEVICE_TYPE_HOST;
3167 60 : else if (gfc_match ("nohost") == MATCH_YES)
3168 21 : c->device_type = OMP_DEVICE_TYPE_NOHOST;
3169 39 : else if (gfc_match ("any") == MATCH_YES)
3170 38 : c->device_type = OMP_DEVICE_TYPE_ANY;
3171 : else
3172 : {
3173 1 : gfc_error ("Expected HOST, NOHOST or ANY at %C");
3174 1 : break;
3175 : }
3176 91 : if (gfc_match (" )") != MATCH_YES)
3177 : break;
3178 91 : continue;
3179 : }
3180 877 : if ((mask & OMP_CLAUSE_DEVICE_RESIDENT)
3181 878 : && gfc_match_omp_variable_list
3182 49 : ("device_resident (",
3183 : &c->lists[OMP_LIST_DEVICE_RESIDENT], true) == MATCH_YES)
3184 48 : continue;
3185 1093 : if ((mask & OMP_CLAUSE_DEVICE)
3186 705 : && openacc
3187 314 : && gfc_match ("device ( ") == MATCH_YES
3188 1094 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
3189 : OMP_MAP_FORCE_TO, true,
3190 : /* allow_derived = */ true))
3191 312 : continue;
3192 469 : if ((mask & OMP_CLAUSE_DEVICE)
3193 393 : && !openacc
3194 860 : && ((m = gfc_match_dupl_check (!c->device, "device", true))
3195 : != MATCH_NO))
3196 : {
3197 351 : if (m == MATCH_ERROR)
3198 0 : goto error;
3199 351 : c->ancestor = false;
3200 351 : if (gfc_match ("device_num : ") == MATCH_YES)
3201 : {
3202 18 : if (gfc_match ("%e )", &c->device) != MATCH_YES)
3203 : {
3204 1 : gfc_error ("Expected integer expression at %C");
3205 1 : break;
3206 : }
3207 : }
3208 333 : else if (gfc_match ("ancestor : ") == MATCH_YES)
3209 : {
3210 45 : bool has_requires = false;
3211 45 : c->ancestor = true;
3212 82 : for (gfc_namespace *ns = gfc_current_ns; ns; ns = ns->parent)
3213 80 : if (ns->omp_requires & OMP_REQ_REVERSE_OFFLOAD)
3214 : {
3215 : has_requires = true;
3216 : break;
3217 : }
3218 45 : if (!has_requires)
3219 : {
3220 2 : gfc_error ("%<ancestor%> device modifier not "
3221 : "preceded by %<requires%> directive "
3222 : "with %<reverse_offload%> clause at %C");
3223 5 : break;
3224 : }
3225 43 : locus old_loc2 = gfc_current_locus;
3226 43 : if (gfc_match ("%e )", &c->device) == MATCH_YES)
3227 : {
3228 43 : int device = 0;
3229 43 : if (!gfc_extract_int (c->device, &device) && device != 1)
3230 : {
3231 1 : gfc_current_locus = old_loc2;
3232 1 : gfc_error ("the %<device%> clause expression must "
3233 : "evaluate to %<1%> at %C");
3234 1 : break;
3235 : }
3236 : }
3237 : else
3238 : {
3239 0 : gfc_error ("Expected integer expression at %C");
3240 0 : break;
3241 : }
3242 : }
3243 288 : else if (gfc_match ("%e )", &c->device) != MATCH_YES)
3244 : {
3245 13 : gfc_error ("Expected integer expression or a single device-"
3246 : "modifier %<device_num%> or %<ancestor%> at %C");
3247 13 : break;
3248 : }
3249 334 : continue;
3250 334 : }
3251 118 : if ((mask & OMP_CLAUSE_DIST_SCHEDULE)
3252 97 : && c->dist_sched_kind == OMP_SCHED_NONE
3253 215 : && gfc_match ("dist_schedule ( static") == MATCH_YES)
3254 : {
3255 97 : m = MATCH_NO;
3256 97 : c->dist_sched_kind = OMP_SCHED_STATIC;
3257 97 : m = gfc_match (" , %e )", &c->dist_chunk_size);
3258 97 : if (m != MATCH_YES)
3259 14 : m = gfc_match_char (')');
3260 14 : if (m != MATCH_YES)
3261 : {
3262 0 : c->dist_sched_kind = OMP_SCHED_NONE;
3263 0 : gfc_current_locus = old_loc;
3264 : }
3265 : else
3266 97 : continue;
3267 : }
3268 32 : if ((mask & OMP_CLAUSE_DYN_GROUPPRIVATE)
3269 21 : && gfc_match_dupl_check (!c->dyn_groupprivate,
3270 : "dyn_groupprivate", true) == MATCH_YES)
3271 : {
3272 12 : if (gfc_match ("fallback ( abort ) : ") == MATCH_YES)
3273 1 : c->fallback = OMP_FALLBACK_ABORT;
3274 11 : else if (gfc_match ("fallback ( default_mem ) : ") == MATCH_YES)
3275 1 : c->fallback = OMP_FALLBACK_DEFAULT_MEM;
3276 10 : else if (gfc_match ("fallback ( null ) : ") == MATCH_YES)
3277 1 : c->fallback = OMP_FALLBACK_NULL;
3278 12 : if (gfc_match_expr (&c->dyn_groupprivate) != MATCH_YES)
3279 0 : return MATCH_ERROR;
3280 12 : if (gfc_match (" )") != MATCH_YES)
3281 1 : goto error;
3282 11 : continue;
3283 : }
3284 : break;
3285 90 : case 'e':
3286 90 : if ((mask & OMP_CLAUSE_ENTER))
3287 : {
3288 90 : m = gfc_match_omp_to_link ("enter (", &c->lists[OMP_LIST_ENTER]);
3289 90 : if (m == MATCH_ERROR)
3290 0 : goto error;
3291 90 : if (m == MATCH_YES)
3292 90 : continue;
3293 : }
3294 : break;
3295 2309 : case 'f':
3296 2358 : if ((mask & OMP_CLAUSE_FAIL)
3297 2309 : && (m = gfc_match_dupl_check (c->fail == OMP_MEMORDER_UNSET,
3298 : "fail", true)) != MATCH_NO)
3299 : {
3300 58 : if (m == MATCH_ERROR)
3301 3 : goto error;
3302 55 : if (gfc_match ("seq_cst") == MATCH_YES)
3303 6 : c->fail = OMP_MEMORDER_SEQ_CST;
3304 49 : else if (gfc_match ("acquire") == MATCH_YES)
3305 14 : c->fail = OMP_MEMORDER_ACQUIRE;
3306 35 : else if (gfc_match ("relaxed") == MATCH_YES)
3307 30 : c->fail = OMP_MEMORDER_RELAXED;
3308 : else
3309 : {
3310 5 : gfc_error ("Expected SEQ_CST, ACQUIRE or RELAXED at %C");
3311 5 : break;
3312 : }
3313 50 : if (gfc_match (" )") != MATCH_YES)
3314 1 : goto error;
3315 49 : continue;
3316 : }
3317 2294 : if ((mask & OMP_CLAUSE_FILTER)
3318 2251 : && (m = gfc_match_dupl_check (!c->filter, "filter", true,
3319 : &c->filter)) != MATCH_NO)
3320 : {
3321 44 : if (m == MATCH_ERROR)
3322 1 : goto error;
3323 43 : continue;
3324 : }
3325 2271 : if ((mask & OMP_CLAUSE_FINAL)
3326 2207 : && (m = gfc_match_dupl_check (!c->final_expr, "final", true,
3327 : &c->final_expr)) != MATCH_NO)
3328 : {
3329 64 : if (m == MATCH_ERROR)
3330 0 : goto error;
3331 64 : continue;
3332 : }
3333 2169 : if ((mask & OMP_CLAUSE_FINALIZE)
3334 2143 : && (m = gfc_match_dupl_check (!c->finalize, "finalize"))
3335 : != MATCH_NO)
3336 : {
3337 26 : if (m == MATCH_ERROR)
3338 0 : goto error;
3339 26 : c->finalize = true;
3340 26 : continue;
3341 : }
3342 3155 : if ((mask & OMP_CLAUSE_FIRSTPRIVATE)
3343 2117 : && gfc_match_omp_variable_list ("firstprivate (",
3344 : &c->lists[OMP_LIST_FIRSTPRIVATE],
3345 : true) == MATCH_YES)
3346 1038 : continue;
3347 2080 : if ((mask & OMP_CLAUSE_FROM)
3348 1079 : && gfc_match_motion_var_list ("from (", &c->lists[OMP_LIST_FROM],
3349 : &head) == MATCH_YES)
3350 1001 : continue;
3351 143 : if ((mask & OMP_CLAUSE_FULL)
3352 78 : && (m = gfc_match_dupl_check (!c->full, "full")) != MATCH_NO)
3353 : {
3354 65 : if (m == MATCH_ERROR)
3355 0 : goto error;
3356 65 : c->full = true;
3357 65 : continue;
3358 : }
3359 : break;
3360 1231 : case 'g':
3361 2423 : if ((mask & OMP_CLAUSE_GANG)
3362 1231 : && (m = gfc_match_dupl_check (!c->gang, "gang")) != MATCH_NO)
3363 : {
3364 1197 : if (m == MATCH_ERROR)
3365 0 : goto error;
3366 1197 : c->gang = true;
3367 1197 : m = match_oacc_clause_gwv (c, GOMP_DIM_GANG);
3368 1197 : if (m == MATCH_ERROR)
3369 : {
3370 5 : gfc_current_locus = old_loc;
3371 5 : break;
3372 : }
3373 1192 : continue;
3374 : }
3375 68 : if ((mask & OMP_CLAUSE_GRAINSIZE)
3376 34 : && (m = gfc_match_dupl_check (!c->grainsize, "grainsize", true))
3377 : != MATCH_NO)
3378 : {
3379 34 : if (m == MATCH_ERROR)
3380 0 : goto error;
3381 34 : if (gfc_match ("strict : ") == MATCH_YES)
3382 1 : c->grainsize_strict = true;
3383 34 : if (gfc_match (" %e )", &c->grainsize) != MATCH_YES)
3384 0 : goto error;
3385 34 : continue;
3386 : }
3387 : break;
3388 465 : case 'h':
3389 513 : if ((mask & OMP_CLAUSE_HAS_DEVICE_ADDR)
3390 513 : && gfc_match_omp_variable_list
3391 48 : ("has_device_addr (", &c->lists[OMP_LIST_HAS_DEVICE_ADDR],
3392 : false, NULL, NULL, true) == MATCH_YES)
3393 48 : continue;
3394 460 : if ((mask & OMP_CLAUSE_HINT)
3395 417 : && (m = gfc_match_dupl_check (!c->hint, "hint", true, &c->hint))
3396 : != MATCH_NO)
3397 : {
3398 43 : if (m == MATCH_ERROR)
3399 0 : goto error;
3400 43 : continue;
3401 : }
3402 374 : if ((mask & OMP_CLAUSE_ASSUMPTIONS)
3403 374 : && gfc_match ("holds ( ") == MATCH_YES)
3404 : {
3405 19 : gfc_expr *e;
3406 19 : if (gfc_match ("%e )", &e) != MATCH_YES)
3407 0 : goto error;
3408 19 : if (c->assume == NULL)
3409 12 : c->assume = gfc_get_omp_assumptions ();
3410 19 : gfc_expr_list *el = XCNEW (gfc_expr_list);
3411 19 : el->expr = e;
3412 19 : el->next = c->assume->holds;
3413 19 : c->assume->holds = el;
3414 19 : continue;
3415 19 : }
3416 709 : if ((mask & OMP_CLAUSE_HOST)
3417 355 : && gfc_match ("host ( ") == MATCH_YES
3418 710 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
3419 : OMP_MAP_FORCE_FROM, true,
3420 : /* allow_derived = */ true))
3421 354 : continue;
3422 : break;
3423 2125 : case 'i':
3424 2148 : if ((mask & OMP_CLAUSE_IF_PRESENT)
3425 2125 : && (m = gfc_match_dupl_check (!c->if_present, "if_present"))
3426 : != MATCH_NO)
3427 : {
3428 23 : if (m == MATCH_ERROR)
3429 0 : goto error;
3430 23 : c->if_present = true;
3431 23 : continue;
3432 : }
3433 2102 : if ((mask & OMP_CLAUSE_IF)
3434 2102 : && (m = gfc_match_dupl_check (!c->if_expr, "if", true))
3435 : != MATCH_NO)
3436 : {
3437 1353 : if (m == MATCH_ERROR)
3438 12 : goto error;
3439 1341 : if (!openacc)
3440 : {
3441 : /* This should match the enum gfc_omp_if_kind order. */
3442 : static const char *ifs[OMP_IF_LAST] = {
3443 : "cancel : %e )",
3444 : "parallel : %e )",
3445 : "simd : %e )",
3446 : "task : %e )",
3447 : "taskloop : %e )",
3448 : "target : %e )",
3449 : "target data : %e )",
3450 : "target update : %e )",
3451 : "target enter data : %e )",
3452 : "target exit data : %e )" };
3453 : int i;
3454 4907 : for (i = 0; i < OMP_IF_LAST; i++)
3455 4503 : if (c->if_exprs[i] == NULL
3456 4503 : && gfc_match (ifs[i], &c->if_exprs[i]) == MATCH_YES)
3457 : break;
3458 542 : if (i < OMP_IF_LAST)
3459 138 : continue;
3460 : }
3461 1203 : if (gfc_match (" %e )", &c->if_expr) == MATCH_YES)
3462 1198 : continue;
3463 5 : goto error;
3464 : }
3465 866 : if ((mask & OMP_CLAUSE_IN_REDUCTION)
3466 749 : && gfc_match_omp_clause_reduction (pc, c, openacc, allow_derived,
3467 : openmp_target) == MATCH_YES)
3468 117 : continue;
3469 657 : if ((mask & OMP_CLAUSE_INBRANCH)
3470 632 : && (m = gfc_match_dupl_check (!c->inbranch && !c->notinbranch,
3471 : "inbranch")) != MATCH_NO)
3472 : {
3473 25 : if (m == MATCH_ERROR)
3474 0 : goto error;
3475 25 : c->inbranch = true;
3476 25 : continue;
3477 : }
3478 849 : if ((mask & OMP_CLAUSE_INDEPENDENT)
3479 607 : && (m = gfc_match_dupl_check (!c->independent, "independent"))
3480 : != MATCH_NO)
3481 : {
3482 242 : if (m == MATCH_ERROR)
3483 0 : goto error;
3484 242 : c->independent = true;
3485 242 : continue;
3486 : }
3487 365 : if ((mask & OMP_CLAUSE_INDIRECT)
3488 365 : && (m = gfc_match_dupl_check (!c->indirect, "indirect"))
3489 : != MATCH_NO)
3490 : {
3491 61 : if (m == MATCH_ERROR)
3492 5 : goto error;
3493 60 : gfc_expr *indirect_expr = NULL;
3494 60 : m = gfc_match (" ( %e )", &indirect_expr);
3495 60 : if (m == MATCH_YES)
3496 : {
3497 13 : if (!gfc_resolve_expr (indirect_expr)
3498 13 : || indirect_expr->ts.type != BT_LOGICAL
3499 23 : || indirect_expr->expr_type != EXPR_CONSTANT)
3500 : {
3501 4 : gfc_error ("INDIRECT clause at %C requires a constant "
3502 : "logical expression");
3503 4 : gfc_free_expr (indirect_expr);
3504 4 : goto error;
3505 : }
3506 9 : c->indirect = indirect_expr->value.logical;
3507 9 : gfc_free_expr (indirect_expr);
3508 : }
3509 : else
3510 47 : c->indirect = 1;
3511 56 : continue;
3512 56 : }
3513 304 : if ((mask & OMP_CLAUSE_INIT)
3514 304 : && gfc_match ("init ( ") == MATCH_YES)
3515 : {
3516 108 : m = gfc_match_omp_init (&c->lists[OMP_LIST_INIT]);
3517 108 : if (m == MATCH_YES)
3518 63 : continue;
3519 45 : goto error;
3520 : }
3521 196 : if ((mask & OMP_CLAUSE_INTEROP)
3522 196 : && (m = gfc_match_dupl_check (!c->lists[OMP_LIST_INTEROP],
3523 : "interop", true)) != MATCH_NO)
3524 : {
3525 : /* Note: the interop objects are saved in reverse order to match
3526 : the order in C/C++. */
3527 125 : if (m == MATCH_YES
3528 63 : && (gfc_match_omp_variable_list ("",
3529 : &c->lists[OMP_LIST_INTEROP],
3530 : false, NULL, NULL, false,
3531 : false, NULL, false, true)
3532 : == MATCH_YES))
3533 62 : continue;
3534 1 : goto error;
3535 : }
3536 253 : if ((mask & OMP_CLAUSE_IS_DEVICE_PTR)
3537 253 : && gfc_match_omp_variable_list
3538 120 : ("is_device_ptr (",
3539 : &c->lists[OMP_LIST_IS_DEVICE_PTR], false) == MATCH_YES)
3540 120 : continue;
3541 : break;
3542 2336 : case 'l':
3543 2336 : if ((mask & OMP_CLAUSE_LASTPRIVATE)
3544 2336 : && gfc_match ("lastprivate ( ") == MATCH_YES)
3545 : {
3546 1433 : bool conditional = gfc_match ("conditional : ") == MATCH_YES;
3547 1433 : head = NULL;
3548 1433 : if (gfc_match_omp_variable_list ("",
3549 : &c->lists[OMP_LIST_LASTPRIVATE],
3550 : false, NULL, &head) == MATCH_YES)
3551 : {
3552 1433 : gfc_omp_namelist *n;
3553 3741 : for (n = *head; n; n = n->next)
3554 2308 : n->u.lastprivate_conditional = conditional;
3555 1433 : continue;
3556 1433 : }
3557 0 : gfc_current_locus = old_loc;
3558 0 : break;
3559 : }
3560 903 : end_colon = false;
3561 903 : head = NULL;
3562 903 : if ((mask & OMP_CLAUSE_LINEAR)
3563 903 : && gfc_match ("linear (") == MATCH_YES)
3564 : {
3565 836 : bool old_linear_modifier = false;
3566 836 : gfc_omp_linear_op linear_op = OMP_LINEAR_DEFAULT;
3567 836 : gfc_expr *step = NULL;
3568 836 : locus saved_loc = gfc_current_locus;
3569 :
3570 836 : if (gfc_match_omp_variable_list (" ref (",
3571 : &c->lists[OMP_LIST_LINEAR],
3572 : false, NULL, &head)
3573 : == MATCH_YES)
3574 : {
3575 : linear_op = OMP_LINEAR_REF;
3576 : old_linear_modifier = true;
3577 : }
3578 808 : else if (gfc_match_omp_variable_list (" val (",
3579 : &c->lists[OMP_LIST_LINEAR],
3580 : false, NULL, &head)
3581 : == MATCH_YES)
3582 : {
3583 : linear_op = OMP_LINEAR_VAL;
3584 : old_linear_modifier = true;
3585 : }
3586 797 : else if (gfc_match_omp_variable_list (" uval (",
3587 : &c->lists[OMP_LIST_LINEAR],
3588 : false, NULL, &head)
3589 : == MATCH_YES)
3590 : {
3591 : linear_op = OMP_LINEAR_UVAL;
3592 : old_linear_modifier = true;
3593 : }
3594 788 : else if (gfc_match_omp_variable_list ("",
3595 : &c->lists[OMP_LIST_LINEAR],
3596 : false, &end_colon, &head)
3597 : == MATCH_YES)
3598 : linear_op = OMP_LINEAR_DEFAULT;
3599 : else
3600 : {
3601 2 : gfc_current_locus = old_loc;
3602 2 : break;
3603 : }
3604 : if (linear_op != OMP_LINEAR_DEFAULT)
3605 : {
3606 48 : if (gfc_match (" :") == MATCH_YES)
3607 31 : end_colon = true;
3608 17 : else if (gfc_match (" )") != MATCH_YES)
3609 : {
3610 0 : gfc_free_omp_namelist (*head, OMP_LIST_LINEAR);
3611 0 : gfc_current_locus = old_loc;
3612 0 : *head = NULL;
3613 0 : break;
3614 : }
3615 : }
3616 834 : gfc_gobble_whitespace ();
3617 834 : if (old_linear_modifier && end_colon)
3618 : {
3619 31 : if (gfc_match (" %e )", &step) != MATCH_YES)
3620 : {
3621 1 : gfc_free_omp_namelist (*head, OMP_LIST_LINEAR);
3622 1 : gfc_current_locus = old_loc;
3623 1 : *head = NULL;
3624 5 : goto error;
3625 : }
3626 : }
3627 833 : if (old_linear_modifier)
3628 : {
3629 47 : char var_names[512]{};
3630 47 : int count, offset = 0;
3631 106 : for (gfc_omp_namelist *n = *head; n; n = n->next)
3632 : {
3633 59 : if (!n->next)
3634 47 : count = snprintf (var_names + offset,
3635 47 : sizeof (var_names) - offset,
3636 47 : "%s", n->sym->name);
3637 : else
3638 12 : count = snprintf (var_names + offset,
3639 12 : sizeof (var_names) - offset,
3640 12 : "%s, ", n->sym->name);
3641 59 : if (count < 0 || count >= ((int)sizeof (var_names))
3642 59 : - offset)
3643 : {
3644 0 : snprintf (var_names, 512, "%s, ..., ",
3645 0 : (*head)->sym->name);
3646 0 : while (n->next)
3647 : n = n->next;
3648 0 : offset = strlen (var_names);
3649 0 : snprintf (var_names + offset,
3650 0 : sizeof (var_names) - offset,
3651 0 : "%s", n->sym->name);
3652 0 : break;
3653 : }
3654 59 : offset += count;
3655 : }
3656 47 : char *var_names_for_warn = var_names;
3657 47 : const char *op_name;
3658 47 : switch (linear_op)
3659 : {
3660 : case OMP_LINEAR_REF: op_name = "ref"; break;
3661 10 : case OMP_LINEAR_VAL: op_name = "val"; break;
3662 9 : case OMP_LINEAR_UVAL: op_name = "uval"; break;
3663 0 : default: gcc_unreachable ();
3664 : }
3665 47 : gfc_warning (OPT_Wdeprecated_openmp,
3666 : "Specification of the list items as "
3667 : "arguments to the modifiers at %L is "
3668 : "deprecated; since OpenMP 5.2, use "
3669 : "%<linear(%s : %s%s)%>", &saved_loc,
3670 : var_names_for_warn, op_name,
3671 47 : step == nullptr ? "" : ", step(...)");
3672 : }
3673 786 : else if (end_colon)
3674 : {
3675 713 : bool has_error = false;
3676 : bool has_modifiers = false;
3677 : bool has_step = false;
3678 713 : bool duplicate_step = false;
3679 713 : bool duplicate_mod = false;
3680 713 : while (true)
3681 : {
3682 713 : old_loc = gfc_current_locus;
3683 713 : bool close_paren = gfc_match ("val )") == MATCH_YES;
3684 713 : if (close_paren || gfc_match ("val , ") == MATCH_YES)
3685 : {
3686 17 : if (linear_op != OMP_LINEAR_DEFAULT)
3687 : {
3688 : duplicate_mod = true;
3689 : break;
3690 : }
3691 16 : linear_op = OMP_LINEAR_VAL;
3692 16 : has_modifiers = true;
3693 16 : if (close_paren)
3694 : break;
3695 10 : continue;
3696 : }
3697 696 : close_paren = gfc_match ("uval )") == MATCH_YES;
3698 696 : if (close_paren || gfc_match ("uval , ") == MATCH_YES)
3699 : {
3700 7 : if (linear_op != OMP_LINEAR_DEFAULT)
3701 : {
3702 : duplicate_mod = true;
3703 : break;
3704 : }
3705 7 : linear_op = OMP_LINEAR_UVAL;
3706 7 : has_modifiers = true;
3707 7 : if (close_paren)
3708 : break;
3709 2 : continue;
3710 : }
3711 689 : close_paren = gfc_match ("ref )") == MATCH_YES;
3712 689 : if (close_paren || gfc_match ("ref , ") == MATCH_YES)
3713 : {
3714 16 : if (linear_op != OMP_LINEAR_DEFAULT)
3715 : {
3716 : duplicate_mod = true;
3717 : break;
3718 : }
3719 15 : linear_op = OMP_LINEAR_REF;
3720 15 : has_modifiers = true;
3721 15 : if (close_paren)
3722 : break;
3723 7 : continue;
3724 : }
3725 673 : close_paren = (gfc_match ("step ( %e ) )", &step)
3726 : == MATCH_YES);
3727 684 : if (close_paren
3728 673 : || gfc_match ("step ( %e ) , ", &step) == MATCH_YES)
3729 : {
3730 38 : if (has_step)
3731 : {
3732 : duplicate_step = true;
3733 : break;
3734 : }
3735 37 : has_modifiers = has_step = true;
3736 37 : if (close_paren)
3737 : break;
3738 11 : continue;
3739 : }
3740 635 : if (!has_modifiers
3741 635 : && gfc_match ("%e )", &step) == MATCH_YES)
3742 : {
3743 635 : if ((step->expr_type == EXPR_FUNCTION
3744 634 : || step->expr_type == EXPR_VARIABLE)
3745 31 : && strcmp (step->symtree->name, "step") == 0)
3746 : {
3747 1 : gfc_current_locus = old_loc;
3748 1 : gfc_match ("step (");
3749 1 : has_error = true;
3750 : }
3751 : break;
3752 : }
3753 : has_error = true;
3754 : break;
3755 : }
3756 49 : if (duplicate_mod || duplicate_step)
3757 : {
3758 3 : gfc_error ("Multiple %qs modifiers specified at %C",
3759 : duplicate_mod ? "linear" : "step");
3760 3 : has_error = true;
3761 : }
3762 683 : if (has_error)
3763 : {
3764 4 : gfc_free_omp_namelist (*head, OMP_LIST_LINEAR);
3765 4 : *head = NULL;
3766 4 : goto error;
3767 : }
3768 : }
3769 829 : if (step == NULL)
3770 : {
3771 130 : step = gfc_get_constant_expr (BT_INTEGER,
3772 : gfc_default_integer_kind,
3773 : &old_loc);
3774 130 : mpz_set_si (step->value.integer, 1);
3775 : }
3776 829 : (*head)->expr = step;
3777 829 : if (linear_op != OMP_LINEAR_DEFAULT || old_linear_modifier)
3778 176 : for (gfc_omp_namelist *n = *head; n; n = n->next)
3779 : {
3780 94 : n->u.linear.op = linear_op;
3781 94 : n->u.linear.old_modifier = old_linear_modifier;
3782 : }
3783 829 : continue;
3784 829 : }
3785 71 : if ((mask & OMP_CLAUSE_LINK)
3786 67 : && openacc
3787 75 : && (gfc_match_oacc_clause_link ("link (",
3788 : &c->lists[OMP_LIST_LINK])
3789 : == MATCH_YES))
3790 4 : continue;
3791 110 : else if ((mask & OMP_CLAUSE_LINK)
3792 63 : && !openacc
3793 122 : && (gfc_match_omp_to_link ("link (",
3794 : &c->lists[OMP_LIST_LINK])
3795 : == MATCH_YES))
3796 47 : continue;
3797 28 : if ((mask & OMP_CLAUSE_LOCAL)
3798 16 : && (gfc_match_omp_to_link ("local (", &c->lists[OMP_LIST_LOCAL])
3799 : == MATCH_YES))
3800 12 : continue;
3801 : break;
3802 5931 : case 'm':
3803 5931 : if ((mask & OMP_CLAUSE_MAP)
3804 5931 : && gfc_match ("map ( ") == MATCH_YES)
3805 : {
3806 5839 : locus old_loc2 = gfc_current_locus;
3807 5839 : int always_modifier = 0;
3808 5839 : int close_modifier = 0;
3809 5839 : int present_modifier = 0;
3810 5839 : int mapper_modifier = 0;
3811 5839 : int iterator_modifier = 0;
3812 5839 : gfc_namespace *ns_iter = NULL, *ns_curr = gfc_current_ns;
3813 5839 : locus second_always_locus = old_loc2;
3814 5839 : locus second_close_locus = old_loc2;
3815 5839 : locus second_mapper_locus = old_loc2;
3816 5839 : locus second_present_locus = old_loc2;
3817 5839 : char mapper_id[GFC_MAX_SYMBOL_LEN + 1] = { '\0' };
3818 5839 : locus second_iterator_locus = old_loc2;
3819 :
3820 6505 : for (;;)
3821 : {
3822 6172 : locus current_locus = gfc_current_locus;
3823 6172 : if (gfc_match ("always ") == MATCH_YES)
3824 : {
3825 148 : if (always_modifier++ == 1)
3826 5 : second_always_locus = current_locus;
3827 : }
3828 6024 : else if (gfc_match ("close ") == MATCH_YES)
3829 : {
3830 69 : if (close_modifier++ == 1)
3831 5 : second_close_locus = current_locus;
3832 : }
3833 5955 : else if (gfc_match ("present ") == MATCH_YES)
3834 : {
3835 67 : if (present_modifier++ == 1)
3836 4 : second_present_locus = current_locus;
3837 : }
3838 5888 : else if (gfc_match ("mapper ( ") == MATCH_YES)
3839 : {
3840 7 : if (mapper_modifier++ == 1)
3841 0 : second_mapper_locus = current_locus;
3842 7 : m = gfc_match (" %n ) ", mapper_id);
3843 7 : if (m != MATCH_YES)
3844 0 : goto error;
3845 7 : if (strcmp (mapper_id, "default") == 0)
3846 3 : mapper_id[0] = '\0';
3847 : }
3848 5881 : else if (gfc_match_iterator (&ns_iter, true) == MATCH_YES)
3849 : {
3850 42 : if (iterator_modifier++ == 1)
3851 1 : second_iterator_locus = current_locus;
3852 : }
3853 : else
3854 : break;
3855 333 : if (gfc_match (", ") != MATCH_YES)
3856 62 : gfc_warning (OPT_Wdeprecated_openmp,
3857 : "The specification of modifiers without "
3858 : "comma separators for the %<map%> clause "
3859 : "at %C has been deprecated since "
3860 : "OpenMP 5.2");
3861 333 : }
3862 :
3863 5839 : gfc_omp_map_op map_op = default_map_op;
3864 5839 : int always_present_modifier
3865 5839 : = always_modifier && present_modifier;
3866 :
3867 5839 : if (gfc_match ("alloc : ") == MATCH_YES)
3868 799 : map_op = (present_modifier ? OMP_MAP_PRESENT_ALLOC
3869 : : OMP_MAP_ALLOC);
3870 5040 : else if (gfc_match ("tofrom : ") == MATCH_YES)
3871 954 : map_op = (always_present_modifier ? OMP_MAP_ALWAYS_PRESENT_TOFROM
3872 950 : : present_modifier ? OMP_MAP_PRESENT_TOFROM
3873 945 : : always_modifier ? OMP_MAP_ALWAYS_TOFROM
3874 : : OMP_MAP_TOFROM);
3875 4086 : else if (gfc_match ("to : ") == MATCH_YES)
3876 1814 : map_op = (always_present_modifier ? OMP_MAP_ALWAYS_PRESENT_TO
3877 1808 : : present_modifier ? OMP_MAP_PRESENT_TO
3878 1796 : : always_modifier ? OMP_MAP_ALWAYS_TO
3879 : : OMP_MAP_TO);
3880 2272 : else if (gfc_match ("from : ") == MATCH_YES)
3881 1654 : map_op = (always_present_modifier ? OMP_MAP_ALWAYS_PRESENT_FROM
3882 1650 : : present_modifier ? OMP_MAP_PRESENT_FROM
3883 1645 : : always_modifier ? OMP_MAP_ALWAYS_FROM
3884 : : OMP_MAP_FROM);
3885 618 : else if (gfc_match ("release : ") == MATCH_YES)
3886 : map_op = OMP_MAP_RELEASE;
3887 564 : else if (gfc_match ("delete : ") == MATCH_YES)
3888 : map_op = OMP_MAP_DELETE;
3889 : else
3890 : {
3891 487 : gfc_current_locus = old_loc2;
3892 487 : always_modifier = 0;
3893 487 : close_modifier = 0;
3894 487 : mapper_modifier = 0;
3895 : }
3896 :
3897 1565 : if (always_modifier > 1)
3898 : {
3899 5 : gfc_error ("too many %<always%> modifiers at %L",
3900 : &second_always_locus);
3901 24 : break;
3902 : }
3903 5834 : if (close_modifier > 1)
3904 : {
3905 4 : gfc_error ("too many %<close%> modifiers at %L",
3906 : &second_close_locus);
3907 4 : break;
3908 : }
3909 5830 : if (present_modifier > 1)
3910 : {
3911 4 : gfc_error ("too many %<present%> modifiers at %L",
3912 : &second_present_locus);
3913 4 : break;
3914 : }
3915 5826 : if (mapper_modifier > 1)
3916 : {
3917 0 : gfc_error ("too many %<mapper%> modifiers at %L",
3918 : &second_mapper_locus);
3919 0 : break;
3920 : }
3921 5826 : if (iterator_modifier > 1)
3922 : {
3923 1 : gfc_error ("too many %<iterator%> modifiers at %L",
3924 : &second_iterator_locus);
3925 1 : break;
3926 : }
3927 :
3928 5825 : head = NULL;
3929 5825 : if (ns_iter)
3930 40 : gfc_current_ns = ns_iter;
3931 5825 : m = gfc_match_omp_variable_list ("", &c->lists[OMP_LIST_MAP],
3932 : false, NULL, &head, true, true);
3933 5825 : gfc_current_ns = ns_curr;
3934 5825 : if (m == MATCH_YES)
3935 : {
3936 5820 : gfc_omp_namelist *n;
3937 13223 : for (n = *head; n; n = n->next)
3938 : {
3939 7403 : n->u.map.op = map_op;
3940 7403 : if (mapper_id[0] != '\0')
3941 : {
3942 4 : n->u3.udm = gfc_get_omp_namelist_udm ();
3943 4 : n->u3.udm->requested_mapper_id
3944 4 : = gfc_get_string ("%s", mapper_id);
3945 : }
3946 7403 : n->u2.ns = ns_iter;
3947 7403 : if (ns_iter)
3948 42 : ns_iter->refs++;
3949 : }
3950 5820 : continue;
3951 5820 : }
3952 5 : gfc_current_locus = old_loc;
3953 5 : break;
3954 : }
3955 126 : if ((mask & OMP_CLAUSE_MERGEABLE)
3956 92 : && (m = gfc_match_dupl_check (!c->mergeable, "mergeable"))
3957 : != MATCH_NO)
3958 : {
3959 34 : if (m == MATCH_ERROR)
3960 0 : goto error;
3961 34 : c->mergeable = true;
3962 34 : continue;
3963 : }
3964 111 : if ((mask & OMP_CLAUSE_MESSAGE)
3965 58 : && (m = gfc_match_dupl_check (!c->message, "message", true,
3966 : &c->message)) != MATCH_NO)
3967 : {
3968 58 : if (m == MATCH_ERROR)
3969 5 : goto error;
3970 53 : continue;
3971 : }
3972 : break;
3973 2914 : case 'n':
3974 2966 : if ((mask & OMP_CLAUSE_NO_CREATE)
3975 1343 : && gfc_match ("no_create ( ") == MATCH_YES
3976 2966 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
3977 : OMP_MAP_IF_PRESENT, true,
3978 : allow_derived))
3979 52 : continue;
3980 2863 : if ((mask & OMP_CLAUSE_ASSUMPTIONS)
3981 2888 : && (m = gfc_match_dupl_check (!c->assume
3982 26 : || !c->assume->no_openmp_constructs,
3983 : "no_openmp_constructs")) != MATCH_NO)
3984 : {
3985 2 : if (m == MATCH_ERROR)
3986 1 : goto error;
3987 1 : if (c->assume == NULL)
3988 0 : c->assume = gfc_get_omp_assumptions ();
3989 1 : c->assume->no_openmp_constructs = true;
3990 1 : continue;
3991 : }
3992 2873 : if ((mask & OMP_CLAUSE_ASSUMPTIONS)
3993 2884 : && (m = gfc_match_dupl_check (!c->assume
3994 24 : || !c->assume->no_openmp_routines,
3995 : "no_openmp_routines")) != MATCH_NO)
3996 : {
3997 13 : if (m == MATCH_ERROR)
3998 0 : goto error;
3999 13 : if (c->assume == NULL)
4000 12 : c->assume = gfc_get_omp_assumptions ();
4001 13 : c->assume->no_openmp_routines = true;
4002 13 : continue;
4003 : }
4004 2851 : if ((mask & OMP_CLAUSE_ASSUMPTIONS)
4005 2857 : && (m = gfc_match_dupl_check (!c->assume || !c->assume->no_openmp,
4006 : "no_openmp")) != MATCH_NO)
4007 : {
4008 4 : if (m == MATCH_ERROR)
4009 0 : goto error;
4010 4 : if (c->assume == NULL)
4011 4 : c->assume = gfc_get_omp_assumptions ();
4012 4 : c->assume->no_openmp = true;
4013 4 : continue;
4014 : }
4015 2849 : if ((mask & OMP_CLAUSE_ASSUMPTIONS)
4016 2850 : && (m = gfc_match_dupl_check (!c->assume
4017 7 : || !c->assume->no_parallelism,
4018 : "no_parallelism")) != MATCH_NO)
4019 : {
4020 6 : if (m == MATCH_ERROR)
4021 0 : goto error;
4022 6 : if (c->assume == NULL)
4023 6 : c->assume = gfc_get_omp_assumptions ();
4024 6 : c->assume->no_parallelism = true;
4025 6 : continue;
4026 : }
4027 :
4028 2847 : if ((mask & OMP_CLAUSE_NOVARIANTS)
4029 2837 : && (m = gfc_match_dupl_check (!c->novariants, "novariants", true,
4030 : &c->novariants))
4031 : != MATCH_NO)
4032 : {
4033 12 : if (m == MATCH_ERROR)
4034 2 : goto error;
4035 10 : continue;
4036 : }
4037 2838 : if ((mask & OMP_CLAUSE_NOCONTEXT)
4038 2825 : && (m = gfc_match_dupl_check (!c->nocontext, "nocontext", true,
4039 : &c->nocontext))
4040 : != MATCH_NO)
4041 : {
4042 15 : if (m == MATCH_ERROR)
4043 2 : goto error;
4044 13 : continue;
4045 : }
4046 2824 : if ((mask & OMP_CLAUSE_NOGROUP)
4047 2810 : && (m = gfc_match_dupl_check (!c->nogroup, "nogroup"))
4048 : != MATCH_NO)
4049 : {
4050 14 : if (m == MATCH_ERROR)
4051 0 : goto error;
4052 14 : c->nogroup = true;
4053 14 : continue;
4054 : }
4055 2946 : if ((mask & OMP_CLAUSE_NOHOST)
4056 2796 : && (m = gfc_match_dupl_check (!c->nohost, "nohost")) != MATCH_NO)
4057 : {
4058 151 : if (m == MATCH_ERROR)
4059 1 : goto error;
4060 150 : c->nohost = true;
4061 150 : continue;
4062 : }
4063 2687 : if ((mask & OMP_CLAUSE_NOTEMPORAL)
4064 2645 : && gfc_match_omp_variable_list ("nontemporal (",
4065 : &c->lists[OMP_LIST_NONTEMPORAL],
4066 : true) == MATCH_YES)
4067 42 : continue;
4068 2627 : if ((mask & OMP_CLAUSE_NOTINBRANCH)
4069 2604 : && (m = gfc_match_dupl_check (!c->notinbranch && !c->inbranch,
4070 : "notinbranch")) != MATCH_NO)
4071 : {
4072 25 : if (m == MATCH_ERROR)
4073 1 : goto error;
4074 24 : c->notinbranch = true;
4075 24 : continue;
4076 : }
4077 2707 : if ((mask & OMP_CLAUSE_NOWAIT)
4078 2578 : && (m = gfc_match_dupl_check (!c->nowait, "nowait")) != MATCH_NO)
4079 : {
4080 132 : if (m == MATCH_ERROR)
4081 3 : goto error;
4082 129 : c->nowait = true;
4083 129 : continue;
4084 : }
4085 3128 : if ((mask & OMP_CLAUSE_NUM_GANGS)
4086 2446 : && (m = gfc_match_dupl_check (!c->num_gangs_expr, "num_gangs",
4087 : true)) != MATCH_NO)
4088 : {
4089 686 : if (m == MATCH_ERROR)
4090 2 : goto error;
4091 684 : if (gfc_match (" %e )", &c->num_gangs_expr) != MATCH_YES)
4092 2 : goto error;
4093 682 : continue;
4094 : }
4095 1786 : if ((mask & OMP_CLAUSE_NUM_TASKS)
4096 1760 : && (m = gfc_match_dupl_check (!c->num_tasks, "num_tasks", true))
4097 : != MATCH_NO)
4098 : {
4099 26 : if (m == MATCH_ERROR)
4100 0 : goto error;
4101 26 : if (gfc_match ("strict : ") == MATCH_YES)
4102 1 : c->num_tasks_strict = true;
4103 26 : if (gfc_match (" %e )", &c->num_tasks) != MATCH_YES)
4104 0 : goto error;
4105 26 : continue;
4106 : }
4107 1863 : if ((mask & OMP_CLAUSE_NUM_TEAMS)
4108 1734 : && (m = gfc_match_dupl_check (!c->num_teams_upper, "num_teams",
4109 : true)) != MATCH_NO)
4110 : {
4111 129 : if (m == MATCH_ERROR)
4112 0 : goto error;
4113 129 : if (gfc_match ("%e ", &c->num_teams_upper) != MATCH_YES)
4114 0 : goto error;
4115 129 : if (gfc_peek_ascii_char () == ':')
4116 : {
4117 21 : c->num_teams_lower = c->num_teams_upper;
4118 21 : c->num_teams_upper = NULL;
4119 21 : if (gfc_match (": %e ", &c->num_teams_upper) != MATCH_YES)
4120 0 : goto error;
4121 : }
4122 129 : if (gfc_match (") ") != MATCH_YES)
4123 0 : goto error;
4124 129 : continue;
4125 : }
4126 2569 : if ((mask & OMP_CLAUSE_NUM_THREADS)
4127 1605 : && (m = gfc_match_dupl_check (!c->num_threads, "num_threads", true,
4128 : &c->num_threads)) != MATCH_NO)
4129 : {
4130 964 : if (m == MATCH_ERROR)
4131 0 : goto error;
4132 964 : continue;
4133 : }
4134 1240 : if ((mask & OMP_CLAUSE_NUM_WORKERS)
4135 641 : && (m = gfc_match_dupl_check (!c->num_workers_expr, "num_workers",
4136 : true, &c->num_workers_expr))
4137 : != MATCH_NO)
4138 : {
4139 603 : if (m == MATCH_ERROR)
4140 4 : goto error;
4141 599 : continue;
4142 : }
4143 : break;
4144 591 : case 'o':
4145 591 : if ((mask & OMP_CLAUSE_ORDERED)
4146 591 : && (m = gfc_match_dupl_check (!c->ordered, "ordered"))
4147 : != MATCH_NO)
4148 : {
4149 343 : if (m == MATCH_ERROR)
4150 0 : goto error;
4151 343 : gfc_expr *cexpr = NULL;
4152 343 : m = gfc_match (" ( %e )", &cexpr);
4153 :
4154 343 : c->ordered = true;
4155 343 : if (m == MATCH_YES)
4156 : {
4157 144 : int ordered = 0;
4158 144 : if (gfc_extract_int (cexpr, &ordered, -1))
4159 0 : ordered = 0;
4160 144 : else if (ordered <= 0)
4161 : {
4162 0 : gfc_error_now ("ORDERED clause argument not"
4163 : " constant positive integer at %C");
4164 0 : ordered = 0;
4165 : }
4166 144 : c->orderedc = ordered;
4167 144 : gfc_free_expr (cexpr);
4168 144 : continue;
4169 144 : }
4170 :
4171 199 : continue;
4172 199 : }
4173 482 : if ((mask & OMP_CLAUSE_ORDER)
4174 248 : && (m = gfc_match_dupl_check (!c->order_concurrent, "order", true))
4175 : != MATCH_NO)
4176 : {
4177 247 : if (m == MATCH_ERROR)
4178 10 : goto error;
4179 237 : if (gfc_match (" reproducible : concurrent )") == MATCH_YES)
4180 55 : c->order_reproducible = true;
4181 182 : else if (gfc_match (" concurrent )") == MATCH_YES)
4182 : ;
4183 50 : else if (gfc_match (" unconstrained : concurrent )") == MATCH_YES)
4184 47 : c->order_unconstrained = true;
4185 : else
4186 : {
4187 3 : gfc_error ("Expected ORDER(CONCURRENT) at %C "
4188 : "with optional %<reproducible%> or "
4189 : "%<unconstrained%> modifier");
4190 3 : goto error;
4191 : }
4192 234 : c->order_concurrent = true;
4193 234 : continue;
4194 : }
4195 : break;
4196 3101 : case 'p':
4197 3101 : if (mask & OMP_CLAUSE_PARTIAL)
4198 : {
4199 276 : if ((m = gfc_match_dupl_check (!c->partial, "partial"))
4200 : != MATCH_NO)
4201 : {
4202 276 : int expr;
4203 276 : if (m == MATCH_ERROR)
4204 0 : goto error;
4205 :
4206 276 : c->partial = -1;
4207 :
4208 276 : gfc_expr *cexpr = NULL;
4209 276 : m = gfc_match (" ( %e )", &cexpr);
4210 276 : if (m == MATCH_NO)
4211 : ;
4212 251 : else if (m == MATCH_YES
4213 251 : && !gfc_extract_int (cexpr, &expr, -1)
4214 502 : && expr > 0)
4215 247 : c->partial = expr;
4216 : else
4217 4 : gfc_error_now ("PARTIAL clause argument not constant "
4218 : "positive integer at %C");
4219 276 : gfc_free_expr (cexpr);
4220 276 : continue;
4221 276 : }
4222 : }
4223 2894 : if ((mask & OMP_CLAUSE_COPY)
4224 877 : && gfc_match ("pcopy ( ") == MATCH_YES
4225 2895 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4226 : OMP_MAP_TOFROM, true, allow_derived))
4227 69 : continue;
4228 2830 : if ((mask & OMP_CLAUSE_COPYIN)
4229 1910 : && gfc_match ("pcopyin ( ") == MATCH_YES
4230 2830 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4231 : OMP_MAP_TO, true, allow_derived))
4232 74 : continue;
4233 2755 : if ((mask & OMP_CLAUSE_COPYOUT)
4234 735 : && gfc_match ("pcopyout ( ") == MATCH_YES
4235 2755 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4236 : OMP_MAP_FROM, true, allow_derived))
4237 73 : continue;
4238 2624 : if ((mask & OMP_CLAUSE_CREATE)
4239 672 : && gfc_match ("pcreate ( ") == MATCH_YES
4240 2624 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4241 : OMP_MAP_ALLOC, true, allow_derived))
4242 15 : continue;
4243 3010 : if ((mask & OMP_CLAUSE_PRESENT)
4244 647 : && gfc_match ("present ( ") == MATCH_YES
4245 3012 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4246 : OMP_MAP_FORCE_PRESENT, false,
4247 : allow_derived))
4248 416 : continue;
4249 2201 : if ((mask & OMP_CLAUSE_COPY)
4250 231 : && gfc_match ("present_or_copy ( ") == MATCH_YES
4251 2201 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4252 : OMP_MAP_TOFROM, true,
4253 : allow_derived))
4254 23 : continue;
4255 2195 : if ((mask & OMP_CLAUSE_COPYIN)
4256 1309 : && gfc_match ("present_or_copyin ( ") == MATCH_YES
4257 2195 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4258 : OMP_MAP_TO, true, allow_derived))
4259 40 : continue;
4260 2150 : if ((mask & OMP_CLAUSE_COPYOUT)
4261 173 : && gfc_match ("present_or_copyout ( ") == MATCH_YES
4262 2150 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4263 : OMP_MAP_FROM, true, allow_derived))
4264 35 : continue;
4265 2108 : if ((mask & OMP_CLAUSE_CREATE)
4266 143 : && gfc_match ("present_or_create ( ") == MATCH_YES
4267 2108 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4268 : OMP_MAP_ALLOC, true, allow_derived))
4269 28 : continue;
4270 2086 : if ((mask & OMP_CLAUSE_PRIORITY)
4271 2052 : && (m = gfc_match_dupl_check (!c->priority, "priority", true,
4272 : &c->priority)) != MATCH_NO)
4273 : {
4274 34 : if (m == MATCH_ERROR)
4275 0 : goto error;
4276 34 : continue;
4277 : }
4278 3959 : if ((mask & OMP_CLAUSE_PRIVATE)
4279 2018 : && gfc_match_omp_variable_list ("private (",
4280 : &c->lists[OMP_LIST_PRIVATE],
4281 : true) == MATCH_YES)
4282 1941 : continue;
4283 141 : if ((mask & OMP_CLAUSE_PROC_BIND)
4284 141 : && (m = gfc_match_dupl_check ((c->proc_bind
4285 64 : == OMP_PROC_BIND_UNKNOWN),
4286 : "proc_bind", true)) != MATCH_NO)
4287 : {
4288 64 : if (m == MATCH_ERROR)
4289 0 : goto error;
4290 64 : if (gfc_match ("primary )") == MATCH_YES)
4291 1 : c->proc_bind = OMP_PROC_BIND_PRIMARY;
4292 63 : else if (gfc_match ("master )") == MATCH_YES)
4293 : {
4294 9 : gfc_warning (OPT_Wdeprecated_openmp,
4295 : "%<master%> affinity policy at %C deprecated "
4296 : "since OpenMP 5.1, use %<primary%>");
4297 9 : c->proc_bind = OMP_PROC_BIND_MASTER;
4298 : }
4299 54 : else if (gfc_match ("spread )") == MATCH_YES)
4300 53 : c->proc_bind = OMP_PROC_BIND_SPREAD;
4301 1 : else if (gfc_match ("close )") == MATCH_YES)
4302 1 : c->proc_bind = OMP_PROC_BIND_CLOSE;
4303 : else
4304 0 : goto error;
4305 64 : continue;
4306 : }
4307 : break;
4308 4583 : case 'r':
4309 5073 : if ((mask & OMP_CLAUSE_ATOMIC)
4310 4583 : && (m = gfc_match_dupl_atomic ((c->atomic_op
4311 : == GFC_OMP_ATOMIC_UNSET),
4312 : "read")) != MATCH_NO)
4313 : {
4314 490 : if (m == MATCH_ERROR)
4315 0 : goto error;
4316 490 : c->atomic_op = GFC_OMP_ATOMIC_READ;
4317 490 : continue;
4318 : }
4319 8149 : if ((mask & OMP_CLAUSE_REDUCTION)
4320 4093 : && gfc_match_omp_clause_reduction (pc, c, openacc,
4321 : allow_derived) == MATCH_YES)
4322 4056 : continue;
4323 47 : if ((mask & OMP_CLAUSE_MEMORDER)
4324 65 : && (m = gfc_match_dupl_memorder ((c->memorder
4325 28 : == OMP_MEMORDER_UNSET),
4326 : "relaxed")) != MATCH_NO)
4327 : {
4328 10 : if (m == MATCH_ERROR)
4329 0 : goto error;
4330 10 : c->memorder = OMP_MEMORDER_RELAXED;
4331 10 : continue;
4332 : }
4333 44 : if ((mask & OMP_CLAUSE_MEMORDER)
4334 45 : && (m = gfc_match_dupl_memorder ((c->memorder
4335 18 : == OMP_MEMORDER_UNSET),
4336 : "release")) != MATCH_NO)
4337 : {
4338 18 : if (m == MATCH_ERROR)
4339 1 : goto error;
4340 17 : c->memorder = OMP_MEMORDER_RELEASE;
4341 17 : continue;
4342 : }
4343 : break;
4344 3036 : case 's':
4345 3129 : if ((mask & OMP_CLAUSE_SAFELEN)
4346 3036 : && (m = gfc_match_dupl_check (!c->safelen_expr, "safelen",
4347 : true, &c->safelen_expr))
4348 : != MATCH_NO)
4349 : {
4350 93 : if (m == MATCH_ERROR)
4351 0 : goto error;
4352 93 : continue;
4353 : }
4354 2943 : if ((mask & OMP_CLAUSE_SCHEDULE)
4355 2943 : && (m = gfc_match_dupl_check (c->sched_kind == OMP_SCHED_NONE,
4356 : "schedule", true)) != MATCH_NO)
4357 : {
4358 809 : if (m == MATCH_ERROR)
4359 0 : goto error;
4360 809 : int nmodifiers = 0;
4361 809 : locus old_loc2 = gfc_current_locus;
4362 827 : do
4363 : {
4364 818 : if (gfc_match ("simd") == MATCH_YES)
4365 : {
4366 18 : c->sched_simd = true;
4367 18 : nmodifiers++;
4368 : }
4369 800 : else if (gfc_match ("monotonic") == MATCH_YES)
4370 : {
4371 30 : c->sched_monotonic = true;
4372 30 : nmodifiers++;
4373 : }
4374 770 : else if (gfc_match ("nonmonotonic") == MATCH_YES)
4375 : {
4376 35 : c->sched_nonmonotonic = true;
4377 35 : nmodifiers++;
4378 : }
4379 : else
4380 : {
4381 735 : if (nmodifiers)
4382 0 : gfc_current_locus = old_loc2;
4383 : break;
4384 : }
4385 92 : if (nmodifiers == 1
4386 83 : && gfc_match (" , ") == MATCH_YES)
4387 9 : continue;
4388 74 : else if (gfc_match (" : ") == MATCH_YES)
4389 : break;
4390 0 : gfc_current_locus = old_loc2;
4391 0 : break;
4392 : }
4393 : while (1);
4394 809 : if (gfc_match ("static") == MATCH_YES)
4395 425 : c->sched_kind = OMP_SCHED_STATIC;
4396 384 : else if (gfc_match ("dynamic") == MATCH_YES)
4397 164 : c->sched_kind = OMP_SCHED_DYNAMIC;
4398 220 : else if (gfc_match ("guided") == MATCH_YES)
4399 127 : c->sched_kind = OMP_SCHED_GUIDED;
4400 93 : else if (gfc_match ("runtime") == MATCH_YES)
4401 85 : c->sched_kind = OMP_SCHED_RUNTIME;
4402 8 : else if (gfc_match ("auto") == MATCH_YES)
4403 8 : c->sched_kind = OMP_SCHED_AUTO;
4404 809 : if (c->sched_kind != OMP_SCHED_NONE)
4405 : {
4406 809 : m = MATCH_NO;
4407 809 : if (c->sched_kind != OMP_SCHED_RUNTIME
4408 809 : && c->sched_kind != OMP_SCHED_AUTO)
4409 716 : m = gfc_match (" , %e )", &c->chunk_size);
4410 716 : if (m != MATCH_YES)
4411 299 : m = gfc_match_char (')');
4412 299 : if (m != MATCH_YES)
4413 0 : c->sched_kind = OMP_SCHED_NONE;
4414 : }
4415 809 : if (c->sched_kind != OMP_SCHED_NONE)
4416 809 : continue;
4417 : else
4418 0 : gfc_current_locus = old_loc;
4419 : }
4420 2317 : if ((mask & OMP_CLAUSE_SELF)
4421 335 : && !(mask & OMP_CLAUSE_HOST) /* OpenACC compute construct */
4422 2374 : && (m = gfc_match_dupl_check (!c->self_expr, "self"))
4423 : != MATCH_NO)
4424 : {
4425 186 : if (m == MATCH_ERROR)
4426 3 : goto error;
4427 183 : m = gfc_match (" ( %e )", &c->self_expr);
4428 183 : if (m == MATCH_ERROR)
4429 : {
4430 0 : gfc_current_locus = old_loc;
4431 0 : break;
4432 : }
4433 183 : else if (m == MATCH_NO)
4434 9 : c->self_expr = gfc_get_logical_expr (gfc_default_logical_kind,
4435 : NULL, true);
4436 183 : continue;
4437 : }
4438 2042 : if ((mask & OMP_CLAUSE_SELF)
4439 149 : && (mask & OMP_CLAUSE_HOST) /* OpenACC 'update' directive */
4440 95 : && gfc_match ("self ( ") == MATCH_YES
4441 2043 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4442 : OMP_MAP_FORCE_FROM, true,
4443 : /* allow_derived = */ true))
4444 94 : continue;
4445 2202 : if ((mask & OMP_CLAUSE_SEQ)
4446 1854 : && (m = gfc_match_dupl_check (!c->seq, "seq")) != MATCH_NO)
4447 : {
4448 348 : if (m == MATCH_ERROR)
4449 0 : goto error;
4450 348 : c->seq = true;
4451 348 : continue;
4452 : }
4453 1647 : if ((mask & OMP_CLAUSE_MEMORDER)
4454 1647 : && (m = gfc_match_dupl_memorder ((c->memorder
4455 141 : == OMP_MEMORDER_UNSET),
4456 : "seq_cst")) != MATCH_NO)
4457 : {
4458 141 : if (m == MATCH_ERROR)
4459 0 : goto error;
4460 141 : c->memorder = OMP_MEMORDER_SEQ_CST;
4461 141 : continue;
4462 : }
4463 2340 : if ((mask & OMP_CLAUSE_SHARED)
4464 1365 : && gfc_match_omp_variable_list ("shared (",
4465 : &c->lists[OMP_LIST_SHARED],
4466 : true) == MATCH_YES)
4467 975 : continue;
4468 508 : if ((mask & OMP_CLAUSE_SIMDLEN)
4469 390 : && (m = gfc_match_dupl_check (!c->simdlen_expr, "simdlen", true,
4470 : &c->simdlen_expr)) != MATCH_NO)
4471 : {
4472 118 : if (m == MATCH_ERROR)
4473 0 : goto error;
4474 118 : continue;
4475 : }
4476 294 : if ((mask & OMP_CLAUSE_SIMD)
4477 272 : && (m = gfc_match_dupl_check (!c->simd, "simd")) != MATCH_NO)
4478 : {
4479 22 : if (m == MATCH_ERROR)
4480 0 : goto error;
4481 22 : c->simd = true;
4482 22 : continue;
4483 : }
4484 289 : if ((mask & OMP_CLAUSE_SEVERITY)
4485 250 : && (m = gfc_match_dupl_check (!c->severity, "severity", true))
4486 : != MATCH_NO)
4487 : {
4488 45 : if (m == MATCH_ERROR)
4489 2 : goto error;
4490 43 : if (gfc_match ("fatal )") == MATCH_YES)
4491 10 : c->severity = OMP_SEVERITY_FATAL;
4492 33 : else if (gfc_match ("warning )") == MATCH_YES)
4493 29 : c->severity = OMP_SEVERITY_WARNING;
4494 : else
4495 : {
4496 4 : gfc_error ("Expected FATAL or WARNING in SEVERITY clause "
4497 : "at %C");
4498 4 : goto error;
4499 : }
4500 39 : continue;
4501 : }
4502 205 : if ((mask & OMP_CLAUSE_SIZES)
4503 205 : && ((m = gfc_match_dupl_check (!c->sizes_list, "sizes"))
4504 : != MATCH_NO))
4505 : {
4506 203 : if (m == MATCH_ERROR)
4507 0 : goto error;
4508 203 : m = match_omp_oacc_expr_list (" (", &c->sizes_list, false, true);
4509 203 : if (m == MATCH_ERROR)
4510 7 : goto error;
4511 196 : if (m == MATCH_YES)
4512 195 : continue;
4513 1 : gfc_error ("Expected %<(%> after %qs at %C", "sizes");
4514 1 : goto error;
4515 : }
4516 : break;
4517 1224 : case 't':
4518 1289 : if ((mask & OMP_CLAUSE_TASK_REDUCTION)
4519 1224 : && gfc_match_omp_clause_reduction (pc, c, openacc,
4520 : allow_derived) == MATCH_YES)
4521 65 : continue;
4522 1233 : if ((mask & OMP_CLAUSE_THREAD_LIMIT)
4523 1159 : && (m = gfc_match_dupl_check (!c->thread_limit, "thread_limit",
4524 : true, &c->thread_limit))
4525 : != MATCH_NO)
4526 : {
4527 74 : if (m == MATCH_ERROR)
4528 0 : goto error;
4529 74 : continue;
4530 : }
4531 1098 : if ((mask & OMP_CLAUSE_THREADS)
4532 1085 : && (m = gfc_match_dupl_check (!c->threads, "threads"))
4533 : != MATCH_NO)
4534 : {
4535 13 : if (m == MATCH_ERROR)
4536 0 : goto error;
4537 13 : c->threads = true;
4538 13 : continue;
4539 : }
4540 1269 : if ((mask & OMP_CLAUSE_TILE)
4541 221 : && !c->tile_list
4542 1293 : && match_omp_oacc_expr_list ("tile (", &c->tile_list,
4543 : true, false) == MATCH_YES)
4544 197 : continue;
4545 875 : if ((mask & OMP_CLAUSE_TO) && (mask & OMP_CLAUSE_LINK))
4546 : {
4547 : /* Declare target: 'to' is an alias for 'enter';
4548 : 'to' is deprecated since 5.2. */
4549 116 : m = gfc_match_omp_to_link ("to (", &c->lists[OMP_LIST_TO]);
4550 116 : if (m == MATCH_ERROR)
4551 0 : goto error;
4552 116 : if (m == MATCH_YES)
4553 : {
4554 116 : gfc_warning (OPT_Wdeprecated_openmp,
4555 : "%<to%> clause with %<declare target%> at %L "
4556 : "deprecated since OpenMP 5.2, use %<enter%>",
4557 : &old_loc);
4558 116 : continue;
4559 : }
4560 : }
4561 1487 : else if ((mask & OMP_CLAUSE_TO)
4562 759 : && gfc_match_motion_var_list ("to (", &c->lists[OMP_LIST_TO],
4563 : &head) == MATCH_YES)
4564 728 : continue;
4565 : break;
4566 1538 : case 'u':
4567 1596 : if ((mask & OMP_CLAUSE_UNIFORM)
4568 1538 : && gfc_match_omp_variable_list ("uniform (",
4569 : &c->lists[OMP_LIST_UNIFORM],
4570 : false) == MATCH_YES)
4571 58 : continue;
4572 1621 : if ((mask & OMP_CLAUSE_UNTIED)
4573 1480 : && (m = gfc_match_dupl_check (!c->untied, "untied")) != MATCH_NO)
4574 : {
4575 141 : if (m == MATCH_ERROR)
4576 0 : goto error;
4577 141 : c->untied = true;
4578 141 : continue;
4579 : }
4580 1583 : if ((mask & OMP_CLAUSE_ATOMIC)
4581 1339 : && (m = gfc_match_dupl_atomic ((c->atomic_op
4582 : == GFC_OMP_ATOMIC_UNSET),
4583 : "update")) != MATCH_NO)
4584 : {
4585 245 : if (m == MATCH_ERROR)
4586 1 : goto error;
4587 244 : c->atomic_op = GFC_OMP_ATOMIC_UPDATE;
4588 244 : continue;
4589 : }
4590 1116 : if ((mask & OMP_CLAUSE_USE)
4591 1094 : && gfc_match_omp_variable_list ("use (",
4592 : &c->lists[OMP_LIST_USE],
4593 : true) == MATCH_YES)
4594 22 : continue;
4595 1132 : if ((mask & OMP_CLAUSE_USE_DEVICE)
4596 1072 : && gfc_match_omp_variable_list ("use_device (",
4597 : &c->lists[OMP_LIST_USE_DEVICE],
4598 : true) == MATCH_YES)
4599 60 : continue;
4600 1175 : if ((mask & OMP_CLAUSE_USE_DEVICE_PTR)
4601 1940 : && gfc_match_omp_variable_list
4602 928 : ("use_device_ptr (",
4603 : &c->lists[OMP_LIST_USE_DEVICE_PTR], false) == MATCH_YES)
4604 163 : continue;
4605 1614 : if ((mask & OMP_CLAUSE_USE_DEVICE_ADDR)
4606 1614 : && gfc_match_omp_variable_list
4607 765 : ("use_device_addr (", &c->lists[OMP_LIST_USE_DEVICE_ADDR],
4608 : false, NULL, NULL, true) == MATCH_YES)
4609 765 : continue;
4610 153 : if ((mask & OMP_CLAUSE_USES_ALLOCATORS)
4611 84 : && (gfc_match ("uses_allocators ( ") == MATCH_YES))
4612 : {
4613 78 : if (gfc_match_omp_clause_uses_allocators (c) != MATCH_YES)
4614 9 : goto error;
4615 69 : continue;
4616 : }
4617 : break;
4618 1570 : case 'v':
4619 : /* VECTOR_LENGTH must be matched before VECTOR, because the latter
4620 : doesn't unconditionally match '('. */
4621 2139 : if ((mask & OMP_CLAUSE_VECTOR_LENGTH)
4622 1570 : && (m = gfc_match_dupl_check (!c->vector_length_expr,
4623 : "vector_length", true,
4624 : &c->vector_length_expr))
4625 : != MATCH_NO)
4626 : {
4627 573 : if (m == MATCH_ERROR)
4628 4 : goto error;
4629 569 : continue;
4630 : }
4631 1989 : if ((mask & OMP_CLAUSE_VECTOR)
4632 997 : && (m = gfc_match_dupl_check (!c->vector, "vector")) != MATCH_NO)
4633 : {
4634 995 : if (m == MATCH_ERROR)
4635 0 : goto error;
4636 995 : c->vector = true;
4637 995 : m = match_oacc_clause_gwv (c, GOMP_DIM_VECTOR);
4638 995 : if (m == MATCH_ERROR)
4639 3 : goto error;
4640 992 : continue;
4641 : }
4642 : break;
4643 1482 : case 'w':
4644 1482 : if ((mask & OMP_CLAUSE_WAIT)
4645 1482 : && gfc_match ("wait") == MATCH_YES)
4646 : {
4647 192 : m = match_omp_oacc_expr_list (" (", &c->wait_list, false, false);
4648 192 : if (m == MATCH_ERROR)
4649 9 : goto error;
4650 183 : else if (m == MATCH_NO)
4651 : {
4652 47 : gfc_expr *expr
4653 47 : = gfc_get_constant_expr (BT_INTEGER,
4654 : gfc_default_integer_kind,
4655 : &gfc_current_locus);
4656 47 : mpz_set_si (expr->value.integer, GOMP_ASYNC_NOVAL);
4657 47 : gfc_expr_list **expr_list = &c->wait_list;
4658 56 : while (*expr_list)
4659 9 : expr_list = &(*expr_list)->next;
4660 47 : *expr_list = gfc_get_expr_list ();
4661 47 : (*expr_list)->expr = expr;
4662 47 : needs_space = true;
4663 : }
4664 183 : continue;
4665 183 : }
4666 1303 : if ((mask & OMP_CLAUSE_WEAK)
4667 1290 : && (m = gfc_match_dupl_check (!c->weak, "weak"))
4668 : != MATCH_NO)
4669 : {
4670 14 : if (m == MATCH_ERROR)
4671 1 : goto error;
4672 13 : c->weak = true;
4673 13 : continue;
4674 : }
4675 2137 : if ((mask & OMP_CLAUSE_WORKER)
4676 1276 : && (m = gfc_match_dupl_check (!c->worker, "worker")) != MATCH_NO)
4677 : {
4678 864 : if (m == MATCH_ERROR)
4679 0 : goto error;
4680 864 : c->worker = true;
4681 864 : m = match_oacc_clause_gwv (c, GOMP_DIM_WORKER);
4682 864 : if (m == MATCH_ERROR)
4683 3 : goto error;
4684 861 : continue;
4685 : }
4686 824 : if ((mask & OMP_CLAUSE_ATOMIC)
4687 412 : && (m = gfc_match_dupl_atomic ((c->atomic_op
4688 : == GFC_OMP_ATOMIC_UNSET),
4689 : "write")) != MATCH_NO)
4690 : {
4691 412 : if (m == MATCH_ERROR)
4692 0 : goto error;
4693 412 : c->atomic_op = GFC_OMP_ATOMIC_WRITE;
4694 412 : continue;
4695 : }
4696 : break;
4697 : }
4698 : break;
4699 46244 : }
4700 :
4701 34557 : end:
4702 34297 : if (error || gfc_match_omp_eos () != MATCH_YES)
4703 : {
4704 537 : if (!gfc_error_flag_test ())
4705 137 : gfc_error ("Failed to match clause at %C");
4706 537 : gfc_free_omp_clauses (c);
4707 537 : return MATCH_ERROR;
4708 : }
4709 :
4710 34020 : *cp = c;
4711 34020 : return MATCH_YES;
4712 :
4713 260 : error:
4714 260 : error = true;
4715 260 : goto end;
4716 : }
4717 :
4718 :
4719 : #define OACC_PARALLEL_CLAUSES \
4720 : (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_NUM_GANGS \
4721 : | OMP_CLAUSE_NUM_WORKERS | OMP_CLAUSE_VECTOR_LENGTH | OMP_CLAUSE_REDUCTION \
4722 : | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT \
4723 : | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT \
4724 : | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE \
4725 : | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH \
4726 : | OMP_CLAUSE_SELF)
4727 : #define OACC_KERNELS_CLAUSES \
4728 : (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_NUM_GANGS \
4729 : | OMP_CLAUSE_NUM_WORKERS | OMP_CLAUSE_VECTOR_LENGTH | OMP_CLAUSE_DEVICEPTR \
4730 : | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT \
4731 : | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT \
4732 : | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH \
4733 : | OMP_CLAUSE_SELF)
4734 : #define OACC_SERIAL_CLAUSES \
4735 : (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_REDUCTION \
4736 : | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT \
4737 : | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT \
4738 : | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE \
4739 : | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH \
4740 : | OMP_CLAUSE_SELF)
4741 : #define OACC_DATA_CLAUSES \
4742 : (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_COPY \
4743 : | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_CREATE \
4744 : | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT | OMP_CLAUSE_ATTACH \
4745 : | OMP_CLAUSE_DEFAULT)
4746 : #define OACC_LOOP_CLAUSES \
4747 : (omp_mask (OMP_CLAUSE_COLLAPSE) | OMP_CLAUSE_GANG | OMP_CLAUSE_WORKER \
4748 : | OMP_CLAUSE_VECTOR | OMP_CLAUSE_SEQ | OMP_CLAUSE_INDEPENDENT \
4749 : | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_AUTO \
4750 : | OMP_CLAUSE_TILE)
4751 : #define OACC_PARALLEL_LOOP_CLAUSES \
4752 : (OACC_LOOP_CLAUSES | OACC_PARALLEL_CLAUSES)
4753 : #define OACC_KERNELS_LOOP_CLAUSES \
4754 : (OACC_LOOP_CLAUSES | OACC_KERNELS_CLAUSES)
4755 : #define OACC_SERIAL_LOOP_CLAUSES \
4756 : (OACC_LOOP_CLAUSES | OACC_SERIAL_CLAUSES)
4757 : #define OACC_HOST_DATA_CLAUSES \
4758 : (omp_mask (OMP_CLAUSE_USE_DEVICE) \
4759 : | OMP_CLAUSE_IF \
4760 : | OMP_CLAUSE_IF_PRESENT)
4761 : #define OACC_DECLARE_CLAUSES \
4762 : (omp_mask (OMP_CLAUSE_COPY) | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT \
4763 : | OMP_CLAUSE_CREATE | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_DEVICE_RESIDENT \
4764 : | OMP_CLAUSE_PRESENT \
4765 : | OMP_CLAUSE_LINK)
4766 : #define OACC_UPDATE_CLAUSES \
4767 : (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_HOST \
4768 : | OMP_CLAUSE_DEVICE | OMP_CLAUSE_WAIT | OMP_CLAUSE_IF_PRESENT \
4769 : | OMP_CLAUSE_SELF)
4770 : #define OACC_ENTER_DATA_CLAUSES \
4771 : (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_WAIT \
4772 : | OMP_CLAUSE_COPYIN | OMP_CLAUSE_CREATE | OMP_CLAUSE_ATTACH)
4773 : #define OACC_EXIT_DATA_CLAUSES \
4774 : (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_WAIT \
4775 : | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_DELETE | OMP_CLAUSE_FINALIZE \
4776 : | OMP_CLAUSE_DETACH)
4777 : #define OACC_WAIT_CLAUSES \
4778 : omp_mask (OMP_CLAUSE_ASYNC) | OMP_CLAUSE_IF
4779 : #define OACC_ROUTINE_CLAUSES \
4780 : (omp_mask (OMP_CLAUSE_GANG) | OMP_CLAUSE_WORKER | OMP_CLAUSE_VECTOR \
4781 : | OMP_CLAUSE_SEQ \
4782 : | OMP_CLAUSE_NOHOST)
4783 :
4784 :
4785 : static match
4786 11804 : match_acc (gfc_exec_op op, const omp_mask mask)
4787 : {
4788 11804 : gfc_omp_clauses *c;
4789 11804 : if (gfc_match_omp_clauses (&c, mask, false, false, true) != MATCH_YES)
4790 : return MATCH_ERROR;
4791 11599 : new_st.op = op;
4792 11599 : new_st.ext.omp_clauses = c;
4793 11599 : return MATCH_YES;
4794 : }
4795 :
4796 : match
4797 1378 : gfc_match_oacc_parallel_loop (void)
4798 : {
4799 1378 : return match_acc (EXEC_OACC_PARALLEL_LOOP, OACC_PARALLEL_LOOP_CLAUSES);
4800 : }
4801 :
4802 :
4803 : match
4804 2974 : gfc_match_oacc_parallel (void)
4805 : {
4806 2974 : return match_acc (EXEC_OACC_PARALLEL, OACC_PARALLEL_CLAUSES);
4807 : }
4808 :
4809 :
4810 : match
4811 129 : gfc_match_oacc_kernels_loop (void)
4812 : {
4813 129 : return match_acc (EXEC_OACC_KERNELS_LOOP, OACC_KERNELS_LOOP_CLAUSES);
4814 : }
4815 :
4816 :
4817 : match
4818 906 : gfc_match_oacc_kernels (void)
4819 : {
4820 906 : return match_acc (EXEC_OACC_KERNELS, OACC_KERNELS_CLAUSES);
4821 : }
4822 :
4823 :
4824 : match
4825 230 : gfc_match_oacc_serial_loop (void)
4826 : {
4827 230 : return match_acc (EXEC_OACC_SERIAL_LOOP, OACC_SERIAL_LOOP_CLAUSES);
4828 : }
4829 :
4830 :
4831 : match
4832 359 : gfc_match_oacc_serial (void)
4833 : {
4834 359 : return match_acc (EXEC_OACC_SERIAL, OACC_SERIAL_CLAUSES);
4835 : }
4836 :
4837 :
4838 : match
4839 689 : gfc_match_oacc_data (void)
4840 : {
4841 689 : return match_acc (EXEC_OACC_DATA, OACC_DATA_CLAUSES);
4842 : }
4843 :
4844 :
4845 : match
4846 65 : gfc_match_oacc_host_data (void)
4847 : {
4848 65 : return match_acc (EXEC_OACC_HOST_DATA, OACC_HOST_DATA_CLAUSES);
4849 : }
4850 :
4851 :
4852 : match
4853 3585 : gfc_match_oacc_loop (void)
4854 : {
4855 3585 : return match_acc (EXEC_OACC_LOOP, OACC_LOOP_CLAUSES);
4856 : }
4857 :
4858 :
4859 : match
4860 178 : gfc_match_oacc_declare (void)
4861 : {
4862 178 : gfc_omp_clauses *c;
4863 178 : gfc_omp_namelist *n;
4864 178 : gfc_namespace *ns = gfc_current_ns;
4865 178 : gfc_oacc_declare *new_oc;
4866 178 : bool module_var = false;
4867 178 : locus where = gfc_current_locus;
4868 :
4869 178 : if (gfc_match_omp_clauses (&c, OACC_DECLARE_CLAUSES, false, false, true)
4870 : != MATCH_YES)
4871 : return MATCH_ERROR;
4872 :
4873 262 : for (n = c->lists[OMP_LIST_DEVICE_RESIDENT]; n != NULL; n = n->next)
4874 90 : n->sym->attr.oacc_declare_device_resident = 1;
4875 :
4876 192 : for (n = c->lists[OMP_LIST_LINK]; n != NULL; n = n->next)
4877 20 : n->sym->attr.oacc_declare_link = 1;
4878 :
4879 318 : for (n = c->lists[OMP_LIST_MAP]; n != NULL; n = n->next)
4880 : {
4881 156 : gfc_symbol *s = n->sym;
4882 :
4883 156 : if (gfc_current_ns->proc_name
4884 156 : && gfc_current_ns->proc_name->attr.flavor == FL_MODULE)
4885 : {
4886 52 : if (n->u.map.op != OMP_MAP_ALLOC && n->u.map.op != OMP_MAP_TO)
4887 : {
4888 6 : gfc_error ("Invalid clause in module with !$ACC DECLARE at %L",
4889 : &where);
4890 6 : return MATCH_ERROR;
4891 : }
4892 :
4893 : module_var = true;
4894 : }
4895 :
4896 150 : if (s->attr.use_assoc)
4897 : {
4898 0 : gfc_error ("Variable is USE-associated with !$ACC DECLARE at %L",
4899 : &where);
4900 0 : return MATCH_ERROR;
4901 : }
4902 :
4903 150 : if ((s->result == s && s->ns->contained != gfc_current_ns)
4904 150 : || ((s->attr.flavor == FL_UNKNOWN || s->attr.flavor == FL_VARIABLE)
4905 135 : && s->ns != gfc_current_ns))
4906 : {
4907 2 : gfc_error ("Variable %qs shall be declared in the same scoping unit "
4908 : "as !$ACC DECLARE at %L", s->name, &where);
4909 2 : return MATCH_ERROR;
4910 : }
4911 :
4912 148 : if ((s->attr.dimension || s->attr.codimension)
4913 76 : && s->attr.dummy && s->as->type != AS_EXPLICIT)
4914 : {
4915 2 : gfc_error ("Assumed-size dummy array with !$ACC DECLARE at %L",
4916 : &where);
4917 2 : return MATCH_ERROR;
4918 : }
4919 :
4920 146 : switch (n->u.map.op)
4921 : {
4922 49 : case OMP_MAP_FORCE_ALLOC:
4923 49 : case OMP_MAP_ALLOC:
4924 49 : s->attr.oacc_declare_create = 1;
4925 49 : break;
4926 :
4927 63 : case OMP_MAP_FORCE_TO:
4928 63 : case OMP_MAP_TO:
4929 63 : s->attr.oacc_declare_copyin = 1;
4930 63 : break;
4931 :
4932 1 : case OMP_MAP_FORCE_DEVICEPTR:
4933 1 : s->attr.oacc_declare_deviceptr = 1;
4934 1 : break;
4935 :
4936 : default:
4937 : break;
4938 : }
4939 : }
4940 :
4941 162 : new_oc = gfc_get_oacc_declare ();
4942 162 : new_oc->next = ns->oacc_declare;
4943 162 : new_oc->module_var = module_var;
4944 162 : new_oc->clauses = c;
4945 162 : new_oc->loc = gfc_current_locus;
4946 162 : ns->oacc_declare = new_oc;
4947 :
4948 162 : return MATCH_YES;
4949 : }
4950 :
4951 :
4952 : match
4953 760 : gfc_match_oacc_update (void)
4954 : {
4955 760 : gfc_omp_clauses *c;
4956 760 : locus here = gfc_current_locus;
4957 :
4958 760 : if (gfc_match_omp_clauses (&c, OACC_UPDATE_CLAUSES, false, false, true)
4959 : != MATCH_YES)
4960 : return MATCH_ERROR;
4961 :
4962 756 : if (!c->lists[OMP_LIST_MAP])
4963 : {
4964 1 : gfc_error ("%<acc update%> must contain at least one "
4965 : "%<device%> or %<host%> or %<self%> clause at %L", &here);
4966 1 : return MATCH_ERROR;
4967 : }
4968 :
4969 755 : new_st.op = EXEC_OACC_UPDATE;
4970 755 : new_st.ext.omp_clauses = c;
4971 755 : return MATCH_YES;
4972 : }
4973 :
4974 :
4975 : match
4976 877 : gfc_match_oacc_enter_data (void)
4977 : {
4978 877 : return match_acc (EXEC_OACC_ENTER_DATA, OACC_ENTER_DATA_CLAUSES);
4979 : }
4980 :
4981 :
4982 : match
4983 612 : gfc_match_oacc_exit_data (void)
4984 : {
4985 612 : return match_acc (EXEC_OACC_EXIT_DATA, OACC_EXIT_DATA_CLAUSES);
4986 : }
4987 :
4988 :
4989 : match
4990 202 : gfc_match_oacc_wait (void)
4991 : {
4992 202 : gfc_omp_clauses *c = gfc_get_omp_clauses ();
4993 202 : gfc_expr_list *wait_list = NULL, *el;
4994 202 : bool space = true;
4995 202 : match m;
4996 :
4997 202 : m = match_omp_oacc_expr_list (" (", &wait_list, true, false);
4998 202 : if (m == MATCH_ERROR)
4999 : return m;
5000 196 : else if (m == MATCH_YES)
5001 126 : space = false;
5002 :
5003 196 : if (gfc_match_omp_clauses (&c, OACC_WAIT_CLAUSES, space, space, true)
5004 : == MATCH_ERROR)
5005 : return MATCH_ERROR;
5006 :
5007 184 : if (wait_list)
5008 261 : for (el = wait_list; el; el = el->next)
5009 : {
5010 140 : if (el->expr == NULL)
5011 : {
5012 2 : gfc_error ("Invalid argument to !$ACC WAIT at %C");
5013 2 : return MATCH_ERROR;
5014 : }
5015 :
5016 138 : if (!gfc_resolve_expr (el->expr)
5017 138 : || el->expr->ts.type != BT_INTEGER || el->expr->rank != 0)
5018 : {
5019 3 : gfc_error ("WAIT clause at %L requires a scalar INTEGER expression",
5020 3 : &el->expr->where);
5021 :
5022 3 : return MATCH_ERROR;
5023 : }
5024 : }
5025 179 : c->wait_list = wait_list;
5026 179 : new_st.op = EXEC_OACC_WAIT;
5027 179 : new_st.ext.omp_clauses = c;
5028 179 : return MATCH_YES;
5029 : }
5030 :
5031 :
5032 : match
5033 97 : gfc_match_oacc_cache (void)
5034 : {
5035 97 : bool readonly = false;
5036 97 : gfc_omp_clauses *c = gfc_get_omp_clauses ();
5037 : /* The OpenACC cache directive explicitly only allows "array elements or
5038 : subarrays", which we're currently not checking here. Either check this
5039 : after the call of gfc_match_omp_variable_list, or add something like a
5040 : only_sections variant next to its allow_sections parameter. */
5041 97 : match m = gfc_match (" ( ");
5042 97 : if (m != MATCH_YES)
5043 : {
5044 0 : gfc_free_omp_clauses(c);
5045 0 : return m;
5046 : }
5047 :
5048 97 : if (gfc_match ("readonly : ") == MATCH_YES)
5049 8 : readonly = true;
5050 :
5051 97 : gfc_omp_namelist **head = NULL;
5052 97 : m = gfc_match_omp_variable_list ("", &c->lists[OMP_LIST_CACHE], true,
5053 : NULL, &head, true);
5054 97 : if (m != MATCH_YES)
5055 : {
5056 2 : gfc_free_omp_clauses(c);
5057 2 : return m;
5058 : }
5059 :
5060 95 : if (readonly)
5061 24 : for (gfc_omp_namelist *n = *head; n; n = n->next)
5062 16 : n->u.map.readonly = true;
5063 :
5064 95 : if (gfc_current_state() != COMP_DO
5065 56 : && gfc_current_state() != COMP_DO_CONCURRENT)
5066 : {
5067 2 : gfc_error ("ACC CACHE directive must be inside of loop %C");
5068 2 : gfc_free_omp_clauses(c);
5069 2 : return MATCH_ERROR;
5070 : }
5071 :
5072 93 : new_st.op = EXEC_OACC_CACHE;
5073 93 : new_st.ext.omp_clauses = c;
5074 93 : return MATCH_YES;
5075 : }
5076 :
5077 : /* Determine the OpenACC 'routine' directive's level of parallelism. */
5078 :
5079 : static oacc_routine_lop
5080 734 : gfc_oacc_routine_lop (gfc_omp_clauses *clauses)
5081 : {
5082 734 : oacc_routine_lop ret = OACC_ROUTINE_LOP_SEQ;
5083 :
5084 734 : if (clauses)
5085 : {
5086 584 : unsigned n_lop_clauses = 0;
5087 :
5088 584 : if (clauses->gang)
5089 : {
5090 164 : ++n_lop_clauses;
5091 164 : ret = OACC_ROUTINE_LOP_GANG;
5092 : }
5093 584 : if (clauses->worker)
5094 : {
5095 114 : ++n_lop_clauses;
5096 114 : ret = OACC_ROUTINE_LOP_WORKER;
5097 : }
5098 584 : if (clauses->vector)
5099 : {
5100 116 : ++n_lop_clauses;
5101 116 : ret = OACC_ROUTINE_LOP_VECTOR;
5102 : }
5103 584 : if (clauses->seq)
5104 : {
5105 206 : ++n_lop_clauses;
5106 206 : ret = OACC_ROUTINE_LOP_SEQ;
5107 : }
5108 :
5109 584 : if (n_lop_clauses > 1)
5110 47 : ret = OACC_ROUTINE_LOP_ERROR;
5111 : }
5112 :
5113 734 : return ret;
5114 : }
5115 :
5116 : match
5117 698 : gfc_match_oacc_routine (void)
5118 : {
5119 698 : locus old_loc;
5120 698 : match m;
5121 698 : gfc_intrinsic_sym *isym = NULL;
5122 698 : gfc_symbol *sym = NULL;
5123 698 : gfc_omp_clauses *c = NULL;
5124 698 : gfc_oacc_routine_name *n = NULL;
5125 698 : oacc_routine_lop lop = OACC_ROUTINE_LOP_NONE;
5126 698 : bool nohost;
5127 :
5128 698 : old_loc = gfc_current_locus;
5129 :
5130 698 : m = gfc_match (" (");
5131 :
5132 698 : if (gfc_current_ns->proc_name
5133 696 : && gfc_current_ns->proc_name->attr.if_source == IFSRC_IFBODY
5134 90 : && m == MATCH_YES)
5135 : {
5136 3 : gfc_error ("Only the !$ACC ROUTINE form without "
5137 : "list is allowed in interface block at %C");
5138 3 : goto cleanup;
5139 : }
5140 :
5141 608 : if (m == MATCH_YES)
5142 : {
5143 295 : char buffer[GFC_MAX_SYMBOL_LEN + 1];
5144 :
5145 295 : m = gfc_match_name (buffer);
5146 295 : if (m == MATCH_YES)
5147 : {
5148 294 : gfc_symtree *st = NULL;
5149 :
5150 : /* First look for an intrinsic symbol. */
5151 294 : isym = gfc_find_function (buffer);
5152 294 : if (!isym)
5153 294 : isym = gfc_find_subroutine (buffer);
5154 : /* If no intrinsic symbol found, search the current namespace. */
5155 294 : if (!isym)
5156 276 : st = gfc_find_symtree (gfc_current_ns->sym_root, buffer);
5157 276 : if (st)
5158 : {
5159 270 : sym = st->n.sym;
5160 : /* If the name in a 'routine' directive refers to the containing
5161 : subroutine or function, then make sure that we'll later handle
5162 : this accordingly. */
5163 270 : if (gfc_current_ns->proc_name != NULL
5164 270 : && strcmp (sym->name, gfc_current_ns->proc_name->name) == 0)
5165 294 : sym = NULL;
5166 : }
5167 :
5168 294 : if (isym == NULL && st == NULL)
5169 : {
5170 6 : gfc_error ("Invalid NAME %qs in !$ACC ROUTINE ( NAME ) at %C",
5171 : buffer);
5172 6 : gfc_current_locus = old_loc;
5173 9 : return MATCH_ERROR;
5174 : }
5175 : }
5176 : else
5177 : {
5178 1 : gfc_error ("Syntax error in !$ACC ROUTINE ( NAME ) at %C");
5179 1 : gfc_current_locus = old_loc;
5180 1 : return MATCH_ERROR;
5181 : }
5182 :
5183 288 : if (gfc_match_char (')') != MATCH_YES)
5184 : {
5185 2 : gfc_error ("Syntax error in !$ACC ROUTINE ( NAME ) at %C, expecting"
5186 : " %<)%> after NAME");
5187 2 : gfc_current_locus = old_loc;
5188 2 : return MATCH_ERROR;
5189 : }
5190 : }
5191 :
5192 686 : if (gfc_match_omp_eos () != MATCH_YES
5193 686 : && (gfc_match_omp_clauses (&c, OACC_ROUTINE_CLAUSES, false, false, true)
5194 : != MATCH_YES))
5195 : return MATCH_ERROR;
5196 :
5197 683 : lop = gfc_oacc_routine_lop (c);
5198 683 : if (lop == OACC_ROUTINE_LOP_ERROR)
5199 : {
5200 47 : gfc_error ("Multiple loop axes specified for routine at %C");
5201 47 : goto cleanup;
5202 : }
5203 636 : nohost = c ? c->nohost : false;
5204 :
5205 636 : if (isym != NULL)
5206 : {
5207 : /* Diagnose any OpenACC 'routine' directive that doesn't match the
5208 : (implicit) one with a 'seq' clause. */
5209 16 : if (c && (c->gang || c->worker || c->vector))
5210 : {
5211 10 : gfc_error ("Intrinsic symbol specified in !$ACC ROUTINE ( NAME )"
5212 : " at %C marked with incompatible GANG, WORKER, or VECTOR"
5213 : " clause");
5214 10 : goto cleanup;
5215 : }
5216 : /* ..., and no 'nohost' clause. */
5217 6 : if (nohost)
5218 : {
5219 2 : gfc_error ("Intrinsic symbol specified in !$ACC ROUTINE ( NAME )"
5220 : " at %C marked with incompatible NOHOST clause");
5221 2 : goto cleanup;
5222 : }
5223 : }
5224 620 : else if (sym != NULL)
5225 : {
5226 151 : bool add = true;
5227 :
5228 : /* For a repeated OpenACC 'routine' directive, diagnose if it doesn't
5229 : match the first one. */
5230 151 : for (gfc_oacc_routine_name *n_p = gfc_current_ns->oacc_routine_names;
5231 346 : n_p;
5232 195 : n_p = n_p->next)
5233 235 : if (n_p->sym == sym)
5234 : {
5235 51 : add = false;
5236 51 : bool nohost_p = n_p->clauses ? n_p->clauses->nohost : false;
5237 51 : if (lop != gfc_oacc_routine_lop (n_p->clauses)
5238 51 : || nohost != nohost_p)
5239 : {
5240 40 : gfc_error ("!$ACC ROUTINE already applied at %C");
5241 40 : goto cleanup;
5242 : }
5243 : }
5244 :
5245 111 : if (add)
5246 : {
5247 100 : sym->attr.oacc_routine_lop = lop;
5248 100 : sym->attr.oacc_routine_nohost = nohost;
5249 :
5250 100 : n = gfc_get_oacc_routine_name ();
5251 100 : n->sym = sym;
5252 100 : n->clauses = c;
5253 100 : n->next = gfc_current_ns->oacc_routine_names;
5254 100 : n->loc = old_loc;
5255 100 : gfc_current_ns->oacc_routine_names = n;
5256 : }
5257 : }
5258 469 : else if (gfc_current_ns->proc_name)
5259 : {
5260 : /* For a repeated OpenACC 'routine' directive, diagnose if it doesn't
5261 : match the first one. */
5262 468 : oacc_routine_lop lop_p = gfc_current_ns->proc_name->attr.oacc_routine_lop;
5263 468 : bool nohost_p = gfc_current_ns->proc_name->attr.oacc_routine_nohost;
5264 468 : if (lop_p != OACC_ROUTINE_LOP_NONE
5265 86 : && (lop != lop_p
5266 86 : || nohost != nohost_p))
5267 : {
5268 56 : gfc_error ("!$ACC ROUTINE already applied at %C");
5269 56 : goto cleanup;
5270 : }
5271 :
5272 412 : if (!gfc_add_omp_declare_target (&gfc_current_ns->proc_name->attr,
5273 : gfc_current_ns->proc_name->name,
5274 : &old_loc))
5275 1 : goto cleanup;
5276 411 : gfc_current_ns->proc_name->attr.oacc_routine_lop = lop;
5277 411 : gfc_current_ns->proc_name->attr.oacc_routine_nohost = nohost;
5278 : }
5279 : else
5280 : /* Something has gone wrong, possibly a syntax error. */
5281 1 : goto cleanup;
5282 :
5283 526 : if (gfc_pure (NULL) && c && (c->gang || c->worker || c->vector))
5284 : {
5285 6 : gfc_error ("!$ACC ROUTINE with GANG, WORKER, or VECTOR clause is not "
5286 : "permitted in PURE procedure at %C");
5287 6 : goto cleanup;
5288 : }
5289 :
5290 :
5291 520 : if (n)
5292 100 : n->clauses = c;
5293 420 : else if (gfc_current_ns->oacc_routine)
5294 0 : gfc_current_ns->oacc_routine_clauses = c;
5295 :
5296 520 : new_st.op = EXEC_OACC_ROUTINE;
5297 520 : new_st.ext.omp_clauses = c;
5298 520 : return MATCH_YES;
5299 :
5300 166 : cleanup:
5301 166 : gfc_current_locus = old_loc;
5302 166 : return MATCH_ERROR;
5303 : }
5304 :
5305 :
5306 : #define OMP_PARALLEL_CLAUSES \
5307 : (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
5308 : | OMP_CLAUSE_SHARED | OMP_CLAUSE_COPYIN | OMP_CLAUSE_REDUCTION \
5309 : | OMP_CLAUSE_IF | OMP_CLAUSE_NUM_THREADS | OMP_CLAUSE_DEFAULT \
5310 : | OMP_CLAUSE_PROC_BIND | OMP_CLAUSE_ALLOCATE)
5311 : #define OMP_DECLARE_SIMD_CLAUSES \
5312 : (omp_mask (OMP_CLAUSE_SIMDLEN) | OMP_CLAUSE_LINEAR \
5313 : | OMP_CLAUSE_UNIFORM | OMP_CLAUSE_ALIGNED | OMP_CLAUSE_INBRANCH \
5314 : | OMP_CLAUSE_NOTINBRANCH)
5315 : #define OMP_DO_CLAUSES \
5316 : (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
5317 : | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION \
5318 : | OMP_CLAUSE_SCHEDULE | OMP_CLAUSE_ORDERED | OMP_CLAUSE_COLLAPSE \
5319 : | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ORDER | OMP_CLAUSE_ALLOCATE \
5320 : | OMP_CLAUSE_NOWAIT)
5321 : #define OMP_LOOP_CLAUSES \
5322 : (omp_mask (OMP_CLAUSE_BIND) | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_ORDER \
5323 : | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION)
5324 :
5325 : #define OMP_SCOPE_CLAUSES \
5326 : (omp_mask (OMP_CLAUSE_PRIVATE) |OMP_CLAUSE_FIRSTPRIVATE \
5327 : | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT)
5328 : #define OMP_SECTIONS_CLAUSES \
5329 : (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
5330 : | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION \
5331 : | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT)
5332 : #define OMP_SIMD_CLAUSES \
5333 : (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_LASTPRIVATE \
5334 : | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_SAFELEN \
5335 : | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ALIGNED | OMP_CLAUSE_SIMDLEN \
5336 : | OMP_CLAUSE_IF | OMP_CLAUSE_ORDER | OMP_CLAUSE_NOTEMPORAL)
5337 : #define OMP_TASK_CLAUSES \
5338 : (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
5339 : | OMP_CLAUSE_SHARED | OMP_CLAUSE_IF | OMP_CLAUSE_DEFAULT \
5340 : | OMP_CLAUSE_UNTIED | OMP_CLAUSE_FINAL | OMP_CLAUSE_MERGEABLE \
5341 : | OMP_CLAUSE_DEPEND | OMP_CLAUSE_PRIORITY | OMP_CLAUSE_IN_REDUCTION \
5342 : | OMP_CLAUSE_DETACH | OMP_CLAUSE_AFFINITY | OMP_CLAUSE_ALLOCATE)
5343 : #define OMP_TASKLOOP_CLAUSES \
5344 : (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
5345 : | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_IF \
5346 : | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_UNTIED | OMP_CLAUSE_FINAL \
5347 : | OMP_CLAUSE_MERGEABLE | OMP_CLAUSE_PRIORITY | OMP_CLAUSE_GRAINSIZE \
5348 : | OMP_CLAUSE_NUM_TASKS | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_NOGROUP \
5349 : | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_IN_REDUCTION | OMP_CLAUSE_ALLOCATE)
5350 : #define OMP_TASKGROUP_CLAUSES \
5351 : (omp_mask (OMP_CLAUSE_TASK_REDUCTION) | OMP_CLAUSE_ALLOCATE)
5352 : #define OMP_TARGET_CLAUSES \
5353 : (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF \
5354 : | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_PRIVATE \
5355 : | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_DEFAULTMAP \
5356 : | OMP_CLAUSE_IS_DEVICE_PTR | OMP_CLAUSE_IN_REDUCTION \
5357 : | OMP_CLAUSE_THREAD_LIMIT | OMP_CLAUSE_ALLOCATE \
5358 : | OMP_CLAUSE_HAS_DEVICE_ADDR | OMP_CLAUSE_USES_ALLOCATORS \
5359 : | OMP_CLAUSE_DYN_GROUPPRIVATE | OMP_CLAUSE_DEVICE_TYPE)
5360 : #define OMP_TARGET_DATA_CLAUSES \
5361 : (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF \
5362 : | OMP_CLAUSE_USE_DEVICE_PTR | OMP_CLAUSE_USE_DEVICE_ADDR)
5363 : #define OMP_TARGET_ENTER_DATA_CLAUSES \
5364 : (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF \
5365 : | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT)
5366 : #define OMP_TARGET_EXIT_DATA_CLAUSES \
5367 : (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF \
5368 : | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT)
5369 : #define OMP_TARGET_UPDATE_CLAUSES \
5370 : (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_IF | OMP_CLAUSE_TO \
5371 : | OMP_CLAUSE_FROM | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT)
5372 : #define OMP_TEAMS_CLAUSES \
5373 : (omp_mask (OMP_CLAUSE_NUM_TEAMS) | OMP_CLAUSE_THREAD_LIMIT \
5374 : | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE \
5375 : | OMP_CLAUSE_SHARED | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_ALLOCATE)
5376 : #define OMP_DISTRIBUTE_CLAUSES \
5377 : (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
5378 : | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_DIST_SCHEDULE \
5379 : | OMP_CLAUSE_ORDER | OMP_CLAUSE_ALLOCATE)
5380 : #define OMP_SINGLE_CLAUSES \
5381 : (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
5382 : | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_COPYPRIVATE)
5383 : #define OMP_ORDERED_CLAUSES \
5384 : (omp_mask (OMP_CLAUSE_THREADS) | OMP_CLAUSE_SIMD)
5385 : #define OMP_DECLARE_TARGET_CLAUSES \
5386 : (omp_mask (OMP_CLAUSE_ENTER) | OMP_CLAUSE_LINK | OMP_CLAUSE_DEVICE_TYPE \
5387 : | OMP_CLAUSE_TO | OMP_CLAUSE_INDIRECT | OMP_CLAUSE_LOCAL)
5388 : #define OMP_ATOMIC_CLAUSES \
5389 : (omp_mask (OMP_CLAUSE_ATOMIC) | OMP_CLAUSE_CAPTURE | OMP_CLAUSE_HINT \
5390 : | OMP_CLAUSE_MEMORDER | OMP_CLAUSE_COMPARE | OMP_CLAUSE_FAIL \
5391 : | OMP_CLAUSE_WEAK)
5392 : #define OMP_MASKED_CLAUSES \
5393 : (omp_mask (OMP_CLAUSE_FILTER))
5394 : #define OMP_ERROR_CLAUSES \
5395 : (omp_mask (OMP_CLAUSE_AT) | OMP_CLAUSE_MESSAGE | OMP_CLAUSE_SEVERITY)
5396 : #define OMP_WORKSHARE_CLAUSES \
5397 : omp_mask (OMP_CLAUSE_NOWAIT)
5398 : #define OMP_UNROLL_CLAUSES \
5399 : (omp_mask (OMP_CLAUSE_FULL) | OMP_CLAUSE_PARTIAL)
5400 : #define OMP_TILE_CLAUSES \
5401 : (omp_mask (OMP_CLAUSE_SIZES))
5402 : #define OMP_ALLOCATORS_CLAUSES \
5403 : omp_mask (OMP_CLAUSE_ALLOCATE)
5404 : #define OMP_INTEROP_CLAUSES \
5405 : (omp_mask (OMP_CLAUSE_DEPEND) | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_DEVICE \
5406 : | OMP_CLAUSE_INIT | OMP_CLAUSE_DESTROY | OMP_CLAUSE_USE)
5407 : #define OMP_DISPATCH_CLAUSES \
5408 : (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOVARIANTS \
5409 : | OMP_CLAUSE_NOCONTEXT | OMP_CLAUSE_IS_DEVICE_PTR | OMP_CLAUSE_NOWAIT \
5410 : | OMP_CLAUSE_HAS_DEVICE_ADDR | OMP_CLAUSE_INTEROP)
5411 :
5412 :
5413 : static match
5414 17214 : match_omp (gfc_exec_op op, const omp_mask mask)
5415 : {
5416 17214 : gfc_omp_clauses *c;
5417 17214 : if (gfc_match_omp_clauses (&c, mask, true, true, false,
5418 : op == EXEC_OMP_TARGET) != MATCH_YES)
5419 : return MATCH_ERROR;
5420 16951 : new_st.op = op;
5421 16951 : new_st.ext.omp_clauses = c;
5422 16951 : return MATCH_YES;
5423 : }
5424 :
5425 : /* Handles both declarative and (deprecated) executable ALLOCATE directive;
5426 : accepts optional list (for executable) and common blocks.
5427 : If no variables have been provided, the single omp namelist has sym == NULL.
5428 :
5429 : Note that the executable ALLOCATE directive permits structure elements only
5430 : in OpenMP 5.0 and 5.1 but not longer in 5.2. See also the comment on the
5431 : 'omp allocators' directive below. The accidental change was reverted for
5432 : OpenMP TR12, permitting them again. See also gfc_match_omp_allocators.
5433 :
5434 : Hence, structure elements are rejected for now, also to make resolving
5435 : OMP_LIST_ALLOCATE simpler (check for duplicates, same symbol in
5436 : Fortran allocate stmt). TODO: Permit structure elements. */
5437 :
5438 : match
5439 274 : gfc_match_omp_allocate (void)
5440 : {
5441 274 : match m;
5442 274 : bool first = true;
5443 274 : gfc_omp_namelist *vars = NULL;
5444 274 : gfc_expr *align = NULL;
5445 274 : gfc_expr *allocator = NULL;
5446 274 : locus loc = gfc_current_locus;
5447 :
5448 274 : m = gfc_match_omp_variable_list (" (", &vars, true, NULL, NULL, true, true,
5449 : NULL, true);
5450 :
5451 274 : if (m == MATCH_ERROR)
5452 : return m;
5453 :
5454 502 : while (true)
5455 : {
5456 502 : gfc_gobble_whitespace ();
5457 502 : if (gfc_match_omp_eos () == MATCH_YES)
5458 : break;
5459 234 : if (!first)
5460 28 : gfc_match (", ");
5461 234 : first = false;
5462 234 : if ((m = gfc_match_dupl_check (!align, "align", true, &align))
5463 : != MATCH_NO)
5464 : {
5465 62 : if (m == MATCH_ERROR)
5466 1 : goto error;
5467 61 : continue;
5468 : }
5469 172 : if ((m = gfc_match_dupl_check (!allocator, "allocator",
5470 : true, &allocator)) != MATCH_NO)
5471 : {
5472 171 : if (m == MATCH_ERROR)
5473 1 : goto error;
5474 170 : continue;
5475 : }
5476 1 : gfc_error ("Expected ALIGN or ALLOCATOR clause at %C");
5477 1 : return MATCH_ERROR;
5478 : }
5479 541 : for (gfc_omp_namelist *n = vars; n; n = n->next)
5480 276 : if (n->expr)
5481 : {
5482 3 : if ((n->expr->ref && n->expr->ref->type == REF_COMPONENT)
5483 3 : || (n->expr->ref->next && n->expr->ref->type == REF_COMPONENT))
5484 1 : gfc_error ("Sorry, structure-element list item at %L in ALLOCATE "
5485 : "directive is not yet supported", &n->expr->where);
5486 : else
5487 2 : gfc_error ("Unexpected expression as list item at %L in ALLOCATE "
5488 : "directive", &n->expr->where);
5489 :
5490 3 : gfc_free_omp_namelist (vars, OMP_LIST_ALLOCATE);
5491 3 : goto error;
5492 : }
5493 :
5494 265 : new_st.op = EXEC_OMP_ALLOCATE;
5495 265 : new_st.ext.omp_clauses = gfc_get_omp_clauses ();
5496 265 : if (vars == NULL)
5497 : {
5498 27 : vars = gfc_get_omp_namelist ();
5499 27 : vars->where = loc;
5500 27 : vars->u.align = align;
5501 27 : vars->u2.allocator = allocator;
5502 27 : new_st.ext.omp_clauses->lists[OMP_LIST_ALLOCATE] = vars;
5503 : }
5504 : else
5505 : {
5506 238 : new_st.ext.omp_clauses->lists[OMP_LIST_ALLOCATE] = vars;
5507 511 : for (; vars; vars = vars->next)
5508 : {
5509 273 : vars->u.align = (align) ? gfc_copy_expr (align) : NULL;
5510 273 : vars->u2.allocator = allocator;
5511 : }
5512 238 : gfc_free_expr (align);
5513 : }
5514 : return MATCH_YES;
5515 :
5516 5 : error:
5517 5 : gfc_free_expr (align);
5518 5 : gfc_free_expr (allocator);
5519 5 : return MATCH_ERROR;
5520 : }
5521 :
5522 : /* In line with OpenMP 5.2 derived-type components are rejected.
5523 : See also comment before gfc_match_omp_allocate. */
5524 :
5525 : match
5526 26 : gfc_match_omp_allocators (void)
5527 : {
5528 26 : return match_omp (EXEC_OMP_ALLOCATORS, OMP_ALLOCATORS_CLAUSES);
5529 : }
5530 :
5531 :
5532 : match
5533 23 : gfc_match_omp_assume (void)
5534 : {
5535 23 : gfc_omp_clauses *c;
5536 23 : locus loc = gfc_current_locus;
5537 23 : if ((gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_ASSUMPTIONS))
5538 : != MATCH_YES)
5539 23 : || (omp_verify_merge_absent_contains (ST_OMP_ASSUME, c->assume, NULL,
5540 : &loc) != MATCH_YES))
5541 7 : return MATCH_ERROR;
5542 16 : new_st.op = EXEC_OMP_ASSUME;
5543 16 : new_st.ext.omp_clauses = c;
5544 16 : return MATCH_YES;
5545 : }
5546 :
5547 :
5548 : match
5549 28 : gfc_match_omp_assumes (void)
5550 : {
5551 28 : gfc_omp_clauses *c;
5552 28 : locus loc = gfc_current_locus;
5553 28 : if (!gfc_current_ns->proc_name
5554 27 : || (gfc_current_ns->proc_name->attr.flavor != FL_MODULE
5555 23 : && !gfc_current_ns->proc_name->attr.subroutine
5556 10 : && !gfc_current_ns->proc_name->attr.function))
5557 : {
5558 2 : gfc_error ("!$OMP ASSUMES at %C must be in the specification part of a "
5559 : "subprogram or module");
5560 2 : return MATCH_ERROR;
5561 : }
5562 26 : if ((gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_ASSUMPTIONS))
5563 : != MATCH_YES)
5564 50 : || (omp_verify_merge_absent_contains (ST_OMP_ASSUMES, c->assume,
5565 24 : gfc_current_ns->omp_assumes, &loc)
5566 : != MATCH_YES))
5567 5 : return MATCH_ERROR;
5568 21 : if (gfc_current_ns->omp_assumes == NULL)
5569 : {
5570 19 : gfc_current_ns->omp_assumes = c->assume;
5571 19 : c->assume = NULL;
5572 : }
5573 2 : else if (gfc_current_ns->omp_assumes && c->assume)
5574 : {
5575 2 : gfc_current_ns->omp_assumes->no_openmp |= c->assume->no_openmp;
5576 2 : gfc_current_ns->omp_assumes->no_openmp_routines
5577 2 : |= c->assume->no_openmp_routines;
5578 2 : gfc_current_ns->omp_assumes->no_openmp_constructs
5579 2 : |= c->assume->no_openmp_constructs;
5580 2 : gfc_current_ns->omp_assumes->no_parallelism |= c->assume->no_parallelism;
5581 2 : if (gfc_current_ns->omp_assumes->holds && c->assume->holds)
5582 : {
5583 : gfc_expr_list *el = gfc_current_ns->omp_assumes->holds;
5584 1 : for ( ; el->next ; el = el->next)
5585 : ;
5586 1 : el->next = c->assume->holds;
5587 1 : }
5588 1 : else if (c->assume->holds)
5589 0 : gfc_current_ns->omp_assumes->holds = c->assume->holds;
5590 2 : c->assume->holds = NULL;
5591 : }
5592 21 : gfc_free_omp_clauses (c);
5593 21 : return MATCH_YES;
5594 : }
5595 :
5596 :
5597 : match
5598 162 : gfc_match_omp_critical (void)
5599 : {
5600 162 : char n[GFC_MAX_SYMBOL_LEN+1];
5601 162 : gfc_omp_clauses *c = NULL;
5602 :
5603 162 : if (gfc_match (" ( %n )", n) != MATCH_YES)
5604 115 : n[0] = '\0';
5605 :
5606 162 : if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_HINT),
5607 162 : /* first = */ n[0] == '\0') != MATCH_YES)
5608 : return MATCH_ERROR;
5609 :
5610 160 : new_st.op = EXEC_OMP_CRITICAL;
5611 160 : new_st.ext.omp_clauses = c;
5612 160 : if (n[0])
5613 47 : c->critical_name = xstrdup (n);
5614 : return MATCH_YES;
5615 : }
5616 :
5617 :
5618 : match
5619 160 : gfc_match_omp_end_critical (void)
5620 : {
5621 160 : char n[GFC_MAX_SYMBOL_LEN+1];
5622 :
5623 160 : if (gfc_match (" ( %n )", n) != MATCH_YES)
5624 113 : n[0] = '\0';
5625 160 : if (gfc_match_omp_eos () != MATCH_YES)
5626 : {
5627 1 : gfc_error ("Unexpected junk after $OMP CRITICAL statement at %C");
5628 1 : return MATCH_ERROR;
5629 : }
5630 :
5631 159 : new_st.op = EXEC_OMP_END_CRITICAL;
5632 159 : new_st.ext.omp_name = n[0] ? xstrdup (n) : NULL;
5633 159 : return MATCH_YES;
5634 : }
5635 :
5636 : /* depobj(depobj) depend(dep-type:loc)|destroy|update(dep-type)
5637 : dep-type = in/out/inout/mutexinoutset/depobj/source/sink
5638 : depend: !source, !sink
5639 : update: !source, !sink, !depobj
5640 : locator = exactly one list item .*/
5641 : match
5642 125 : gfc_match_omp_depobj (void)
5643 : {
5644 125 : gfc_omp_clauses *c = NULL;
5645 125 : gfc_expr *depobj;
5646 :
5647 125 : if (gfc_match (" ( %v ) ", &depobj) != MATCH_YES)
5648 : {
5649 2 : gfc_error ("Expected %<( depobj )%> at %C");
5650 2 : return MATCH_ERROR;
5651 : }
5652 123 : if (gfc_match ("update ( ") == MATCH_YES)
5653 : {
5654 12 : c = gfc_get_omp_clauses ();
5655 12 : if (gfc_match ("inoutset )") == MATCH_YES)
5656 2 : c->depobj_update = OMP_DEPEND_INOUTSET;
5657 10 : else if (gfc_match ("inout )") == MATCH_YES)
5658 1 : c->depobj_update = OMP_DEPEND_INOUT;
5659 9 : else if (gfc_match ("in )") == MATCH_YES)
5660 2 : c->depobj_update = OMP_DEPEND_IN;
5661 7 : else if (gfc_match ("out )") == MATCH_YES)
5662 2 : c->depobj_update = OMP_DEPEND_OUT;
5663 5 : else if (gfc_match ("mutexinoutset )") == MATCH_YES)
5664 2 : c->depobj_update = OMP_DEPEND_MUTEXINOUTSET;
5665 : else
5666 : {
5667 3 : gfc_error ("Expected IN, OUT, INOUT, INOUTSET or MUTEXINOUTSET "
5668 : "followed by %<)%> at %C");
5669 3 : goto error;
5670 : }
5671 : }
5672 111 : else if (gfc_match ("destroy ") == MATCH_YES)
5673 : {
5674 16 : gfc_expr *destroyobj = NULL;
5675 16 : c = gfc_get_omp_clauses ();
5676 16 : c->destroy = true;
5677 :
5678 16 : if (gfc_match (" ( %v ) ", &destroyobj) == MATCH_YES)
5679 : {
5680 3 : if (destroyobj->symtree != depobj->symtree)
5681 2 : gfc_warning (OPT_Wopenmp, "The same depend object should be used as"
5682 : " DEPOBJ argument at %L and as DESTROY argument at %L",
5683 : &depobj->where, &destroyobj->where);
5684 3 : gfc_free_expr (destroyobj);
5685 : }
5686 : }
5687 95 : else if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_DEPEND), true, false)
5688 : != MATCH_YES)
5689 2 : goto error;
5690 :
5691 118 : if (c->depobj_update == OMP_DEPEND_UNSET && !c->destroy)
5692 : {
5693 93 : if (!c->doacross_source && !c->lists[OMP_LIST_DEPEND])
5694 : {
5695 1 : gfc_error ("Expected DEPEND, UPDATE, or DESTROY clause at %C");
5696 1 : goto error;
5697 : }
5698 92 : if (c->lists[OMP_LIST_DEPEND]->u.depend_doacross_op == OMP_DEPEND_DEPOBJ)
5699 : {
5700 1 : gfc_error ("DEPEND clause at %L of OMP DEPOBJ construct shall not "
5701 : "have dependence-type DEPOBJ",
5702 : c->lists[OMP_LIST_DEPEND]
5703 : ? &c->lists[OMP_LIST_DEPEND]->where : &gfc_current_locus);
5704 1 : goto error;
5705 : }
5706 91 : if (c->lists[OMP_LIST_DEPEND]->next)
5707 : {
5708 1 : gfc_error ("DEPEND clause at %L of OMP DEPOBJ construct shall have "
5709 : "only a single locator",
5710 : &c->lists[OMP_LIST_DEPEND]->next->where);
5711 1 : goto error;
5712 : }
5713 : }
5714 :
5715 115 : c->depobj = depobj;
5716 115 : new_st.op = EXEC_OMP_DEPOBJ;
5717 115 : new_st.ext.omp_clauses = c;
5718 115 : return MATCH_YES;
5719 :
5720 8 : error:
5721 8 : gfc_free_expr (depobj);
5722 8 : gfc_free_omp_clauses (c);
5723 8 : return MATCH_ERROR;
5724 : }
5725 :
5726 : match
5727 160 : gfc_match_omp_dispatch (void)
5728 : {
5729 160 : return match_omp (EXEC_OMP_DISPATCH, OMP_DISPATCH_CLAUSES);
5730 : }
5731 :
5732 : match
5733 57 : gfc_match_omp_distribute (void)
5734 : {
5735 57 : return match_omp (EXEC_OMP_DISTRIBUTE, OMP_DISTRIBUTE_CLAUSES);
5736 : }
5737 :
5738 :
5739 : match
5740 44 : gfc_match_omp_distribute_parallel_do (void)
5741 : {
5742 44 : return match_omp (EXEC_OMP_DISTRIBUTE_PARALLEL_DO,
5743 44 : (OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
5744 44 : | OMP_DO_CLAUSES)
5745 44 : & ~(omp_mask (OMP_CLAUSE_ORDERED)
5746 44 : | OMP_CLAUSE_LINEAR | OMP_CLAUSE_NOWAIT));
5747 : }
5748 :
5749 :
5750 : match
5751 34 : gfc_match_omp_distribute_parallel_do_simd (void)
5752 : {
5753 34 : return match_omp (EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD,
5754 34 : (OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
5755 34 : | OMP_DO_CLAUSES | OMP_SIMD_CLAUSES)
5756 34 : & ~(omp_mask (OMP_CLAUSE_ORDERED) | OMP_CLAUSE_NOWAIT));
5757 : }
5758 :
5759 :
5760 : match
5761 52 : gfc_match_omp_distribute_simd (void)
5762 : {
5763 52 : return match_omp (EXEC_OMP_DISTRIBUTE_SIMD,
5764 52 : OMP_DISTRIBUTE_CLAUSES | OMP_SIMD_CLAUSES);
5765 : }
5766 :
5767 :
5768 : match
5769 1253 : gfc_match_omp_do (void)
5770 : {
5771 1253 : return match_omp (EXEC_OMP_DO, OMP_DO_CLAUSES);
5772 : }
5773 :
5774 :
5775 : match
5776 137 : gfc_match_omp_do_simd (void)
5777 : {
5778 137 : return match_omp (EXEC_OMP_DO_SIMD, OMP_DO_CLAUSES | OMP_SIMD_CLAUSES);
5779 : }
5780 :
5781 :
5782 : match
5783 70 : gfc_match_omp_loop (void)
5784 : {
5785 70 : return match_omp (EXEC_OMP_LOOP, OMP_LOOP_CLAUSES);
5786 : }
5787 :
5788 :
5789 : match
5790 35 : gfc_match_omp_teams_loop (void)
5791 : {
5792 35 : return match_omp (EXEC_OMP_TEAMS_LOOP, OMP_TEAMS_CLAUSES | OMP_LOOP_CLAUSES);
5793 : }
5794 :
5795 :
5796 : match
5797 18 : gfc_match_omp_target_teams_loop (void)
5798 : {
5799 18 : return match_omp (EXEC_OMP_TARGET_TEAMS_LOOP,
5800 18 : OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES | OMP_LOOP_CLAUSES);
5801 : }
5802 :
5803 :
5804 : match
5805 31 : gfc_match_omp_parallel_loop (void)
5806 : {
5807 31 : return match_omp (EXEC_OMP_PARALLEL_LOOP,
5808 31 : OMP_PARALLEL_CLAUSES | OMP_LOOP_CLAUSES);
5809 : }
5810 :
5811 :
5812 : match
5813 16 : gfc_match_omp_target_parallel_loop (void)
5814 : {
5815 16 : return match_omp (EXEC_OMP_TARGET_PARALLEL_LOOP,
5816 16 : (OMP_TARGET_CLAUSES | OMP_PARALLEL_CLAUSES
5817 16 : | OMP_LOOP_CLAUSES));
5818 : }
5819 :
5820 :
5821 : match
5822 101 : gfc_match_omp_error (void)
5823 : {
5824 101 : locus loc = gfc_current_locus;
5825 101 : match m = match_omp (EXEC_OMP_ERROR, OMP_ERROR_CLAUSES);
5826 101 : if (m != MATCH_YES)
5827 : return m;
5828 :
5829 82 : gfc_omp_clauses *c = new_st.ext.omp_clauses;
5830 82 : if (c->severity == OMP_SEVERITY_UNSET)
5831 45 : c->severity = OMP_SEVERITY_FATAL;
5832 82 : if (new_st.ext.omp_clauses->at == OMP_AT_EXECUTION)
5833 : return MATCH_YES;
5834 37 : if (c->message
5835 37 : && (!gfc_resolve_expr (c->message)
5836 16 : || c->message->ts.type != BT_CHARACTER
5837 14 : || c->message->ts.kind != gfc_default_character_kind
5838 13 : || c->message->rank != 0))
5839 : {
5840 4 : gfc_error ("MESSAGE clause at %L requires a scalar default-kind "
5841 : "CHARACTER expression",
5842 4 : &new_st.ext.omp_clauses->message->where);
5843 4 : return MATCH_ERROR;
5844 : }
5845 33 : if (c->message && !gfc_is_constant_expr (c->message))
5846 : {
5847 2 : gfc_error ("Constant character expression required in MESSAGE clause "
5848 2 : "at %L", &new_st.ext.omp_clauses->message->where);
5849 2 : return MATCH_ERROR;
5850 : }
5851 31 : if (c->message)
5852 : {
5853 10 : const char *msg = G_("$OMP ERROR encountered at %L: %s");
5854 10 : gcc_assert (c->message->expr_type == EXPR_CONSTANT);
5855 10 : gfc_charlen_t slen = c->message->value.character.length;
5856 10 : int i = gfc_validate_kind (BT_CHARACTER, gfc_default_character_kind,
5857 : false);
5858 10 : size_t size = slen * gfc_character_kinds[i].bit_size / 8;
5859 10 : unsigned char *s = XCNEWVAR (unsigned char, size + 1);
5860 10 : gfc_encode_character (gfc_default_character_kind, slen,
5861 10 : c->message->value.character.string,
5862 : (unsigned char *) s, size);
5863 10 : s[size] = '\0';
5864 10 : if (c->severity == OMP_SEVERITY_WARNING)
5865 6 : gfc_warning_now (0, msg, &loc, s);
5866 : else
5867 4 : gfc_error_now (msg, &loc, s);
5868 10 : free (s);
5869 : }
5870 : else
5871 : {
5872 21 : const char *msg = G_("$OMP ERROR encountered at %L");
5873 21 : if (c->severity == OMP_SEVERITY_WARNING)
5874 7 : gfc_warning_now (0, msg, &loc);
5875 : else
5876 14 : gfc_error_now (msg, &loc);
5877 : }
5878 : return MATCH_YES;
5879 : }
5880 :
5881 : match
5882 86 : gfc_match_omp_flush (void)
5883 : {
5884 86 : gfc_omp_namelist *list = NULL;
5885 86 : gfc_omp_clauses *c = NULL;
5886 86 : gfc_gobble_whitespace ();
5887 86 : enum gfc_omp_memorder mo = OMP_MEMORDER_UNSET;
5888 86 : if (gfc_match_omp_eos () == MATCH_NO && gfc_peek_ascii_char () != '(')
5889 : {
5890 14 : if (gfc_match ("seq_cst") == MATCH_YES)
5891 : mo = OMP_MEMORDER_SEQ_CST;
5892 11 : else if (gfc_match ("acq_rel") == MATCH_YES)
5893 : mo = OMP_MEMORDER_ACQ_REL;
5894 8 : else if (gfc_match ("release") == MATCH_YES)
5895 : mo = OMP_MEMORDER_RELEASE;
5896 5 : else if (gfc_match ("acquire") == MATCH_YES)
5897 : mo = OMP_MEMORDER_ACQUIRE;
5898 : else
5899 : {
5900 2 : gfc_error ("Expected SEQ_CST, AQC_REL, RELEASE, or ACQUIRE at %C");
5901 2 : return MATCH_ERROR;
5902 : }
5903 12 : c = gfc_get_omp_clauses ();
5904 12 : c->memorder = mo;
5905 : }
5906 84 : gfc_match_omp_variable_list (" (", &list, true);
5907 84 : if (list && mo != OMP_MEMORDER_UNSET)
5908 : {
5909 4 : gfc_error ("List specified together with memory order clause in FLUSH "
5910 : "directive at %C");
5911 4 : gfc_free_omp_namelist (list, OMP_LIST_NONE);
5912 4 : gfc_free_omp_clauses (c);
5913 4 : return MATCH_ERROR;
5914 : }
5915 80 : if (gfc_match_omp_eos () != MATCH_YES)
5916 : {
5917 0 : gfc_error ("Unexpected junk after $OMP FLUSH statement at %C");
5918 0 : gfc_free_omp_namelist (list, OMP_LIST_NONE);
5919 0 : gfc_free_omp_clauses (c);
5920 0 : return MATCH_ERROR;
5921 : }
5922 80 : new_st.op = EXEC_OMP_FLUSH;
5923 80 : new_st.ext.omp_namelist = list;
5924 80 : new_st.ext.omp_clauses = c;
5925 80 : return MATCH_YES;
5926 : }
5927 :
5928 :
5929 : match
5930 188 : gfc_match_omp_declare_simd (void)
5931 : {
5932 188 : locus where = gfc_current_locus;
5933 188 : gfc_symbol *proc_name;
5934 188 : gfc_omp_clauses *c;
5935 188 : gfc_omp_declare_simd *ods;
5936 188 : bool needs_space = false;
5937 :
5938 188 : switch (gfc_match (" ( "))
5939 : {
5940 144 : case MATCH_YES:
5941 144 : if (gfc_match_symbol (&proc_name, /* host assoc = */ true) != MATCH_YES
5942 144 : || gfc_match (" ) ") != MATCH_YES)
5943 0 : return MATCH_ERROR;
5944 : break;
5945 44 : case MATCH_NO: proc_name = NULL; needs_space = true; break;
5946 : case MATCH_ERROR: return MATCH_ERROR;
5947 : }
5948 :
5949 188 : if (gfc_match_omp_clauses (&c, OMP_DECLARE_SIMD_CLAUSES, true,
5950 : needs_space) != MATCH_YES)
5951 : return MATCH_ERROR;
5952 :
5953 183 : if (gfc_current_ns->is_block_data)
5954 : {
5955 1 : gfc_free_omp_clauses (c);
5956 1 : return MATCH_YES;
5957 : }
5958 :
5959 182 : ods = gfc_get_omp_declare_simd ();
5960 182 : ods->where = where;
5961 182 : ods->proc_name = proc_name;
5962 182 : ods->clauses = c;
5963 182 : ods->next = gfc_current_ns->omp_declare_simd;
5964 182 : gfc_current_ns->omp_declare_simd = ods;
5965 182 : return MATCH_YES;
5966 : }
5967 :
5968 :
5969 : /* Find a matching "!$omp declare mapper" for typespec TS in symtree ST. */
5970 :
5971 : gfc_omp_udm *
5972 30 : gfc_omp_udm_find (gfc_symtree *st, gfc_typespec *ts)
5973 : {
5974 30 : gfc_omp_udm *omp_udm;
5975 :
5976 30 : if (st == NULL)
5977 : return NULL;
5978 :
5979 14 : gfc_symbol *dt = (ts->type == BT_CLASS
5980 0 : ? CLASS_DATA (ts->u.derived)->ts.u.derived
5981 : : ts->u.derived);
5982 15 : for (omp_udm = st->n.omp_udm; omp_udm; omp_udm = omp_udm->next)
5983 : {
5984 5 : if (dt == omp_udm->ts.u.derived)
5985 : return omp_udm;
5986 : /* Special case for comparing derived types across namespaces. If the
5987 : true names and module names are the same and the module name is
5988 : nonnull, then they are equal. */
5989 1 : if (dt->module && omp_udm->ts.u.derived->module
5990 1 : && strcmp (dt->name, omp_udm->ts.u.derived->name) == 0
5991 1 : && strcmp (dt->module, omp_udm->ts.u.derived->module) == 0)
5992 : return omp_udm;
5993 : }
5994 :
5995 : return NULL;
5996 : }
5997 :
5998 :
5999 : /* Match !$omp declare mapper([ mapper-identifier : ] type :: var) clauses-list */
6000 :
6001 : match
6002 28 : gfc_match_omp_declare_mapper (void)
6003 : {
6004 28 : match m;
6005 28 : gfc_typespec ts;
6006 28 : char mapper_id[GFC_MAX_SYMBOL_LEN + 1];
6007 28 : char var[GFC_MAX_SYMBOL_LEN + 1];
6008 28 : gfc_namespace *mapper_ns = NULL;
6009 28 : gfc_symtree *var_st;
6010 28 : gfc_symtree *st;
6011 28 : gfc_omp_udm *omp_udm = NULL, *prev_udm = NULL;
6012 28 : locus where = gfc_current_locus;
6013 :
6014 28 : if (gfc_match_char ('(') != MATCH_YES)
6015 : {
6016 1 : gfc_error ("Expected %<(%> at %C");
6017 1 : return MATCH_ERROR;
6018 : }
6019 :
6020 27 : locus old_locus = gfc_current_locus;
6021 :
6022 27 : m = gfc_match (" %n : ", mapper_id);
6023 :
6024 27 : if (m == MATCH_ERROR)
6025 : return MATCH_ERROR;
6026 :
6027 : /* As a special case, a mapper named "default" and an unnamed mapper are
6028 : both the default mapper for a given type. */
6029 27 : if (strcmp (mapper_id, "default") == 0)
6030 0 : mapper_id[0] = '\0';
6031 :
6032 27 : if (gfc_peek_ascii_char () == ':')
6033 : {
6034 : /* If we see '::', the user did not name the mapper, and instead we just
6035 : saw the type. So backtrack and try parsing as a type instead. */
6036 14 : mapper_id[0] = '\0';
6037 14 : gfc_current_locus = old_locus;
6038 : }
6039 27 : old_locus = gfc_current_locus;
6040 :
6041 27 : m = gfc_match_type_spec (&ts);
6042 27 : if (m != MATCH_YES)
6043 : {
6044 4 : gfc_error ("Expected either a type name at %L or a map-type "
6045 : "identifier, a colon, or a type name", &old_locus);
6046 4 : return MATCH_ERROR;
6047 : }
6048 :
6049 23 : if (ts.type != BT_DERIVED)
6050 : {
6051 1 : gfc_error ("!$OMP DECLARE MAPPER with non-derived type at %L", &old_locus);
6052 1 : return MATCH_ERROR;
6053 : }
6054 :
6055 22 : if (gfc_match (" :: ") != MATCH_YES)
6056 : {
6057 0 : gfc_error ("Expected %<::%> at %C");
6058 0 : return MATCH_ERROR;
6059 : }
6060 :
6061 22 : if (gfc_match_name (var) != MATCH_YES)
6062 : {
6063 1 : gfc_error ("Expected variable name at %C");
6064 1 : return MATCH_ERROR;
6065 : }
6066 :
6067 21 : if (gfc_match_char (')') != MATCH_YES)
6068 : {
6069 2 : gfc_error ("Expected %<)%> at %C");
6070 2 : return MATCH_ERROR;
6071 : }
6072 :
6073 19 : st = gfc_find_symtree (gfc_current_ns->omp_udm_root, mapper_id);
6074 :
6075 : /* Now we need to set up a new namespace, and create a new sym_tree for our
6076 : dummy variable so we can use it in the following list of mapping
6077 : clauses. */
6078 :
6079 19 : gfc_current_ns = mapper_ns = gfc_get_namespace (gfc_current_ns, 1);
6080 19 : mapper_ns->proc_name = mapper_ns->parent->proc_name;
6081 19 : mapper_ns->omp_udm_ns = 1;
6082 :
6083 19 : gfc_get_sym_tree (var, mapper_ns, &var_st, false);
6084 19 : var_st->n.sym->ts = ts;
6085 19 : var_st->n.sym->attr.omp_udm_artificial_var = 1;
6086 19 : var_st->n.sym->attr.flavor = FL_VARIABLE;
6087 19 : gfc_commit_symbols ();
6088 :
6089 19 : gfc_omp_clauses *clauses = NULL;
6090 :
6091 19 : m = gfc_match_omp_clauses (&clauses, omp_mask (OMP_CLAUSE_MAP), true, true,
6092 : false, false, OMP_MAP_UNSET);
6093 19 : if (m != MATCH_YES)
6094 1 : goto failure;
6095 :
6096 18 : omp_udm = gfc_get_omp_udm ();
6097 18 : omp_udm->next = NULL;
6098 18 : omp_udm->where = where;
6099 18 : omp_udm->mapper_id = gfc_get_string ("%s", mapper_id);
6100 18 : omp_udm->ts = ts;
6101 18 : omp_udm->var_sym = var_st->n.sym;
6102 18 : omp_udm->mapper_ns = mapper_ns;
6103 18 : omp_udm->clauses = clauses;
6104 :
6105 18 : gfc_current_ns = mapper_ns->parent;
6106 :
6107 18 : prev_udm = gfc_omp_udm_find (st, &ts);
6108 18 : if (prev_udm)
6109 : {
6110 2 : if (mapper_id[0])
6111 1 : gfc_error ("Redefinition of !$OMP DECLARE MAPPER at %L for type %qs with id %qs",
6112 : &where, gfc_typename (&ts), mapper_id);
6113 : else
6114 1 : gfc_error ("Redefinition of !$OMP DECLARE MAPPER at %L for type %qs",
6115 : &where, gfc_typename (&ts));
6116 2 : inform (gfc_get_location (&prev_udm->where),
6117 : "Previous !$OMP DECLARE MAPPER here");
6118 2 : return MATCH_ERROR;
6119 : }
6120 16 : else if (st)
6121 : {
6122 0 : omp_udm->next = st->n.omp_udm;
6123 0 : st->n.omp_udm = omp_udm;
6124 : }
6125 : else
6126 : {
6127 16 : st = gfc_new_symtree (&gfc_current_ns->omp_udm_root, mapper_id);
6128 16 : st->n.omp_udm = omp_udm;
6129 : }
6130 :
6131 : return MATCH_YES;
6132 :
6133 1 : failure:
6134 1 : if (mapper_ns)
6135 1 : gfc_current_ns = mapper_ns->parent;
6136 1 : gfc_free_omp_udm (omp_udm);
6137 :
6138 1 : return MATCH_ERROR;
6139 : }
6140 :
6141 : /* For 'declare reduction', matches either the combiner or initializer
6142 : expression, either can be an assignment of 'omp_sym1 = ...'
6143 : or a subroutine call, i.e. 'subroutine-name(argument-list)'. */
6144 :
6145 : static bool
6146 922 : match_udr_expr (gfc_symtree *omp_sym1, gfc_symtree *omp_sym2)
6147 : {
6148 922 : match m;
6149 922 : locus old_loc = gfc_current_locus;
6150 922 : char sname[GFC_MAX_SYMBOL_LEN + 1];
6151 922 : gfc_symbol *sym;
6152 922 : gfc_namespace *ns = gfc_current_ns;
6153 922 : gfc_expr *lvalue = NULL, *rvalue = NULL;
6154 922 : gfc_symtree *st;
6155 922 : gfc_actual_arglist *arglist;
6156 :
6157 922 : m = gfc_match (" %v =", &lvalue);
6158 922 : if (m != MATCH_YES)
6159 210 : gfc_current_locus = old_loc;
6160 : else
6161 : {
6162 712 : m = gfc_match (" %e )", &rvalue);
6163 712 : if (m == MATCH_YES)
6164 : {
6165 702 : ns->code = gfc_get_code (EXEC_ASSIGN);
6166 702 : ns->code->expr1 = lvalue;
6167 702 : ns->code->expr2 = rvalue;
6168 702 : ns->code->loc = old_loc;
6169 702 : return true;
6170 : }
6171 :
6172 10 : gfc_current_locus = old_loc;
6173 10 : gfc_free_expr (lvalue);
6174 : }
6175 :
6176 220 : m = gfc_match (" %n", sname);
6177 220 : if (m != MATCH_YES)
6178 4 : goto syntax;
6179 :
6180 216 : if (strcmp (sname, omp_sym1->name) == 0
6181 203 : || strcmp (sname, omp_sym2->name) == 0)
6182 14 : goto syntax;
6183 :
6184 202 : gfc_current_ns = ns->parent;
6185 202 : if (gfc_get_ha_sym_tree (sname, &st))
6186 0 : goto syntax;
6187 :
6188 202 : sym = st->n.sym;
6189 202 : if (sym->attr.flavor != FL_PROCEDURE
6190 74 : && sym->attr.flavor != FL_UNKNOWN)
6191 1 : goto syntax;
6192 :
6193 201 : if (!sym->attr.generic
6194 191 : && !sym->attr.subroutine
6195 73 : && !sym->attr.function)
6196 : {
6197 73 : if (!(sym->attr.external && !sym->attr.referenced))
6198 : {
6199 : /* ...create a symbol in this scope... */
6200 73 : if (sym->ns != gfc_current_ns
6201 73 : && gfc_get_sym_tree (sname, NULL, &st, false) == 1)
6202 0 : goto syntax;
6203 :
6204 73 : if (sym != st->n.sym)
6205 73 : sym = st->n.sym;
6206 : }
6207 :
6208 : /* ...and then to try to make the symbol into a subroutine. */
6209 73 : if (!gfc_add_subroutine (&sym->attr, sym->name, NULL))
6210 0 : goto syntax;
6211 : }
6212 :
6213 201 : gfc_set_sym_referenced (sym);
6214 201 : gfc_gobble_whitespace ();
6215 201 : if (gfc_peek_ascii_char () != '(')
6216 6 : goto syntax;
6217 :
6218 195 : gfc_current_ns = ns;
6219 195 : m = gfc_match_actual_arglist (1, &arglist);
6220 195 : if (m != MATCH_YES)
6221 0 : goto syntax;
6222 :
6223 195 : if (gfc_match_char (')') != MATCH_YES)
6224 0 : goto syntax;
6225 :
6226 195 : gfc_clear_error ();
6227 195 : ns->code = gfc_get_code (EXEC_CALL);
6228 195 : ns->code->symtree = st;
6229 195 : ns->code->ext.actual = arglist;
6230 195 : ns->code->loc = old_loc;
6231 195 : return true;
6232 25 : syntax:
6233 25 : gfc_clear_error ();
6234 25 : gfc_error ("Expected either %<%s = expr%> or %<subroutine-name(argument-list)"
6235 : "%> followed by %<)%> at %L", omp_sym1->name, &old_loc);
6236 25 : return false;
6237 : }
6238 :
6239 : static bool
6240 1203 : gfc_omp_udr_predef (gfc_omp_reduction_op rop, const char *name,
6241 : gfc_typespec *ts, const char **n)
6242 : {
6243 1203 : if (!gfc_numeric_ts (ts) && ts->type != BT_LOGICAL)
6244 : return false;
6245 :
6246 673 : switch (rop)
6247 : {
6248 19 : case OMP_REDUCTION_PLUS:
6249 19 : case OMP_REDUCTION_MINUS:
6250 19 : case OMP_REDUCTION_TIMES:
6251 19 : return ts->type != BT_LOGICAL;
6252 12 : case OMP_REDUCTION_AND:
6253 12 : case OMP_REDUCTION_OR:
6254 12 : case OMP_REDUCTION_EQV:
6255 12 : case OMP_REDUCTION_NEQV:
6256 12 : return ts->type == BT_LOGICAL;
6257 641 : case OMP_REDUCTION_USER:
6258 641 : if (name[0] != '.' && (ts->type == BT_INTEGER || ts->type == BT_REAL))
6259 : {
6260 569 : gfc_symbol *sym;
6261 :
6262 569 : gfc_find_symbol (name, NULL, 1, &sym);
6263 569 : if (sym != NULL)
6264 : {
6265 93 : if (sym->attr.intrinsic)
6266 0 : *n = sym->name;
6267 93 : else if ((sym->attr.flavor != FL_UNKNOWN
6268 81 : && sym->attr.flavor != FL_PROCEDURE)
6269 69 : || sym->attr.external
6270 54 : || sym->attr.generic
6271 54 : || sym->attr.entry
6272 54 : || sym->attr.result
6273 54 : || sym->attr.dummy
6274 54 : || sym->attr.subroutine
6275 50 : || sym->attr.pointer
6276 50 : || sym->attr.target
6277 50 : || sym->attr.cray_pointer
6278 50 : || sym->attr.cray_pointee
6279 50 : || (sym->attr.proc != PROC_UNKNOWN
6280 0 : && sym->attr.proc != PROC_INTRINSIC)
6281 50 : || sym->attr.if_source != IFSRC_UNKNOWN
6282 50 : || sym == sym->ns->proc_name)
6283 43 : *n = NULL;
6284 : else
6285 50 : *n = sym->name;
6286 : }
6287 : else
6288 476 : *n = name;
6289 569 : if (*n
6290 526 : && (strcmp (*n, "max") == 0 || strcmp (*n, "min") == 0))
6291 56 : return true;
6292 531 : else if (*n
6293 488 : && ts->type == BT_INTEGER
6294 402 : && (strcmp (*n, "iand") == 0
6295 396 : || strcmp (*n, "ior") == 0
6296 390 : || strcmp (*n, "ieor") == 0))
6297 : return true;
6298 : }
6299 : break;
6300 : default:
6301 : break;
6302 : }
6303 : return false;
6304 : }
6305 :
6306 : gfc_omp_udr *
6307 666 : gfc_omp_udr_find (gfc_symtree *st, gfc_typespec *ts)
6308 : {
6309 666 : gfc_omp_udr *omp_udr;
6310 :
6311 666 : if (st == NULL)
6312 : return NULL;
6313 :
6314 112 : gfc_symbol *dt = NULL;
6315 112 : if (ts->type == BT_DERIVED || ts->type == BT_CLASS)
6316 25 : dt = (ts->type == BT_CLASS
6317 0 : ? CLASS_DATA (ts->u.derived)->ts.u.derived : ts->u.derived);
6318 260 : for (omp_udr = st->n.omp_udr; omp_udr; omp_udr = omp_udr->next)
6319 161 : if (omp_udr->ts.type == ts->type
6320 91 : || (dt && omp_udr->ts.type == BT_DERIVED))
6321 : {
6322 70 : if (dt && omp_udr->ts.type == BT_DERIVED)
6323 : {
6324 15 : gfc_symbol *dtu = omp_udr->ts.u.derived;
6325 15 : if (dt == dtu)
6326 : return omp_udr;
6327 : /* Special case for comparing derived types across namespaces. If
6328 : the true names and module names are the same and the module name
6329 : is nonnull, then they are equal. */
6330 7 : if (dt->module && dtu->module
6331 1 : && strcmp (dt->name, dtu->name) == 0
6332 1 : && strcmp (dt->module, dtu->module) == 0)
6333 : return omp_udr;
6334 : }
6335 55 : else if (omp_udr->ts.kind == ts->kind)
6336 : {
6337 20 : if (omp_udr->ts.type == BT_CHARACTER)
6338 : {
6339 17 : if (omp_udr->ts.u.cl->length == NULL
6340 15 : || ts->u.cl->length == NULL)
6341 : return omp_udr;
6342 15 : if (omp_udr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
6343 : return omp_udr;
6344 15 : if (ts->u.cl->length->expr_type != EXPR_CONSTANT)
6345 : return omp_udr;
6346 15 : if (omp_udr->ts.u.cl->length->ts.type != BT_INTEGER)
6347 : return omp_udr;
6348 15 : if (ts->u.cl->length->ts.type != BT_INTEGER)
6349 : return omp_udr;
6350 15 : if (gfc_compare_expr (omp_udr->ts.u.cl->length,
6351 : ts->u.cl->length, INTRINSIC_EQ) != 0)
6352 15 : continue;
6353 : }
6354 3 : return omp_udr;
6355 : }
6356 : }
6357 : return NULL;
6358 : }
6359 :
6360 : match
6361 587 : gfc_match_omp_declare_reduction (void)
6362 : {
6363 587 : match m;
6364 587 : gfc_intrinsic_op op;
6365 587 : char name[GFC_MAX_SYMBOL_LEN + 3];
6366 587 : auto_vec<gfc_typespec, 5> tss;
6367 587 : gfc_typespec ts;
6368 587 : unsigned int i;
6369 587 : gfc_symtree *st;
6370 587 : locus where = gfc_current_locus;
6371 587 : locus end_loc = gfc_current_locus;
6372 587 : bool end_loc_set = false;
6373 587 : gfc_omp_reduction_op rop = OMP_REDUCTION_NONE;
6374 :
6375 587 : if (gfc_match_char ('(') != MATCH_YES)
6376 : {
6377 4 : gfc_error ("Expected %<(%> at %C");
6378 4 : return MATCH_ERROR;
6379 : }
6380 :
6381 583 : m = gfc_match (" %o : ", &op);
6382 583 : if (m == MATCH_ERROR)
6383 : return MATCH_ERROR;
6384 583 : if (m == MATCH_YES)
6385 : {
6386 142 : snprintf (name, sizeof name, "operator %s", gfc_op2string (op));
6387 142 : rop = (gfc_omp_reduction_op) op;
6388 : }
6389 : else
6390 : {
6391 441 : m = gfc_match_defined_op_name (name + 1, 1);
6392 441 : if (m == MATCH_ERROR)
6393 : return MATCH_ERROR;
6394 440 : if (m == MATCH_YES)
6395 : {
6396 41 : name[0] = '.';
6397 41 : strcat (name, ".");
6398 41 : if (gfc_match (" : ") != MATCH_YES)
6399 : {
6400 0 : gfc_error ("Expected %<:%> at %C");
6401 0 : return MATCH_ERROR;
6402 : }
6403 : }
6404 : else
6405 : {
6406 399 : if (gfc_match (" %n : ", name) != MATCH_YES)
6407 : {
6408 4 : gfc_error ("Expected an identfifier or operator as reduction "
6409 : "identifier followed by a colon at %C");
6410 4 : return MATCH_ERROR;
6411 : }
6412 : }
6413 : rop = OMP_REDUCTION_USER;
6414 : }
6415 :
6416 578 : m = gfc_match_type_spec (&ts);
6417 578 : if (m != MATCH_YES)
6418 : {
6419 4 : gfc_error ("Expected type spec at %C");
6420 4 : return MATCH_ERROR;
6421 : }
6422 : /* Treat len=: the same as len=*. */
6423 574 : if (ts.type == BT_CHARACTER)
6424 61 : ts.deferred = false;
6425 574 : tss.safe_push (ts);
6426 :
6427 1189 : while (gfc_match_char (',') == MATCH_YES)
6428 : {
6429 42 : m = gfc_match_type_spec (&ts);
6430 42 : if (m != MATCH_YES)
6431 : {
6432 1 : gfc_error ("Expected type spec at %C");
6433 1 : return MATCH_ERROR;
6434 : }
6435 41 : tss.safe_push (ts);
6436 : }
6437 573 : if (gfc_match_char (':') != MATCH_YES)
6438 : {
6439 6 : gfc_error ("Expected %<:%> or %<,%> at %C");
6440 6 : return MATCH_ERROR;
6441 : }
6442 :
6443 567 : st = gfc_find_symtree (gfc_current_ns->omp_udr_root, name);
6444 1111 : for (i = 0; i < tss.length (); i++)
6445 : {
6446 603 : gfc_symtree *omp_out, *omp_in;
6447 603 : gfc_symtree *omp_priv = NULL, *omp_orig = NULL;
6448 603 : gfc_namespace *combiner_ns, *initializer_ns = NULL;
6449 603 : gfc_omp_udr *prev_udr, *omp_udr;
6450 603 : const char *predef_name = NULL;
6451 :
6452 603 : omp_udr = gfc_get_omp_udr ();
6453 603 : omp_udr->name = gfc_get_string ("%s", name);
6454 603 : omp_udr->rop = rop;
6455 603 : omp_udr->ts = tss[i];
6456 603 : omp_udr->where = where;
6457 :
6458 603 : gfc_current_ns = combiner_ns = gfc_get_namespace (gfc_current_ns, 1);
6459 603 : combiner_ns->proc_name = combiner_ns->parent->proc_name;
6460 :
6461 603 : gfc_get_sym_tree ("omp_out", combiner_ns, &omp_out, false);
6462 603 : gfc_get_sym_tree ("omp_in", combiner_ns, &omp_in, false);
6463 603 : combiner_ns->omp_udr_ns = 1;
6464 603 : omp_out->n.sym->ts = tss[i];
6465 603 : omp_in->n.sym->ts = tss[i];
6466 603 : omp_out->n.sym->attr.omp_udr_artificial_var = 1;
6467 603 : omp_in->n.sym->attr.omp_udr_artificial_var = 1;
6468 603 : omp_out->n.sym->attr.flavor = FL_VARIABLE;
6469 603 : omp_in->n.sym->attr.flavor = FL_VARIABLE;
6470 603 : gfc_commit_symbols ();
6471 603 : omp_udr->combiner_ns = combiner_ns;
6472 603 : omp_udr->omp_out = omp_out->n.sym;
6473 603 : omp_udr->omp_in = omp_in->n.sym;
6474 :
6475 603 : locus old_loc = gfc_current_locus;
6476 :
6477 603 : if (!match_udr_expr (omp_out, omp_in))
6478 : {
6479 19 : syntax:
6480 59 : gfc_current_ns = combiner_ns->parent;
6481 59 : gfc_undo_symbols ();
6482 59 : gfc_free_omp_udr (omp_udr);
6483 59 : return MATCH_ERROR;
6484 : }
6485 :
6486 584 : if (gfc_match (" initializer ( ") == MATCH_YES)
6487 : {
6488 319 : gfc_current_ns = combiner_ns->parent;
6489 319 : initializer_ns = gfc_get_namespace (gfc_current_ns, 1);
6490 319 : gfc_current_ns = initializer_ns;
6491 319 : initializer_ns->proc_name = initializer_ns->parent->proc_name;
6492 :
6493 319 : gfc_get_sym_tree ("omp_priv", initializer_ns, &omp_priv, false);
6494 319 : gfc_get_sym_tree ("omp_orig", initializer_ns, &omp_orig, false);
6495 319 : initializer_ns->omp_udr_ns = 1;
6496 319 : omp_priv->n.sym->ts = tss[i];
6497 319 : omp_orig->n.sym->ts = tss[i];
6498 319 : omp_priv->n.sym->attr.omp_udr_artificial_var = 1;
6499 319 : omp_orig->n.sym->attr.omp_udr_artificial_var = 1;
6500 319 : omp_priv->n.sym->attr.flavor = FL_VARIABLE;
6501 319 : omp_orig->n.sym->attr.flavor = FL_VARIABLE;
6502 319 : gfc_commit_symbols ();
6503 319 : omp_udr->initializer_ns = initializer_ns;
6504 319 : omp_udr->omp_priv = omp_priv->n.sym;
6505 319 : omp_udr->omp_orig = omp_orig->n.sym;
6506 :
6507 319 : if (!match_udr_expr (omp_priv, omp_orig))
6508 6 : goto syntax;
6509 : }
6510 :
6511 578 : gfc_current_ns = combiner_ns->parent;
6512 578 : if (!end_loc_set)
6513 : {
6514 542 : end_loc_set = true;
6515 542 : end_loc = gfc_current_locus;
6516 : }
6517 578 : gfc_current_locus = old_loc;
6518 :
6519 578 : prev_udr = gfc_omp_udr_find (st, &tss[i]);
6520 578 : if (gfc_omp_udr_predef (rop, name, &tss[i], &predef_name)
6521 : /* Don't error on !$omp declare reduction (min : integer : ...)
6522 : just yet, there could be integer :: min afterwards,
6523 : making it valid. When the UDR is resolved, we'll get
6524 : to it again. */
6525 578 : && (rop != OMP_REDUCTION_USER || name[0] == '.'))
6526 : {
6527 27 : if (predef_name)
6528 0 : gfc_error_now ("Redefinition of predefined %qs in "
6529 : "!$OMP DECLARE REDUCTION at %L",
6530 : predef_name, &where);
6531 : else
6532 27 : gfc_error_now ("Redefinition of predefined %qs in "
6533 : "!$OMP DECLARE REDUCTION at %L", name, &where);
6534 27 : goto syntax;
6535 : }
6536 551 : else if (prev_udr)
6537 : {
6538 7 : gfc_error_now ("Redefinition of %qs in !$OMP DECLARE REDUCTION at %L",
6539 : name, &where);
6540 7 : inform (gfc_get_location (&prev_udr->where),
6541 : "Previous !$OMP DECLARE REDUCTION");
6542 7 : goto syntax;
6543 : }
6544 544 : else if (st)
6545 : {
6546 98 : omp_udr->next = st->n.omp_udr;
6547 98 : st->n.omp_udr = omp_udr;
6548 : }
6549 : else
6550 : {
6551 446 : st = gfc_new_symtree (&gfc_current_ns->omp_udr_root, name);
6552 446 : st->n.omp_udr = omp_udr;
6553 : }
6554 : }
6555 :
6556 508 : if (end_loc_set)
6557 : {
6558 508 : gfc_current_locus = end_loc;
6559 508 : if (gfc_match_omp_eos () != MATCH_YES)
6560 : {
6561 4 : gfc_error ("Unexpected junk at %C");
6562 4 : return MATCH_ERROR;
6563 : }
6564 : return MATCH_YES;
6565 : }
6566 : return MATCH_ERROR;
6567 587 : }
6568 :
6569 :
6570 : match
6571 472 : gfc_match_omp_declare_target (void)
6572 : {
6573 472 : locus old_loc;
6574 472 : match m;
6575 472 : gfc_omp_clauses *c = NULL;
6576 472 : enum gfc_omp_list_type list;
6577 472 : gfc_omp_namelist *n;
6578 472 : gfc_symbol *s;
6579 :
6580 472 : old_loc = gfc_current_locus;
6581 :
6582 472 : if (gfc_current_ns->proc_name
6583 472 : && gfc_match_omp_eos () == MATCH_YES)
6584 : {
6585 138 : if (!gfc_add_omp_declare_target (&gfc_current_ns->proc_name->attr,
6586 138 : gfc_current_ns->proc_name->name,
6587 : &old_loc))
6588 0 : goto cleanup;
6589 : return MATCH_YES;
6590 : }
6591 :
6592 334 : if (gfc_current_ns->proc_name
6593 334 : && gfc_current_ns->proc_name->attr.if_source == IFSRC_IFBODY)
6594 : {
6595 2 : gfc_error ("Only the !$OMP DECLARE TARGET form without "
6596 : "clauses is allowed in interface block at %C");
6597 2 : goto cleanup;
6598 : }
6599 :
6600 332 : m = gfc_match (" (");
6601 332 : if (m == MATCH_YES)
6602 : {
6603 86 : c = gfc_get_omp_clauses ();
6604 86 : gfc_current_locus = old_loc;
6605 86 : m = gfc_match_omp_to_link (" (", &c->lists[OMP_LIST_ENTER]);
6606 86 : if (m != MATCH_YES)
6607 0 : goto syntax;
6608 86 : if (gfc_match_omp_eos () != MATCH_YES)
6609 : {
6610 0 : gfc_error ("Unexpected junk after !$OMP DECLARE TARGET at %C");
6611 0 : goto cleanup;
6612 : }
6613 : }
6614 246 : else if (gfc_match_omp_clauses (&c, OMP_DECLARE_TARGET_CLAUSES) != MATCH_YES)
6615 : return MATCH_ERROR;
6616 :
6617 326 : gfc_buffer_error (false);
6618 :
6619 326 : static const enum gfc_omp_list_type to_enter_link_lists[]
6620 : = { OMP_LIST_TO, OMP_LIST_ENTER, OMP_LIST_LINK, OMP_LIST_LOCAL };
6621 1630 : for (size_t listn = 0; listn < ARRAY_SIZE (to_enter_link_lists)
6622 1630 : && (list = to_enter_link_lists[listn], true); ++listn)
6623 1849 : for (n = c->lists[list]; n; n = n->next)
6624 545 : if (n->sym)
6625 504 : n->sym->mark = 0;
6626 41 : else if (n->u.common->head)
6627 41 : n->u.common->head->mark = 0;
6628 :
6629 326 : if (c->device_type == OMP_DEVICE_TYPE_UNSET)
6630 258 : c->device_type = OMP_DEVICE_TYPE_ANY;
6631 1304 : for (size_t listn = 0; listn < ARRAY_SIZE (to_enter_link_lists)
6632 1630 : && (list = to_enter_link_lists[listn], true); ++listn)
6633 1849 : for (n = c->lists[list]; n; n = n->next)
6634 545 : if (n->sym)
6635 : {
6636 504 : if (n->sym->attr.in_common)
6637 1 : gfc_error_now ("OMP DECLARE TARGET variable at %L is an "
6638 : "element of a COMMON block", &n->where);
6639 503 : else if (n->sym->attr.omp_groupprivate && list != OMP_LIST_LOCAL)
6640 12 : gfc_error_now ("List item %qs at %L not appear in the %qs clause "
6641 : "as it was previously specified in a GROUPPRIVATE "
6642 : "directive", n->sym->name, &n->where,
6643 : list == OMP_LIST_LINK
6644 5 : ? "link" : list == OMP_LIST_TO ? "to" : "enter");
6645 496 : else if (n->sym->mark)
6646 9 : gfc_error_now ("Variable at %L mentioned multiple times in "
6647 : "clauses of the same OMP DECLARE TARGET directive",
6648 : &n->where);
6649 487 : else if ((n->sym->attr.omp_declare_target_link
6650 482 : || n->sym->attr.omp_declare_target_local)
6651 : && list != OMP_LIST_LINK
6652 7 : && list != OMP_LIST_LOCAL)
6653 1 : gfc_error_now ("OMP DECLARE TARGET variable at %L previously "
6654 : "mentioned in %s clause and later in %s clause",
6655 : &n->where,
6656 : n->sym->attr.omp_declare_target_link ? "LINK"
6657 : : "LOCAL",
6658 : list == OMP_LIST_TO ? "TO" : "ENTER");
6659 486 : else if (n->sym->attr.omp_declare_target
6660 14 : && (list == OMP_LIST_LINK || list == OMP_LIST_LOCAL))
6661 1 : gfc_error_now ("OMP DECLARE TARGET variable at %L previously "
6662 : "mentioned in TO or ENTER clause and later in "
6663 : "%s clause", &n->where,
6664 : list == OMP_LIST_LINK ? "LINK" : "LOCAL");
6665 : else
6666 : {
6667 485 : if (list == OMP_LIST_TO || list == OMP_LIST_ENTER)
6668 446 : gfc_add_omp_declare_target (&n->sym->attr, n->sym->name,
6669 : &n->sym->declared_at);
6670 485 : if (list == OMP_LIST_LINK)
6671 30 : gfc_add_omp_declare_target_link (&n->sym->attr, n->sym->name,
6672 30 : &n->sym->declared_at);
6673 485 : if (list == OMP_LIST_LOCAL)
6674 9 : gfc_add_omp_declare_target_local (&n->sym->attr, n->sym->name,
6675 9 : &n->sym->declared_at);
6676 : }
6677 504 : if (n->sym->attr.omp_device_type != OMP_DEVICE_TYPE_UNSET
6678 36 : && n->sym->attr.omp_device_type != c->device_type)
6679 : {
6680 12 : const char *dt = "any";
6681 12 : if (n->sym->attr.omp_device_type == OMP_DEVICE_TYPE_NOHOST)
6682 : dt = "nohost";
6683 8 : else if (n->sym->attr.omp_device_type == OMP_DEVICE_TYPE_HOST)
6684 4 : dt = "host";
6685 12 : if (n->sym->attr.omp_groupprivate)
6686 1 : gfc_error_now ("List item %qs at %L set in previous OMP "
6687 : "GROUPPRIVATE directive to the different "
6688 : "DEVICE_TYPE %qs", n->sym->name, &n->where, dt);
6689 : else
6690 11 : gfc_error_now ("List item %qs at %L set in previous OMP "
6691 : "DECLARE TARGET directive to the different "
6692 : "DEVICE_TYPE %qs", n->sym->name, &n->where, dt);
6693 : }
6694 504 : n->sym->attr.omp_device_type = c->device_type;
6695 504 : if (c->indirect && c->device_type != OMP_DEVICE_TYPE_ANY)
6696 : {
6697 1 : gfc_error_now ("DEVICE_TYPE must be ANY when used with INDIRECT "
6698 : "at %L", &n->where);
6699 1 : c->indirect = 0;
6700 : }
6701 504 : n->sym->attr.omp_declare_target_indirect = c->indirect;
6702 504 : if (list == OMP_LIST_LINK && c->device_type == OMP_DEVICE_TYPE_NOHOST)
6703 3 : gfc_error_now ("List item %qs at %L set with NOHOST specified may "
6704 : "not appear in a LINK clause", n->sym->name,
6705 : &n->where);
6706 504 : n->sym->mark = 1;
6707 : }
6708 : else /* common block */
6709 : {
6710 41 : if (n->u.common->omp_groupprivate && list != OMP_LIST_LOCAL)
6711 7 : gfc_error_now ("Common block %</%s/%> at %L not appear in the %qs "
6712 : "clause as it was previously specified in a "
6713 : "GROUPPRIVATE directive",
6714 7 : n->u.common->name, &n->where,
6715 : list == OMP_LIST_LINK
6716 5 : ? "link" : list == OMP_LIST_TO ? "to" : "enter");
6717 34 : else if (n->u.common->head && n->u.common->head->mark)
6718 4 : gfc_error_now ("Common block %</%s/%> at %L mentioned multiple "
6719 : "times in clauses of the same OMP DECLARE TARGET "
6720 4 : "directive", n->u.common->name, &n->where);
6721 30 : else if ((n->u.common->omp_declare_target_link
6722 26 : || n->u.common->omp_declare_target_local)
6723 : && list != OMP_LIST_LINK
6724 6 : && list != OMP_LIST_LOCAL)
6725 2 : gfc_error_now ("Common block %</%s/%> at %L previously mentioned "
6726 : "in %s clause and later in %s clause",
6727 1 : n->u.common->name, &n->where,
6728 : n->u.common->omp_declare_target_link ? "LINK"
6729 : : "LOCAL",
6730 : list == OMP_LIST_TO ? "TO" : "ENTER");
6731 29 : else if (n->u.common->omp_declare_target
6732 4 : && (list == OMP_LIST_LINK || list == OMP_LIST_LOCAL))
6733 1 : gfc_error_now ("Common block %</%s/%> at %L previously mentioned "
6734 : "in TO or ENTER clause and later in %s clause",
6735 1 : n->u.common->name, &n->where,
6736 : list == OMP_LIST_LINK ? "LINK" : "LOCAL");
6737 41 : if (n->u.common->omp_device_type != OMP_DEVICE_TYPE_UNSET
6738 21 : && n->u.common->omp_device_type != c->device_type)
6739 : {
6740 1 : const char *dt = "any";
6741 1 : if (n->u.common->omp_device_type == OMP_DEVICE_TYPE_NOHOST)
6742 : dt = "nohost";
6743 0 : else if (n->u.common->omp_device_type == OMP_DEVICE_TYPE_HOST)
6744 0 : dt = "host";
6745 1 : if (n->u.common->omp_groupprivate)
6746 1 : gfc_error_now ("Common block %</%s/%> at %L set in previous OMP "
6747 : "GROUPPRIVATE directive to the different "
6748 1 : "DEVICE_TYPE %qs", n->u.common->name, &n->where,
6749 : dt);
6750 : else
6751 0 : gfc_error_now ("Common block %</%s/%> at %L set in previous OMP "
6752 : "DECLARE TARGET directive to the different "
6753 0 : "DEVICE_TYPE %qs", n->u.common->name, &n->where,
6754 : dt);
6755 : }
6756 41 : n->u.common->omp_device_type = c->device_type;
6757 :
6758 41 : if (c->indirect && c->device_type != OMP_DEVICE_TYPE_ANY)
6759 : {
6760 0 : gfc_error_now ("DEVICE_TYPE must be ANY when used with INDIRECT "
6761 : "at %L", &n->where);
6762 0 : c->indirect = 0;
6763 : }
6764 41 : if (list == OMP_LIST_LINK && c->device_type == OMP_DEVICE_TYPE_NOHOST)
6765 1 : gfc_error_now ("Common block %</%s/%> at %L set with NOHOST "
6766 : "specified may not appear in a LINK clause",
6767 1 : n->u.common->name, &n->where);
6768 :
6769 41 : if (list == OMP_LIST_TO || list == OMP_LIST_ENTER)
6770 21 : n->u.common->omp_declare_target = 1;
6771 41 : if (list == OMP_LIST_LINK)
6772 15 : n->u.common->omp_declare_target_link = 1;
6773 41 : if (list == OMP_LIST_LOCAL)
6774 5 : n->u.common->omp_declare_target_local = 1;
6775 :
6776 110 : for (s = n->u.common->head; s; s = s->common_next)
6777 : {
6778 69 : s->mark = 1;
6779 69 : if (list == OMP_LIST_TO || list == OMP_LIST_ENTER)
6780 33 : gfc_add_omp_declare_target (&s->attr, s->name, &n->where);
6781 69 : if (list == OMP_LIST_LINK)
6782 31 : gfc_add_omp_declare_target_link (&s->attr, s->name, &n->where);
6783 69 : if (list == OMP_LIST_LOCAL)
6784 5 : gfc_add_omp_declare_target_local (&s->attr, s->name, &n->where);
6785 69 : s->attr.omp_device_type = c->device_type;
6786 69 : s->attr.omp_declare_target_indirect = c->indirect;
6787 : }
6788 : }
6789 326 : if ((c->device_type || c->indirect)
6790 326 : && !c->lists[OMP_LIST_ENTER]
6791 151 : && !c->lists[OMP_LIST_TO]
6792 47 : && !c->lists[OMP_LIST_LINK]
6793 10 : && !c->lists[OMP_LIST_LOCAL])
6794 2 : gfc_warning_now (OPT_Wopenmp,
6795 : "OMP DECLARE TARGET directive at %L with only "
6796 : "DEVICE_TYPE or INDIRECT clauses is ignored",
6797 : &old_loc);
6798 :
6799 326 : gfc_buffer_error (true);
6800 :
6801 326 : if (c)
6802 326 : gfc_free_omp_clauses (c);
6803 326 : return MATCH_YES;
6804 :
6805 0 : syntax:
6806 0 : gfc_error ("Syntax error in !$OMP DECLARE TARGET list at %C");
6807 :
6808 2 : cleanup:
6809 2 : gfc_current_locus = old_loc;
6810 2 : if (c)
6811 0 : gfc_free_omp_clauses (c);
6812 : return MATCH_ERROR;
6813 : }
6814 :
6815 : /* Skip over and ignore trait-property-extensions.
6816 :
6817 : trait-property-extension :
6818 : trait-property-name
6819 : identifier (trait-property-extension[, trait-property-extension[, ...]])
6820 : constant integer expression
6821 : */
6822 :
6823 : static match gfc_ignore_trait_property_extension_list (void);
6824 :
6825 : static match
6826 7 : gfc_ignore_trait_property_extension (void)
6827 : {
6828 7 : char buf[GFC_MAX_SYMBOL_LEN + 1];
6829 7 : gfc_expr *expr;
6830 :
6831 : /* Identifier form of trait-property name, possibly followed by
6832 : a list of (recursive) trait-property-extensions. */
6833 7 : if (gfc_match_name (buf) == MATCH_YES)
6834 : {
6835 0 : if (gfc_match (" (") == MATCH_YES)
6836 0 : return gfc_ignore_trait_property_extension_list ();
6837 : return MATCH_YES;
6838 : }
6839 :
6840 : /* Literal constant. */
6841 7 : if (gfc_match_literal_constant (&expr, 0) == MATCH_YES)
6842 : return MATCH_YES;
6843 :
6844 : /* FIXME: constant integer expressions. */
6845 0 : gfc_error ("Expected trait-property-extension at %C");
6846 0 : return MATCH_ERROR;
6847 : }
6848 :
6849 : static match
6850 5 : gfc_ignore_trait_property_extension_list (void)
6851 : {
6852 9 : while (1)
6853 : {
6854 7 : if (gfc_ignore_trait_property_extension () != MATCH_YES)
6855 : return MATCH_ERROR;
6856 7 : if (gfc_match (" ,") == MATCH_YES)
6857 2 : continue;
6858 5 : if (gfc_match (" )") == MATCH_YES)
6859 : return MATCH_YES;
6860 0 : gfc_error ("expected %<)%> at %C");
6861 0 : return MATCH_ERROR;
6862 : }
6863 : }
6864 :
6865 :
6866 : match
6867 110 : gfc_match_omp_interop (void)
6868 : {
6869 110 : return match_omp (EXEC_OMP_INTEROP, OMP_INTEROP_CLAUSES);
6870 : }
6871 :
6872 :
6873 : /* OpenMP 5.0:
6874 :
6875 : trait-selector:
6876 : trait-selector-name[([trait-score:]trait-property[,trait-property[,...]])]
6877 :
6878 : trait-score:
6879 : score(score-expression) */
6880 :
6881 : static match
6882 637 : gfc_match_omp_context_selector (gfc_omp_set_selector *oss)
6883 : {
6884 775 : do
6885 : {
6886 775 : char selector[GFC_MAX_SYMBOL_LEN + 1];
6887 :
6888 775 : if (gfc_match_name (selector) != MATCH_YES)
6889 : {
6890 2 : gfc_error ("expected trait selector name at %C");
6891 39 : return MATCH_ERROR;
6892 : }
6893 :
6894 773 : gfc_omp_selector *os = gfc_get_omp_selector ();
6895 773 : if (oss->code == OMP_TRAIT_SET_CONSTRUCT
6896 335 : && !strcmp (selector, "do"))
6897 48 : os->code = OMP_TRAIT_CONSTRUCT_FOR;
6898 725 : else if (oss->code == OMP_TRAIT_SET_CONSTRUCT
6899 287 : && !strcmp (selector, "for"))
6900 1 : os->code = OMP_TRAIT_INVALID;
6901 : else
6902 724 : os->code = omp_lookup_ts_code (oss->code, selector);
6903 773 : os->next = oss->trait_selectors;
6904 773 : oss->trait_selectors = os;
6905 :
6906 773 : if (os->code == OMP_TRAIT_INVALID)
6907 : {
6908 18 : gfc_warning (OPT_Wopenmp,
6909 : "unknown selector %qs for context selector set %qs "
6910 : "at %C",
6911 18 : selector, omp_tss_map[oss->code]);
6912 18 : if (gfc_match (" (") == MATCH_YES
6913 18 : && gfc_ignore_trait_property_extension_list () != MATCH_YES)
6914 : return MATCH_ERROR;
6915 18 : if (gfc_match (" ,") == MATCH_YES)
6916 1 : continue;
6917 598 : break;
6918 : }
6919 :
6920 755 : enum omp_tp_type property_kind = omp_ts_map[os->code].tp_type;
6921 755 : bool allow_score = omp_ts_map[os->code].allow_score;
6922 :
6923 755 : if (gfc_match (" (") == MATCH_YES)
6924 : {
6925 431 : if (property_kind == OMP_TRAIT_PROPERTY_NONE)
6926 : {
6927 6 : gfc_error ("selector %qs does not accept any properties at %C",
6928 : selector);
6929 6 : return MATCH_ERROR;
6930 : }
6931 :
6932 425 : if (gfc_match (" score") == MATCH_YES)
6933 : {
6934 63 : if (!allow_score)
6935 : {
6936 10 : gfc_error ("%<score%> cannot be specified in traits "
6937 : "in the %qs trait-selector-set at %C",
6938 10 : omp_tss_map[oss->code]);
6939 10 : return MATCH_ERROR;
6940 : }
6941 53 : if (gfc_match (" (") != MATCH_YES)
6942 : {
6943 0 : gfc_error ("expected %<(%> at %C");
6944 0 : return MATCH_ERROR;
6945 : }
6946 53 : if (gfc_match_expr (&os->score) != MATCH_YES)
6947 : return MATCH_ERROR;
6948 :
6949 52 : if (gfc_match (" )") != MATCH_YES)
6950 : {
6951 0 : gfc_error ("expected %<)%> at %C");
6952 0 : return MATCH_ERROR;
6953 : }
6954 :
6955 52 : if (gfc_match (" :") != MATCH_YES)
6956 : {
6957 0 : gfc_error ("expected : at %C");
6958 0 : return MATCH_ERROR;
6959 : }
6960 : }
6961 :
6962 414 : gfc_omp_trait_property *otp = gfc_get_omp_trait_property ();
6963 414 : otp->property_kind = property_kind;
6964 414 : otp->next = os->properties;
6965 414 : os->properties = otp;
6966 :
6967 414 : switch (property_kind)
6968 : {
6969 25 : case OMP_TRAIT_PROPERTY_ID:
6970 25 : {
6971 25 : char buf[GFC_MAX_SYMBOL_LEN + 1];
6972 25 : if (gfc_match_name (buf) == MATCH_YES)
6973 : {
6974 24 : otp->name = XNEWVEC (char, strlen (buf) + 1);
6975 24 : strcpy (otp->name, buf);
6976 : }
6977 : else
6978 : {
6979 1 : gfc_error ("expected identifier at %C");
6980 1 : free (otp);
6981 1 : os->properties = nullptr;
6982 1 : return MATCH_ERROR;
6983 : }
6984 : }
6985 24 : break;
6986 290 : case OMP_TRAIT_PROPERTY_NAME_LIST:
6987 343 : do
6988 : {
6989 290 : char buf[GFC_MAX_SYMBOL_LEN + 1];
6990 290 : if (gfc_match_name (buf) == MATCH_YES)
6991 : {
6992 170 : otp->name = XNEWVEC (char, strlen (buf) + 1);
6993 170 : strcpy (otp->name, buf);
6994 170 : otp->is_name = true;
6995 : }
6996 120 : else if (gfc_match_literal_constant (&otp->expr, 0)
6997 : != MATCH_YES
6998 120 : || otp->expr->ts.type != BT_CHARACTER)
6999 : {
7000 5 : gfc_error ("expected identifier or string literal "
7001 : "at %C");
7002 5 : free (otp);
7003 5 : os->properties = nullptr;
7004 5 : return MATCH_ERROR;
7005 : }
7006 :
7007 285 : if (gfc_match (" ,") == MATCH_YES)
7008 : {
7009 53 : otp = gfc_get_omp_trait_property ();
7010 53 : otp->property_kind = property_kind;
7011 53 : otp->next = os->properties;
7012 53 : os->properties = otp;
7013 : }
7014 : else
7015 : break;
7016 53 : }
7017 : while (1);
7018 232 : break;
7019 137 : case OMP_TRAIT_PROPERTY_DEV_NUM_EXPR:
7020 137 : case OMP_TRAIT_PROPERTY_BOOL_EXPR:
7021 137 : if (gfc_match_expr (&otp->expr) != MATCH_YES)
7022 : {
7023 3 : gfc_error ("expected expression at %C");
7024 3 : free (otp);
7025 3 : os->properties = nullptr;
7026 3 : return MATCH_ERROR;
7027 : }
7028 : break;
7029 15 : case OMP_TRAIT_PROPERTY_CLAUSE_LIST:
7030 15 : {
7031 15 : if (os->code == OMP_TRAIT_CONSTRUCT_SIMD)
7032 : {
7033 15 : gfc_matching_omp_context_selector = true;
7034 15 : if (gfc_match_omp_clauses (&otp->clauses,
7035 15 : OMP_DECLARE_SIMD_CLAUSES,
7036 : true, false, false)
7037 : != MATCH_YES)
7038 : {
7039 1 : gfc_matching_omp_context_selector = false;
7040 1 : gfc_error ("expected simd clause at %C");
7041 1 : return MATCH_ERROR;
7042 : }
7043 14 : gfc_matching_omp_context_selector = false;
7044 : }
7045 0 : else if (os->code == OMP_TRAIT_IMPLEMENTATION_REQUIRES)
7046 : {
7047 : /* FIXME: The "requires" selector was added in OpenMP 5.1.
7048 : Currently only the now-deprecated syntax
7049 : from OpenMP 5.0 is supported.
7050 : TODO: When implementing, update modules.cc as well. */
7051 0 : sorry_at (gfc_get_location (&gfc_current_locus),
7052 : "%<requires%> selector is not supported yet");
7053 0 : return MATCH_ERROR;
7054 : }
7055 : else
7056 0 : gcc_unreachable ();
7057 14 : break;
7058 : }
7059 0 : default:
7060 0 : gcc_unreachable ();
7061 : }
7062 :
7063 404 : if (gfc_match (" )") != MATCH_YES)
7064 : {
7065 2 : gfc_error ("expected %<)%> at %C");
7066 2 : return MATCH_ERROR;
7067 : }
7068 : }
7069 324 : else if (property_kind != OMP_TRAIT_PROPERTY_NONE
7070 324 : && property_kind != OMP_TRAIT_PROPERTY_CLAUSE_LIST
7071 8 : && property_kind != OMP_TRAIT_PROPERTY_EXTENSION)
7072 : {
7073 8 : if (gfc_match (" (") != MATCH_YES)
7074 : {
7075 8 : gfc_error ("expected %<(%> at %C");
7076 8 : return MATCH_ERROR;
7077 : }
7078 : }
7079 :
7080 718 : if (gfc_match (" ,") != MATCH_YES)
7081 : break;
7082 : }
7083 : while (1);
7084 :
7085 598 : return MATCH_YES;
7086 : }
7087 :
7088 : /* OpenMP 5.0:
7089 :
7090 : trait-set-selector[,trait-set-selector[,...]]
7091 :
7092 : trait-set-selector:
7093 : trait-set-selector-name = { trait-selector[, trait-selector[, ...]] }
7094 :
7095 : trait-set-selector-name:
7096 : constructor
7097 : device
7098 : implementation
7099 : user */
7100 :
7101 : static match
7102 577 : gfc_match_omp_context_selector_specification (gfc_omp_set_selector **oss_head)
7103 : {
7104 713 : do
7105 : {
7106 645 : match m;
7107 645 : char buf[GFC_MAX_SYMBOL_LEN + 1];
7108 645 : enum omp_tss_code set = OMP_TRAIT_SET_INVALID;
7109 :
7110 645 : m = gfc_match_name (buf);
7111 645 : if (m == MATCH_YES)
7112 643 : set = omp_lookup_tss_code (buf);
7113 :
7114 643 : if (set == OMP_TRAIT_SET_INVALID)
7115 : {
7116 5 : gfc_error ("expected context selector set name at %C");
7117 47 : return MATCH_ERROR;
7118 : }
7119 :
7120 640 : m = gfc_match (" =");
7121 640 : if (m != MATCH_YES)
7122 : {
7123 1 : gfc_error ("expected %<=%> at %C");
7124 1 : return MATCH_ERROR;
7125 : }
7126 :
7127 639 : m = gfc_match (" {");
7128 639 : if (m != MATCH_YES)
7129 : {
7130 2 : gfc_error ("expected %<{%> at %C");
7131 2 : return MATCH_ERROR;
7132 : }
7133 :
7134 637 : gfc_omp_set_selector *oss = gfc_get_omp_set_selector ();
7135 637 : oss->next = *oss_head;
7136 637 : oss->code = set;
7137 637 : *oss_head = oss;
7138 :
7139 637 : if (gfc_match_omp_context_selector (oss) != MATCH_YES)
7140 : return MATCH_ERROR;
7141 :
7142 598 : m = gfc_match (" }");
7143 598 : if (m != MATCH_YES)
7144 : {
7145 0 : gfc_error ("expected %<}%> at %C");
7146 0 : return MATCH_ERROR;
7147 : }
7148 :
7149 598 : m = gfc_match (" ,");
7150 598 : if (m != MATCH_YES)
7151 : break;
7152 68 : }
7153 : while (1);
7154 :
7155 530 : return MATCH_YES;
7156 : }
7157 :
7158 :
7159 : match
7160 419 : gfc_match_omp_declare_variant (void)
7161 : {
7162 419 : char buf[GFC_MAX_SYMBOL_LEN + 1];
7163 :
7164 419 : if (gfc_match (" (") != MATCH_YES)
7165 : {
7166 2 : gfc_error ("expected %<(%> at %C");
7167 2 : return MATCH_ERROR;
7168 : }
7169 :
7170 417 : gfc_symtree *base_proc_st, *variant_proc_st;
7171 417 : if (gfc_match_name (buf) != MATCH_YES)
7172 : {
7173 2 : gfc_error ("expected name at %C");
7174 2 : return MATCH_ERROR;
7175 : }
7176 :
7177 415 : if (gfc_get_ha_sym_tree (buf, &base_proc_st))
7178 : return MATCH_ERROR;
7179 :
7180 415 : if (gfc_match (" :") == MATCH_YES)
7181 : {
7182 16 : if (gfc_match_name (buf) != MATCH_YES)
7183 : {
7184 0 : gfc_error ("expected variant name at %C");
7185 0 : return MATCH_ERROR;
7186 : }
7187 :
7188 16 : if (gfc_get_ha_sym_tree (buf, &variant_proc_st))
7189 : return MATCH_ERROR;
7190 : }
7191 : else
7192 : {
7193 : /* Base procedure not specified. */
7194 399 : variant_proc_st = base_proc_st;
7195 399 : base_proc_st = NULL;
7196 : }
7197 :
7198 415 : gfc_omp_declare_variant *odv;
7199 415 : odv = gfc_get_omp_declare_variant ();
7200 415 : odv->where = gfc_current_locus;
7201 415 : odv->variant_proc_symtree = variant_proc_st;
7202 415 : odv->adjust_args_list = NULL;
7203 415 : odv->base_proc_symtree = base_proc_st;
7204 415 : odv->next = NULL;
7205 415 : odv->error_p = false;
7206 :
7207 : /* Add the new declare variant to the end of the list. */
7208 415 : gfc_omp_declare_variant **prev_next = &gfc_current_ns->omp_declare_variant;
7209 555 : while (*prev_next)
7210 140 : prev_next = &((*prev_next)->next);
7211 415 : *prev_next = odv;
7212 :
7213 415 : if (gfc_match (" )") != MATCH_YES)
7214 : {
7215 1 : gfc_error ("expected %<)%> at %C");
7216 1 : return MATCH_ERROR;
7217 : }
7218 :
7219 414 : bool has_match = false, has_adjust_args = false, has_append_args = false;
7220 414 : bool error_p = false;
7221 414 : locus adjust_args_loc;
7222 414 : locus append_args_loc;
7223 :
7224 414 : gfc_gobble_whitespace ();
7225 414 : gfc_match_char (',');
7226 632 : for (;;)
7227 : {
7228 523 : gfc_gobble_whitespace ();
7229 :
7230 523 : enum clause
7231 : {
7232 : clause_match,
7233 : clause_adjust_args,
7234 : clause_append_args
7235 : } ccode;
7236 :
7237 523 : if (gfc_match ("match") == MATCH_YES)
7238 : ccode = clause_match;
7239 119 : else if (gfc_match ("adjust_args") == MATCH_YES)
7240 : {
7241 517 : ccode = clause_adjust_args;
7242 : adjust_args_loc = gfc_current_locus;
7243 : }
7244 38 : else if (gfc_match ("append_args") == MATCH_YES)
7245 : {
7246 517 : ccode = clause_append_args;
7247 : append_args_loc = gfc_current_locus;
7248 : }
7249 : else
7250 : {
7251 : error_p = true;
7252 : break;
7253 : }
7254 :
7255 517 : if (gfc_match (" ( ") != MATCH_YES)
7256 : {
7257 1 : gfc_error ("expected %<(%> at %C");
7258 1 : return MATCH_ERROR;
7259 : }
7260 :
7261 516 : if (ccode == clause_match)
7262 : {
7263 403 : if (has_match)
7264 : {
7265 1 : gfc_error ("%qs clause at %L specified more than once",
7266 : "match", &gfc_current_locus);
7267 1 : return MATCH_ERROR;
7268 : }
7269 402 : has_match = true;
7270 402 : if (gfc_match_omp_context_selector_specification (&odv->set_selectors)
7271 : != MATCH_YES)
7272 : return MATCH_ERROR;
7273 362 : if (gfc_match (" )") != MATCH_YES)
7274 : {
7275 0 : gfc_error ("expected %<)%> at %C");
7276 0 : return MATCH_ERROR;
7277 : }
7278 : }
7279 113 : else if (ccode == clause_adjust_args)
7280 : {
7281 81 : has_adjust_args = true;
7282 81 : bool need_device_ptr_p = false;
7283 81 : bool need_device_addr_p = false;
7284 81 : if (gfc_match ("nothing ") == MATCH_YES)
7285 : ;
7286 58 : else if (gfc_match ("need_device_ptr ") == MATCH_YES)
7287 : need_device_ptr_p = true;
7288 9 : else if (gfc_match ("need_device_addr ") == MATCH_YES)
7289 : need_device_addr_p = true;
7290 : else
7291 : {
7292 2 : gfc_error ("expected %<nothing%>, %<need_device_ptr%> or "
7293 : "%<need_device_addr%> at %C");
7294 2 : return MATCH_ERROR;
7295 : }
7296 79 : if (gfc_match (": ") != MATCH_YES)
7297 : {
7298 1 : gfc_error ("expected %<:%> at %C");
7299 1 : return MATCH_ERROR;
7300 : }
7301 : gfc_omp_namelist *tail = NULL;
7302 : bool need_range = false, have_range = false;
7303 125 : while (true)
7304 : {
7305 125 : gfc_omp_namelist *p = gfc_get_omp_namelist ();
7306 125 : p->where = gfc_current_locus;
7307 125 : p->u.adj_args.need_ptr = need_device_ptr_p;
7308 125 : p->u.adj_args.need_addr = need_device_addr_p;
7309 125 : if (tail)
7310 : {
7311 47 : tail->next = p;
7312 47 : tail = tail->next;
7313 : }
7314 : else
7315 : {
7316 78 : gfc_omp_namelist **q = &odv->adjust_args_list;
7317 78 : if (*q)
7318 : {
7319 50 : for (; (*q)->next; q = &(*q)->next)
7320 : ;
7321 28 : (*q)->next = p;
7322 : }
7323 : else
7324 50 : *q = p;
7325 : tail = p;
7326 : }
7327 125 : if (gfc_match (": ") == MATCH_YES)
7328 : {
7329 2 : if (have_range)
7330 : {
7331 0 : gfc_error ("unexpected %<:%> at %C");
7332 2 : return MATCH_ERROR;
7333 : }
7334 2 : p->u.adj_args.range_start = have_range = true;
7335 2 : need_range = false;
7336 49 : continue;
7337 : }
7338 123 : if (have_range && gfc_match (", ") == MATCH_YES)
7339 : {
7340 1 : have_range = false;
7341 1 : continue;
7342 : }
7343 122 : if (have_range && gfc_match (") ") == MATCH_YES)
7344 : break;
7345 121 : locus saved_loc = gfc_current_locus;
7346 :
7347 : /* Without ranges, only arg names or integer literals permitted;
7348 : handle literals here as gfc_match_expr simplifies the expr. */
7349 121 : if (gfc_match_literal_constant (&p->expr, true) == MATCH_YES)
7350 : {
7351 17 : gfc_gobble_whitespace ();
7352 17 : char c = gfc_peek_ascii_char ();
7353 17 : if (c != ')' && c != ',' && c != ':')
7354 : {
7355 1 : gfc_free_expr (p->expr);
7356 1 : p->expr = NULL;
7357 1 : gfc_current_locus = saved_loc;
7358 : }
7359 : }
7360 121 : if (!p->expr && gfc_match ("omp_num_args") == MATCH_YES)
7361 : {
7362 6 : if (!have_range)
7363 3 : p->u.adj_args.range_start = need_range = true;
7364 : else
7365 : need_range = false;
7366 :
7367 6 : locus saved_loc2 = gfc_current_locus;
7368 6 : gfc_gobble_whitespace ();
7369 6 : char c = gfc_peek_ascii_char ();
7370 6 : if (c == '+' || c == '-')
7371 : {
7372 5 : if (gfc_match ("+ %e", &p->expr) == MATCH_YES)
7373 1 : p->u.adj_args.omp_num_args_plus = true;
7374 4 : else if (gfc_match ("- %e", &p->expr) == MATCH_YES)
7375 4 : p->u.adj_args.omp_num_args_minus = true;
7376 0 : else if (!gfc_error_check ())
7377 : {
7378 0 : gfc_error ("expected constant integer expression "
7379 : "at %C");
7380 0 : p->u.adj_args.error_p = true;
7381 0 : return MATCH_ERROR;
7382 : }
7383 5 : p->where = gfc_get_location_range (&saved_loc, 1,
7384 : &saved_loc, 1,
7385 : &gfc_current_locus);
7386 : }
7387 : else
7388 : {
7389 1 : p->where = gfc_get_location_range (&saved_loc, 1,
7390 : &saved_loc, 1,
7391 : &saved_loc2);
7392 1 : p->u.adj_args.omp_num_args_plus = true;
7393 : }
7394 : }
7395 115 : else if (!p->expr)
7396 : {
7397 99 : match m = gfc_match_expr (&p->expr);
7398 99 : if (m != MATCH_YES)
7399 : {
7400 1 : gfc_error ("expected dummy parameter name, "
7401 : "%<omp_num_args%> or constant positive integer"
7402 : " at %C");
7403 1 : p->u.adj_args.error_p = true;
7404 1 : return MATCH_ERROR;
7405 : }
7406 98 : if (p->expr->expr_type == EXPR_CONSTANT && !have_range)
7407 98 : need_range = true; /* Constant expr but not literal. */
7408 98 : p->where = p->expr->where;
7409 : }
7410 : else
7411 16 : p->where = p->expr->where;
7412 120 : gfc_gobble_whitespace ();
7413 120 : match m = gfc_match (": ");
7414 120 : if (need_range && m != MATCH_YES)
7415 : {
7416 1 : gfc_error ("expected %<:%> at %C");
7417 1 : return MATCH_ERROR;
7418 : }
7419 119 : if (m == MATCH_YES)
7420 : {
7421 6 : p->u.adj_args.range_start = have_range = true;
7422 6 : need_range = false;
7423 6 : continue;
7424 : }
7425 113 : need_range = have_range = false;
7426 113 : if (gfc_match (", ") == MATCH_YES)
7427 38 : continue;
7428 75 : if (gfc_match (") ") == MATCH_YES)
7429 : break;
7430 : }
7431 : }
7432 32 : else if (ccode == clause_append_args)
7433 : {
7434 32 : if (has_append_args)
7435 : {
7436 1 : gfc_error ("%qs clause at %L specified more than once",
7437 : "append_args", &gfc_current_locus);
7438 1 : return MATCH_ERROR;
7439 : }
7440 56 : has_append_args = true;
7441 : gfc_omp_namelist *append_args_last = NULL;
7442 81 : do
7443 : {
7444 56 : gfc_gobble_whitespace ();
7445 56 : if (gfc_match ("interop ") != MATCH_YES)
7446 : {
7447 0 : gfc_error ("expected %<interop%> at %C");
7448 3 : return MATCH_ERROR;
7449 : }
7450 56 : if (gfc_match ("( ") != MATCH_YES)
7451 : {
7452 0 : gfc_error ("expected %<(%> at %C");
7453 0 : return MATCH_ERROR;
7454 : }
7455 :
7456 56 : bool target, targetsync;
7457 56 : char *type_str = NULL;
7458 56 : int type_str_len;
7459 56 : locus loc = gfc_current_locus;
7460 56 : if (gfc_parser_omp_clause_init_modifiers (target, targetsync,
7461 : &type_str, type_str_len,
7462 : false) == MATCH_ERROR)
7463 : return MATCH_ERROR;
7464 :
7465 54 : gfc_omp_namelist *n = gfc_get_omp_namelist();
7466 54 : n->where = loc;
7467 54 : n->u.init.target = target;
7468 54 : n->u.init.targetsync = targetsync;
7469 54 : n->u.init.len = type_str_len;
7470 54 : n->u2.init_interop = type_str;
7471 54 : if (odv->append_args_list)
7472 : {
7473 25 : append_args_last->next = n;
7474 25 : append_args_last = n;
7475 : }
7476 : else
7477 29 : append_args_last = odv->append_args_list = n;
7478 :
7479 54 : gfc_gobble_whitespace ();
7480 54 : if (gfc_match_char (',') == MATCH_YES)
7481 25 : continue;
7482 29 : if (gfc_match_char (')') == MATCH_YES)
7483 : break;
7484 1 : gfc_error ("Expected %<,%> or %<)%> at %C");
7485 1 : return MATCH_ERROR;
7486 : }
7487 : while (true);
7488 : }
7489 466 : gfc_gobble_whitespace ();
7490 466 : if (gfc_match_omp_eos () == MATCH_YES)
7491 : break;
7492 109 : gfc_match_char (',');
7493 109 : }
7494 :
7495 363 : if (error_p || (!has_match && !has_adjust_args && !has_append_args))
7496 : {
7497 6 : gfc_error ("expected %<match%>, %<adjust_args%> or %<append_args%> at %C");
7498 6 : return MATCH_ERROR;
7499 : }
7500 :
7501 357 : if (!has_match)
7502 : {
7503 3 : gfc_error ("expected %<match%> clause at %C");
7504 3 : return MATCH_ERROR;
7505 : }
7506 :
7507 : return MATCH_YES;
7508 : }
7509 :
7510 :
7511 : static match
7512 160 : match_omp_metadirective (bool begin_p)
7513 : {
7514 160 : locus old_loc = gfc_current_locus;
7515 160 : gfc_omp_variant *variants_head;
7516 160 : gfc_omp_variant **next_variant = &variants_head;
7517 160 : bool default_seen = false;
7518 :
7519 : /* Parse the context selectors. */
7520 656 : for (;;)
7521 : {
7522 408 : bool default_p = false;
7523 408 : gfc_omp_set_selector *selectors = NULL;
7524 :
7525 408 : gfc_gobble_whitespace ();
7526 408 : if (gfc_match_eos () == MATCH_YES)
7527 : break;
7528 266 : gfc_match_char (',');
7529 266 : gfc_gobble_whitespace ();
7530 :
7531 266 : locus variant_locus = gfc_current_locus;
7532 :
7533 266 : if (gfc_match ("default ( ") == MATCH_YES)
7534 : {
7535 82 : default_p = true;
7536 82 : gfc_warning (OPT_Wdeprecated_openmp,
7537 : "%<default%> clause with metadirective at %L "
7538 : "deprecated since OpenMP 5.2", &variant_locus);
7539 : }
7540 184 : else if (gfc_match ("otherwise ( ") == MATCH_YES)
7541 : default_p = true;
7542 177 : else if (gfc_match ("when ( ") != MATCH_YES)
7543 : {
7544 1 : gfc_error ("expected %<when%>, %<otherwise%>, or %<default%> at %C");
7545 1 : gfc_current_locus = old_loc;
7546 18 : return MATCH_ERROR;
7547 : }
7548 89 : if (default_p && default_seen)
7549 : {
7550 3 : gfc_error ("too many %<otherwise%> or %<default%> clauses "
7551 : "in %<metadirective%> at %C");
7552 3 : gfc_current_locus = old_loc;
7553 3 : return MATCH_ERROR;
7554 : }
7555 262 : else if (default_seen)
7556 : {
7557 1 : gfc_error ("%<otherwise%> or %<default%> clause "
7558 : "must appear last in %<metadirective%> at %C");
7559 1 : gfc_current_locus = old_loc;
7560 1 : return MATCH_ERROR;
7561 : }
7562 :
7563 261 : if (!default_p)
7564 : {
7565 175 : if (gfc_match_omp_context_selector_specification (&selectors)
7566 : != MATCH_YES)
7567 : return MATCH_ERROR;
7568 :
7569 168 : if (gfc_match (" : ") != MATCH_YES)
7570 : {
7571 1 : gfc_error ("expected %<:%> at %C");
7572 1 : gfc_current_locus = old_loc;
7573 1 : return MATCH_ERROR;
7574 : }
7575 :
7576 167 : gfc_commit_symbols ();
7577 : }
7578 :
7579 253 : gfc_matching_omp_context_selector = true;
7580 253 : gfc_statement directive = match_omp_directive ();
7581 253 : gfc_matching_omp_context_selector = false;
7582 :
7583 253 : if (is_omp_declarative_stmt (directive))
7584 0 : sorry_at (gfc_get_location (&gfc_current_locus),
7585 : "declarative directive variants are not supported");
7586 :
7587 253 : if (gfc_error_flag_test ())
7588 : {
7589 2 : gfc_current_locus = old_loc;
7590 2 : return MATCH_ERROR;
7591 : }
7592 :
7593 251 : if (gfc_match (" )") != MATCH_YES)
7594 : {
7595 0 : gfc_error ("Expected %<)%> at %C");
7596 0 : gfc_current_locus = old_loc;
7597 0 : return MATCH_ERROR;
7598 : }
7599 :
7600 251 : gfc_commit_symbols ();
7601 :
7602 251 : if (begin_p
7603 251 : && directive != ST_NONE
7604 251 : && gfc_omp_end_stmt (directive) == ST_NONE)
7605 : {
7606 3 : gfc_error ("variant directive used in OMP BEGIN METADIRECTIVE "
7607 : "at %C must have a corresponding end directive");
7608 3 : gfc_current_locus = old_loc;
7609 3 : return MATCH_ERROR;
7610 : }
7611 :
7612 248 : if (default_p)
7613 : default_seen = true;
7614 :
7615 248 : gfc_omp_variant *omv = gfc_get_omp_variant ();
7616 248 : omv->selectors = selectors;
7617 248 : omv->stmt = directive;
7618 248 : omv->where = variant_locus;
7619 :
7620 248 : if (directive == ST_NONE)
7621 : {
7622 : /* The directive was a 'nothing' directive. */
7623 15 : omv->code = gfc_get_code (EXEC_CONTINUE);
7624 15 : omv->code->ext.omp_clauses = NULL;
7625 : }
7626 : else
7627 : {
7628 233 : omv->code = gfc_get_code (new_st.op);
7629 233 : omv->code->ext.omp_clauses = new_st.ext.omp_clauses;
7630 : /* Prevent the OpenMP clauses from being freed via NEW_ST. */
7631 233 : new_st.ext.omp_clauses = NULL;
7632 : }
7633 :
7634 248 : *next_variant = omv;
7635 248 : next_variant = &omv->next;
7636 248 : }
7637 :
7638 142 : if (gfc_match_omp_eos () != MATCH_YES)
7639 : {
7640 0 : gfc_error ("Unexpected junk after OMP METADIRECTIVE at %C");
7641 0 : gfc_current_locus = old_loc;
7642 0 : return MATCH_ERROR;
7643 : }
7644 :
7645 : /* Add a 'default (nothing)' clause if no default is explicitly given. */
7646 142 : if (!default_seen)
7647 : {
7648 65 : gfc_omp_variant *omv = gfc_get_omp_variant ();
7649 65 : omv->stmt = ST_NONE;
7650 65 : omv->code = gfc_get_code (EXEC_CONTINUE);
7651 65 : omv->code->ext.omp_clauses = NULL;
7652 65 : omv->where = old_loc;
7653 65 : omv->selectors = NULL;
7654 :
7655 65 : *next_variant = omv;
7656 65 : next_variant = &omv->next;
7657 : }
7658 :
7659 142 : new_st.op = EXEC_OMP_METADIRECTIVE;
7660 142 : new_st.ext.omp_variants = variants_head;
7661 :
7662 142 : return MATCH_YES;
7663 : }
7664 :
7665 : match
7666 43 : gfc_match_omp_begin_metadirective (void)
7667 : {
7668 43 : return match_omp_metadirective (true);
7669 : }
7670 :
7671 : match
7672 117 : gfc_match_omp_metadirective (void)
7673 : {
7674 117 : return match_omp_metadirective (false);
7675 : }
7676 :
7677 : /* Match 'omp threadprivate' or 'omp groupprivate'. */
7678 : static match
7679 259 : gfc_match_omp_thread_group_private (bool is_groupprivate)
7680 : {
7681 259 : locus old_loc;
7682 259 : char n[GFC_MAX_SYMBOL_LEN+1];
7683 259 : gfc_symbol *sym;
7684 259 : match m;
7685 259 : gfc_symtree *st;
7686 259 : struct sym_loc_t { gfc_symbol *sym; gfc_common_head *com; locus loc; };
7687 259 : auto_vec<sym_loc_t> syms;
7688 :
7689 259 : old_loc = gfc_current_locus;
7690 :
7691 259 : m = gfc_match (" ( ");
7692 259 : if (m != MATCH_YES)
7693 : return m;
7694 :
7695 369 : for (;;)
7696 : {
7697 314 : locus sym_loc = gfc_current_locus;
7698 314 : m = gfc_match_symbol (&sym, 0);
7699 314 : switch (m)
7700 : {
7701 209 : case MATCH_YES:
7702 209 : if (sym->attr.in_common)
7703 0 : gfc_error_now ("%qs variable at %L is an element of a COMMON block",
7704 : is_groupprivate ? "groupprivate" : "threadprivate",
7705 : &sym_loc);
7706 209 : else if (!is_groupprivate
7707 209 : && !gfc_add_threadprivate (&sym->attr, sym->name, &sym_loc))
7708 16 : goto cleanup;
7709 207 : else if (is_groupprivate)
7710 : {
7711 30 : if (!gfc_add_omp_groupprivate (&sym->attr, sym->name, &sym_loc))
7712 4 : goto cleanup;
7713 26 : syms.safe_push ({sym, nullptr, sym_loc});
7714 : }
7715 203 : goto next_item;
7716 : case MATCH_NO:
7717 : break;
7718 0 : case MATCH_ERROR:
7719 0 : goto cleanup;
7720 : }
7721 :
7722 105 : m = gfc_match (" / %n /", n);
7723 105 : if (m == MATCH_ERROR)
7724 0 : goto cleanup;
7725 105 : if (m == MATCH_NO || n[0] == '\0')
7726 0 : goto syntax;
7727 :
7728 105 : st = gfc_find_symtree (gfc_current_ns->common_root, n);
7729 105 : if (st == NULL)
7730 : {
7731 2 : gfc_error ("COMMON block /%s/ not found at %L", n, &sym_loc);
7732 2 : goto cleanup;
7733 : }
7734 103 : syms.safe_push ({nullptr, st->n.common, sym_loc});
7735 103 : if (is_groupprivate)
7736 30 : st->n.common->omp_groupprivate = 1;
7737 : else
7738 73 : st->n.common->threadprivate = 1;
7739 236 : for (sym = st->n.common->head; sym; sym = sym->common_next)
7740 141 : if (!is_groupprivate
7741 141 : && !gfc_add_threadprivate (&sym->attr, sym->name, &sym_loc))
7742 3 : goto cleanup;
7743 138 : else if (is_groupprivate
7744 138 : && !gfc_add_omp_groupprivate (&sym->attr, sym->name, &sym_loc))
7745 5 : goto cleanup;
7746 :
7747 95 : next_item:
7748 298 : if (gfc_match_char (')') == MATCH_YES)
7749 : break;
7750 55 : if (gfc_match_char (',') != MATCH_YES)
7751 0 : goto syntax;
7752 55 : }
7753 :
7754 243 : if (is_groupprivate)
7755 : {
7756 39 : gfc_omp_clauses *c;
7757 39 : m = gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_DEVICE_TYPE));
7758 39 : if (m == MATCH_ERROR)
7759 0 : return MATCH_ERROR;
7760 :
7761 39 : if (c->device_type == OMP_DEVICE_TYPE_UNSET)
7762 19 : c->device_type = OMP_DEVICE_TYPE_ANY;
7763 :
7764 86 : for (size_t i = 0; i < syms.length (); i++)
7765 47 : if (syms[i].sym)
7766 : {
7767 24 : sym_loc_t &n = syms[i];
7768 24 : if (n.sym->attr.in_common)
7769 0 : gfc_error_now ("Variable %qs at %L is an element of a COMMON "
7770 : "block", n.sym->name, &n.loc);
7771 24 : else if (n.sym->attr.omp_declare_target
7772 23 : || n.sym->attr.omp_declare_target_link)
7773 2 : gfc_error_now ("List item %qs at %L implies OMP DECLARE TARGET "
7774 : "with the LOCAL clause, but it has been specified"
7775 : " with a different clause before",
7776 : n.sym->name, &n.loc);
7777 24 : if (n.sym->attr.omp_device_type != OMP_DEVICE_TYPE_UNSET
7778 5 : && n.sym->attr.omp_device_type != c->device_type)
7779 : {
7780 2 : const char *dt = "any";
7781 2 : if (n.sym->attr.omp_device_type == OMP_DEVICE_TYPE_HOST)
7782 : dt = "host";
7783 0 : else if (n.sym->attr.omp_device_type == OMP_DEVICE_TYPE_NOHOST)
7784 0 : dt = "nohost";
7785 2 : gfc_error_now ("List item %qs at %L set in previous OMP DECLARE "
7786 : "TARGET directive to the different DEVICE_TYPE %qs",
7787 : n.sym->name, &n.loc, dt);
7788 : }
7789 24 : gfc_add_omp_declare_target_local (&n.sym->attr, n.sym->name,
7790 : &n.loc);
7791 24 : n.sym->attr.omp_device_type = c->device_type;
7792 : }
7793 : else /* Common block. */
7794 : {
7795 23 : sym_loc_t &n = syms[i];
7796 23 : if (n.com->omp_declare_target
7797 22 : || n.com->omp_declare_target_link)
7798 2 : gfc_error_now ("List item %</%s/%> at %L implies OMP DECLARE "
7799 : "TARGET with the LOCAL clause, but it has been "
7800 : "specified with a different clause before",
7801 2 : n.com->name, &n.loc);
7802 23 : if (n.com->omp_device_type != OMP_DEVICE_TYPE_UNSET
7803 5 : && n.com->omp_device_type != c->device_type)
7804 : {
7805 2 : const char *dt = "any";
7806 2 : if (n.com->omp_device_type == OMP_DEVICE_TYPE_HOST)
7807 : dt = "host";
7808 0 : else if (n.com->omp_device_type == OMP_DEVICE_TYPE_NOHOST)
7809 0 : dt = "nohost";
7810 2 : gfc_error_now ("List item %qs at %L set in previous OMP DECLARE"
7811 : " TARGET directive to the different DEVICE_TYPE "
7812 2 : "%qs", n.com->name, &n.loc, dt);
7813 : }
7814 23 : n.com->omp_declare_target_local = 1;
7815 23 : n.com->omp_device_type = c->device_type;
7816 46 : for (gfc_symbol *s = n.com->head; s; s = s->common_next)
7817 : {
7818 23 : gfc_add_omp_declare_target_local (&s->attr, s->name, &n.loc);
7819 23 : s->attr.omp_device_type = c->device_type;
7820 : }
7821 : }
7822 39 : free (c);
7823 : }
7824 :
7825 243 : if (gfc_match_omp_eos () != MATCH_YES)
7826 : {
7827 0 : gfc_error ("Unexpected junk after OMP %s at %C",
7828 : is_groupprivate ? "GROUPPRIVATE" : "THREADPRIVATE");
7829 0 : goto cleanup;
7830 : }
7831 :
7832 : return MATCH_YES;
7833 :
7834 0 : syntax:
7835 0 : gfc_error ("Syntax error in !$OMP %s list at %C",
7836 : is_groupprivate ? "GROUPPRIVATE" : "THREADPRIVATE");
7837 :
7838 16 : cleanup:
7839 16 : gfc_current_locus = old_loc;
7840 16 : return MATCH_ERROR;
7841 259 : }
7842 :
7843 :
7844 : match
7845 48 : gfc_match_omp_groupprivate (void)
7846 : {
7847 48 : return gfc_match_omp_thread_group_private (true);
7848 : }
7849 :
7850 :
7851 : match
7852 211 : gfc_match_omp_threadprivate (void)
7853 : {
7854 211 : return gfc_match_omp_thread_group_private (false);
7855 : }
7856 :
7857 :
7858 : match
7859 2160 : gfc_match_omp_parallel (void)
7860 : {
7861 2160 : return match_omp (EXEC_OMP_PARALLEL, OMP_PARALLEL_CLAUSES);
7862 : }
7863 :
7864 :
7865 : match
7866 1203 : gfc_match_omp_parallel_do (void)
7867 : {
7868 1203 : return match_omp (EXEC_OMP_PARALLEL_DO,
7869 1203 : (OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES)
7870 1203 : & ~(omp_mask (OMP_CLAUSE_NOWAIT)));
7871 : }
7872 :
7873 :
7874 : match
7875 298 : gfc_match_omp_parallel_do_simd (void)
7876 : {
7877 298 : return match_omp (EXEC_OMP_PARALLEL_DO_SIMD,
7878 298 : (OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES | OMP_SIMD_CLAUSES)
7879 298 : & ~(omp_mask (OMP_CLAUSE_NOWAIT)));
7880 : }
7881 :
7882 :
7883 : match
7884 14 : gfc_match_omp_parallel_masked (void)
7885 : {
7886 14 : return match_omp (EXEC_OMP_PARALLEL_MASKED,
7887 14 : OMP_PARALLEL_CLAUSES | OMP_MASKED_CLAUSES);
7888 : }
7889 :
7890 : match
7891 10 : gfc_match_omp_parallel_masked_taskloop (void)
7892 : {
7893 10 : return match_omp (EXEC_OMP_PARALLEL_MASKED_TASKLOOP,
7894 10 : (OMP_PARALLEL_CLAUSES | OMP_MASKED_CLAUSES
7895 10 : | OMP_TASKLOOP_CLAUSES)
7896 10 : & ~(omp_mask (OMP_CLAUSE_IN_REDUCTION)));
7897 : }
7898 :
7899 : match
7900 13 : gfc_match_omp_parallel_masked_taskloop_simd (void)
7901 : {
7902 13 : return match_omp (EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD,
7903 13 : (OMP_PARALLEL_CLAUSES | OMP_MASKED_CLAUSES
7904 13 : | OMP_TASKLOOP_CLAUSES | OMP_SIMD_CLAUSES)
7905 13 : & ~(omp_mask (OMP_CLAUSE_IN_REDUCTION)));
7906 : }
7907 :
7908 : match
7909 14 : gfc_match_omp_parallel_master (void)
7910 : {
7911 14 : gfc_warning (OPT_Wdeprecated_openmp,
7912 : "%<master%> construct at %C deprecated since OpenMP 5.1, use "
7913 : "%<masked%>");
7914 14 : return match_omp (EXEC_OMP_PARALLEL_MASTER, OMP_PARALLEL_CLAUSES);
7915 : }
7916 :
7917 : match
7918 15 : gfc_match_omp_parallel_master_taskloop (void)
7919 : {
7920 15 : gfc_warning (OPT_Wdeprecated_openmp,
7921 : "%<master%> construct at %C deprecated since OpenMP 5.1, "
7922 : "use %<masked%>");
7923 15 : return match_omp (EXEC_OMP_PARALLEL_MASTER_TASKLOOP,
7924 15 : (OMP_PARALLEL_CLAUSES | OMP_TASKLOOP_CLAUSES)
7925 15 : & ~(omp_mask (OMP_CLAUSE_IN_REDUCTION)));
7926 : }
7927 :
7928 : match
7929 21 : gfc_match_omp_parallel_master_taskloop_simd (void)
7930 : {
7931 21 : gfc_warning (OPT_Wdeprecated_openmp,
7932 : "%<master%> construct at %C deprecated since OpenMP 5.1, "
7933 : "use %<masked%>");
7934 21 : return match_omp (EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD,
7935 21 : (OMP_PARALLEL_CLAUSES | OMP_TASKLOOP_CLAUSES
7936 21 : | OMP_SIMD_CLAUSES)
7937 21 : & ~(omp_mask (OMP_CLAUSE_IN_REDUCTION)));
7938 : }
7939 :
7940 : match
7941 59 : gfc_match_omp_parallel_sections (void)
7942 : {
7943 59 : return match_omp (EXEC_OMP_PARALLEL_SECTIONS,
7944 59 : (OMP_PARALLEL_CLAUSES | OMP_SECTIONS_CLAUSES)
7945 59 : & ~(omp_mask (OMP_CLAUSE_NOWAIT)));
7946 : }
7947 :
7948 :
7949 : match
7950 56 : gfc_match_omp_parallel_workshare (void)
7951 : {
7952 56 : return match_omp (EXEC_OMP_PARALLEL_WORKSHARE, OMP_PARALLEL_CLAUSES);
7953 : }
7954 :
7955 : void
7956 49715 : gfc_check_omp_requires (gfc_namespace *ns, int ref_omp_requires)
7957 : {
7958 49715 : const char *msg = G_("Program unit at %L has OpenMP device "
7959 : "constructs/routines but does not set !$OMP REQUIRES %s "
7960 : "but other program units do");
7961 49715 : if (ns->omp_target_seen
7962 1292 : && (ns->omp_requires & OMP_REQ_TARGET_MASK)
7963 1292 : != (ref_omp_requires & OMP_REQ_TARGET_MASK))
7964 : {
7965 6 : gcc_assert (ns->proc_name);
7966 6 : if ((ref_omp_requires & OMP_REQ_REVERSE_OFFLOAD)
7967 5 : && !(ns->omp_requires & OMP_REQ_REVERSE_OFFLOAD))
7968 4 : gfc_error (msg, &ns->proc_name->declared_at, "REVERSE_OFFLOAD");
7969 6 : if ((ref_omp_requires & OMP_REQ_UNIFIED_ADDRESS)
7970 1 : && !(ns->omp_requires & OMP_REQ_UNIFIED_ADDRESS))
7971 1 : gfc_error (msg, &ns->proc_name->declared_at, "UNIFIED_ADDRESS");
7972 6 : if ((ref_omp_requires & OMP_REQ_UNIFIED_SHARED_MEMORY)
7973 4 : && !(ns->omp_requires & OMP_REQ_UNIFIED_SHARED_MEMORY))
7974 2 : gfc_error (msg, &ns->proc_name->declared_at, "UNIFIED_SHARED_MEMORY");
7975 6 : if ((ref_omp_requires & OMP_REQ_SELF_MAPS)
7976 1 : && !(ns->omp_requires & OMP_REQ_UNIFIED_SHARED_MEMORY))
7977 1 : gfc_error (msg, &ns->proc_name->declared_at, "SELF_MAPS");
7978 : }
7979 49715 : }
7980 :
7981 : bool
7982 126 : gfc_omp_requires_add_clause (gfc_omp_requires_kind clause,
7983 : const char *clause_name, locus *loc,
7984 : const char *module_name)
7985 : {
7986 126 : gfc_namespace *prog_unit = gfc_current_ns;
7987 150 : while (prog_unit->parent)
7988 : {
7989 26 : if (gfc_state_stack->previous
7990 26 : && gfc_state_stack->previous->state == COMP_INTERFACE)
7991 : break;
7992 : /* A submodule namespace may have its parent set to the ancestor module
7993 : for host-association purposes. Do not escape the submodule boundary:
7994 : the submodule itself is the program unit for OMP REQUIRES purposes. */
7995 25 : if (prog_unit->proc_name
7996 25 : && prog_unit->proc_name->attr.flavor == FL_MODULE)
7997 : break;
7998 : prog_unit = prog_unit->parent;
7999 : }
8000 :
8001 : /* Requires added after use. */
8002 126 : if (prog_unit->omp_target_seen
8003 24 : && (clause & OMP_REQ_TARGET_MASK)
8004 24 : && !(prog_unit->omp_requires & clause))
8005 : {
8006 0 : if (module_name)
8007 0 : gfc_error ("!$OMP REQUIRES clause %qs specified via module %qs use "
8008 : "at %L comes after using a device construct/routine",
8009 : clause_name, module_name, loc);
8010 : else
8011 0 : gfc_error ("!$OMP REQUIRES clause %qs specified at %L comes after "
8012 : "using a device construct/routine", clause_name, loc);
8013 0 : return false;
8014 : }
8015 :
8016 : /* Overriding atomic_default_mem_order clause value. */
8017 126 : if ((clause & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
8018 34 : && (prog_unit->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
8019 6 : && (prog_unit->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
8020 6 : != (int) clause)
8021 : {
8022 3 : const char *other;
8023 3 : switch (prog_unit->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
8024 : {
8025 : case OMP_REQ_ATOMIC_MEM_ORDER_SEQ_CST: other = "seq_cst"; break;
8026 0 : case OMP_REQ_ATOMIC_MEM_ORDER_ACQ_REL: other = "acq_rel"; break;
8027 1 : case OMP_REQ_ATOMIC_MEM_ORDER_ACQUIRE: other = "acquire"; break;
8028 1 : case OMP_REQ_ATOMIC_MEM_ORDER_RELAXED: other = "relaxed"; break;
8029 0 : case OMP_REQ_ATOMIC_MEM_ORDER_RELEASE: other = "release"; break;
8030 0 : default: gcc_unreachable ();
8031 : }
8032 :
8033 3 : if (module_name)
8034 0 : gfc_error ("!$OMP REQUIRES clause %<atomic_default_mem_order(%s)%> "
8035 : "specified via module %qs use at %L overrides a previous "
8036 : "%<atomic_default_mem_order(%s)%> (which might be through "
8037 : "using a module)", clause_name, module_name, loc, other);
8038 : else
8039 3 : gfc_error ("!$OMP REQUIRES clause %<atomic_default_mem_order(%s)%> "
8040 : "specified at %L overrides a previous "
8041 : "%<atomic_default_mem_order(%s)%> (which might be through "
8042 : "using a module)", clause_name, loc, other);
8043 3 : return false;
8044 : }
8045 :
8046 : /* Requires via module not at program-unit level and not repeating clause. */
8047 123 : if (prog_unit != gfc_current_ns && !(prog_unit->omp_requires & clause))
8048 : {
8049 0 : if (clause & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
8050 0 : gfc_error ("!$OMP REQUIRES clause %<atomic_default_mem_order(%s)%> "
8051 : "specified via module %qs use at %L but same clause is "
8052 : "not specified for the program unit", clause_name,
8053 : module_name, loc);
8054 : else
8055 0 : gfc_error ("!$OMP REQUIRES clause %qs specified via module %qs use at "
8056 : "%L but same clause is not specified for the program unit",
8057 : clause_name, module_name, loc);
8058 0 : return false;
8059 : }
8060 :
8061 123 : if (!gfc_state_stack->previous
8062 115 : || gfc_state_stack->previous->state != COMP_INTERFACE)
8063 122 : prog_unit->omp_requires |= clause;
8064 : return true;
8065 : }
8066 :
8067 : match
8068 98 : gfc_match_omp_requires (void)
8069 : {
8070 98 : static const char *clauses[] = {"reverse_offload",
8071 : "unified_address",
8072 : "unified_shared_memory",
8073 : "self_maps",
8074 : "dynamic_allocators",
8075 : "atomic_default"};
8076 98 : const char *clause = NULL;
8077 98 : int requires_clauses = 0;
8078 98 : bool first = true;
8079 98 : locus old_loc;
8080 :
8081 : /* A submodule's namespace may have its parent pointer set to the ancestor
8082 : module namespace for host-association purposes. The submodule spec part
8083 : is still a valid program-unit spec part for OMP REQUIRES. Only reject
8084 : the directive when we are genuinely nested inside a procedure. */
8085 98 : if (gfc_current_ns->parent
8086 8 : && !(gfc_current_ns->proc_name
8087 8 : && gfc_current_ns->proc_name->attr.flavor == FL_MODULE)
8088 7 : && (!gfc_state_stack->previous
8089 7 : || gfc_state_stack->previous->state != COMP_INTERFACE))
8090 : {
8091 6 : gfc_error ("!$OMP REQUIRES at %C must appear in the specification part "
8092 : "of a program unit");
8093 6 : return MATCH_ERROR;
8094 : }
8095 :
8096 276 : while (true)
8097 : {
8098 184 : old_loc = gfc_current_locus;
8099 184 : gfc_omp_requires_kind requires_clause;
8100 92 : if ((first || gfc_match_char (',') != MATCH_YES)
8101 184 : && (first && gfc_match_space () != MATCH_YES))
8102 0 : goto error;
8103 184 : first = false;
8104 184 : gfc_gobble_whitespace ();
8105 184 : old_loc = gfc_current_locus;
8106 :
8107 184 : if (gfc_match_omp_eos () != MATCH_NO)
8108 : break;
8109 103 : if (gfc_match (clauses[0]) == MATCH_YES)
8110 : {
8111 34 : clause = clauses[0];
8112 34 : requires_clause = OMP_REQ_REVERSE_OFFLOAD;
8113 34 : if (requires_clauses & OMP_REQ_REVERSE_OFFLOAD)
8114 1 : goto duplicate_clause;
8115 : }
8116 69 : else if (gfc_match (clauses[1]) == MATCH_YES)
8117 : {
8118 9 : clause = clauses[1];
8119 9 : requires_clause = OMP_REQ_UNIFIED_ADDRESS;
8120 9 : if (requires_clauses & OMP_REQ_UNIFIED_ADDRESS)
8121 1 : goto duplicate_clause;
8122 : }
8123 60 : else if (gfc_match (clauses[2]) == MATCH_YES)
8124 : {
8125 14 : clause = clauses[2];
8126 14 : requires_clause = OMP_REQ_UNIFIED_SHARED_MEMORY;
8127 14 : if (requires_clauses & OMP_REQ_UNIFIED_SHARED_MEMORY)
8128 1 : goto duplicate_clause;
8129 : }
8130 46 : else if (gfc_match (clauses[3]) == MATCH_YES)
8131 : {
8132 7 : clause = clauses[3];
8133 7 : requires_clause = OMP_REQ_SELF_MAPS;
8134 7 : if (requires_clauses & OMP_REQ_SELF_MAPS)
8135 0 : goto duplicate_clause;
8136 : }
8137 39 : else if (gfc_match (clauses[4]) == MATCH_YES)
8138 : {
8139 7 : clause = clauses[4];
8140 7 : requires_clause = OMP_REQ_DYNAMIC_ALLOCATORS;
8141 7 : if (requires_clauses & OMP_REQ_DYNAMIC_ALLOCATORS)
8142 1 : goto duplicate_clause;
8143 : }
8144 32 : else if (gfc_match ("atomic_default_mem_order (") == MATCH_YES)
8145 : {
8146 31 : clause = clauses[5];
8147 31 : if (requires_clauses & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
8148 1 : goto duplicate_clause;
8149 30 : if (gfc_match (" seq_cst )") == MATCH_YES)
8150 : {
8151 : clause = "seq_cst";
8152 : requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_SEQ_CST;
8153 : }
8154 18 : else if (gfc_match (" acq_rel )") == MATCH_YES)
8155 : {
8156 : clause = "acq_rel";
8157 : requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_ACQ_REL;
8158 : }
8159 12 : else if (gfc_match (" acquire )") == MATCH_YES)
8160 : {
8161 : clause = "acquire";
8162 : requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_ACQUIRE;
8163 : }
8164 9 : else if (gfc_match (" relaxed )") == MATCH_YES)
8165 : {
8166 : clause = "relaxed";
8167 : requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_RELAXED;
8168 : }
8169 5 : else if (gfc_match (" release )") == MATCH_YES)
8170 : {
8171 : clause = "release";
8172 : requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_RELEASE;
8173 : }
8174 : else
8175 : {
8176 2 : gfc_error ("Expected ACQ_REL, ACQUIRE, RELAXED, RELEASE or "
8177 : "SEQ_CST for ATOMIC_DEFAULT_MEM_ORDER clause at %C");
8178 2 : goto error;
8179 : }
8180 : }
8181 : else
8182 1 : goto error;
8183 :
8184 95 : if (!gfc_omp_requires_add_clause (requires_clause, clause, &old_loc, NULL))
8185 3 : goto error;
8186 92 : requires_clauses |= requires_clause;
8187 92 : }
8188 :
8189 81 : if (requires_clauses == 0)
8190 : {
8191 1 : if (!gfc_error_flag_test ())
8192 1 : gfc_error ("Clause expected at %C");
8193 1 : goto error;
8194 : }
8195 : return MATCH_YES;
8196 :
8197 5 : duplicate_clause:
8198 5 : gfc_error ("%qs clause at %L specified more than once", clause, &old_loc);
8199 12 : error:
8200 12 : if (!gfc_error_flag_test ())
8201 1 : gfc_error ("Expected UNIFIED_ADDRESS, UNIFIED_SHARED_MEMORY, SELF_MAPS, "
8202 : "DYNAMIC_ALLOCATORS, REVERSE_OFFLOAD, or "
8203 : "ATOMIC_DEFAULT_MEM_ORDER clause at %L", &old_loc);
8204 : return MATCH_ERROR;
8205 : }
8206 :
8207 :
8208 : match
8209 51 : gfc_match_omp_scan (void)
8210 : {
8211 51 : bool incl;
8212 51 : gfc_omp_clauses *c = gfc_get_omp_clauses ();
8213 51 : gfc_gobble_whitespace ();
8214 51 : if ((incl = (gfc_match ("inclusive") == MATCH_YES))
8215 51 : || gfc_match ("exclusive") == MATCH_YES)
8216 : {
8217 70 : if (gfc_match_omp_variable_list (" (", &c->lists[incl ? OMP_LIST_SCAN_IN
8218 : : OMP_LIST_SCAN_EX],
8219 : false) != MATCH_YES)
8220 : {
8221 0 : gfc_free_omp_clauses (c);
8222 0 : return MATCH_ERROR;
8223 : }
8224 : }
8225 : else
8226 : {
8227 1 : gfc_error ("Expected INCLUSIVE or EXCLUSIVE clause at %C");
8228 1 : gfc_free_omp_clauses (c);
8229 1 : return MATCH_ERROR;
8230 : }
8231 50 : if (gfc_match_omp_eos () != MATCH_YES)
8232 : {
8233 1 : gfc_error ("Unexpected junk after !$OMP SCAN at %C");
8234 1 : gfc_free_omp_clauses (c);
8235 1 : return MATCH_ERROR;
8236 : }
8237 :
8238 49 : new_st.op = EXEC_OMP_SCAN;
8239 49 : new_st.ext.omp_clauses = c;
8240 49 : return MATCH_YES;
8241 : }
8242 :
8243 :
8244 : match
8245 58 : gfc_match_omp_scope (void)
8246 : {
8247 58 : return match_omp (EXEC_OMP_SCOPE, OMP_SCOPE_CLAUSES);
8248 : }
8249 :
8250 :
8251 : match
8252 82 : gfc_match_omp_sections (void)
8253 : {
8254 82 : return match_omp (EXEC_OMP_SECTIONS, OMP_SECTIONS_CLAUSES);
8255 : }
8256 :
8257 :
8258 : match
8259 782 : gfc_match_omp_simd (void)
8260 : {
8261 782 : return match_omp (EXEC_OMP_SIMD, OMP_SIMD_CLAUSES);
8262 : }
8263 :
8264 :
8265 : match
8266 570 : gfc_match_omp_single (void)
8267 : {
8268 570 : return match_omp (EXEC_OMP_SINGLE, OMP_SINGLE_CLAUSES);
8269 : }
8270 :
8271 :
8272 : match
8273 2244 : gfc_match_omp_target (void)
8274 : {
8275 2244 : return match_omp (EXEC_OMP_TARGET, OMP_TARGET_CLAUSES);
8276 : }
8277 :
8278 :
8279 : match
8280 1399 : gfc_match_omp_target_data (void)
8281 : {
8282 1399 : return match_omp (EXEC_OMP_TARGET_DATA, OMP_TARGET_DATA_CLAUSES);
8283 : }
8284 :
8285 :
8286 : match
8287 468 : gfc_match_omp_target_enter_data (void)
8288 : {
8289 468 : return match_omp (EXEC_OMP_TARGET_ENTER_DATA, OMP_TARGET_ENTER_DATA_CLAUSES);
8290 : }
8291 :
8292 :
8293 : match
8294 365 : gfc_match_omp_target_exit_data (void)
8295 : {
8296 365 : return match_omp (EXEC_OMP_TARGET_EXIT_DATA, OMP_TARGET_EXIT_DATA_CLAUSES);
8297 : }
8298 :
8299 :
8300 : match
8301 27 : gfc_match_omp_target_parallel (void)
8302 : {
8303 27 : return match_omp (EXEC_OMP_TARGET_PARALLEL,
8304 27 : (OMP_TARGET_CLAUSES | OMP_PARALLEL_CLAUSES)
8305 27 : & ~(omp_mask (OMP_CLAUSE_COPYIN)));
8306 : }
8307 :
8308 :
8309 : match
8310 81 : gfc_match_omp_target_parallel_do (void)
8311 : {
8312 81 : return match_omp (EXEC_OMP_TARGET_PARALLEL_DO,
8313 81 : (OMP_TARGET_CLAUSES | OMP_PARALLEL_CLAUSES
8314 81 : | OMP_DO_CLAUSES) & ~(omp_mask (OMP_CLAUSE_COPYIN)));
8315 : }
8316 :
8317 :
8318 : match
8319 19 : gfc_match_omp_target_parallel_do_simd (void)
8320 : {
8321 19 : return match_omp (EXEC_OMP_TARGET_PARALLEL_DO_SIMD,
8322 19 : (OMP_TARGET_CLAUSES | OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES
8323 19 : | OMP_SIMD_CLAUSES) & ~(omp_mask (OMP_CLAUSE_COPYIN)));
8324 : }
8325 :
8326 :
8327 : match
8328 34 : gfc_match_omp_target_simd (void)
8329 : {
8330 34 : return match_omp (EXEC_OMP_TARGET_SIMD,
8331 34 : OMP_TARGET_CLAUSES | OMP_SIMD_CLAUSES);
8332 : }
8333 :
8334 :
8335 : match
8336 74 : gfc_match_omp_target_teams (void)
8337 : {
8338 74 : return match_omp (EXEC_OMP_TARGET_TEAMS,
8339 74 : OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES);
8340 : }
8341 :
8342 :
8343 : match
8344 19 : gfc_match_omp_target_teams_distribute (void)
8345 : {
8346 19 : return match_omp (EXEC_OMP_TARGET_TEAMS_DISTRIBUTE,
8347 19 : OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES
8348 19 : | OMP_DISTRIBUTE_CLAUSES);
8349 : }
8350 :
8351 :
8352 : match
8353 64 : gfc_match_omp_target_teams_distribute_parallel_do (void)
8354 : {
8355 64 : return match_omp (EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO,
8356 64 : (OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES
8357 64 : | OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
8358 64 : | OMP_DO_CLAUSES)
8359 64 : & ~(omp_mask (OMP_CLAUSE_ORDERED))
8360 64 : & ~(omp_mask (OMP_CLAUSE_LINEAR)));
8361 : }
8362 :
8363 :
8364 : match
8365 35 : gfc_match_omp_target_teams_distribute_parallel_do_simd (void)
8366 : {
8367 35 : return match_omp (EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD,
8368 35 : (OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES
8369 35 : | OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
8370 35 : | OMP_DO_CLAUSES | OMP_SIMD_CLAUSES)
8371 35 : & ~(omp_mask (OMP_CLAUSE_ORDERED)));
8372 : }
8373 :
8374 :
8375 : match
8376 21 : gfc_match_omp_target_teams_distribute_simd (void)
8377 : {
8378 21 : return match_omp (EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD,
8379 21 : OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES
8380 21 : | OMP_DISTRIBUTE_CLAUSES | OMP_SIMD_CLAUSES);
8381 : }
8382 :
8383 :
8384 : match
8385 1725 : gfc_match_omp_target_update (void)
8386 : {
8387 1725 : return match_omp (EXEC_OMP_TARGET_UPDATE, OMP_TARGET_UPDATE_CLAUSES);
8388 : }
8389 :
8390 :
8391 : match
8392 1182 : gfc_match_omp_task (void)
8393 : {
8394 1182 : return match_omp (EXEC_OMP_TASK, OMP_TASK_CLAUSES);
8395 : }
8396 :
8397 :
8398 : match
8399 72 : gfc_match_omp_taskloop (void)
8400 : {
8401 72 : return match_omp (EXEC_OMP_TASKLOOP, OMP_TASKLOOP_CLAUSES);
8402 : }
8403 :
8404 :
8405 : match
8406 40 : gfc_match_omp_taskloop_simd (void)
8407 : {
8408 40 : return match_omp (EXEC_OMP_TASKLOOP_SIMD,
8409 40 : OMP_TASKLOOP_CLAUSES | OMP_SIMD_CLAUSES);
8410 : }
8411 :
8412 :
8413 : match
8414 147 : gfc_match_omp_taskwait (void)
8415 : {
8416 147 : if (gfc_match_omp_eos () == MATCH_YES)
8417 : {
8418 133 : new_st.op = EXEC_OMP_TASKWAIT;
8419 133 : new_st.ext.omp_clauses = NULL;
8420 133 : return MATCH_YES;
8421 : }
8422 14 : return match_omp (EXEC_OMP_TASKWAIT,
8423 14 : omp_mask (OMP_CLAUSE_DEPEND) | OMP_CLAUSE_NOWAIT);
8424 : }
8425 :
8426 :
8427 : match
8428 10 : gfc_match_omp_taskyield (void)
8429 : {
8430 10 : if (gfc_match_omp_eos () != MATCH_YES)
8431 : {
8432 0 : gfc_error ("Unexpected junk after TASKYIELD clause at %C");
8433 0 : return MATCH_ERROR;
8434 : }
8435 10 : new_st.op = EXEC_OMP_TASKYIELD;
8436 10 : new_st.ext.omp_clauses = NULL;
8437 10 : return MATCH_YES;
8438 : }
8439 :
8440 :
8441 : match
8442 150 : gfc_match_omp_teams (void)
8443 : {
8444 150 : return match_omp (EXEC_OMP_TEAMS, OMP_TEAMS_CLAUSES);
8445 : }
8446 :
8447 :
8448 : match
8449 22 : gfc_match_omp_teams_distribute (void)
8450 : {
8451 22 : return match_omp (EXEC_OMP_TEAMS_DISTRIBUTE,
8452 22 : OMP_TEAMS_CLAUSES | OMP_DISTRIBUTE_CLAUSES);
8453 : }
8454 :
8455 :
8456 : match
8457 39 : gfc_match_omp_teams_distribute_parallel_do (void)
8458 : {
8459 39 : return match_omp (EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO,
8460 39 : (OMP_TEAMS_CLAUSES | OMP_DISTRIBUTE_CLAUSES
8461 39 : | OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES)
8462 39 : & ~(omp_mask (OMP_CLAUSE_ORDERED)
8463 39 : | OMP_CLAUSE_LINEAR | OMP_CLAUSE_NOWAIT));
8464 : }
8465 :
8466 :
8467 : match
8468 62 : gfc_match_omp_teams_distribute_parallel_do_simd (void)
8469 : {
8470 62 : return match_omp (EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD,
8471 62 : (OMP_TEAMS_CLAUSES | OMP_DISTRIBUTE_CLAUSES
8472 62 : | OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES
8473 62 : | OMP_SIMD_CLAUSES)
8474 62 : & ~(omp_mask (OMP_CLAUSE_ORDERED) | OMP_CLAUSE_NOWAIT));
8475 : }
8476 :
8477 :
8478 : match
8479 44 : gfc_match_omp_teams_distribute_simd (void)
8480 : {
8481 44 : return match_omp (EXEC_OMP_TEAMS_DISTRIBUTE_SIMD,
8482 44 : OMP_TEAMS_CLAUSES | OMP_DISTRIBUTE_CLAUSES
8483 44 : | OMP_SIMD_CLAUSES);
8484 : }
8485 :
8486 : match
8487 203 : gfc_match_omp_tile (void)
8488 : {
8489 203 : return match_omp (EXEC_OMP_TILE, OMP_TILE_CLAUSES);
8490 : }
8491 :
8492 : match
8493 415 : gfc_match_omp_unroll (void)
8494 : {
8495 415 : return match_omp (EXEC_OMP_UNROLL, OMP_UNROLL_CLAUSES);
8496 : }
8497 :
8498 : match
8499 39 : gfc_match_omp_workshare (void)
8500 : {
8501 39 : return match_omp (EXEC_OMP_WORKSHARE, OMP_WORKSHARE_CLAUSES);
8502 : }
8503 :
8504 :
8505 : match
8506 55 : gfc_match_omp_masked (void)
8507 : {
8508 55 : return match_omp (EXEC_OMP_MASKED, OMP_MASKED_CLAUSES);
8509 : }
8510 :
8511 : match
8512 10 : gfc_match_omp_masked_taskloop (void)
8513 : {
8514 10 : return match_omp (EXEC_OMP_MASKED_TASKLOOP,
8515 10 : OMP_MASKED_CLAUSES | OMP_TASKLOOP_CLAUSES);
8516 : }
8517 :
8518 : match
8519 16 : gfc_match_omp_masked_taskloop_simd (void)
8520 : {
8521 16 : return match_omp (EXEC_OMP_MASKED_TASKLOOP_SIMD,
8522 16 : (OMP_MASKED_CLAUSES | OMP_TASKLOOP_CLAUSES
8523 16 : | OMP_SIMD_CLAUSES));
8524 : }
8525 :
8526 : match
8527 111 : gfc_match_omp_master (void)
8528 : {
8529 111 : gfc_warning (OPT_Wdeprecated_openmp,
8530 : "%<master%> construct at %C deprecated since OpenMP 5.1, "
8531 : "use %<masked%>");
8532 111 : if (gfc_match_omp_eos () != MATCH_YES)
8533 : {
8534 1 : gfc_error ("Unexpected junk after $OMP MASTER statement at %C");
8535 1 : return MATCH_ERROR;
8536 : }
8537 110 : new_st.op = EXEC_OMP_MASTER;
8538 110 : new_st.ext.omp_clauses = NULL;
8539 110 : return MATCH_YES;
8540 : }
8541 :
8542 : match
8543 16 : gfc_match_omp_master_taskloop (void)
8544 : {
8545 16 : gfc_warning (OPT_Wdeprecated_openmp,
8546 : "%<master%> construct at %C deprecated since OpenMP 5.1, "
8547 : "use %<masked%>");
8548 16 : return match_omp (EXEC_OMP_MASTER_TASKLOOP, OMP_TASKLOOP_CLAUSES);
8549 : }
8550 :
8551 : match
8552 21 : gfc_match_omp_master_taskloop_simd (void)
8553 : {
8554 21 : gfc_warning (OPT_Wdeprecated_openmp,
8555 : "%<master%> construct at %C deprecated since OpenMP 5.1, use "
8556 : "%<masked%>");
8557 21 : return match_omp (EXEC_OMP_MASTER_TASKLOOP_SIMD,
8558 21 : OMP_TASKLOOP_CLAUSES | OMP_SIMD_CLAUSES);
8559 : }
8560 :
8561 : match
8562 235 : gfc_match_omp_ordered (void)
8563 : {
8564 235 : return match_omp (EXEC_OMP_ORDERED, OMP_ORDERED_CLAUSES);
8565 : }
8566 :
8567 : match
8568 24 : gfc_match_omp_nothing (void)
8569 : {
8570 24 : if (gfc_match_omp_eos () != MATCH_YES)
8571 : {
8572 1 : gfc_error ("Unexpected junk after $OMP NOTHING statement at %C");
8573 1 : return MATCH_ERROR;
8574 : }
8575 : /* Will use ST_NONE; therefore, no EXEC_OMP_ is needed. */
8576 : return MATCH_YES;
8577 : }
8578 :
8579 : match
8580 317 : gfc_match_omp_ordered_depend (void)
8581 : {
8582 317 : return match_omp (EXEC_OMP_ORDERED, omp_mask (OMP_CLAUSE_DOACROSS));
8583 : }
8584 :
8585 :
8586 : /* omp atomic [clause-list]
8587 : - atomic-clause: read | write | update
8588 : - capture
8589 : - memory-order-clause: seq_cst | acq_rel | release | acquire | relaxed
8590 : - hint(hint-expr)
8591 : - OpenMP 5.1: compare | fail (seq_cst | acquire | relaxed ) | weak
8592 : */
8593 :
8594 : match
8595 2171 : gfc_match_omp_atomic (void)
8596 : {
8597 2171 : gfc_omp_clauses *c;
8598 2171 : locus loc = gfc_current_locus;
8599 :
8600 2171 : if (gfc_match_omp_clauses (&c, OMP_ATOMIC_CLAUSES, true, true) != MATCH_YES)
8601 : return MATCH_ERROR;
8602 :
8603 2153 : if (c->atomic_op == GFC_OMP_ATOMIC_UNSET)
8604 1011 : c->atomic_op = GFC_OMP_ATOMIC_UPDATE;
8605 :
8606 2153 : if (c->capture && c->atomic_op != GFC_OMP_ATOMIC_UPDATE)
8607 3 : gfc_error ("!$OMP ATOMIC at %L with %s clause is incompatible with "
8608 : "READ or WRITE", &loc, "CAPTURE");
8609 2153 : if (c->compare && c->atomic_op != GFC_OMP_ATOMIC_UPDATE)
8610 3 : gfc_error ("!$OMP ATOMIC at %L with %s clause is incompatible with "
8611 : "READ or WRITE", &loc, "COMPARE");
8612 2153 : if (c->fail != OMP_MEMORDER_UNSET && c->atomic_op != GFC_OMP_ATOMIC_UPDATE)
8613 2 : gfc_error ("!$OMP ATOMIC at %L with %s clause is incompatible with "
8614 : "READ or WRITE", &loc, "FAIL");
8615 2153 : if (c->weak && !c->compare)
8616 : {
8617 5 : gfc_error ("!$OMP ATOMIC at %L with %s clause requires %s clause", &loc,
8618 : "WEAK", "COMPARE");
8619 5 : c->weak = false;
8620 : }
8621 :
8622 2153 : if (c->memorder == OMP_MEMORDER_UNSET)
8623 : {
8624 1969 : gfc_namespace *prog_unit = gfc_current_ns;
8625 1969 : while (prog_unit->parent
8626 2525 : && !(prog_unit->proc_name
8627 556 : && prog_unit->proc_name->attr.flavor == FL_MODULE))
8628 : prog_unit = prog_unit->parent;
8629 1969 : switch (prog_unit->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
8630 : {
8631 1936 : case 0:
8632 1936 : case OMP_REQ_ATOMIC_MEM_ORDER_RELAXED:
8633 1936 : c->memorder = OMP_MEMORDER_RELAXED;
8634 1936 : break;
8635 7 : case OMP_REQ_ATOMIC_MEM_ORDER_SEQ_CST:
8636 7 : c->memorder = OMP_MEMORDER_SEQ_CST;
8637 7 : break;
8638 16 : case OMP_REQ_ATOMIC_MEM_ORDER_ACQ_REL:
8639 16 : if (c->capture)
8640 5 : c->memorder = OMP_MEMORDER_ACQ_REL;
8641 11 : else if (c->atomic_op == GFC_OMP_ATOMIC_READ)
8642 3 : c->memorder = OMP_MEMORDER_ACQUIRE;
8643 : else
8644 8 : c->memorder = OMP_MEMORDER_RELEASE;
8645 : break;
8646 5 : case OMP_REQ_ATOMIC_MEM_ORDER_ACQUIRE:
8647 5 : if (c->atomic_op == GFC_OMP_ATOMIC_WRITE)
8648 : {
8649 1 : gfc_error ("!$OMP ATOMIC WRITE at %L incompatible with "
8650 : "ACQUIRES clause implicitly provided by a "
8651 : "REQUIRES directive", &loc);
8652 1 : c->memorder = OMP_MEMORDER_SEQ_CST;
8653 : }
8654 : else
8655 4 : c->memorder = OMP_MEMORDER_ACQUIRE;
8656 : break;
8657 5 : case OMP_REQ_ATOMIC_MEM_ORDER_RELEASE:
8658 5 : if (c->atomic_op == GFC_OMP_ATOMIC_READ)
8659 : {
8660 1 : gfc_error ("!$OMP ATOMIC READ at %L incompatible with "
8661 : "RELEASE clause implicitly provided by a "
8662 : "REQUIRES directive", &loc);
8663 1 : c->memorder = OMP_MEMORDER_SEQ_CST;
8664 : }
8665 : else
8666 4 : c->memorder = OMP_MEMORDER_RELEASE;
8667 : break;
8668 0 : default:
8669 0 : gcc_unreachable ();
8670 : }
8671 : }
8672 : else
8673 184 : switch (c->atomic_op)
8674 : {
8675 29 : case GFC_OMP_ATOMIC_READ:
8676 29 : if (c->memorder == OMP_MEMORDER_RELEASE)
8677 : {
8678 1 : gfc_error ("!$OMP ATOMIC READ at %L incompatible with "
8679 : "RELEASE clause", &loc);
8680 1 : c->memorder = OMP_MEMORDER_SEQ_CST;
8681 : }
8682 28 : else if (c->memorder == OMP_MEMORDER_ACQ_REL)
8683 1 : c->memorder = OMP_MEMORDER_ACQUIRE;
8684 : break;
8685 35 : case GFC_OMP_ATOMIC_WRITE:
8686 35 : if (c->memorder == OMP_MEMORDER_ACQUIRE)
8687 : {
8688 1 : gfc_error ("!$OMP ATOMIC WRITE at %L incompatible with "
8689 : "ACQUIRE clause", &loc);
8690 1 : c->memorder = OMP_MEMORDER_SEQ_CST;
8691 : }
8692 34 : else if (c->memorder == OMP_MEMORDER_ACQ_REL)
8693 1 : c->memorder = OMP_MEMORDER_RELEASE;
8694 : break;
8695 : default:
8696 : break;
8697 : }
8698 2153 : gfc_error_check ();
8699 2153 : new_st.ext.omp_clauses = c;
8700 2153 : new_st.op = EXEC_OMP_ATOMIC;
8701 2153 : return MATCH_YES;
8702 : }
8703 :
8704 :
8705 : /* acc atomic [ read | write | update | capture] */
8706 :
8707 : match
8708 552 : gfc_match_oacc_atomic (void)
8709 : {
8710 552 : gfc_omp_clauses *c = gfc_get_omp_clauses ();
8711 552 : c->atomic_op = GFC_OMP_ATOMIC_UPDATE;
8712 552 : c->memorder = OMP_MEMORDER_RELAXED;
8713 552 : gfc_gobble_whitespace ();
8714 552 : if (gfc_match ("update") == MATCH_YES)
8715 : ;
8716 373 : else if (gfc_match ("read") == MATCH_YES)
8717 17 : c->atomic_op = GFC_OMP_ATOMIC_READ;
8718 356 : else if (gfc_match ("write") == MATCH_YES)
8719 13 : c->atomic_op = GFC_OMP_ATOMIC_WRITE;
8720 343 : else if (gfc_match ("capture") == MATCH_YES)
8721 319 : c->capture = true;
8722 552 : gfc_gobble_whitespace ();
8723 552 : if (gfc_match_omp_eos () != MATCH_YES)
8724 : {
8725 9 : gfc_error ("Unexpected junk after !$ACC ATOMIC statement at %C");
8726 9 : gfc_free_omp_clauses (c);
8727 9 : return MATCH_ERROR;
8728 : }
8729 543 : new_st.ext.omp_clauses = c;
8730 543 : new_st.op = EXEC_OACC_ATOMIC;
8731 543 : return MATCH_YES;
8732 : }
8733 :
8734 :
8735 : match
8736 614 : gfc_match_omp_barrier (void)
8737 : {
8738 614 : if (gfc_match_omp_eos () != MATCH_YES)
8739 : {
8740 0 : gfc_error ("Unexpected junk after $OMP BARRIER statement at %C");
8741 0 : return MATCH_ERROR;
8742 : }
8743 614 : new_st.op = EXEC_OMP_BARRIER;
8744 614 : new_st.ext.omp_clauses = NULL;
8745 614 : return MATCH_YES;
8746 : }
8747 :
8748 :
8749 : match
8750 188 : gfc_match_omp_taskgroup (void)
8751 : {
8752 188 : return match_omp (EXEC_OMP_TASKGROUP, OMP_TASKGROUP_CLAUSES);
8753 : }
8754 :
8755 :
8756 : static enum gfc_omp_cancel_kind
8757 492 : gfc_match_omp_cancel_kind (void)
8758 : {
8759 492 : if (gfc_match_space () != MATCH_YES)
8760 : return OMP_CANCEL_UNKNOWN;
8761 492 : if (gfc_match ("parallel") == MATCH_YES)
8762 : return OMP_CANCEL_PARALLEL;
8763 352 : if (gfc_match ("sections") == MATCH_YES)
8764 : return OMP_CANCEL_SECTIONS;
8765 253 : if (gfc_match ("do") == MATCH_YES)
8766 : return OMP_CANCEL_DO;
8767 123 : if (gfc_match ("taskgroup") == MATCH_YES)
8768 : return OMP_CANCEL_TASKGROUP;
8769 : return OMP_CANCEL_UNKNOWN;
8770 : }
8771 :
8772 :
8773 : match
8774 319 : gfc_match_omp_cancel (void)
8775 : {
8776 319 : gfc_omp_clauses *c;
8777 319 : enum gfc_omp_cancel_kind kind = gfc_match_omp_cancel_kind ();
8778 319 : if (kind == OMP_CANCEL_UNKNOWN)
8779 : return MATCH_ERROR;
8780 319 : if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_IF), false) != MATCH_YES)
8781 : return MATCH_ERROR;
8782 316 : c->cancel = kind;
8783 316 : new_st.op = EXEC_OMP_CANCEL;
8784 316 : new_st.ext.omp_clauses = c;
8785 316 : return MATCH_YES;
8786 : }
8787 :
8788 :
8789 : match
8790 173 : gfc_match_omp_cancellation_point (void)
8791 : {
8792 173 : gfc_omp_clauses *c;
8793 173 : enum gfc_omp_cancel_kind kind = gfc_match_omp_cancel_kind ();
8794 173 : if (kind == OMP_CANCEL_UNKNOWN)
8795 : {
8796 2 : gfc_error ("Expected construct-type PARALLEL, SECTIONS, DO or TASKGROUP "
8797 : "in $OMP CANCELLATION POINT statement at %C");
8798 2 : return MATCH_ERROR;
8799 : }
8800 171 : if (gfc_match_omp_eos () != MATCH_YES)
8801 : {
8802 0 : gfc_error ("Unexpected junk after $OMP CANCELLATION POINT statement "
8803 : "at %C");
8804 0 : return MATCH_ERROR;
8805 : }
8806 171 : c = gfc_get_omp_clauses ();
8807 171 : c->cancel = kind;
8808 171 : new_st.op = EXEC_OMP_CANCELLATION_POINT;
8809 171 : new_st.ext.omp_clauses = c;
8810 171 : return MATCH_YES;
8811 : }
8812 :
8813 :
8814 : match
8815 2733 : gfc_match_omp_end_nowait (void)
8816 : {
8817 2733 : bool nowait = false;
8818 2733 : if (gfc_match ("% nowait") == MATCH_YES)
8819 258 : nowait = true;
8820 2733 : if (gfc_match_omp_eos () != MATCH_YES)
8821 : {
8822 4 : if (nowait)
8823 3 : gfc_error ("Unexpected junk after NOWAIT clause at %C");
8824 : else
8825 1 : gfc_error ("Unexpected junk at %C");
8826 4 : return MATCH_ERROR;
8827 : }
8828 2729 : new_st.op = EXEC_OMP_END_NOWAIT;
8829 2729 : new_st.ext.omp_bool = nowait;
8830 2729 : return MATCH_YES;
8831 : }
8832 :
8833 :
8834 : match
8835 566 : gfc_match_omp_end_single (void)
8836 : {
8837 566 : gfc_omp_clauses *c;
8838 566 : if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_COPYPRIVATE)
8839 : | OMP_CLAUSE_NOWAIT) != MATCH_YES)
8840 : return MATCH_ERROR;
8841 566 : new_st.op = EXEC_OMP_END_SINGLE;
8842 566 : new_st.ext.omp_clauses = c;
8843 566 : return MATCH_YES;
8844 : }
8845 :
8846 :
8847 : static bool
8848 37142 : oacc_is_loop (gfc_code *code)
8849 : {
8850 37142 : return code->op == EXEC_OACC_PARALLEL_LOOP
8851 : || code->op == EXEC_OACC_KERNELS_LOOP
8852 20087 : || code->op == EXEC_OACC_SERIAL_LOOP
8853 13457 : || code->op == EXEC_OACC_LOOP;
8854 : }
8855 :
8856 : static void
8857 5733 : resolve_scalar_int_expr (gfc_expr *expr, const char *clause)
8858 : {
8859 5733 : if (!gfc_resolve_expr (expr)
8860 5733 : || expr->ts.type != BT_INTEGER
8861 11395 : || expr->rank != 0)
8862 89 : gfc_error ("%s clause at %L requires a scalar INTEGER expression",
8863 : clause, &expr->where);
8864 5733 : }
8865 :
8866 : static void
8867 3946 : resolve_positive_int_expr (gfc_expr *expr, const char *clause)
8868 : {
8869 3946 : resolve_scalar_int_expr (expr, clause);
8870 3946 : if (expr->expr_type == EXPR_CONSTANT
8871 3525 : && expr->ts.type == BT_INTEGER
8872 3492 : && mpz_sgn (expr->value.integer) <= 0)
8873 54 : gfc_warning ((flag_openmp || flag_openmp_simd) ? OPT_Wopenmp : 0,
8874 : "INTEGER expression of %s clause at %L must be positive",
8875 : clause, &expr->where);
8876 3946 : }
8877 :
8878 : static void
8879 86 : resolve_nonnegative_int_expr (gfc_expr *expr, const char *clause)
8880 : {
8881 86 : resolve_scalar_int_expr (expr, clause);
8882 86 : if (expr->expr_type == EXPR_CONSTANT
8883 13 : && expr->ts.type == BT_INTEGER
8884 11 : && mpz_sgn (expr->value.integer) < 0)
8885 6 : gfc_warning ((flag_openmp || flag_openmp_simd) ? OPT_Wopenmp : 0,
8886 : "INTEGER expression of %s clause at %L must be non-negative",
8887 : clause, &expr->where);
8888 86 : }
8889 :
8890 : /* Emits error when symbol is pointer, cray pointer or cray pointee
8891 : of derived of polymorphic type. */
8892 :
8893 : static void
8894 98 : check_symbol_not_pointer (gfc_symbol *sym, locus loc, const char *name)
8895 : {
8896 98 : if (sym->ts.type == BT_DERIVED && sym->attr.cray_pointer)
8897 0 : gfc_error ("Cray pointer object %qs of derived type in %s clause at %L",
8898 : sym->name, name, &loc);
8899 98 : if (sym->ts.type == BT_DERIVED && sym->attr.cray_pointee)
8900 0 : gfc_error ("Cray pointee object %qs of derived type in %s clause at %L",
8901 : sym->name, name, &loc);
8902 :
8903 98 : if ((sym->ts.type == BT_ASSUMED && sym->attr.pointer)
8904 98 : || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
8905 0 : && CLASS_DATA (sym)->attr.pointer))
8906 0 : gfc_error ("POINTER object %qs of polymorphic type in %s clause at %L",
8907 : sym->name, name, &loc);
8908 98 : if ((sym->ts.type == BT_ASSUMED && sym->attr.cray_pointer)
8909 98 : || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
8910 0 : && CLASS_DATA (sym)->attr.cray_pointer))
8911 0 : gfc_error ("Cray pointer object %qs of polymorphic type in %s clause at %L",
8912 : sym->name, name, &loc);
8913 98 : if ((sym->ts.type == BT_ASSUMED && sym->attr.cray_pointee)
8914 98 : || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
8915 0 : && CLASS_DATA (sym)->attr.cray_pointee))
8916 0 : gfc_error ("Cray pointee object %qs of polymorphic type in %s clause at %L",
8917 : sym->name, name, &loc);
8918 98 : }
8919 :
8920 : /* Emits error when symbol represents assumed size/rank array. */
8921 :
8922 : static void
8923 14844 : check_array_not_assumed (gfc_symbol *sym, locus loc, const char *name)
8924 : {
8925 14844 : if (sym->as && sym->as->type == AS_ASSUMED_SIZE)
8926 13 : gfc_error ("Assumed size array %qs in %s clause at %L",
8927 : sym->name, name, &loc);
8928 14844 : if (sym->as && sym->as->type == AS_ASSUMED_RANK)
8929 11 : gfc_error ("Assumed rank array %qs in %s clause at %L",
8930 : sym->name, name, &loc);
8931 14844 : }
8932 :
8933 : static void
8934 5850 : resolve_oacc_data_clauses (gfc_symbol *sym, locus loc, const char *name)
8935 : {
8936 0 : check_array_not_assumed (sym, loc, name);
8937 0 : }
8938 :
8939 : static void
8940 65 : resolve_oacc_deviceptr_clause (gfc_symbol *sym, locus loc, const char *name)
8941 : {
8942 65 : if (sym->attr.pointer
8943 64 : || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
8944 0 : && CLASS_DATA (sym)->attr.class_pointer))
8945 1 : gfc_error ("POINTER object %qs in %s clause at %L",
8946 : sym->name, name, &loc);
8947 65 : if (sym->attr.cray_pointer
8948 63 : || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
8949 0 : && CLASS_DATA (sym)->attr.cray_pointer))
8950 2 : gfc_error ("Cray pointer object %qs in %s clause at %L",
8951 : sym->name, name, &loc);
8952 65 : if (sym->attr.cray_pointee
8953 63 : || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
8954 0 : && CLASS_DATA (sym)->attr.cray_pointee))
8955 2 : gfc_error ("Cray pointee object %qs in %s clause at %L",
8956 : sym->name, name, &loc);
8957 65 : if (sym->attr.allocatable
8958 64 : || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
8959 0 : && CLASS_DATA (sym)->attr.allocatable))
8960 1 : gfc_error ("ALLOCATABLE object %qs in %s clause at %L",
8961 : sym->name, name, &loc);
8962 65 : if (sym->attr.value)
8963 1 : gfc_error ("VALUE object %qs in %s clause at %L",
8964 : sym->name, name, &loc);
8965 65 : check_array_not_assumed (sym, loc, name);
8966 65 : }
8967 :
8968 :
8969 : struct resolve_omp_udr_callback_data
8970 : {
8971 : gfc_symbol *sym1, *sym2;
8972 : };
8973 :
8974 :
8975 : static int
8976 1413 : resolve_omp_udr_callback (gfc_expr **e, int *, void *data)
8977 : {
8978 1413 : struct resolve_omp_udr_callback_data *rcd
8979 : = (struct resolve_omp_udr_callback_data *) data;
8980 1413 : if ((*e)->expr_type == EXPR_VARIABLE
8981 801 : && ((*e)->symtree->n.sym == rcd->sym1
8982 255 : || (*e)->symtree->n.sym == rcd->sym2))
8983 : {
8984 801 : gfc_ref *ref = gfc_get_ref ();
8985 801 : ref->type = REF_ARRAY;
8986 801 : ref->u.ar.where = (*e)->where;
8987 801 : ref->u.ar.as = (*e)->symtree->n.sym->as;
8988 801 : ref->u.ar.type = AR_FULL;
8989 801 : ref->u.ar.dimen = 0;
8990 801 : ref->next = (*e)->ref;
8991 801 : (*e)->ref = ref;
8992 : }
8993 1413 : return 0;
8994 : }
8995 :
8996 :
8997 : static int
8998 3004 : resolve_omp_udr_callback2 (gfc_expr **e, int *, void *)
8999 : {
9000 3004 : if ((*e)->expr_type == EXPR_FUNCTION
9001 360 : && (*e)->value.function.isym == NULL)
9002 : {
9003 174 : gfc_symbol *sym = (*e)->symtree->n.sym;
9004 174 : if (!sym->attr.intrinsic
9005 174 : && sym->attr.if_source == IFSRC_UNKNOWN)
9006 4 : gfc_error ("Implicitly declared function %s used in "
9007 : "!$OMP DECLARE REDUCTION at %L", sym->name, &(*e)->where);
9008 : }
9009 3004 : return 0;
9010 : }
9011 :
9012 :
9013 : static gfc_code *
9014 801 : resolve_omp_udr_clause (gfc_omp_namelist *n, gfc_namespace *ns,
9015 : gfc_symbol *sym1, gfc_symbol *sym2)
9016 : {
9017 801 : gfc_code *copy;
9018 801 : gfc_symbol sym1_copy, sym2_copy;
9019 :
9020 801 : if (ns->code->op == EXEC_ASSIGN)
9021 : {
9022 629 : copy = gfc_get_code (EXEC_ASSIGN);
9023 629 : copy->expr1 = gfc_copy_expr (ns->code->expr1);
9024 629 : copy->expr2 = gfc_copy_expr (ns->code->expr2);
9025 : }
9026 : else
9027 : {
9028 172 : copy = gfc_get_code (EXEC_CALL);
9029 172 : copy->symtree = ns->code->symtree;
9030 172 : copy->ext.actual = gfc_copy_actual_arglist (ns->code->ext.actual);
9031 : }
9032 801 : copy->loc = ns->code->loc;
9033 801 : sym1_copy = *sym1;
9034 801 : sym2_copy = *sym2;
9035 801 : *sym1 = *n->sym;
9036 801 : *sym2 = *n->sym;
9037 801 : sym1->name = sym1_copy.name;
9038 801 : sym2->name = sym2_copy.name;
9039 801 : ns->proc_name = ns->parent->proc_name;
9040 801 : if (n->sym->attr.dimension)
9041 : {
9042 348 : struct resolve_omp_udr_callback_data rcd;
9043 348 : rcd.sym1 = sym1;
9044 348 : rcd.sym2 = sym2;
9045 348 : gfc_code_walker (©, gfc_dummy_code_callback,
9046 : resolve_omp_udr_callback, &rcd);
9047 : }
9048 801 : gfc_resolve_code (copy, gfc_current_ns);
9049 801 : if (copy->op == EXEC_CALL && copy->resolved_isym == NULL)
9050 : {
9051 172 : gfc_symbol *sym = copy->resolved_sym;
9052 172 : if (sym
9053 170 : && !sym->attr.intrinsic
9054 170 : && sym->attr.if_source == IFSRC_UNKNOWN)
9055 4 : gfc_error ("Implicitly declared subroutine %s used in "
9056 : "!$OMP DECLARE REDUCTION at %L", sym->name,
9057 : ©->loc);
9058 : }
9059 801 : gfc_code_walker (©, gfc_dummy_code_callback,
9060 : resolve_omp_udr_callback2, NULL);
9061 801 : *sym1 = sym1_copy;
9062 801 : *sym2 = sym2_copy;
9063 801 : return copy;
9064 : }
9065 :
9066 : /* Assume that a constant expression in the range 1 (omp_default_mem_alloc)
9067 : to GOMP_OMP_PREDEF_ALLOC_MAX, or GOMP_OMPX_PREDEF_ALLOC_MIN to
9068 : GOMP_OMPX_PREDEF_ALLOC_MAX is fine. The original symbol name is already
9069 : lost during matching via gfc_match_expr. */
9070 : static bool
9071 130 : is_predefined_allocator (gfc_expr *expr)
9072 : {
9073 130 : return (gfc_resolve_expr (expr)
9074 129 : && expr->rank == 0
9075 124 : && expr->ts.type == BT_INTEGER
9076 119 : && expr->ts.kind == gfc_c_intptr_kind
9077 114 : && expr->expr_type == EXPR_CONSTANT
9078 239 : && ((mpz_sgn (expr->value.integer) > 0
9079 107 : && mpz_cmp_si (expr->value.integer,
9080 : GOMP_OMP_PREDEF_ALLOC_MAX) <= 0)
9081 4 : || (mpz_cmp_si (expr->value.integer,
9082 : GOMP_OMPX_PREDEF_ALLOC_MIN) >= 0
9083 1 : && mpz_cmp_si (expr->value.integer,
9084 130 : GOMP_OMPX_PREDEF_ALLOC_MAX) <= 0)));
9085 : }
9086 :
9087 : /* Resolve declarative ALLOCATE statement. Note: Common block vars only appear
9088 : as /block/ not individual, which is ensured during parsing. */
9089 :
9090 : void
9091 62 : gfc_resolve_omp_allocate (gfc_namespace *ns, gfc_omp_namelist *list)
9092 : {
9093 278 : for (gfc_omp_namelist *n = list; n; n = n->next)
9094 : {
9095 216 : if (n->sym->attr.result || n->sym->result == n->sym)
9096 : {
9097 1 : gfc_error ("Unexpected function-result variable %qs at %L in "
9098 : "declarative !$OMP ALLOCATE", n->sym->name, &n->where);
9099 31 : continue;
9100 : }
9101 215 : if (ns->omp_allocate->sym->attr.proc_pointer)
9102 : {
9103 0 : gfc_error ("Procedure pointer %qs not supported with !$OMP "
9104 : "ALLOCATE at %L", n->sym->name, &n->where);
9105 0 : continue;
9106 : }
9107 215 : if (n->sym->attr.flavor != FL_VARIABLE)
9108 : {
9109 3 : gfc_error ("Argument %qs at %L to declarative !$OMP ALLOCATE "
9110 : "directive must be a variable", n->sym->name,
9111 : &n->where);
9112 3 : continue;
9113 : }
9114 212 : if (ns != n->sym->ns || n->sym->attr.use_assoc || n->sym->attr.imported)
9115 : {
9116 8 : gfc_error ("Argument %qs at %L to declarative !$OMP ALLOCATE shall be"
9117 : " in the same scope as the variable declaration",
9118 : n->sym->name, &n->where);
9119 8 : continue;
9120 : }
9121 204 : if (n->sym->attr.dummy)
9122 : {
9123 3 : gfc_error ("Unexpected dummy argument %qs as argument at %L to "
9124 : "declarative !$OMP ALLOCATE", n->sym->name, &n->where);
9125 3 : continue;
9126 : }
9127 201 : if (n->sym->attr.codimension)
9128 : {
9129 0 : gfc_error ("Unexpected coarray argument %qs as argument at %L to "
9130 : "declarative !$OMP ALLOCATE", n->sym->name, &n->where);
9131 0 : continue;
9132 : }
9133 201 : if (n->sym->attr.omp_allocate)
9134 : {
9135 5 : if (n->sym->attr.in_common)
9136 : {
9137 1 : gfc_error ("Duplicated common block %</%s/%> in !$OMP ALLOCATE "
9138 1 : "at %L", n->sym->common_head->name, &n->where);
9139 3 : while (n->next && n->next->sym
9140 3 : && n->sym->common_head == n->next->sym->common_head)
9141 : n = n->next;
9142 : }
9143 : else
9144 4 : gfc_error ("Duplicated variable %qs in !$OMP ALLOCATE at %L",
9145 : n->sym->name, &n->where);
9146 5 : continue;
9147 : }
9148 : /* For 'equivalence(a,b)', a 'union_type {<type> a,b} equiv.0' is created
9149 : with a value expression for 'a' as 'equiv.0.a' (likewise for b); while
9150 : this can be handled, EQUIVALENCE is marked as obsolescent since Fortran
9151 : 2018 and also not widely used. However, it could be supported,
9152 : if needed. */
9153 196 : if (n->sym->attr.in_equivalence)
9154 : {
9155 2 : gfc_error ("Sorry, EQUIVALENCE object %qs not supported with !$OMP "
9156 : "ALLOCATE at %L", n->sym->name, &n->where);
9157 2 : continue;
9158 : }
9159 : /* Similar for Cray pointer/pointee - they could be implemented but as
9160 : common vendor extension but nowadays rarely used and requiring
9161 : -fcray-pointer, there is no need to support them. */
9162 194 : if (n->sym->attr.cray_pointer || n->sym->attr.cray_pointee)
9163 : {
9164 2 : gfc_error ("Sorry, Cray pointers and pointees such as %qs are not "
9165 : "supported with !$OMP ALLOCATE at %L",
9166 : n->sym->name, &n->where);
9167 2 : continue;
9168 : }
9169 192 : n->sym->attr.omp_allocate = 1;
9170 192 : if ((n->sym->ts.type == BT_CLASS && n->sym->attr.class_ok
9171 0 : && CLASS_DATA (n->sym)->attr.allocatable)
9172 192 : || (n->sym->ts.type != BT_CLASS && n->sym->attr.allocatable))
9173 1 : gfc_error ("Unexpected allocatable variable %qs at %L in declarative "
9174 : "!$OMP ALLOCATE directive", n->sym->name, &n->where);
9175 191 : else if ((n->sym->ts.type == BT_CLASS && n->sym->attr.class_ok
9176 0 : && CLASS_DATA (n->sym)->attr.class_pointer)
9177 191 : || (n->sym->ts.type != BT_CLASS && n->sym->attr.pointer))
9178 1 : gfc_error ("Unexpected pointer variable %qs at %L in declarative "
9179 : "!$OMP ALLOCATE directive", n->sym->name, &n->where);
9180 192 : HOST_WIDE_INT alignment = 0;
9181 198 : if (n->u.align
9182 192 : && (!gfc_resolve_expr (n->u.align)
9183 27 : || n->u.align->ts.type != BT_INTEGER
9184 26 : || n->u.align->rank != 0
9185 24 : || n->u.align->expr_type != EXPR_CONSTANT
9186 23 : || gfc_extract_hwi (n->u.align, &alignment)
9187 23 : || !pow2p_hwi (alignment)))
9188 : {
9189 6 : gfc_error ("ALIGN requires a scalar positive constant integer "
9190 : "alignment expression at %L that is a power of two",
9191 6 : &n->u.align->where);
9192 6 : while (n->sym->attr.in_common && n->next && n->next->sym
9193 6 : && n->sym->common_head == n->next->sym->common_head)
9194 : n = n->next;
9195 6 : continue;
9196 : }
9197 186 : if (n->sym->attr.in_common || n->sym->attr.save || n->sym->ns->save_all
9198 63 : || (n->sym->ns->proc_name
9199 63 : && (n->sym->ns->proc_name->attr.flavor == FL_PROGRAM
9200 : || n->sym->ns->proc_name->attr.flavor == FL_MODULE
9201 : || n->sym->ns->proc_name->attr.flavor == FL_BLOCK_DATA)))
9202 : {
9203 131 : bool com = n->sym->attr.in_common;
9204 131 : if (!n->u2.allocator)
9205 1 : gfc_error ("An ALLOCATOR clause is required as the list item "
9206 : "%<%s%s%s%> at %L has the SAVE attribute", com ? "/" : "",
9207 0 : com ? n->sym->common_head->name : n->sym->name,
9208 : com ? "/" : "", &n->where);
9209 130 : else if (!is_predefined_allocator (n->u2.allocator))
9210 24 : gfc_error ("Predefined allocator required in ALLOCATOR clause at %L"
9211 : " as the list item %<%s%s%s%> at %L has the SAVE attribute",
9212 24 : &n->u2.allocator->where, com ? "/" : "",
9213 24 : com ? n->sym->common_head->name : n->sym->name,
9214 : com ? "/" : "", &n->where);
9215 : /* Static variables may not use omp_cgroup_mem_alloc (6),
9216 : omp_pteam_mem_alloc (7), or omp_thread_mem_alloc (8). */
9217 106 : else if (mpz_cmp_si (n->u2.allocator->value.integer,
9218 : 6 /* cgroup */) >= 0
9219 34 : && mpz_cmp_si (n->u2.allocator->value.integer,
9220 : 8 /* thread */) <= 0)
9221 : {
9222 33 : STATIC_ASSERT (GOMP_OMP_PREDEF_ALLOC_CGROUP == 6);
9223 33 : STATIC_ASSERT (GOMP_OMP_PREDEF_ALLOC_PTEAM == 7);
9224 33 : STATIC_ASSERT (GOMP_OMP_PREDEF_ALLOC_THREAD == 8);
9225 33 : const char *alloc_name[] = {"omp_cgroup_mem_alloc",
9226 : "omp_pteam_mem_alloc",
9227 : "omp_thread_mem_alloc" };
9228 33 : gfc_error ("Predefined allocator %qs in ALLOCATOR clause at %L, "
9229 : "used for list item %<%s%s%s%> at %L, may not be used"
9230 : " for static variables",
9231 33 : alloc_name[mpz_get_ui (n->u2.allocator->value.integer)
9232 33 : - 6 /* cgroup */], &n->u2.allocator->where,
9233 : com ? "/" : "",
9234 33 : com ? n->sym->common_head->name : n->sym->name,
9235 : com ? "/" : "", &n->where);
9236 : }
9237 67 : while (n->sym->attr.in_common && n->next && n->next->sym
9238 186 : && n->sym->common_head == n->next->sym->common_head)
9239 : n = n->next;
9240 : }
9241 55 : else if (n->u2.allocator
9242 55 : && (!gfc_resolve_expr (n->u2.allocator)
9243 20 : || n->u2.allocator->ts.type != BT_INTEGER
9244 19 : || n->u2.allocator->rank != 0
9245 18 : || n->u2.allocator->ts.kind != gfc_c_intptr_kind))
9246 3 : gfc_error ("Expected integer expression of the "
9247 : "%<omp_allocator_handle_kind%> kind at %L",
9248 3 : &n->u2.allocator->where);
9249 : }
9250 62 : }
9251 :
9252 : /* Resolve ASSUME's and ASSUMES' assumption clauses. Note that absent/contains
9253 : is handled during parse time in omp_verify_merge_absent_contains. */
9254 :
9255 : void
9256 29 : gfc_resolve_omp_assumptions (gfc_omp_assumptions *assume)
9257 : {
9258 46 : for (gfc_expr_list *el = assume->holds; el; el = el->next)
9259 17 : if (!gfc_resolve_expr (el->expr)
9260 17 : || el->expr->ts.type != BT_LOGICAL
9261 32 : || el->expr->rank != 0)
9262 4 : gfc_error ("HOLDS expression at %L must be a scalar logical expression",
9263 4 : &el->expr->where);
9264 29 : }
9265 :
9266 :
9267 : /* Resolve the OpenMP ALLOCATE clauses. */
9268 :
9269 : static void
9270 32620 : resolve_omp_allocate_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
9271 : gfc_namespace *ns)
9272 : {
9273 32620 : gfc_omp_namelist *n;
9274 32620 : enum gfc_omp_list_type list;
9275 :
9276 32620 : if (!omp_clauses->lists[OMP_LIST_ALLOCATE])
9277 : return;
9278 795 : for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; n = n->next)
9279 : {
9280 515 : if (n->u2.allocator
9281 515 : && (!gfc_resolve_expr (n->u2.allocator)
9282 290 : || n->u2.allocator->ts.type != BT_INTEGER
9283 288 : || n->u2.allocator->rank != 0
9284 287 : || n->u2.allocator->ts.kind != gfc_c_intptr_kind))
9285 : {
9286 8 : gfc_error ("Expected integer expression of the "
9287 : "%<omp_allocator_handle_kind%> kind at %L",
9288 8 : &n->u2.allocator->where);
9289 28 : break;
9290 : }
9291 507 : if (!n->u.align)
9292 399 : continue;
9293 108 : HOST_WIDE_INT alignment = 0;
9294 108 : if (!gfc_resolve_expr (n->u.align)
9295 108 : || n->u.align->ts.type != BT_INTEGER
9296 105 : || n->u.align->rank != 0
9297 102 : || n->u.align->expr_type != EXPR_CONSTANT
9298 99 : || gfc_extract_hwi (n->u.align, &alignment)
9299 99 : || alignment <= 0
9300 207 : || !pow2p_hwi (alignment))
9301 : {
9302 12 : gfc_error ("ALIGN requires a scalar positive constant integer "
9303 : "alignment expression at %L that is a power of two",
9304 12 : &n->u.align->where);
9305 12 : break;
9306 : }
9307 : }
9308 :
9309 : /* Check for 2 things here.
9310 : 1. There is no duplication of variable in allocate clause.
9311 : 2. Variable in allocate clause are also present in some
9312 : privatization clase (non-composite case). */
9313 815 : for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; n = n->next)
9314 515 : if (n->sym)
9315 489 : n->sym->mark = 0;
9316 :
9317 : gfc_omp_namelist *prev = NULL;
9318 815 : for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; )
9319 : {
9320 515 : if (n->sym == NULL)
9321 : {
9322 26 : n = n->next;
9323 26 : continue;
9324 : }
9325 489 : if (n->sym->mark == 1)
9326 : {
9327 3 : gfc_warning (OPT_Wopenmp, "%qs appears more than once in "
9328 : "%<allocate%> at %L" , n->sym->name, &n->where);
9329 : /* We have already seen this variable so it is a duplicate.
9330 : Remove it. */
9331 3 : if (prev != NULL && prev->next == n)
9332 : {
9333 3 : prev->next = n->next;
9334 3 : n->next = NULL;
9335 3 : gfc_free_omp_namelist (n, OMP_LIST_ALLOCATE);
9336 3 : n = prev->next;
9337 : }
9338 3 : continue;
9339 : }
9340 486 : n->sym->mark = 1;
9341 486 : prev = n;
9342 486 : n = n->next;
9343 : }
9344 :
9345 : /* Non-composite constructs. */
9346 300 : if (code && code->op < EXEC_OMP_DO_SIMD)
9347 : {
9348 4760 : for (list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
9349 4641 : list = gfc_omp_list_type (list + 1))
9350 4641 : switch (list)
9351 : {
9352 1071 : case OMP_LIST_PRIVATE:
9353 1071 : case OMP_LIST_FIRSTPRIVATE:
9354 1071 : case OMP_LIST_LASTPRIVATE:
9355 1071 : case OMP_LIST_REDUCTION:
9356 1071 : case OMP_LIST_REDUCTION_INSCAN:
9357 1071 : case OMP_LIST_REDUCTION_TASK:
9358 1071 : case OMP_LIST_IN_REDUCTION:
9359 1071 : case OMP_LIST_TASK_REDUCTION:
9360 1071 : case OMP_LIST_LINEAR:
9361 1370 : for (n = omp_clauses->lists[list]; n; n = n->next)
9362 299 : n->sym->mark = 0;
9363 : break;
9364 : default:
9365 : break;
9366 : }
9367 :
9368 410 : for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; n = n->next)
9369 291 : if (n->sym->mark == 1)
9370 4 : gfc_error ("%qs specified in %<allocate%> clause at %L but not "
9371 : "in an explicit privatization clause",
9372 : n->sym->name, &n->where);
9373 : }
9374 71 : if (!(code
9375 300 : && (code->op == EXEC_OMP_ALLOCATORS || code->op == EXEC_OMP_ALLOCATE)
9376 73 : && code->block
9377 72 : && code->block->next
9378 71 : && code->block->next->op == EXEC_ALLOCATE))
9379 232 : return;
9380 :
9381 68 : if (code->op == EXEC_OMP_ALLOCATE)
9382 49 : gfc_warning (OPT_Wdeprecated_openmp,
9383 : "The use of one or more %<allocate%> directives with "
9384 : "an associated %<allocate%> statement at %L is "
9385 : "deprecated since OpenMP 5.2, use an %<allocators%> "
9386 : "directive", &code->loc);
9387 68 : gfc_alloc *a;
9388 68 : gfc_omp_namelist *n_null = NULL;
9389 68 : bool missing_allocator = false;
9390 68 : gfc_symbol *missing_allocator_sym = NULL;
9391 161 : for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; n = n->next)
9392 : {
9393 93 : if (n->u2.allocator == NULL)
9394 : {
9395 77 : if (!missing_allocator_sym)
9396 59 : missing_allocator_sym = n->sym;
9397 : missing_allocator = true;
9398 : }
9399 93 : if (n->sym == NULL)
9400 : {
9401 26 : n_null = n;
9402 26 : continue;
9403 : }
9404 67 : if (n->sym->attr.codimension)
9405 2 : gfc_error ("Unexpected coarray %qs in %<allocate%> at %L",
9406 : n->sym->name, &n->where);
9407 103 : for (a = code->block->next->ext.alloc.list; a; a = a->next)
9408 101 : if (a->expr->expr_type == EXPR_VARIABLE
9409 101 : && a->expr->symtree->n.sym == n->sym)
9410 : {
9411 65 : gfc_ref *ref;
9412 82 : for (ref = a->expr->ref; ref; ref = ref->next)
9413 17 : if (ref->type == REF_COMPONENT)
9414 : break;
9415 : if (ref == NULL)
9416 : break;
9417 : }
9418 67 : if (a == NULL)
9419 2 : gfc_error ("%qs specified in %<allocate%> at %L but not "
9420 : "in the associated ALLOCATE statement",
9421 2 : n->sym->name, &n->where);
9422 : }
9423 : /* If there is an ALLOCATE directive without list argument, a
9424 : namelist with its allocator/align clauses and n->sym = NULL is
9425 : created during parsing; here, we add all not otherwise specified
9426 : items from the Fortran allocate to that list.
9427 : For an ALLOCATORS directive, not listed items use the normal
9428 : Fortran way.
9429 : The behavior of an ALLOCATE directive that does not list all
9430 : arguments but there is no directive without list argument is not
9431 : well specified. Thus, we reject such code below. In OpenMP 5.2
9432 : the executable ALLOCATE directive is deprecated and in 6.0
9433 : deleted such that no spec clarification is to be expected. */
9434 125 : for (a = code->block->next->ext.alloc.list; a; a = a->next)
9435 89 : if (a->expr->expr_type == EXPR_VARIABLE)
9436 : {
9437 154 : for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; n = n->next)
9438 122 : if (a->expr->symtree->n.sym == n->sym)
9439 : {
9440 57 : gfc_ref *ref;
9441 72 : for (ref = a->expr->ref; ref; ref = ref->next)
9442 15 : if (ref->type == REF_COMPONENT)
9443 : break;
9444 : if (ref == NULL)
9445 : break;
9446 : }
9447 89 : if (n == NULL && n_null == NULL)
9448 : {
9449 : /* OK for ALLOCATORS but for ALLOCATE: Unspecified whether
9450 : that should use the default allocator of OpenMP or the
9451 : Fortran allocator. Thus, just reject it. */
9452 7 : if (code->op == EXEC_OMP_ALLOCATE)
9453 1 : gfc_error ("%qs listed in %<allocate%> statement at %L "
9454 : "but it is neither explicitly in listed in "
9455 : "the %<!$OMP ALLOCATE%> directive nor exists"
9456 : " a directive without argument list",
9457 1 : a->expr->symtree->n.sym->name,
9458 : &a->expr->where);
9459 : break;
9460 : }
9461 82 : if (n == NULL)
9462 : {
9463 25 : if (a->expr->symtree->n.sym->attr.codimension)
9464 1 : gfc_error ("Unexpected coarray %qs in %<allocate%> at "
9465 : "%L, implicitly listed in %<!$OMP ALLOCATE%>"
9466 : " at %L", a->expr->symtree->n.sym->name,
9467 : &a->expr->where, &n_null->where);
9468 : break;
9469 : }
9470 : }
9471 68 : gfc_namespace *prog_unit = ns;
9472 87 : while (prog_unit->parent)
9473 : prog_unit = prog_unit->parent;
9474 : gfc_namespace *fn_ns = ns;
9475 72 : while (fn_ns)
9476 : {
9477 70 : if (ns->proc_name
9478 70 : && (ns->proc_name->attr.subroutine
9479 6 : || ns->proc_name->attr.function))
9480 : break;
9481 4 : fn_ns = fn_ns->parent;
9482 : }
9483 68 : if (missing_allocator
9484 58 : && !(prog_unit->omp_requires & OMP_REQ_DYNAMIC_ALLOCATORS)
9485 58 : && ((fn_ns && fn_ns->proc_name->attr.omp_declare_target)
9486 55 : || omp_clauses->contained_in_target_construct))
9487 : {
9488 6 : if (code->op == EXEC_OMP_ALLOCATORS)
9489 2 : gfc_error ("ALLOCATORS directive at %L inside a target region "
9490 : "must specify an ALLOCATOR modifier for %qs",
9491 : &code->loc, missing_allocator_sym->name);
9492 4 : else if (missing_allocator_sym)
9493 2 : gfc_error ("ALLOCATE directive at %L inside a target region "
9494 : "must specify an ALLOCATOR clause for %qs",
9495 : &code->loc, missing_allocator_sym->name);
9496 : else
9497 2 : gfc_error ("ALLOCATE directive at %L inside a target region "
9498 : "must specify an ALLOCATOR clause", &code->loc);
9499 : }
9500 : }
9501 :
9502 :
9503 : /* Diagnose list items that appear multiple times in OpenMP or OpenACC clauses,
9504 : unless permitted by the specification. */
9505 :
9506 : static void
9507 32620 : check_omp_clauses_dupl_syms (gfc_code *code, gfc_omp_clauses *omp_clauses,
9508 : bool openacc)
9509 : {
9510 32620 : gfc_omp_namelist *n;
9511 32620 : enum gfc_omp_list_type list;
9512 :
9513 : /* Check that no symbol appears on multiple clauses, except that
9514 : a symbol can appear on both firstprivate and lastprivate. */
9515 1304800 : for (list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
9516 1272180 : list = gfc_omp_list_type (list + 1))
9517 1318015 : for (n = omp_clauses->lists[list]; n; n = n->next)
9518 : {
9519 45835 : if (!n->sym) /* omp_all_memory. */
9520 47 : continue;
9521 45788 : n->sym->mark = 0;
9522 45788 : n->sym->comp_mark = 0;
9523 45788 : n->sym->data_mark = 0;
9524 45788 : n->sym->dev_mark = 0;
9525 45788 : n->sym->gen_mark = 0;
9526 45788 : n->sym->reduc_mark = 0;
9527 : }
9528 1304800 : for (list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
9529 1272180 : list = gfc_omp_list_type (list + 1))
9530 1272180 : if (list != OMP_LIST_FIRSTPRIVATE
9531 1272180 : && list != OMP_LIST_LASTPRIVATE
9532 1272180 : && list != OMP_LIST_ALIGNED
9533 1174320 : && list != OMP_LIST_DEPEND
9534 1174320 : && list != OMP_LIST_FROM
9535 1109080 : && list != OMP_LIST_TO
9536 1109080 : && list != OMP_LIST_INTEROP
9537 1043840 : && (list != OMP_LIST_REDUCTION || !openacc)
9538 1031215 : && list != OMP_LIST_ALLOCATE)
9539 1033522 : for (n = omp_clauses->lists[list]; n; n = n->next)
9540 : {
9541 34927 : bool component_ref_p = false;
9542 :
9543 : /* Allow multiple components of the same (e.g. derived-type)
9544 : variable here. Duplicate components are detected elsewhere. */
9545 34927 : if (n->expr && n->expr->expr_type == EXPR_VARIABLE)
9546 16007 : for (gfc_ref *ref = n->expr->ref; ref; ref = ref->next)
9547 9737 : if (ref->type == REF_COMPONENT)
9548 3190 : component_ref_p = true;
9549 34927 : if ((list == OMP_LIST_IS_DEVICE_PTR
9550 34927 : || list == OMP_LIST_HAS_DEVICE_ADDR)
9551 313 : && !component_ref_p)
9552 : {
9553 313 : if (n->sym->gen_mark
9554 311 : || n->sym->dev_mark
9555 310 : || n->sym->reduc_mark
9556 310 : || n->sym->mark)
9557 5 : gfc_error ("Symbol %qs present on multiple clauses at %L",
9558 : n->sym->name, &n->where);
9559 : else
9560 308 : n->sym->dev_mark = 1;
9561 : }
9562 34614 : else if ((list == OMP_LIST_USE_DEVICE_PTR
9563 34614 : || list == OMP_LIST_USE_DEVICE_ADDR
9564 34614 : || list == OMP_LIST_PRIVATE
9565 : || list == OMP_LIST_SHARED)
9566 12855 : && !component_ref_p)
9567 : {
9568 12855 : if (n->sym->gen_mark || n->sym->dev_mark || n->sym->reduc_mark)
9569 13 : gfc_error ("Symbol %qs present on multiple clauses at %L",
9570 : n->sym->name, &n->where);
9571 : else
9572 : {
9573 12842 : n->sym->gen_mark = 1;
9574 : /* Set both generic and device bits if we have
9575 : use_device_*(x) or shared(x). This allows us to diagnose
9576 : "map(x) private(x)" below. */
9577 12842 : if (list != OMP_LIST_PRIVATE)
9578 3456 : n->sym->dev_mark = 1;
9579 : }
9580 : }
9581 21759 : else if ((list == OMP_LIST_REDUCTION
9582 21759 : || list == OMP_LIST_REDUCTION_TASK
9583 19299 : || list == OMP_LIST_REDUCTION_INSCAN
9584 19299 : || list == OMP_LIST_IN_REDUCTION
9585 19086 : || list == OMP_LIST_TASK_REDUCTION)
9586 2673 : && !component_ref_p)
9587 : {
9588 : /* Attempts to mix reduction types are diagnosed below. */
9589 2673 : if (n->sym->gen_mark || n->sym->dev_mark)
9590 2 : gfc_error ("Symbol %qs present on multiple clauses at %L",
9591 : n->sym->name, &n->where);
9592 2673 : n->sym->reduc_mark = 1;
9593 : }
9594 19086 : else if ((!component_ref_p && n->sym->comp_mark)
9595 19085 : || (component_ref_p && n->sym->mark))
9596 : {
9597 42 : if (openacc)
9598 3 : gfc_error ("Symbol %qs has mixed component and non-component "
9599 3 : "accesses at %L", n->sym->name, &n->where);
9600 : }
9601 19044 : else if ((openacc || list != OMP_LIST_MAP) && n->sym->mark)
9602 88 : gfc_error ("Symbol %qs present on multiple clauses at %L",
9603 : n->sym->name, &n->where);
9604 : else
9605 : {
9606 18956 : if (component_ref_p)
9607 2466 : n->sym->comp_mark = 1;
9608 : else
9609 16490 : n->sym->mark = 1;
9610 : }
9611 : }
9612 :
9613 : /* Detect specifically the case where we have "map(x) private(x)" and raise
9614 : an error. If we have "...simd" combined directives though, the "private"
9615 : applies to the simd part, so this is permitted though. */
9616 42014 : for (n = omp_clauses->lists[OMP_LIST_PRIVATE]; n; n = n->next)
9617 9394 : if (n->sym->mark
9618 6 : && n->sym->gen_mark
9619 6 : && !n->sym->dev_mark
9620 6 : && !n->sym->reduc_mark
9621 5 : && code->op != EXEC_OMP_TARGET_SIMD
9622 : && code->op != EXEC_OMP_TARGET_PARALLEL_DO_SIMD
9623 : && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD
9624 : && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD)
9625 1 : gfc_error ("Symbol %qs present on multiple clauses at %L",
9626 : n->sym->name, &n->where);
9627 :
9628 : gcc_assert (OMP_LIST_LASTPRIVATE == OMP_LIST_FIRSTPRIVATE + 1);
9629 97860 : for (list = OMP_LIST_FIRSTPRIVATE; list <= OMP_LIST_LASTPRIVATE;
9630 65240 : list = gfc_omp_list_type (list + 1))
9631 69463 : for (n = omp_clauses->lists[list]; n; n = n->next)
9632 4223 : if (n->sym->data_mark || n->sym->gen_mark || n->sym->dev_mark)
9633 : {
9634 9 : gfc_error ("Symbol %qs present on multiple clauses at %L",
9635 : n->sym->name, &n->where);
9636 9 : n->sym->data_mark = n->sym->gen_mark = n->sym->dev_mark = 0;
9637 : }
9638 4214 : else if (n->sym->mark
9639 18 : && code->op != EXEC_OMP_TARGET_TEAMS
9640 : && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE
9641 : && code->op != EXEC_OMP_TARGET_TEAMS_LOOP
9642 : && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD
9643 : && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO
9644 : && code->op != EXEC_OMP_TARGET_PARALLEL
9645 : && code->op != EXEC_OMP_TARGET_PARALLEL_DO
9646 : && code->op != EXEC_OMP_TARGET_PARALLEL_LOOP
9647 : && code->op != EXEC_OMP_TARGET_PARALLEL_DO_SIMD
9648 : && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD)
9649 7 : gfc_error ("Symbol %qs present on both data and map clauses "
9650 : "at %L", n->sym->name, &n->where);
9651 :
9652 34535 : for (n = omp_clauses->lists[OMP_LIST_FIRSTPRIVATE]; n; n = n->next)
9653 : {
9654 1915 : if (n->sym->data_mark || n->sym->gen_mark || n->sym->dev_mark)
9655 7 : gfc_error ("Symbol %qs present on multiple clauses at %L",
9656 : n->sym->name, &n->where);
9657 : else
9658 1908 : n->sym->data_mark = 1;
9659 : }
9660 :
9661 : /* LASTPRIVATE clauses. */
9662 34928 : for (n = omp_clauses->lists[OMP_LIST_LASTPRIVATE]; n; n = n->next)
9663 2308 : n->sym->data_mark = 0;
9664 34928 : for (n = omp_clauses->lists[OMP_LIST_LASTPRIVATE]; n; n = n->next)
9665 : {
9666 2308 : if (n->sym->data_mark || n->sym->gen_mark || n->sym->dev_mark)
9667 0 : gfc_error ("Symbol %qs present on multiple clauses at %L",
9668 : n->sym->name, &n->where);
9669 : else
9670 2308 : n->sym->data_mark = 1;
9671 : }
9672 :
9673 : /* ALIGNED clauses. */
9674 32770 : for (n = omp_clauses->lists[OMP_LIST_ALIGNED]; n; n = n->next)
9675 150 : n->sym->mark = 0;
9676 :
9677 32770 : for (n = omp_clauses->lists[OMP_LIST_ALIGNED]; n; n = n->next)
9678 : {
9679 150 : if (n->sym->mark)
9680 0 : gfc_error ("Symbol %qs present on multiple clauses at %L",
9681 : n->sym->name, &n->where);
9682 : else
9683 150 : n->sym->mark = 1;
9684 : }
9685 :
9686 : /* FROM and TO clauses. */
9687 33390 : for (n = omp_clauses->lists[OMP_LIST_TO]; n; n = n->next)
9688 770 : n->sym->mark = 0;
9689 33653 : for (n = omp_clauses->lists[OMP_LIST_FROM]; n; n = n->next)
9690 1033 : if (n->expr == NULL)
9691 1015 : n->sym->mark = 1;
9692 33390 : for (n = omp_clauses->lists[OMP_LIST_TO]; n; n = n->next)
9693 : {
9694 770 : if (n->expr == NULL && n->sym->mark)
9695 0 : gfc_error ("Symbol %qs present on both FROM and TO clauses at %L",
9696 : n->sym->name, &n->where);
9697 : else
9698 770 : n->sym->mark = 1;
9699 : }
9700 :
9701 : /* OpenACC reductions. */
9702 32620 : if (openacc)
9703 : {
9704 14761 : for (n = omp_clauses->lists[OMP_LIST_REDUCTION]; n; n = n->next)
9705 2136 : n->sym->mark = 0;
9706 14761 : for (n = omp_clauses->lists[OMP_LIST_REDUCTION]; n; n = n->next)
9707 : {
9708 2136 : if (n->sym->mark)
9709 0 : gfc_error ("Symbol %qs present on multiple clauses at %L",
9710 : n->sym->name, &n->where);
9711 : else
9712 2136 : n->sym->mark = 1;
9713 :
9714 : /* OpenACC does not support reductions on arrays. */
9715 2136 : if (n->sym->as)
9716 71 : gfc_error ("Array %qs is not permitted in reduction at %L",
9717 : n->sym->name, &n->where);
9718 : }
9719 : }
9720 32620 : }
9721 :
9722 : /* OpenMP/OpenACC: Resolve the list item of a MAP, TO, FROM, CACHE, AFFINITY
9723 : or DEPEND clause. */
9724 :
9725 : static void
9726 20943 : resolve_omp_clauses_aff_dep_map_cache (gfc_code *code,
9727 : gfc_omp_namelist *n,
9728 : const char *name,
9729 : enum gfc_omp_list_type list,
9730 : gfc_omp_clauses *omp_clauses,
9731 : bool openacc)
9732 : {
9733 20943 : gcc_checking_assert (list == OMP_LIST_AFFINITY || list == OMP_LIST_DEPEND
9734 : || list == OMP_LIST_MAP || list == OMP_LIST_TO
9735 : || list == OMP_LIST_FROM || list == OMP_LIST_CACHE);
9736 :
9737 20943 : if (list != OMP_LIST_CACHE && n->u2.ns && !n->u2.ns->resolved)
9738 : {
9739 109 : n->u2.ns->resolved = 1;
9740 109 : for (gfc_symbol *sym = n->u2.ns->omp_affinity_iterators;
9741 235 : sym; sym = sym->tlink)
9742 : {
9743 126 : gfc_constructor *c;
9744 126 : c = gfc_constructor_first (sym->value->value.constructor);
9745 126 : if (!gfc_resolve_expr (c->expr)
9746 126 : || c->expr->ts.type != BT_INTEGER
9747 250 : || c->expr->rank != 0)
9748 2 : gfc_error ("Scalar integer expression for range begin expected "
9749 2 : "at %L", &c->expr->where);
9750 126 : c = gfc_constructor_next (c);
9751 126 : if (!gfc_resolve_expr (c->expr)
9752 126 : || c->expr->ts.type != BT_INTEGER
9753 250 : || c->expr->rank != 0)
9754 2 : gfc_error ("Scalar integer expression for range end expected at %L",
9755 2 : &c->expr->where);
9756 126 : c = gfc_constructor_next (c);
9757 126 : if (c && (!gfc_resolve_expr (c->expr)
9758 16 : || c->expr->ts.type != BT_INTEGER
9759 14 : || c->expr->rank != 0))
9760 2 : gfc_error ("Scalar integer expression for range step expected "
9761 2 : "at %L", &c->expr->where);
9762 124 : else if (c
9763 14 : && c->expr->expr_type == EXPR_CONSTANT
9764 12 : && mpz_cmp_si (c->expr->value.integer, 0) == 0)
9765 2 : gfc_error ("Nonzero range step expected at %L", &c->expr->where);
9766 : }
9767 : }
9768 20842 : if (list == OMP_LIST_DEPEND)
9769 : {
9770 1963 : if (n->u.depend_doacross_op == OMP_DEPEND_SINK_FIRST
9771 : || n->u.depend_doacross_op == OMP_DOACROSS_SINK_FIRST
9772 1963 : || n->u.depend_doacross_op == OMP_DOACROSS_SINK)
9773 : {
9774 1233 : if (omp_clauses->doacross_source)
9775 : {
9776 0 : gfc_error ("Dependence-type SINK used together with SOURCE on "
9777 : "the same construct at %L", &n->where);
9778 0 : omp_clauses->doacross_source = false;
9779 : }
9780 1233 : else if (n->expr)
9781 : {
9782 571 : if (!gfc_resolve_expr (n->expr)
9783 571 : || n->expr->ts.type != BT_INTEGER
9784 1142 : || n->expr->rank != 0)
9785 0 : gfc_error ("SINK addend not a constant integer at %L",
9786 : &n->where);
9787 : }
9788 1233 : if (n->sym == NULL
9789 4 : && (n->expr == NULL
9790 3 : || mpz_cmp_si (n->expr->value.integer, -1) != 0))
9791 2 : gfc_error ("omp_cur_iteration at %L requires %<-1%> as "
9792 : "logical offset", &n->where);
9793 1233 : return;
9794 : }
9795 730 : if (n->u.depend_doacross_op == OMP_DEPEND_DEPOBJ
9796 38 : && !n->expr
9797 22 : && (n->sym->ts.type != BT_INTEGER
9798 22 : || n->sym->ts.kind != 2 * gfc_index_integer_kind
9799 22 : || n->sym->attr.dimension))
9800 0 : gfc_error ("Locator %qs at %L in DEPEND clause of depobj type shall be "
9801 : "a scalar integer of OMP_DEPEND_KIND kind",
9802 : n->sym->name, &n->where);
9803 730 : else if (n->u.depend_doacross_op == OMP_DEPEND_DEPOBJ
9804 38 : && n->expr
9805 746 : && (!gfc_resolve_expr (n->expr)
9806 16 : || n->expr->ts.type != BT_INTEGER
9807 16 : || n->expr->ts.kind != 2 * gfc_index_integer_kind
9808 16 : || n->expr->rank != 0))
9809 0 : gfc_error ("Locator at %L in DEPEND clause of depobj type shall be a "
9810 0 : "scalar integer of OMP_DEPEND_KIND kind", &n->expr->where);
9811 : }
9812 19710 : gfc_ref *lastref = NULL, *lastslice = NULL;
9813 19710 : bool resolved = false;
9814 19710 : if (n->expr)
9815 : {
9816 6539 : lastref = n->expr->ref;
9817 6539 : resolved = gfc_resolve_expr (n->expr);
9818 :
9819 : /* Look through component refs to find last array reference. */
9820 6539 : if (resolved)
9821 : {
9822 16571 : for (gfc_ref *ref = n->expr->ref; ref; ref = ref->next)
9823 10050 : if (ref->type == REF_COMPONENT
9824 : || ref->type == REF_SUBSTRING
9825 10050 : || ref->type == REF_INQUIRY)
9826 : lastref = ref;
9827 6799 : else if (ref->type == REF_ARRAY)
9828 : {
9829 14290 : for (int i = 0; i < ref->u.ar.dimen; i++)
9830 7491 : if (ref->u.ar.dimen_type[i] == DIMEN_RANGE)
9831 6277 : lastslice = ref;
9832 : lastref = ref;
9833 : }
9834 :
9835 : /* The "!$acc cache" directive allows rectangular subarrays to be
9836 : specified, with some restrictions on the form of bounds (not
9837 : implemented). Only raise an error here if we're really sure the
9838 : array isn't contiguous. An expression such as arr(-n:n,-n:n)
9839 : could be contiguous even if it looks like it may not be. */
9840 6521 : if (code
9841 6502 : && code->op != EXEC_OACC_UPDATE
9842 5720 : && list != OMP_LIST_CACHE
9843 5720 : && list != OMP_LIST_DEPEND
9844 5398 : && !gfc_is_simply_contiguous (n->expr, false, true)
9845 1517 : && gfc_is_not_contiguous (n->expr)
9846 6534 : && !(lastslice && (lastslice->next
9847 3 : || lastslice->type != REF_ARRAY)))
9848 3 : gfc_error ("Array is not contiguous at %L", &n->where);
9849 : }
9850 : }
9851 19710 : if (list == OMP_LIST_MAP
9852 17041 : && (n->sym->attr.omp_groupprivate
9853 17040 : || n->sym->attr.omp_declare_target_local))
9854 2 : gfc_error ("%qs argument to MAP clause at %L must not be a device-local "
9855 : "variable, including GROUPPRIVATE", n->sym->name, &n->where);
9856 19710 : if (openacc
9857 19710 : && list == OMP_LIST_MAP
9858 9571 : && (n->u.map.op == OMP_MAP_ATTACH || n->u.map.op == OMP_MAP_DETACH))
9859 : {
9860 117 : symbol_attribute attr;
9861 117 : if (n->expr)
9862 99 : attr = gfc_expr_attr (n->expr);
9863 : else
9864 18 : attr = n->sym->attr;
9865 117 : if (!attr.pointer && !attr.allocatable)
9866 7 : gfc_error ("%qs clause argument must be ALLOCATABLE or a POINTER at %L",
9867 7 : (n->u.map.op == OMP_MAP_ATTACH) ? "attach" : "detach",
9868 : &n->where);
9869 : }
9870 19710 : if (lastref
9871 13183 : || (n->expr && (!resolved || n->expr->expr_type != EXPR_VARIABLE)))
9872 : {
9873 6539 : if (!lastslice && lastref && lastref->type == REF_SUBSTRING)
9874 11 : gfc_error ("Unexpected substring reference in %s clause at %L",
9875 : name, &n->where);
9876 6528 : else if (!lastslice && lastref && lastref->type == REF_INQUIRY)
9877 : {
9878 12 : gcc_assert (lastref->u.i == INQUIRY_RE || lastref->u.i == INQUIRY_IM);
9879 12 : gfc_error ("Unexpected complex-parts designator reference in %s "
9880 : "clause at %L", name, &n->where);
9881 : }
9882 6516 : else if (!resolved
9883 6498 : || n->expr->expr_type != EXPR_VARIABLE
9884 6486 : || (lastslice
9885 5615 : && (lastslice->next || lastslice->type != REF_ARRAY)))
9886 46 : gfc_error ("%qs in %s clause at %L is not a proper array section",
9887 46 : n->sym->name, name, &n->where);
9888 : else if (lastslice)
9889 : {
9890 : int i;
9891 : gfc_array_ref *ar = &lastslice->u.ar;
9892 11873 : for (i = 0; i < ar->dimen; i++)
9893 6275 : if (ar->stride[i] && code && code->op != EXEC_OACC_UPDATE)
9894 : {
9895 1 : gfc_error ("Stride should not be specified for array section "
9896 : "in %s clause at %L", name, &n->where);
9897 1 : break;
9898 : }
9899 6274 : else if (ar->dimen_type[i] != DIMEN_ELEMENT
9900 6274 : && ar->dimen_type[i] != DIMEN_RANGE)
9901 : {
9902 0 : gfc_error ("%qs in %s clause at %L is not a proper array "
9903 0 : "section", n->sym->name, name, &n->where);
9904 0 : break;
9905 : }
9906 6274 : else if ((list == OMP_LIST_DEPEND || list == OMP_LIST_AFFINITY)
9907 161 : && ar->start[i]
9908 133 : && ar->start[i]->expr_type == EXPR_CONSTANT
9909 97 : && ar->end[i]
9910 72 : && ar->end[i]->expr_type == EXPR_CONSTANT
9911 72 : && mpz_cmp (ar->start[i]->value.integer,
9912 72 : ar->end[i]->value.integer) > 0)
9913 : {
9914 0 : gfc_error ("%qs in %s clause at %L is a zero size array "
9915 0 : "section", n->sym->name,
9916 : list == OMP_LIST_DEPEND ? "DEPEND" : "AFFINITY",
9917 : &n->where);
9918 0 : break;
9919 : }
9920 : }
9921 : }
9922 13171 : else if (openacc)
9923 : {
9924 5915 : if (list == OMP_LIST_MAP && n->u.map.op == OMP_MAP_FORCE_DEVICEPTR)
9925 65 : resolve_oacc_deviceptr_clause (n->sym, n->where, name);
9926 : else
9927 5850 : resolve_oacc_data_clauses (n->sym, n->where, name);
9928 : }
9929 7256 : else if (list != OMP_LIST_DEPEND
9930 6763 : && n->sym->as
9931 3339 : && n->sym->as->type == AS_ASSUMED_SIZE)
9932 5 : gfc_error ("Assumed size array %qs in %s clause at %L",
9933 : n->sym->name, name, &n->where);
9934 19710 : if (code && list == OMP_LIST_MAP && !openacc)
9935 7432 : switch (code->op)
9936 : {
9937 6157 : case EXEC_OMP_TARGET:
9938 6157 : case EXEC_OMP_TARGET_PARALLEL:
9939 6157 : case EXEC_OMP_TARGET_PARALLEL_DO:
9940 6157 : case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
9941 6157 : case EXEC_OMP_TARGET_PARALLEL_LOOP:
9942 6157 : case EXEC_OMP_TARGET_SIMD:
9943 6157 : case EXEC_OMP_TARGET_TEAMS:
9944 6157 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
9945 6157 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
9946 6157 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
9947 6157 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
9948 6157 : case EXEC_OMP_TARGET_TEAMS_LOOP:
9949 6157 : case EXEC_OMP_TARGET_DATA:
9950 6157 : switch (n->u.map.op)
9951 : {
9952 : case OMP_MAP_TO:
9953 : case OMP_MAP_ALWAYS_TO:
9954 : case OMP_MAP_PRESENT_TO:
9955 : case OMP_MAP_ALWAYS_PRESENT_TO:
9956 : case OMP_MAP_FROM:
9957 : case OMP_MAP_ALWAYS_FROM:
9958 : case OMP_MAP_PRESENT_FROM:
9959 : case OMP_MAP_ALWAYS_PRESENT_FROM:
9960 : case OMP_MAP_TOFROM:
9961 : case OMP_MAP_ALWAYS_TOFROM:
9962 : case OMP_MAP_PRESENT_TOFROM:
9963 : case OMP_MAP_ALWAYS_PRESENT_TOFROM:
9964 : case OMP_MAP_ALLOC:
9965 : case OMP_MAP_PRESENT_ALLOC:
9966 : break;
9967 2 : default:
9968 2 : gfc_error ("TARGET%s with map-type other than TO, "
9969 : "FROM, TOFROM, or ALLOC on MAP clause "
9970 : "at %L",
9971 : code->op == EXEC_OMP_TARGET_DATA
9972 : ? " DATA" : "", &n->where);
9973 2 : break;
9974 : }
9975 : break;
9976 697 : case EXEC_OMP_TARGET_ENTER_DATA:
9977 697 : switch (n->u.map.op)
9978 : {
9979 : case OMP_MAP_TO:
9980 : case OMP_MAP_ALWAYS_TO:
9981 : case OMP_MAP_PRESENT_TO:
9982 : case OMP_MAP_ALWAYS_PRESENT_TO:
9983 : case OMP_MAP_ALLOC:
9984 : case OMP_MAP_PRESENT_ALLOC:
9985 : break;
9986 178 : case OMP_MAP_TOFROM:
9987 178 : n->u.map.op = OMP_MAP_TO;
9988 178 : break;
9989 3 : case OMP_MAP_ALWAYS_TOFROM:
9990 3 : n->u.map.op = OMP_MAP_ALWAYS_TO;
9991 3 : break;
9992 2 : case OMP_MAP_PRESENT_TOFROM:
9993 2 : n->u.map.op = OMP_MAP_PRESENT_TO;
9994 2 : break;
9995 2 : case OMP_MAP_ALWAYS_PRESENT_TOFROM:
9996 2 : n->u.map.op = OMP_MAP_ALWAYS_PRESENT_TO;
9997 2 : break;
9998 2 : default:
9999 2 : gfc_error ("TARGET ENTER DATA with map-type other "
10000 : "than TO, TOFROM or ALLOC on MAP clause "
10001 : "at %L", &n->where);
10002 2 : break;
10003 : }
10004 : break;
10005 578 : case EXEC_OMP_TARGET_EXIT_DATA:
10006 578 : switch (n->u.map.op)
10007 : {
10008 : case OMP_MAP_FROM:
10009 : case OMP_MAP_ALWAYS_FROM:
10010 : case OMP_MAP_PRESENT_FROM:
10011 : case OMP_MAP_ALWAYS_PRESENT_FROM:
10012 : case OMP_MAP_RELEASE:
10013 : case OMP_MAP_DELETE:
10014 : break;
10015 132 : case OMP_MAP_TOFROM:
10016 132 : n->u.map.op = OMP_MAP_FROM;
10017 132 : break;
10018 1 : case OMP_MAP_ALWAYS_TOFROM:
10019 1 : n->u.map.op = OMP_MAP_ALWAYS_FROM;
10020 1 : break;
10021 0 : case OMP_MAP_PRESENT_TOFROM:
10022 0 : n->u.map.op = OMP_MAP_PRESENT_FROM;
10023 0 : break;
10024 0 : case OMP_MAP_ALWAYS_PRESENT_TOFROM:
10025 0 : n->u.map.op = OMP_MAP_ALWAYS_PRESENT_FROM;
10026 0 : break;
10027 2 : default:
10028 2 : gfc_error ("TARGET EXIT DATA with map-type other "
10029 : "than FROM, TOFROM, RELEASE, or DELETE on "
10030 : "MAP clause at %L", &n->where);
10031 2 : break;
10032 : }
10033 : break;
10034 : default:
10035 : break;
10036 : }
10037 19710 : if (list == OMP_LIST_MAP || list == OMP_LIST_TO || list == OMP_LIST_FROM)
10038 : {
10039 18844 : gfc_typespec *ts = n->expr ? &n->expr->ts : &n->sym->ts;
10040 :
10041 18844 : if (ts->type == BT_DERIVED || ts->type == BT_CLASS)
10042 : {
10043 9 : const char *mapper_id = (n->u3.udm
10044 999 : ? n->u3.udm->requested_mapper_id : "");
10045 999 : gfc_omp_udm *udm = gfc_find_omp_udm (gfc_current_ns, mapper_id, ts);
10046 999 : if (mapper_id[0] != '\0' && !udm)
10047 1 : gfc_error ("User-defined mapper %qs not found at %L",
10048 : mapper_id, &n->where);
10049 995 : else if (udm)
10050 : {
10051 26 : if (!n->u3.udm)
10052 : {
10053 18 : gcc_assert (mapper_id[0] == '\0');
10054 18 : n->u3.udm = gfc_get_omp_namelist_udm ();
10055 18 : n->u3.udm->requested_mapper_id = mapper_id;
10056 : }
10057 26 : n->u3.udm->resolved_udm = udm;
10058 : }
10059 : }
10060 : }
10061 :
10062 19710 : if (list != OMP_LIST_DEPEND)
10063 : {
10064 18980 : n->sym->attr.referenced = 1;
10065 18980 : if (n->sym->attr.threadprivate)
10066 1 : gfc_error ("THREADPRIVATE object %qs in %s clause at %L",
10067 : n->sym->name, name, &n->where);
10068 18980 : if (n->sym->attr.cray_pointee)
10069 14 : gfc_error ("Cray pointee %qs in %s clause at %L",
10070 : n->sym->name, name, &n->where);
10071 : }
10072 : }
10073 :
10074 : /* OpenMP directive resolving routines. */
10075 :
10076 : static void
10077 32620 : resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
10078 : gfc_namespace *ns, bool openacc = false)
10079 : {
10080 32620 : gfc_omp_namelist *n, *last;
10081 32620 : gfc_expr_list *el;
10082 32620 : enum gfc_omp_list_type list;
10083 32620 : int ifc;
10084 32620 : bool if_without_mod = false;
10085 32620 : gfc_omp_linear_op linear_op = OMP_LINEAR_DEFAULT;
10086 32620 : static const char *clause_names[]
10087 : = { "PRIVATE", "FIRSTPRIVATE", "LASTPRIVATE", "COPYPRIVATE", "SHARED",
10088 : "COPYIN", "UNIFORM", "AFFINITY", "ALIGNED", "LINEAR", "DEPEND", "MAP",
10089 : "TO", "FROM", "INCLUSIVE", "EXCLUSIVE",
10090 : "REDUCTION", "REDUCTION" /*inscan*/, "REDUCTION" /*task*/,
10091 : "IN_REDUCTION", "TASK_REDUCTION",
10092 : "DEVICE_RESIDENT", "LINK", "LOCAL", "USE_DEVICE",
10093 : "CACHE", "IS_DEVICE_PTR", "USE_DEVICE_PTR", "USE_DEVICE_ADDR",
10094 : "NONTEMPORAL", "ALLOCATE", "HAS_DEVICE_ADDR", "ENTER",
10095 : "USES_ALLOCATORS", "INIT", "USE", "DESTROY", "INTEROP", "ADJUST_ARGS" };
10096 32620 : STATIC_ASSERT (ARRAY_SIZE (clause_names) == OMP_LIST_NUM);
10097 :
10098 32620 : if (omp_clauses == NULL)
10099 : return;
10100 :
10101 32620 : if (ns == NULL)
10102 32176 : ns = gfc_current_ns;
10103 :
10104 32620 : check_omp_clauses_dupl_syms (code, omp_clauses, openacc);
10105 :
10106 32620 : if (omp_clauses->orderedc && omp_clauses->orderedc < omp_clauses->collapse)
10107 0 : gfc_error ("ORDERED clause parameter is less than COLLAPSE at %L",
10108 : &code->loc);
10109 32620 : if (omp_clauses->order_concurrent && omp_clauses->ordered)
10110 4 : gfc_error ("ORDER clause must not be used together with ORDERED at %L",
10111 : &code->loc);
10112 32620 : if (omp_clauses->if_expr)
10113 : {
10114 1190 : gfc_expr *expr = omp_clauses->if_expr;
10115 1190 : if (!gfc_resolve_expr (expr)
10116 1190 : || expr->ts.type != BT_LOGICAL || expr->rank != 0)
10117 16 : gfc_error ("IF clause at %L requires a scalar LOGICAL expression",
10118 : &expr->where);
10119 : if_without_mod = true;
10120 : }
10121 358820 : for (ifc = 0; ifc < OMP_IF_LAST; ifc++)
10122 326200 : if (omp_clauses->if_exprs[ifc])
10123 : {
10124 137 : gfc_expr *expr = omp_clauses->if_exprs[ifc];
10125 137 : bool ok = true;
10126 137 : if (!gfc_resolve_expr (expr)
10127 137 : || expr->ts.type != BT_LOGICAL || expr->rank != 0)
10128 0 : gfc_error ("IF clause at %L requires a scalar LOGICAL expression",
10129 : &expr->where);
10130 137 : else if (if_without_mod)
10131 : {
10132 1 : gfc_error ("IF clause without modifier at %L used together with "
10133 : "IF clauses with modifiers",
10134 1 : &omp_clauses->if_expr->where);
10135 1 : if_without_mod = false;
10136 : }
10137 : else
10138 136 : switch (code->op)
10139 : {
10140 13 : case EXEC_OMP_CANCEL:
10141 13 : ok = ifc == OMP_IF_CANCEL;
10142 13 : break;
10143 :
10144 16 : case EXEC_OMP_PARALLEL:
10145 16 : case EXEC_OMP_PARALLEL_DO:
10146 16 : case EXEC_OMP_PARALLEL_LOOP:
10147 16 : case EXEC_OMP_PARALLEL_MASKED:
10148 16 : case EXEC_OMP_PARALLEL_MASTER:
10149 16 : case EXEC_OMP_PARALLEL_SECTIONS:
10150 16 : case EXEC_OMP_PARALLEL_WORKSHARE:
10151 16 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
10152 16 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
10153 16 : ok = ifc == OMP_IF_PARALLEL;
10154 16 : break;
10155 :
10156 28 : case EXEC_OMP_PARALLEL_DO_SIMD:
10157 28 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
10158 28 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
10159 28 : ok = ifc == OMP_IF_PARALLEL || ifc == OMP_IF_SIMD;
10160 28 : break;
10161 :
10162 8 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
10163 8 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
10164 8 : ok = ifc == OMP_IF_PARALLEL || ifc == OMP_IF_TASKLOOP;
10165 8 : break;
10166 :
10167 12 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
10168 12 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
10169 12 : ok = (ifc == OMP_IF_PARALLEL
10170 12 : || ifc == OMP_IF_TASKLOOP
10171 : || ifc == OMP_IF_SIMD);
10172 : break;
10173 :
10174 0 : case EXEC_OMP_SIMD:
10175 0 : case EXEC_OMP_DO_SIMD:
10176 0 : case EXEC_OMP_DISTRIBUTE_SIMD:
10177 0 : case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
10178 0 : ok = ifc == OMP_IF_SIMD;
10179 0 : break;
10180 :
10181 1 : case EXEC_OMP_TASK:
10182 1 : ok = ifc == OMP_IF_TASK;
10183 1 : break;
10184 :
10185 5 : case EXEC_OMP_TASKLOOP:
10186 5 : case EXEC_OMP_MASKED_TASKLOOP:
10187 5 : case EXEC_OMP_MASTER_TASKLOOP:
10188 5 : ok = ifc == OMP_IF_TASKLOOP;
10189 5 : break;
10190 :
10191 20 : case EXEC_OMP_TASKLOOP_SIMD:
10192 20 : case EXEC_OMP_MASKED_TASKLOOP_SIMD:
10193 20 : case EXEC_OMP_MASTER_TASKLOOP_SIMD:
10194 20 : ok = ifc == OMP_IF_TASKLOOP || ifc == OMP_IF_SIMD;
10195 20 : break;
10196 :
10197 5 : case EXEC_OMP_TARGET:
10198 5 : case EXEC_OMP_TARGET_TEAMS:
10199 5 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
10200 5 : case EXEC_OMP_TARGET_TEAMS_LOOP:
10201 5 : ok = ifc == OMP_IF_TARGET;
10202 5 : break;
10203 :
10204 4 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
10205 4 : case EXEC_OMP_TARGET_SIMD:
10206 4 : ok = ifc == OMP_IF_TARGET || ifc == OMP_IF_SIMD;
10207 4 : break;
10208 :
10209 1 : case EXEC_OMP_TARGET_DATA:
10210 1 : ok = ifc == OMP_IF_TARGET_DATA;
10211 1 : break;
10212 :
10213 1 : case EXEC_OMP_TARGET_UPDATE:
10214 1 : ok = ifc == OMP_IF_TARGET_UPDATE;
10215 1 : break;
10216 :
10217 1 : case EXEC_OMP_TARGET_ENTER_DATA:
10218 1 : ok = ifc == OMP_IF_TARGET_ENTER_DATA;
10219 1 : break;
10220 :
10221 1 : case EXEC_OMP_TARGET_EXIT_DATA:
10222 1 : ok = ifc == OMP_IF_TARGET_EXIT_DATA;
10223 1 : break;
10224 :
10225 10 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
10226 10 : case EXEC_OMP_TARGET_PARALLEL:
10227 10 : case EXEC_OMP_TARGET_PARALLEL_DO:
10228 10 : case EXEC_OMP_TARGET_PARALLEL_LOOP:
10229 10 : ok = ifc == OMP_IF_TARGET || ifc == OMP_IF_PARALLEL;
10230 10 : break;
10231 :
10232 10 : case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
10233 10 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
10234 10 : ok = (ifc == OMP_IF_TARGET
10235 10 : || ifc == OMP_IF_PARALLEL
10236 : || ifc == OMP_IF_SIMD);
10237 : break;
10238 :
10239 : default:
10240 : ok = false;
10241 : break;
10242 : }
10243 115 : if (!ok)
10244 : {
10245 2 : static const char *ifs[] = {
10246 : "CANCEL",
10247 : "PARALLEL",
10248 : "SIMD",
10249 : "TASK",
10250 : "TASKLOOP",
10251 : "TARGET",
10252 : "TARGET DATA",
10253 : "TARGET UPDATE",
10254 : "TARGET ENTER DATA",
10255 : "TARGET EXIT DATA"
10256 : };
10257 2 : gfc_error ("IF clause modifier %s at %L not appropriate for "
10258 : "the current OpenMP construct", ifs[ifc], &expr->where);
10259 : }
10260 : }
10261 :
10262 32620 : if (omp_clauses->self_expr)
10263 : {
10264 177 : gfc_expr *expr = omp_clauses->self_expr;
10265 177 : if (!gfc_resolve_expr (expr)
10266 177 : || expr->ts.type != BT_LOGICAL || expr->rank != 0)
10267 6 : gfc_error ("SELF clause at %L requires a scalar LOGICAL expression",
10268 : &expr->where);
10269 : }
10270 :
10271 32620 : if (omp_clauses->final_expr)
10272 : {
10273 64 : gfc_expr *expr = omp_clauses->final_expr;
10274 64 : if (!gfc_resolve_expr (expr)
10275 64 : || expr->ts.type != BT_LOGICAL || expr->rank != 0)
10276 0 : gfc_error ("FINAL clause at %L requires a scalar LOGICAL expression",
10277 : &expr->where);
10278 : }
10279 32620 : if (omp_clauses->novariants)
10280 : {
10281 9 : gfc_expr *expr = omp_clauses->novariants;
10282 18 : if (!gfc_resolve_expr (expr) || expr->ts.type != BT_LOGICAL
10283 17 : || expr->rank != 0)
10284 1 : gfc_error (
10285 : "NOVARIANTS clause at %L requires a scalar LOGICAL expression",
10286 : &expr->where);
10287 32620 : if_without_mod = true;
10288 : }
10289 32620 : if (omp_clauses->nocontext)
10290 : {
10291 12 : gfc_expr *expr = omp_clauses->nocontext;
10292 24 : if (!gfc_resolve_expr (expr) || expr->ts.type != BT_LOGICAL
10293 23 : || expr->rank != 0)
10294 1 : gfc_error (
10295 : "NOCONTEXT clause at %L requires a scalar LOGICAL expression",
10296 : &expr->where);
10297 32620 : if_without_mod = true;
10298 : }
10299 32620 : if (omp_clauses->num_threads)
10300 964 : resolve_positive_int_expr (omp_clauses->num_threads, "NUM_THREADS");
10301 32620 : if (omp_clauses->dyn_groupprivate)
10302 10 : resolve_nonnegative_int_expr (omp_clauses->dyn_groupprivate,
10303 : "DYN_GROUPPRIVATE");
10304 32620 : if (omp_clauses->chunk_size)
10305 : {
10306 510 : gfc_expr *expr = omp_clauses->chunk_size;
10307 510 : if (!gfc_resolve_expr (expr)
10308 510 : || expr->ts.type != BT_INTEGER || expr->rank != 0)
10309 0 : gfc_error ("SCHEDULE clause's chunk_size at %L requires "
10310 : "a scalar INTEGER expression", &expr->where);
10311 510 : else if (expr->expr_type == EXPR_CONSTANT
10312 : && expr->ts.type == BT_INTEGER
10313 485 : && mpz_sgn (expr->value.integer) <= 0)
10314 2 : gfc_warning (OPT_Wopenmp, "INTEGER expression of SCHEDULE clause's "
10315 : "chunk_size at %L must be positive", &expr->where);
10316 : }
10317 32620 : if (omp_clauses->sched_kind != OMP_SCHED_NONE
10318 891 : && omp_clauses->sched_nonmonotonic)
10319 : {
10320 34 : if (omp_clauses->sched_monotonic)
10321 2 : gfc_error ("Both MONOTONIC and NONMONOTONIC schedule modifiers "
10322 : "specified at %L", &code->loc);
10323 32 : else if (omp_clauses->ordered)
10324 4 : gfc_error ("NONMONOTONIC schedule modifier specified with ORDERED "
10325 : "clause at %L", &code->loc);
10326 : }
10327 :
10328 32620 : if (omp_clauses->depobj
10329 32620 : && (!gfc_resolve_expr (omp_clauses->depobj)
10330 115 : || omp_clauses->depobj->ts.type != BT_INTEGER
10331 114 : || omp_clauses->depobj->ts.kind != 2 * gfc_index_integer_kind
10332 113 : || omp_clauses->depobj->rank != 0))
10333 4 : gfc_error ("DEPOBJ in DEPOBJ construct at %L shall be a scalar integer "
10334 4 : "of OMP_DEPEND_KIND kind", &omp_clauses->depobj->where);
10335 :
10336 : /* Check that list items are variables. */
10337 1304800 : for (list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
10338 1272180 : list = gfc_omp_list_type (list + 1))
10339 1318015 : for (n = omp_clauses->lists[list]; n; n = n->next)
10340 : {
10341 45835 : if (!n->sym) /* omp_all_memory. */
10342 47 : continue;
10343 45788 : if (n->sym->attr.flavor == FL_VARIABLE
10344 277 : || n->sym->attr.proc_pointer
10345 236 : || (!code
10346 0 : && !ns->omp_udm_ns
10347 0 : && (!n->sym->attr.dummy || n->sym->ns != ns)))
10348 : {
10349 45552 : if (!code
10350 302 : && !ns->omp_udm_ns
10351 264 : && (!n->sym->attr.dummy || n->sym->ns != ns))
10352 0 : gfc_error ("Variable %qs is not a dummy argument at %L",
10353 : n->sym->name, &n->where);
10354 45552 : continue;
10355 : }
10356 236 : if (n->sym->attr.flavor == FL_PROCEDURE
10357 153 : && n->sym->result == n->sym
10358 138 : && n->sym->attr.function)
10359 : {
10360 138 : if (ns->proc_name == n->sym
10361 44 : || (ns->parent && ns->parent->proc_name == n->sym))
10362 101 : continue;
10363 37 : if (ns->proc_name->attr.entry_master)
10364 : {
10365 32 : gfc_entry_list *el = ns->entries;
10366 51 : for (; el; el = el->next)
10367 51 : if (el->sym == n->sym)
10368 : break;
10369 32 : if (el)
10370 32 : continue;
10371 : }
10372 5 : if (ns->parent
10373 3 : && ns->parent->proc_name->attr.entry_master)
10374 : {
10375 2 : gfc_entry_list *el = ns->parent->entries;
10376 3 : for (; el; el = el->next)
10377 3 : if (el->sym == n->sym)
10378 : break;
10379 2 : if (el)
10380 2 : continue;
10381 : }
10382 : }
10383 101 : if (list == OMP_LIST_MAP
10384 18 : && n->sym->attr.flavor == FL_PARAMETER)
10385 : {
10386 : /* OpenACC since 3.4 permits for Fortran named constants, but
10387 : permits removing then as optimization is not needed and such
10388 : ignore them. Likewise below for FIRSTPRIVATE. */
10389 12 : if (openacc)
10390 10 : gfc_warning (OPT_Wsurprising, "Clause for object %qs at %L is "
10391 : "ignored as parameters need not be copied",
10392 : n->sym->name, &n->where);
10393 : else
10394 2 : gfc_error ("Object %qs is not a variable at %L; parameters"
10395 : " cannot be and need not be mapped", n->sym->name,
10396 : &n->where);
10397 : }
10398 89 : else if (openacc && n->sym->attr.flavor == FL_PARAMETER)
10399 9 : gfc_warning (OPT_Wsurprising, "Clause for object %qs at %L is ignored"
10400 : " as it is a parameter", n->sym->name, &n->where);
10401 80 : else if (list != OMP_LIST_USES_ALLOCATORS)
10402 30 : gfc_error ("Object %qs is not a variable at %L", n->sym->name,
10403 : &n->where);
10404 : }
10405 :
10406 32620 : if (omp_clauses->lists[OMP_LIST_REDUCTION_INSCAN])
10407 : {
10408 69 : locus *loc = &omp_clauses->lists[OMP_LIST_REDUCTION_INSCAN]->where;
10409 69 : if (code->op != EXEC_OMP_DO
10410 : && code->op != EXEC_OMP_SIMD
10411 : && code->op != EXEC_OMP_DO_SIMD
10412 : && code->op != EXEC_OMP_PARALLEL_DO
10413 : && code->op != EXEC_OMP_PARALLEL_DO_SIMD)
10414 23 : gfc_error ("%<inscan%> REDUCTION clause on construct other than DO, "
10415 : "SIMD, DO SIMD, PARALLEL DO, PARALLEL DO SIMD at %L",
10416 : loc);
10417 69 : if (omp_clauses->ordered)
10418 2 : gfc_error ("ORDERED clause specified together with %<inscan%> "
10419 : "REDUCTION clause at %L", loc);
10420 69 : if (omp_clauses->sched_kind != OMP_SCHED_NONE)
10421 3 : gfc_error ("SCHEDULE clause specified together with %<inscan%> "
10422 : "REDUCTION clause at %L", loc);
10423 : }
10424 :
10425 32620 : if (code
10426 32379 : && code->op == EXEC_OMP_INTEROP
10427 63 : && omp_clauses->lists[OMP_LIST_DEPEND])
10428 : {
10429 12 : if (!omp_clauses->lists[OMP_LIST_INIT]
10430 5 : && !omp_clauses->lists[OMP_LIST_USE]
10431 1 : && !omp_clauses->lists[OMP_LIST_DESTROY])
10432 : {
10433 1 : gfc_error ("DEPEND clause at %L requires action clause with "
10434 : "%<targetsync%> interop-type",
10435 : &omp_clauses->lists[OMP_LIST_DEPEND]->where);
10436 : }
10437 22 : for (n = omp_clauses->lists[OMP_LIST_INIT]; n; n = n->next)
10438 12 : if (!n->u.init.targetsync)
10439 : {
10440 2 : gfc_error ("DEPEND clause at %L requires %<targetsync%> "
10441 : "interop-type, lacking it for %qs at %L",
10442 2 : &omp_clauses->lists[OMP_LIST_DEPEND]->where,
10443 2 : n->sym->name, &n->where);
10444 2 : break;
10445 : }
10446 : }
10447 32379 : if (code && (code->op == EXEC_OMP_INTEROP || code->op == EXEC_OMP_DISPATCH))
10448 1085 : for (list = OMP_LIST_INIT; list <= OMP_LIST_INTEROP;
10449 868 : list = gfc_omp_list_type (list + 1))
10450 1123 : for (n = omp_clauses->lists[list]; n; n = n->next)
10451 : {
10452 255 : if (n->sym->ts.type != BT_INTEGER
10453 252 : || n->sym->ts.kind != gfc_index_integer_kind
10454 248 : || n->sym->attr.dimension
10455 243 : || n->sym->attr.flavor != FL_VARIABLE)
10456 16 : gfc_error ("%qs at %L in %qs clause must be a scalar integer "
10457 : "variable of %<omp_interop_kind%> kind", n->sym->name,
10458 : &n->where, clause_names[list]);
10459 255 : if (list != OMP_LIST_USE && list != OMP_LIST_INTEROP
10460 109 : && n->sym->attr.intent == INTENT_IN)
10461 2 : gfc_error ("%qs at %L in %qs clause must be definable",
10462 : n->sym->name, &n->where, clause_names[list]);
10463 : }
10464 :
10465 32620 : resolve_omp_allocate_clauses (code, omp_clauses, ns);
10466 :
10467 32620 : bool has_inscan = false, has_notinscan = false;
10468 1304800 : for (enum gfc_omp_list_type list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
10469 1272180 : list = gfc_omp_list_type (list + 1))
10470 1272180 : if ((n = omp_clauses->lists[list]) != NULL)
10471 : {
10472 29299 : const char *name = clause_names[list];
10473 :
10474 29299 : switch (list)
10475 : {
10476 : case OMP_LIST_COPYIN:
10477 267 : for (; n != NULL; n = n->next)
10478 : {
10479 170 : if (!n->sym->attr.threadprivate)
10480 0 : gfc_error ("Non-THREADPRIVATE object %qs in COPYIN clause"
10481 : " at %L", n->sym->name, &n->where);
10482 : }
10483 : break;
10484 83 : case OMP_LIST_COPYPRIVATE:
10485 83 : if (omp_clauses->nowait)
10486 6 : gfc_error ("NOWAIT clause must not be used with COPYPRIVATE "
10487 : "clause at %L", &n->where);
10488 376 : for (; n != NULL; n = n->next)
10489 : {
10490 293 : if (n->sym->as && n->sym->as->type == AS_ASSUMED_SIZE)
10491 0 : gfc_error ("Assumed size array %qs in COPYPRIVATE clause "
10492 : "at %L", n->sym->name, &n->where);
10493 293 : if (n->sym->attr.pointer && n->sym->attr.intent == INTENT_IN)
10494 1 : gfc_error ("INTENT(IN) POINTER %qs in COPYPRIVATE clause "
10495 : "at %L", n->sym->name, &n->where);
10496 : }
10497 : break;
10498 : case OMP_LIST_SHARED:
10499 2604 : for (; n != NULL; n = n->next)
10500 : {
10501 1642 : if (n->sym->attr.threadprivate)
10502 0 : gfc_error ("THREADPRIVATE object %qs in SHARED clause at "
10503 : "%L", n->sym->name, &n->where);
10504 1642 : if (n->sym->attr.cray_pointee)
10505 1 : gfc_error ("Cray pointee %qs in SHARED clause at %L",
10506 : n->sym->name, &n->where);
10507 1642 : if (n->sym->attr.associate_var)
10508 8 : gfc_error ("Associate name %qs in SHARED clause at %L",
10509 8 : n->sym->attr.select_type_temporary
10510 4 : ? n->sym->assoc->target->symtree->n.sym->name
10511 : : n->sym->name, &n->where);
10512 1642 : if (omp_clauses->detach
10513 1 : && n->sym == omp_clauses->detach->symtree->n.sym)
10514 1 : gfc_error ("DETACH event handle %qs in SHARED clause at %L",
10515 : n->sym->name, &n->where);
10516 : }
10517 : break;
10518 : case OMP_LIST_ALIGNED:
10519 256 : for (; n != NULL; n = n->next)
10520 : {
10521 150 : if (!n->sym->attr.pointer
10522 45 : && !n->sym->attr.allocatable
10523 30 : && !n->sym->attr.cray_pointer
10524 18 : && (n->sym->ts.type != BT_DERIVED
10525 18 : || (n->sym->ts.u.derived->from_intmod
10526 : != INTMOD_ISO_C_BINDING)
10527 18 : || (n->sym->ts.u.derived->intmod_sym_id
10528 : != ISOCBINDING_PTR)))
10529 0 : gfc_error ("%qs in ALIGNED clause must be POINTER, "
10530 : "ALLOCATABLE, Cray pointer or C_PTR at %L",
10531 : n->sym->name, &n->where);
10532 150 : else if (n->expr)
10533 : {
10534 147 : if (!gfc_resolve_expr (n->expr)
10535 147 : || n->expr->ts.type != BT_INTEGER
10536 146 : || n->expr->rank != 0
10537 146 : || n->expr->expr_type != EXPR_CONSTANT
10538 292 : || mpz_sgn (n->expr->value.integer) <= 0)
10539 4 : gfc_error ("%qs in ALIGNED clause at %L requires a scalar"
10540 : " positive constant integer alignment "
10541 4 : "expression", n->sym->name, &n->where);
10542 : }
10543 : }
10544 : break;
10545 : case OMP_LIST_AFFINITY:
10546 : case OMP_LIST_DEPEND:
10547 : case OMP_LIST_MAP:
10548 : case OMP_LIST_TO:
10549 : case OMP_LIST_FROM:
10550 : case OMP_LIST_CACHE:
10551 33196 : for (; n != NULL; n = n->next)
10552 20943 : resolve_omp_clauses_aff_dep_map_cache (code, n, name, list,
10553 : omp_clauses, openacc);
10554 : break;
10555 : case OMP_LIST_IS_DEVICE_PTR:
10556 : last = NULL;
10557 377 : for (n = omp_clauses->lists[list]; n != NULL; )
10558 : {
10559 257 : if ((n->sym->ts.type != BT_DERIVED
10560 71 : || !n->sym->ts.u.derived->ts.is_iso_c
10561 71 : || (n->sym->ts.u.derived->intmod_sym_id
10562 : != ISOCBINDING_PTR))
10563 187 : && code->op == EXEC_OMP_DISPATCH)
10564 : /* Non-TARGET (i.e. DISPATCH) requires a C_PTR. */
10565 3 : gfc_error ("List item %qs in %s clause at %L must be of "
10566 : "TYPE(C_PTR)", n->sym->name, name, &n->where);
10567 254 : else if (n->sym->ts.type != BT_DERIVED
10568 70 : || !n->sym->ts.u.derived->ts.is_iso_c
10569 70 : || (n->sym->ts.u.derived->intmod_sym_id
10570 : != ISOCBINDING_PTR))
10571 : {
10572 : /* For TARGET, non-C_PTR are deprecated and handled as
10573 : has_device_addr. */
10574 184 : gfc_warning (OPT_Wdeprecated_openmp,
10575 : "Non-C_PTR type argument at %L is deprecated, "
10576 : "use HAS_DEVICE_ADDR", &n->where);
10577 184 : gfc_omp_namelist *n2 = n;
10578 184 : n = n->next;
10579 184 : if (last)
10580 0 : last->next = n;
10581 : else
10582 184 : omp_clauses->lists[list] = n;
10583 184 : n2->next = omp_clauses->lists[OMP_LIST_HAS_DEVICE_ADDR];
10584 184 : omp_clauses->lists[OMP_LIST_HAS_DEVICE_ADDR] = n2;
10585 184 : continue;
10586 184 : }
10587 73 : last = n;
10588 73 : n = n->next;
10589 : }
10590 : break;
10591 : case OMP_LIST_HAS_DEVICE_ADDR:
10592 : case OMP_LIST_USE_DEVICE_ADDR:
10593 : break;
10594 : case OMP_LIST_USE_DEVICE_PTR:
10595 : /* Non-C_PTR are deprecated and handled as use_device_ADDR. */
10596 : last = NULL;
10597 475 : for (n = omp_clauses->lists[list]; n != NULL; )
10598 : {
10599 312 : gfc_omp_namelist *n2 = n;
10600 312 : if (n->sym->ts.type != BT_DERIVED
10601 18 : || !n->sym->ts.u.derived->ts.is_iso_c)
10602 : {
10603 294 : gfc_warning (OPT_Wdeprecated_openmp,
10604 : "Non-C_PTR type argument at %L is "
10605 : "deprecated, use USE_DEVICE_ADDR", &n->where);
10606 294 : n = n->next;
10607 294 : if (last)
10608 0 : last->next = n;
10609 : else
10610 294 : omp_clauses->lists[list] = n;
10611 294 : n2->next = omp_clauses->lists[OMP_LIST_USE_DEVICE_ADDR];
10612 294 : omp_clauses->lists[OMP_LIST_USE_DEVICE_ADDR] = n2;
10613 294 : continue;
10614 : }
10615 18 : last = n;
10616 18 : n = n->next;
10617 : }
10618 : break;
10619 65 : case OMP_LIST_USES_ALLOCATORS:
10620 65 : {
10621 65 : if (n != NULL
10622 65 : && n->u.memspace_sym
10623 20 : && (n->u.memspace_sym->attr.flavor != FL_PARAMETER
10624 18 : || n->u.memspace_sym->ts.type != BT_INTEGER
10625 18 : || n->u.memspace_sym->ts.kind != gfc_c_intptr_kind
10626 18 : || n->u.memspace_sym->attr.dimension
10627 18 : || (!startswith (n->u.memspace_sym->name, "omp_")
10628 0 : && !startswith (n->u.memspace_sym->name, "ompx_"))
10629 18 : || !endswith (n->u.memspace_sym->name, "_mem_space")))
10630 3 : gfc_error ("Memspace %qs at %L in USES_ALLOCATORS must be "
10631 : "a predefined memory space",
10632 : n->u.memspace_sym->name, &n->where);
10633 180 : for (; n != NULL; n = n->next)
10634 : {
10635 122 : if (n->sym->ts.type != BT_INTEGER
10636 121 : || n->sym->ts.kind != gfc_c_intptr_kind
10637 120 : || n->sym->attr.dimension)
10638 3 : gfc_error ("Allocator %qs at %L in USES_ALLOCATORS must "
10639 : "be a scalar integer of kind "
10640 : "%<omp_allocator_handle_kind%>", n->sym->name,
10641 : &n->where);
10642 119 : else if (n->sym->attr.flavor != FL_VARIABLE
10643 50 : && strcmp (n->sym->name, "omp_null_allocator") != 0
10644 165 : && ((!startswith (n->sym->name, "omp_")
10645 1 : && !startswith (n->sym->name, "ompx_"))
10646 45 : || !endswith (n->sym->name, "_mem_alloc")))
10647 2 : gfc_error ("Allocator %qs at %L in USES_ALLOCATORS must "
10648 : "either a variable or a predefined allocator",
10649 : n->sym->name, &n->where);
10650 117 : else if ((n->u.memspace_sym || n->u2.traits_sym)
10651 61 : && n->sym->attr.flavor != FL_VARIABLE)
10652 3 : gfc_error ("A memory space or traits array may not be "
10653 : "specified for predefined allocator %qs at %L",
10654 : n->sym->name, &n->where);
10655 122 : if (n->u2.traits_sym
10656 50 : && (n->u2.traits_sym->attr.flavor != FL_PARAMETER
10657 47 : || !n->u2.traits_sym->attr.dimension
10658 45 : || n->u2.traits_sym->as->rank != 1
10659 45 : || n->u2.traits_sym->ts.type != BT_DERIVED
10660 43 : || strcmp (n->u2.traits_sym->ts.u.derived->name,
10661 : "omp_alloctrait") != 0))
10662 : {
10663 7 : gfc_error ("Traits array %qs in USES_ALLOCATORS %L must "
10664 : "be a one-dimensional named constant array of "
10665 : "type %<omp_alloctrait%>",
10666 : n->u2.traits_sym->name, &n->where);
10667 7 : break;
10668 : }
10669 : }
10670 : break;
10671 : }
10672 : default:
10673 34776 : for (; n != NULL; n = n->next)
10674 : {
10675 20380 : if (n->sym == NULL)
10676 : {
10677 26 : gcc_assert (code->op == EXEC_OMP_ALLOCATORS
10678 : || code->op == EXEC_OMP_ALLOCATE);
10679 26 : continue;
10680 : }
10681 20354 : bool bad = false;
10682 20354 : bool is_reduction = (list == OMP_LIST_REDUCTION
10683 : || list == OMP_LIST_REDUCTION_INSCAN
10684 : || list == OMP_LIST_REDUCTION_TASK
10685 : || list == OMP_LIST_IN_REDUCTION
10686 20354 : || list == OMP_LIST_TASK_REDUCTION);
10687 20354 : if (list == OMP_LIST_REDUCTION_INSCAN)
10688 : has_inscan = true;
10689 20282 : else if (is_reduction)
10690 4737 : has_notinscan = true;
10691 20354 : if (has_inscan && has_notinscan && is_reduction)
10692 : {
10693 3 : gfc_error ("%<inscan%> and non-%<inscan%> %<reduction%> "
10694 : "clauses on the same construct at %L",
10695 : &n->where);
10696 3 : break;
10697 : }
10698 20351 : if (n->sym->attr.threadprivate)
10699 1 : gfc_error ("THREADPRIVATE object %qs in %s clause at %L",
10700 : n->sym->name, name, &n->where);
10701 20351 : if (n->sym->attr.cray_pointee)
10702 14 : gfc_error ("Cray pointee %qs in %s clause at %L",
10703 : n->sym->name, name, &n->where);
10704 20351 : if (n->sym->attr.associate_var)
10705 22 : gfc_error ("Associate name %qs in %s clause at %L",
10706 22 : n->sym->attr.select_type_temporary
10707 4 : ? n->sym->assoc->target->symtree->n.sym->name
10708 : : n->sym->name, name, &n->where);
10709 20351 : if (list != OMP_LIST_PRIVATE && is_reduction)
10710 : {
10711 4806 : if (n->sym->attr.proc_pointer)
10712 1 : gfc_error ("Procedure pointer %qs in %s clause at %L",
10713 : n->sym->name, name, &n->where);
10714 4806 : if (n->sym->attr.pointer)
10715 3 : gfc_error ("POINTER object %qs in %s clause at %L",
10716 : n->sym->name, name, &n->where);
10717 4806 : if (n->sym->attr.cray_pointer)
10718 5 : gfc_error ("Cray pointer %qs in %s clause at %L",
10719 : n->sym->name, name, &n->where);
10720 : }
10721 20351 : if (code
10722 20351 : && (oacc_is_loop (code)
10723 : || code->op == EXEC_OACC_PARALLEL
10724 : || code->op == EXEC_OACC_SERIAL))
10725 8741 : check_array_not_assumed (n->sym, n->where, name);
10726 11610 : else if (list != OMP_LIST_UNIFORM
10727 11493 : && n->sym->as && n->sym->as->type == AS_ASSUMED_SIZE)
10728 2 : gfc_error ("Assumed size array %qs in %s clause at %L",
10729 : n->sym->name, name, &n->where);
10730 20351 : if (n->sym->attr.in_namelist && !is_reduction)
10731 0 : gfc_error ("Variable %qs in %s clause is used in "
10732 : "NAMELIST statement at %L",
10733 : n->sym->name, name, &n->where);
10734 20351 : if (n->sym->attr.pointer && n->sym->attr.intent == INTENT_IN)
10735 3 : switch (list)
10736 : {
10737 3 : case OMP_LIST_PRIVATE:
10738 3 : case OMP_LIST_LASTPRIVATE:
10739 3 : case OMP_LIST_LINEAR:
10740 : /* case OMP_LIST_REDUCTION: */
10741 3 : gfc_error ("INTENT(IN) POINTER %qs in %s clause at %L",
10742 : n->sym->name, name, &n->where);
10743 3 : break;
10744 : default:
10745 : break;
10746 : }
10747 20351 : if (omp_clauses->detach
10748 3 : && (list == OMP_LIST_PRIVATE
10749 : || list == OMP_LIST_FIRSTPRIVATE
10750 : || list == OMP_LIST_LASTPRIVATE)
10751 3 : && n->sym == omp_clauses->detach->symtree->n.sym)
10752 1 : gfc_error ("DETACH event handle %qs in %s clause at %L",
10753 : n->sym->name, name, &n->where);
10754 :
10755 20351 : if (!openacc
10756 20351 : && (list == OMP_LIST_PRIVATE
10757 20351 : || list == OMP_LIST_FIRSTPRIVATE)
10758 4704 : && ((n->sym->ts.type == BT_DERIVED
10759 158 : && n->sym->ts.u.derived->attr.alloc_comp)
10760 4594 : || n->sym->ts.type == BT_CLASS))
10761 170 : switch (code->op)
10762 : {
10763 8 : case EXEC_OMP_TARGET:
10764 8 : case EXEC_OMP_TARGET_PARALLEL:
10765 8 : case EXEC_OMP_TARGET_PARALLEL_DO:
10766 8 : case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
10767 8 : case EXEC_OMP_TARGET_PARALLEL_LOOP:
10768 8 : case EXEC_OMP_TARGET_SIMD:
10769 8 : case EXEC_OMP_TARGET_TEAMS:
10770 8 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
10771 8 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
10772 8 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
10773 8 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
10774 8 : case EXEC_OMP_TARGET_TEAMS_LOOP:
10775 8 : if (n->sym->ts.type == BT_DERIVED
10776 2 : && n->sym->ts.u.derived->attr.alloc_comp)
10777 3 : gfc_error ("Sorry, list item %qs at %L with allocatable"
10778 : " components is not yet supported in %s "
10779 : "clause", n->sym->name, &n->where,
10780 : list == OMP_LIST_PRIVATE ? "PRIVATE"
10781 : : "FIRSTPRIVATE");
10782 : else
10783 9 : gfc_error ("Polymorphic list item %qs at %L in %s "
10784 : "clause has unspecified behavior and "
10785 : "unsupported", n->sym->name, &n->where,
10786 : list == OMP_LIST_PRIVATE ? "PRIVATE"
10787 : : "FIRSTPRIVATE");
10788 : break;
10789 : default:
10790 : break;
10791 : }
10792 :
10793 20351 : switch (list)
10794 : {
10795 104 : case OMP_LIST_REDUCTION_TASK:
10796 104 : if (code
10797 104 : && (code->op == EXEC_OMP_LOOP
10798 : || code->op == EXEC_OMP_TASKLOOP
10799 : || code->op == EXEC_OMP_TASKLOOP_SIMD
10800 : || code->op == EXEC_OMP_MASKED_TASKLOOP
10801 : || code->op == EXEC_OMP_MASKED_TASKLOOP_SIMD
10802 : || code->op == EXEC_OMP_MASTER_TASKLOOP
10803 : || code->op == EXEC_OMP_MASTER_TASKLOOP_SIMD
10804 : || code->op == EXEC_OMP_PARALLEL_LOOP
10805 : || code->op == EXEC_OMP_PARALLEL_MASKED_TASKLOOP
10806 : || code->op == EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD
10807 : || code->op == EXEC_OMP_PARALLEL_MASTER_TASKLOOP
10808 : || code->op == EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD
10809 : || code->op == EXEC_OMP_TARGET_PARALLEL_LOOP
10810 : || code->op == EXEC_OMP_TARGET_TEAMS_LOOP
10811 : || code->op == EXEC_OMP_TEAMS
10812 : || code->op == EXEC_OMP_TEAMS_DISTRIBUTE
10813 : || code->op == EXEC_OMP_TEAMS_LOOP))
10814 : {
10815 17 : gfc_error ("Only DEFAULT permitted as reduction-"
10816 : "modifier in REDUCTION clause at %L",
10817 : &n->where);
10818 17 : break;
10819 : }
10820 4789 : gcc_fallthrough ();
10821 4789 : case OMP_LIST_REDUCTION:
10822 4789 : case OMP_LIST_IN_REDUCTION:
10823 4789 : case OMP_LIST_TASK_REDUCTION:
10824 4789 : case OMP_LIST_REDUCTION_INSCAN:
10825 4789 : switch (n->u.reduction_op)
10826 : {
10827 2655 : case OMP_REDUCTION_PLUS:
10828 2655 : case OMP_REDUCTION_TIMES:
10829 2655 : case OMP_REDUCTION_MINUS:
10830 2655 : if (!gfc_numeric_ts (&n->sym->ts))
10831 : bad = true;
10832 : break;
10833 1112 : case OMP_REDUCTION_AND:
10834 1112 : case OMP_REDUCTION_OR:
10835 1112 : case OMP_REDUCTION_EQV:
10836 1112 : case OMP_REDUCTION_NEQV:
10837 1112 : if (n->sym->ts.type != BT_LOGICAL)
10838 : bad = true;
10839 : break;
10840 480 : case OMP_REDUCTION_MAX:
10841 480 : case OMP_REDUCTION_MIN:
10842 480 : if (n->sym->ts.type != BT_INTEGER
10843 212 : && n->sym->ts.type != BT_REAL)
10844 : bad = true;
10845 : break;
10846 192 : case OMP_REDUCTION_IAND:
10847 192 : case OMP_REDUCTION_IOR:
10848 192 : case OMP_REDUCTION_IEOR:
10849 192 : if (n->sym->ts.type != BT_INTEGER)
10850 : bad = true;
10851 : break;
10852 : case OMP_REDUCTION_USER:
10853 : bad = true;
10854 : break;
10855 : default:
10856 : break;
10857 : }
10858 : if (!bad)
10859 4215 : n->u2.udr = NULL;
10860 : else
10861 : {
10862 574 : const char *udr_name = NULL;
10863 574 : if (n->u2.udr)
10864 : {
10865 470 : udr_name = n->u2.udr->udr->name;
10866 470 : n->u2.udr->udr
10867 940 : = gfc_find_omp_udr (NULL, udr_name,
10868 470 : &n->sym->ts);
10869 470 : if (n->u2.udr->udr == NULL)
10870 : {
10871 0 : free (n->u2.udr);
10872 0 : n->u2.udr = NULL;
10873 : }
10874 : }
10875 574 : if (n->u2.udr == NULL)
10876 : {
10877 104 : if (udr_name == NULL)
10878 104 : switch (n->u.reduction_op)
10879 : {
10880 50 : case OMP_REDUCTION_PLUS:
10881 50 : case OMP_REDUCTION_TIMES:
10882 50 : case OMP_REDUCTION_MINUS:
10883 50 : case OMP_REDUCTION_AND:
10884 50 : case OMP_REDUCTION_OR:
10885 50 : case OMP_REDUCTION_EQV:
10886 50 : case OMP_REDUCTION_NEQV:
10887 50 : udr_name = gfc_op2string ((gfc_intrinsic_op)
10888 : n->u.reduction_op);
10889 50 : break;
10890 : case OMP_REDUCTION_MAX:
10891 : udr_name = "max";
10892 : break;
10893 9 : case OMP_REDUCTION_MIN:
10894 9 : udr_name = "min";
10895 9 : break;
10896 12 : case OMP_REDUCTION_IAND:
10897 12 : udr_name = "iand";
10898 12 : break;
10899 12 : case OMP_REDUCTION_IOR:
10900 12 : udr_name = "ior";
10901 12 : break;
10902 9 : case OMP_REDUCTION_IEOR:
10903 9 : udr_name = "ieor";
10904 9 : break;
10905 0 : default:
10906 0 : gcc_unreachable ();
10907 : }
10908 104 : gfc_error ("!$OMP DECLARE REDUCTION %s not found "
10909 : "for type %s at %L", udr_name,
10910 104 : gfc_typename (&n->sym->ts), &n->where);
10911 : }
10912 : else
10913 : {
10914 470 : gfc_omp_udr *udr = n->u2.udr->udr;
10915 470 : n->u.reduction_op = OMP_REDUCTION_USER;
10916 470 : n->u2.udr->combiner
10917 940 : = resolve_omp_udr_clause (n, udr->combiner_ns,
10918 470 : udr->omp_out,
10919 470 : udr->omp_in);
10920 470 : if (udr->initializer_ns)
10921 331 : n->u2.udr->initializer
10922 331 : = resolve_omp_udr_clause (n,
10923 : udr->initializer_ns,
10924 331 : udr->omp_priv,
10925 331 : udr->omp_orig);
10926 : }
10927 : }
10928 : break;
10929 874 : case OMP_LIST_LINEAR:
10930 874 : if (code)
10931 : {
10932 727 : bool is_worksharing_for = false;
10933 727 : switch (code->op)
10934 : {
10935 54 : case EXEC_OMP_DO:
10936 54 : case EXEC_OMP_PARALLEL_DO:
10937 54 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
10938 54 : case EXEC_OMP_TARGET_PARALLEL_DO:
10939 54 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
10940 54 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
10941 54 : is_worksharing_for = true;
10942 54 : break;
10943 : default:
10944 : break;
10945 : }
10946 :
10947 54 : if (is_worksharing_for
10948 54 : && (n->sym->attr.dimension
10949 53 : || n->sym->attr.allocatable))
10950 : {
10951 1 : if (n->sym->attr.allocatable)
10952 0 : gfc_error ("Sorry, ALLOCATABLE object %qs in "
10953 : "LINEAR clause on worksharing-loop "
10954 : "construct at %L is not yet supported",
10955 : n->sym->name, &n->where);
10956 : else
10957 1 : gfc_error ("Sorry, array %qs in LINEAR clause "
10958 : "on worksharing-loop construct at %L "
10959 : "is not yet supported",
10960 : n->sym->name, &n->where);
10961 : break;
10962 : }
10963 : }
10964 :
10965 726 : if (code
10966 726 : && n->u.linear.op != OMP_LINEAR_DEFAULT
10967 23 : && n->u.linear.op != linear_op)
10968 : {
10969 23 : if (n->u.linear.old_modifier)
10970 : {
10971 9 : gfc_error ("LINEAR clause modifier used on DO or "
10972 : "SIMD construct at %L", &n->where);
10973 9 : linear_op = n->u.linear.op;
10974 : }
10975 14 : else if (n->u.linear.op != OMP_LINEAR_VAL)
10976 : {
10977 6 : gfc_error ("LINEAR clause modifier other than VAL "
10978 : "used on DO or SIMD construct at %L",
10979 : &n->where);
10980 6 : linear_op = n->u.linear.op;
10981 : }
10982 : }
10983 850 : else if (n->u.linear.op != OMP_LINEAR_REF
10984 800 : && n->sym->ts.type != BT_INTEGER)
10985 1 : gfc_error ("LINEAR variable %qs must be INTEGER "
10986 : "at %L", n->sym->name, &n->where);
10987 849 : else if ((n->u.linear.op == OMP_LINEAR_REF
10988 799 : || n->u.linear.op == OMP_LINEAR_UVAL)
10989 61 : && n->sym->attr.value)
10990 0 : gfc_error ("LINEAR dummy argument %qs with VALUE "
10991 : "attribute with %s modifier at %L",
10992 : n->sym->name,
10993 : n->u.linear.op == OMP_LINEAR_REF
10994 : ? "REF" : "UVAL", &n->where);
10995 849 : else if (n->expr)
10996 : {
10997 830 : gfc_expr *expr = n->expr;
10998 830 : if (!gfc_resolve_expr (expr)
10999 830 : || expr->ts.type != BT_INTEGER
11000 1660 : || expr->rank != 0)
11001 0 : gfc_error ("%qs in LINEAR clause at %L requires "
11002 : "a scalar integer linear-step expression",
11003 0 : n->sym->name, &n->where);
11004 830 : else if (!code && expr->expr_type != EXPR_CONSTANT)
11005 : {
11006 11 : if (expr->expr_type == EXPR_VARIABLE
11007 7 : && expr->symtree->n.sym->attr.dummy
11008 6 : && expr->symtree->n.sym->ns == ns)
11009 : {
11010 6 : gfc_omp_namelist *n2;
11011 6 : for (n2 = omp_clauses->lists[OMP_LIST_UNIFORM];
11012 6 : n2; n2 = n2->next)
11013 6 : if (n2->sym == expr->symtree->n.sym)
11014 : break;
11015 6 : if (n2)
11016 : break;
11017 : }
11018 5 : gfc_error ("%qs in LINEAR clause at %L requires "
11019 : "a constant integer linear-step "
11020 : "expression or dummy argument "
11021 : "specified in UNIFORM clause",
11022 5 : n->sym->name, &n->where);
11023 : }
11024 : }
11025 : break;
11026 : /* Workaround for PR middle-end/26316, nothing really needs
11027 : to be done here for OMP_LIST_PRIVATE. */
11028 9394 : case OMP_LIST_PRIVATE:
11029 9394 : gcc_assert (code && code->op != EXEC_NOP);
11030 : break;
11031 98 : case OMP_LIST_USE_DEVICE:
11032 98 : if (n->sym->attr.allocatable
11033 98 : || (n->sym->ts.type == BT_CLASS && CLASS_DATA (n->sym)
11034 0 : && CLASS_DATA (n->sym)->attr.allocatable))
11035 0 : gfc_error ("ALLOCATABLE object %qs in %s clause at %L",
11036 : n->sym->name, name, &n->where);
11037 98 : if (n->sym->ts.type == BT_CLASS
11038 0 : && CLASS_DATA (n->sym)
11039 0 : && CLASS_DATA (n->sym)->attr.class_pointer)
11040 0 : gfc_error ("POINTER object %qs of polymorphic type in "
11041 : "%s clause at %L", n->sym->name, name,
11042 : &n->where);
11043 98 : if (n->sym->attr.cray_pointer)
11044 2 : gfc_error ("Cray pointer object %qs in %s clause at %L",
11045 : n->sym->name, name, &n->where);
11046 96 : else if (n->sym->attr.cray_pointee)
11047 2 : gfc_error ("Cray pointee object %qs in %s clause at %L",
11048 : n->sym->name, name, &n->where);
11049 94 : else if (n->sym->attr.flavor == FL_VARIABLE
11050 93 : && !n->sym->as
11051 54 : && !n->sym->attr.pointer)
11052 13 : gfc_error ("%s clause variable %qs at %L is neither "
11053 : "a POINTER nor an array", name,
11054 : n->sym->name, &n->where);
11055 : /* FALLTHRU */
11056 98 : case OMP_LIST_DEVICE_RESIDENT:
11057 98 : check_symbol_not_pointer (n->sym, n->where, name);
11058 98 : check_array_not_assumed (n->sym, n->where, name);
11059 98 : break;
11060 : default:
11061 : break;
11062 : }
11063 : }
11064 : break;
11065 : }
11066 : }
11067 : /* OpenMP 5.1: use_device_ptr acts like use_device_addr, except for
11068 : type(c_ptr). */
11069 32620 : if (omp_clauses->lists[OMP_LIST_USE_DEVICE_PTR])
11070 : {
11071 9 : gfc_omp_namelist *n_prev, *n_next, *n_addr;
11072 9 : n_addr = omp_clauses->lists[OMP_LIST_USE_DEVICE_ADDR];
11073 28 : for (; n_addr && n_addr->next; n_addr = n_addr->next)
11074 : ;
11075 : n_prev = NULL;
11076 : n = omp_clauses->lists[OMP_LIST_USE_DEVICE_PTR];
11077 27 : while (n)
11078 : {
11079 18 : n_next = n->next;
11080 18 : if (n->sym->ts.type != BT_DERIVED
11081 18 : || n->sym->ts.u.derived->ts.f90_type != BT_VOID)
11082 : {
11083 0 : n->next = NULL;
11084 0 : if (n_addr)
11085 0 : n_addr->next = n;
11086 : else
11087 0 : omp_clauses->lists[OMP_LIST_USE_DEVICE_ADDR] = n;
11088 0 : n_addr = n;
11089 0 : if (n_prev)
11090 0 : n_prev->next = n_next;
11091 : else
11092 0 : omp_clauses->lists[OMP_LIST_USE_DEVICE_PTR] = n_next;
11093 : }
11094 : else
11095 : n_prev = n;
11096 : n = n_next;
11097 : }
11098 : }
11099 32620 : if (omp_clauses->safelen_expr)
11100 93 : resolve_positive_int_expr (omp_clauses->safelen_expr, "SAFELEN");
11101 32620 : if (omp_clauses->simdlen_expr)
11102 123 : resolve_positive_int_expr (omp_clauses->simdlen_expr, "SIMDLEN");
11103 32620 : if (omp_clauses->num_teams_lower)
11104 21 : resolve_positive_int_expr (omp_clauses->num_teams_lower, "NUM_TEAMS");
11105 32620 : if (omp_clauses->num_teams_upper)
11106 129 : resolve_positive_int_expr (omp_clauses->num_teams_upper, "NUM_TEAMS");
11107 32620 : if (omp_clauses->num_teams_lower
11108 21 : && omp_clauses->num_teams_lower->expr_type == EXPR_CONSTANT
11109 7 : && omp_clauses->num_teams_upper->expr_type == EXPR_CONSTANT
11110 7 : && mpz_cmp (omp_clauses->num_teams_lower->value.integer,
11111 7 : omp_clauses->num_teams_upper->value.integer) > 0)
11112 2 : gfc_warning (OPT_Wopenmp, "NUM_TEAMS lower bound at %L larger than upper "
11113 : "bound at %L", &omp_clauses->num_teams_lower->where,
11114 : &omp_clauses->num_teams_upper->where);
11115 32620 : if (omp_clauses->device)
11116 333 : resolve_scalar_int_expr (omp_clauses->device, "DEVICE");
11117 32620 : if (omp_clauses->filter)
11118 42 : resolve_nonnegative_int_expr (omp_clauses->filter, "FILTER");
11119 32620 : if (omp_clauses->hint)
11120 : {
11121 42 : resolve_scalar_int_expr (omp_clauses->hint, "HINT");
11122 42 : if (omp_clauses->hint->ts.type != BT_INTEGER
11123 40 : || omp_clauses->hint->expr_type != EXPR_CONSTANT
11124 38 : || mpz_sgn (omp_clauses->hint->value.integer) < 0)
11125 5 : gfc_error ("Value of HINT clause at %L shall be a valid "
11126 : "constant hint expression", &omp_clauses->hint->where);
11127 : }
11128 32620 : if (omp_clauses->priority)
11129 34 : resolve_nonnegative_int_expr (omp_clauses->priority, "PRIORITY");
11130 32620 : if (omp_clauses->dist_chunk_size)
11131 : {
11132 83 : gfc_expr *expr = omp_clauses->dist_chunk_size;
11133 83 : if (!gfc_resolve_expr (expr)
11134 83 : || expr->ts.type != BT_INTEGER || expr->rank != 0)
11135 0 : gfc_error ("DIST_SCHEDULE clause's chunk_size at %L requires "
11136 : "a scalar INTEGER expression", &expr->where);
11137 : }
11138 32620 : if (omp_clauses->thread_limit)
11139 74 : resolve_positive_int_expr (omp_clauses->thread_limit, "THREAD_LIMIT");
11140 32620 : if (omp_clauses->grainsize)
11141 34 : resolve_positive_int_expr (omp_clauses->grainsize, "GRAINSIZE");
11142 32620 : if (omp_clauses->num_tasks)
11143 26 : resolve_positive_int_expr (omp_clauses->num_tasks, "NUM_TASKS");
11144 32620 : if (omp_clauses->grainsize && omp_clauses->num_tasks)
11145 1 : gfc_error ("%<GRAINSIZE%> clause at %L must not be used together with "
11146 : "%<NUM_TASKS%> clause", &omp_clauses->grainsize->where);
11147 32620 : if (omp_clauses->lists[OMP_LIST_REDUCTION] && omp_clauses->nogroup)
11148 1 : gfc_error ("%<REDUCTION%> clause at %L must not be used together with "
11149 : "%<NOGROUP%> clause",
11150 : &omp_clauses->lists[OMP_LIST_REDUCTION]->where);
11151 32620 : if (omp_clauses->full && omp_clauses->partial)
11152 0 : gfc_error ("%<FULL%> clause at %C must not be used together with "
11153 : "%<PARTIAL%> clause");
11154 32620 : if (omp_clauses->async)
11155 610 : if (omp_clauses->async_expr)
11156 610 : resolve_scalar_int_expr (omp_clauses->async_expr, "ASYNC");
11157 32620 : if (omp_clauses->num_gangs_expr)
11158 682 : resolve_positive_int_expr (omp_clauses->num_gangs_expr, "NUM_GANGS");
11159 32620 : if (omp_clauses->num_workers_expr)
11160 599 : resolve_positive_int_expr (omp_clauses->num_workers_expr, "NUM_WORKERS");
11161 32620 : if (omp_clauses->vector_length_expr)
11162 569 : resolve_positive_int_expr (omp_clauses->vector_length_expr,
11163 : "VECTOR_LENGTH");
11164 32620 : if (omp_clauses->gang_num_expr)
11165 114 : resolve_positive_int_expr (omp_clauses->gang_num_expr, "GANG");
11166 32620 : if (omp_clauses->gang_static_expr)
11167 94 : resolve_positive_int_expr (omp_clauses->gang_static_expr, "GANG");
11168 32620 : if (omp_clauses->worker_expr)
11169 101 : resolve_positive_int_expr (omp_clauses->worker_expr, "WORKER");
11170 32620 : if (omp_clauses->vector_expr)
11171 132 : resolve_positive_int_expr (omp_clauses->vector_expr, "VECTOR");
11172 32959 : for (el = omp_clauses->wait_list; el; el = el->next)
11173 339 : resolve_scalar_int_expr (el->expr, "WAIT");
11174 32620 : if (omp_clauses->collapse && omp_clauses->tile_list)
11175 4 : gfc_error ("Incompatible use of TILE and COLLAPSE at %L", &code->loc);
11176 32620 : if (omp_clauses->message)
11177 : {
11178 45 : gfc_expr *expr = omp_clauses->message;
11179 45 : if (!gfc_resolve_expr (expr)
11180 45 : || expr->ts.kind != gfc_default_character_kind
11181 87 : || expr->ts.type != BT_CHARACTER || expr->rank != 0)
11182 4 : gfc_error ("MESSAGE clause at %L requires a scalar default-kind "
11183 : "CHARACTER expression", &expr->where);
11184 : }
11185 32620 : if (!openacc
11186 32620 : && code
11187 19754 : && omp_clauses->lists[OMP_LIST_MAP] == NULL
11188 15967 : && omp_clauses->lists[OMP_LIST_USE_DEVICE_PTR] == NULL
11189 15964 : && omp_clauses->lists[OMP_LIST_USE_DEVICE_ADDR] == NULL)
11190 : {
11191 15941 : const char *p = NULL;
11192 15941 : switch (code->op)
11193 : {
11194 1 : case EXEC_OMP_TARGET_ENTER_DATA: p = "TARGET ENTER DATA"; break;
11195 1 : case EXEC_OMP_TARGET_EXIT_DATA: p = "TARGET EXIT DATA"; break;
11196 : default: break;
11197 : }
11198 15941 : if (code->op == EXEC_OMP_TARGET_DATA)
11199 1 : gfc_error ("TARGET DATA must contain at least one MAP, USE_DEVICE_PTR, "
11200 : "or USE_DEVICE_ADDR clause at %L", &code->loc);
11201 15940 : else if (p)
11202 2 : gfc_error ("%s must contain at least one MAP clause at %L",
11203 : p, &code->loc);
11204 : }
11205 32620 : if (omp_clauses->sizes_list)
11206 : {
11207 : gfc_expr_list *el;
11208 572 : for (el = omp_clauses->sizes_list; el; el = el->next)
11209 : {
11210 377 : resolve_scalar_int_expr (el->expr, "SIZES");
11211 377 : if (el->expr->expr_type != EXPR_CONSTANT)
11212 1 : gfc_error ("SIZES requires constant expression at %L",
11213 : &el->expr->where);
11214 376 : else if (el->expr->expr_type == EXPR_CONSTANT
11215 376 : && el->expr->ts.type == BT_INTEGER
11216 376 : && mpz_sgn (el->expr->value.integer) <= 0)
11217 2 : gfc_error ("INTEGER expression of %s clause at %L must be "
11218 : "positive", "SIZES", &el->expr->where);
11219 : }
11220 : }
11221 :
11222 32620 : if (!openacc && omp_clauses->detach)
11223 : {
11224 125 : if (!gfc_resolve_expr (omp_clauses->detach)
11225 125 : || omp_clauses->detach->ts.type != BT_INTEGER
11226 124 : || omp_clauses->detach->ts.kind != gfc_c_intptr_kind
11227 248 : || omp_clauses->detach->rank != 0)
11228 3 : gfc_error ("%qs at %L should be a scalar of type "
11229 : "integer(kind=omp_event_handle_kind)",
11230 3 : omp_clauses->detach->symtree->n.sym->name,
11231 3 : &omp_clauses->detach->where);
11232 122 : else if (omp_clauses->detach->symtree->n.sym->attr.dimension > 0)
11233 1 : gfc_error ("The event handle at %L must not be an array element",
11234 : &omp_clauses->detach->where);
11235 121 : else if (omp_clauses->detach->symtree->n.sym->ts.type == BT_DERIVED
11236 120 : || omp_clauses->detach->symtree->n.sym->ts.type == BT_CLASS)
11237 1 : gfc_error ("The event handle at %L must not be part of "
11238 : "a derived type or class", &omp_clauses->detach->where);
11239 :
11240 125 : if (omp_clauses->mergeable)
11241 2 : gfc_error ("%<DETACH%> clause at %L must not be used together with "
11242 2 : "%<MERGEABLE%> clause", &omp_clauses->detach->where);
11243 : }
11244 :
11245 12625 : if (openacc
11246 12625 : && code->op == EXEC_OACC_HOST_DATA
11247 60 : && omp_clauses->lists[OMP_LIST_USE_DEVICE] == NULL)
11248 1 : gfc_error ("%<host_data%> construct at %L requires %<use_device%> clause",
11249 : &code->loc);
11250 :
11251 32620 : if (omp_clauses->assume)
11252 16 : gfc_resolve_omp_assumptions (omp_clauses->assume);
11253 : }
11254 :
11255 :
11256 : /* Return true if SYM is ever referenced in EXPR except in the SE node. */
11257 :
11258 : static bool
11259 4991 : expr_references_sym (gfc_expr *e, gfc_symbol *s, gfc_expr *se)
11260 : {
11261 6617 : gfc_actual_arglist *arg;
11262 6617 : if (e == NULL || e == se)
11263 : return false;
11264 5366 : switch (e->expr_type)
11265 : {
11266 3120 : case EXPR_CONSTANT:
11267 3120 : case EXPR_NULL:
11268 3120 : case EXPR_VARIABLE:
11269 3120 : case EXPR_STRUCTURE:
11270 3120 : case EXPR_ARRAY:
11271 3120 : if (e->symtree != NULL
11272 1152 : && e->symtree->n.sym == s)
11273 : return true;
11274 : return false;
11275 0 : case EXPR_SUBSTRING:
11276 0 : if (e->ref != NULL
11277 0 : && (expr_references_sym (e->ref->u.ss.start, s, se)
11278 0 : || expr_references_sym (e->ref->u.ss.end, s, se)))
11279 0 : return true;
11280 : return false;
11281 1735 : case EXPR_OP:
11282 1735 : if (expr_references_sym (e->value.op.op2, s, se))
11283 : return true;
11284 1626 : return expr_references_sym (e->value.op.op1, s, se);
11285 511 : case EXPR_FUNCTION:
11286 896 : for (arg = e->value.function.actual; arg; arg = arg->next)
11287 586 : if (expr_references_sym (arg->expr, s, se))
11288 : return true;
11289 : return false;
11290 0 : default:
11291 0 : gcc_unreachable ();
11292 : }
11293 : }
11294 :
11295 :
11296 : /* If EXPR is a conversion function that widens the type
11297 : if WIDENING is true or narrows the type if NARROW is true,
11298 : return the inner expression, otherwise return NULL. */
11299 :
11300 : static gfc_expr *
11301 5911 : is_conversion (gfc_expr *expr, bool narrowing, bool widening)
11302 : {
11303 5911 : gfc_typespec *ts1, *ts2;
11304 :
11305 5911 : if (expr->expr_type != EXPR_FUNCTION
11306 917 : || expr->value.function.isym == NULL
11307 894 : || expr->value.function.esym != NULL
11308 894 : || expr->value.function.isym->id != GFC_ISYM_CONVERSION
11309 388 : || (!narrowing && !widening))
11310 : return NULL;
11311 :
11312 388 : if (narrowing && widening)
11313 267 : return expr->value.function.actual->expr;
11314 :
11315 121 : if (widening)
11316 : {
11317 121 : ts1 = &expr->ts;
11318 121 : ts2 = &expr->value.function.actual->expr->ts;
11319 : }
11320 : else
11321 : {
11322 0 : ts1 = &expr->value.function.actual->expr->ts;
11323 0 : ts2 = &expr->ts;
11324 : }
11325 :
11326 121 : if (ts1->type > ts2->type
11327 49 : || (ts1->type == ts2->type && ts1->kind > ts2->kind))
11328 121 : return expr->value.function.actual->expr;
11329 :
11330 : return NULL;
11331 : }
11332 :
11333 : static bool
11334 6855 : is_scalar_intrinsic_expr (gfc_expr *expr, bool must_be_var, bool conv_ok)
11335 : {
11336 6855 : if (must_be_var
11337 4020 : && (expr->expr_type != EXPR_VARIABLE || !expr->symtree))
11338 : {
11339 37 : if (!conv_ok)
11340 : return false;
11341 37 : gfc_expr *conv = is_conversion (expr, true, true);
11342 37 : if (!conv)
11343 : return false;
11344 36 : if (conv->expr_type != EXPR_VARIABLE || !conv->symtree)
11345 : return false;
11346 : }
11347 6852 : return (expr->rank == 0
11348 6848 : && !gfc_is_coindexed (expr)
11349 13700 : && (expr->ts.type == BT_INTEGER
11350 : || expr->ts.type == BT_REAL
11351 : || expr->ts.type == BT_COMPLEX
11352 : || expr->ts.type == BT_LOGICAL));
11353 : }
11354 :
11355 : static void
11356 2697 : resolve_omp_atomic (gfc_code *code)
11357 : {
11358 2697 : gfc_code *atomic_code = code->block;
11359 2697 : gfc_symbol *var;
11360 2697 : gfc_expr *stmt_expr2, *capt_expr2;
11361 2697 : gfc_omp_atomic_op aop
11362 2697 : = (gfc_omp_atomic_op) (atomic_code->ext.omp_clauses->atomic_op
11363 : & GFC_OMP_ATOMIC_MASK);
11364 2697 : gfc_code *stmt = NULL, *capture_stmt = NULL, *tailing_stmt = NULL;
11365 2697 : gfc_expr *comp_cond = NULL;
11366 2697 : locus *loc = NULL;
11367 :
11368 2697 : code = code->block->next;
11369 : /* resolve_blocks asserts this is initially EXEC_ASSIGN or EXEC_IF
11370 : If it changed to EXEC_NOP, assume an error has been emitted already. */
11371 2697 : if (code->op == EXEC_NOP)
11372 : return;
11373 :
11374 2696 : if (atomic_code->ext.omp_clauses->compare
11375 156 : && atomic_code->ext.omp_clauses->capture)
11376 : {
11377 : /* Must be either "if (x == e) then; x = d; else; v = x; end if"
11378 : or "v = expr" followed/preceded by
11379 : "if (x == e) then; x = d; end if" or "if (x == e) x = d". */
11380 103 : gfc_code *next = code;
11381 103 : if (code->op == EXEC_ASSIGN)
11382 : {
11383 19 : capture_stmt = code;
11384 19 : next = code->next;
11385 : }
11386 103 : if (next->op == EXEC_IF
11387 103 : && next->block
11388 103 : && next->block->op == EXEC_IF
11389 103 : && next->block->next
11390 102 : && next->block->next->op == EXEC_ASSIGN)
11391 : {
11392 102 : comp_cond = next->block->expr1;
11393 102 : stmt = next->block->next;
11394 102 : if (stmt->next)
11395 : {
11396 0 : loc = &stmt->loc;
11397 0 : goto unexpected;
11398 : }
11399 : }
11400 1 : else if (capture_stmt)
11401 : {
11402 0 : gfc_error ("Expected IF at %L in atomic compare capture",
11403 : &next->loc);
11404 0 : return;
11405 : }
11406 103 : if (stmt && !capture_stmt && next->block->block)
11407 : {
11408 64 : if (next->block->block->expr1)
11409 : {
11410 0 : gfc_error ("Expected ELSE at %L in atomic compare capture",
11411 : &next->block->block->expr1->where);
11412 0 : return;
11413 : }
11414 64 : if (!code->block->block->next
11415 64 : || code->block->block->next->op != EXEC_ASSIGN)
11416 : {
11417 0 : loc = (code->block->block->next ? &code->block->block->next->loc
11418 : : &code->block->block->loc);
11419 0 : goto unexpected;
11420 : }
11421 64 : capture_stmt = code->block->block->next;
11422 64 : if (capture_stmt->next)
11423 : {
11424 0 : loc = &capture_stmt->next->loc;
11425 0 : goto unexpected;
11426 : }
11427 : }
11428 103 : if (stmt && !capture_stmt && next->next->op == EXEC_ASSIGN)
11429 : capture_stmt = next->next;
11430 84 : else if (!capture_stmt)
11431 : {
11432 1 : loc = &code->loc;
11433 1 : goto unexpected;
11434 : }
11435 : }
11436 2593 : else if (atomic_code->ext.omp_clauses->compare)
11437 : {
11438 : /* Must be: "if (x == e) then; x = d; end if" or "if (x == e) x = d". */
11439 53 : if (code->op == EXEC_IF
11440 53 : && code->block
11441 53 : && code->block->op == EXEC_IF
11442 53 : && code->block->next
11443 51 : && code->block->next->op == EXEC_ASSIGN)
11444 : {
11445 51 : comp_cond = code->block->expr1;
11446 51 : stmt = code->block->next;
11447 51 : if (stmt->next || code->block->block)
11448 : {
11449 0 : loc = stmt->next ? &stmt->next->loc : &code->block->block->loc;
11450 0 : goto unexpected;
11451 : }
11452 : }
11453 : else
11454 : {
11455 2 : loc = &code->loc;
11456 2 : goto unexpected;
11457 : }
11458 : }
11459 2540 : else if (atomic_code->ext.omp_clauses->capture)
11460 : {
11461 : /* Must be: "v = x" followed/preceded by "x = ...". */
11462 489 : if (code->op != EXEC_ASSIGN)
11463 0 : goto unexpected;
11464 489 : if (code->next->op != EXEC_ASSIGN)
11465 : {
11466 0 : loc = &code->next->loc;
11467 0 : goto unexpected;
11468 : }
11469 489 : gfc_expr *expr2, *expr2_next;
11470 489 : expr2 = is_conversion (code->expr2, true, true);
11471 489 : if (expr2 == NULL)
11472 447 : expr2 = code->expr2;
11473 489 : expr2_next = is_conversion (code->next->expr2, true, true);
11474 489 : if (expr2_next == NULL)
11475 478 : expr2_next = code->next->expr2;
11476 489 : if (code->expr1->expr_type == EXPR_VARIABLE
11477 489 : && code->next->expr1->expr_type == EXPR_VARIABLE
11478 489 : && expr2->expr_type == EXPR_VARIABLE
11479 243 : && expr2_next->expr_type == EXPR_VARIABLE)
11480 : {
11481 1 : if (code->expr1->symtree->n.sym == expr2_next->symtree->n.sym)
11482 : {
11483 : stmt = code;
11484 : capture_stmt = code->next;
11485 : }
11486 : else
11487 : {
11488 489 : capture_stmt = code;
11489 489 : stmt = code->next;
11490 : }
11491 : }
11492 488 : else if (expr2->expr_type == EXPR_VARIABLE)
11493 : {
11494 : capture_stmt = code;
11495 : stmt = code->next;
11496 : }
11497 : else
11498 : {
11499 247 : stmt = code;
11500 247 : capture_stmt = code->next;
11501 : }
11502 : /* Shall be NULL but can happen for invalid code. */
11503 489 : tailing_stmt = code->next->next;
11504 : }
11505 : else
11506 : {
11507 : /* x = ... */
11508 2051 : stmt = code;
11509 2051 : if (!atomic_code->ext.omp_clauses->compare && stmt->op != EXEC_ASSIGN)
11510 1 : goto unexpected;
11511 : /* Shall be NULL but can happen for invalid code. */
11512 2050 : tailing_stmt = code->next;
11513 : }
11514 :
11515 2692 : if (comp_cond)
11516 : {
11517 153 : if (comp_cond->expr_type != EXPR_OP
11518 153 : || (comp_cond->value.op.op != INTRINSIC_EQ
11519 : && comp_cond->value.op.op != INTRINSIC_EQ_OS
11520 : && comp_cond->value.op.op != INTRINSIC_EQV))
11521 : {
11522 0 : gfc_error ("Expected %<==%>, %<.EQ.%> or %<.EQV.%> atomic comparison "
11523 : "expression at %L", &comp_cond->where);
11524 0 : return;
11525 : }
11526 153 : if (!is_scalar_intrinsic_expr (comp_cond->value.op.op1, true, true))
11527 : {
11528 1 : gfc_error ("Expected scalar intrinsic variable at %L in atomic "
11529 1 : "comparison", &comp_cond->value.op.op1->where);
11530 1 : return;
11531 : }
11532 152 : if (!gfc_resolve_expr (comp_cond->value.op.op2))
11533 : return;
11534 152 : if (!is_scalar_intrinsic_expr (comp_cond->value.op.op2, false, false))
11535 : {
11536 0 : gfc_error ("Expected scalar intrinsic expression at %L in atomic "
11537 0 : "comparison", &comp_cond->value.op.op1->where);
11538 0 : return;
11539 : }
11540 : }
11541 :
11542 2691 : if (!is_scalar_intrinsic_expr (stmt->expr1, true, false))
11543 : {
11544 4 : gfc_error ("!$OMP ATOMIC statement must set a scalar variable of "
11545 4 : "intrinsic type at %L", &stmt->expr1->where);
11546 4 : return;
11547 : }
11548 :
11549 2687 : if (!gfc_resolve_expr (stmt->expr2))
11550 : return;
11551 2683 : if (!is_scalar_intrinsic_expr (stmt->expr2, false, false))
11552 : {
11553 0 : gfc_error ("!$OMP ATOMIC statement must assign an expression of "
11554 0 : "intrinsic type at %L", &stmt->expr2->where);
11555 0 : return;
11556 : }
11557 :
11558 2683 : if (gfc_expr_attr (stmt->expr1).allocatable)
11559 : {
11560 0 : gfc_error ("!$OMP ATOMIC with ALLOCATABLE variable at %L",
11561 0 : &stmt->expr1->where);
11562 0 : return;
11563 : }
11564 :
11565 : /* Should be diagnosed above already. */
11566 2683 : gcc_assert (tailing_stmt == NULL);
11567 :
11568 2683 : var = stmt->expr1->symtree->n.sym;
11569 2683 : stmt_expr2 = is_conversion (stmt->expr2, true, true);
11570 2683 : if (stmt_expr2 == NULL)
11571 2527 : stmt_expr2 = stmt->expr2;
11572 :
11573 2683 : switch (aop)
11574 : {
11575 503 : case GFC_OMP_ATOMIC_READ:
11576 503 : if (stmt_expr2->expr_type != EXPR_VARIABLE)
11577 0 : gfc_error ("!$OMP ATOMIC READ statement must read from a scalar "
11578 : "variable of intrinsic type at %L", &stmt_expr2->where);
11579 : return;
11580 421 : case GFC_OMP_ATOMIC_WRITE:
11581 421 : if (expr_references_sym (stmt_expr2, var, NULL))
11582 0 : gfc_error ("expr in !$OMP ATOMIC WRITE assignment var = expr "
11583 : "must be scalar and cannot reference var at %L",
11584 : &stmt_expr2->where);
11585 : return;
11586 1759 : default:
11587 1759 : break;
11588 : }
11589 :
11590 1759 : if (atomic_code->ext.omp_clauses->capture)
11591 : {
11592 588 : if (!is_scalar_intrinsic_expr (capture_stmt->expr1, true, false))
11593 : {
11594 0 : gfc_error ("!$OMP ATOMIC capture-statement must set a scalar "
11595 : "variable of intrinsic type at %L",
11596 0 : &capture_stmt->expr1->where);
11597 0 : return;
11598 : }
11599 :
11600 588 : if (!is_scalar_intrinsic_expr (capture_stmt->expr2, true, true))
11601 : {
11602 2 : gfc_error ("!$OMP ATOMIC capture-statement requires a scalar variable"
11603 2 : " of intrinsic type at %L", &capture_stmt->expr2->where);
11604 2 : return;
11605 : }
11606 586 : capt_expr2 = is_conversion (capture_stmt->expr2, true, true);
11607 586 : if (capt_expr2 == NULL)
11608 564 : capt_expr2 = capture_stmt->expr2;
11609 :
11610 586 : if (capt_expr2->symtree->n.sym != var)
11611 : {
11612 1 : gfc_error ("!$OMP ATOMIC CAPTURE capture statement reads from "
11613 : "different variable than update statement writes "
11614 : "into at %L", &capture_stmt->expr2->where);
11615 1 : return;
11616 : }
11617 : }
11618 :
11619 1756 : if (atomic_code->ext.omp_clauses->compare)
11620 : {
11621 149 : gfc_expr *var_expr;
11622 149 : if (comp_cond->value.op.op1->expr_type == EXPR_VARIABLE)
11623 : var_expr = comp_cond->value.op.op1;
11624 : else
11625 12 : var_expr = comp_cond->value.op.op1->value.function.actual->expr;
11626 149 : if (var_expr->symtree->n.sym != var)
11627 : {
11628 2 : gfc_error ("For !$OMP ATOMIC COMPARE, the first operand in comparison"
11629 : " at %L must be the variable %qs that the update statement"
11630 : " writes into at %L", &var_expr->where, var->name,
11631 2 : &stmt->expr1->where);
11632 2 : return;
11633 : }
11634 147 : if (stmt_expr2->rank != 0 || expr_references_sym (stmt_expr2, var, NULL))
11635 : {
11636 1 : gfc_error ("expr in !$OMP ATOMIC COMPARE assignment var = expr "
11637 : "must be scalar and cannot reference var at %L",
11638 : &stmt_expr2->where);
11639 1 : return;
11640 : }
11641 : }
11642 1607 : else if (atomic_code->ext.omp_clauses->capture
11643 1607 : && !expr_references_sym (stmt_expr2, var, NULL))
11644 22 : atomic_code->ext.omp_clauses->atomic_op
11645 22 : = (gfc_omp_atomic_op) (atomic_code->ext.omp_clauses->atomic_op
11646 : | GFC_OMP_ATOMIC_SWAP);
11647 1585 : else if (stmt_expr2->expr_type == EXPR_OP)
11648 : {
11649 1229 : gfc_expr *v = NULL, *e, *c;
11650 1229 : gfc_intrinsic_op op = stmt_expr2->value.op.op;
11651 1229 : gfc_intrinsic_op alt_op = INTRINSIC_NONE;
11652 :
11653 1229 : if (atomic_code->ext.omp_clauses->fail != OMP_MEMORDER_UNSET)
11654 3 : gfc_error ("!$OMP ATOMIC UPDATE at %L with FAIL clause requires either"
11655 : " the COMPARE clause or using the intrinsic MIN/MAX "
11656 : "procedure", &atomic_code->loc);
11657 1229 : switch (op)
11658 : {
11659 742 : case INTRINSIC_PLUS:
11660 742 : alt_op = INTRINSIC_MINUS;
11661 742 : break;
11662 94 : case INTRINSIC_TIMES:
11663 94 : alt_op = INTRINSIC_DIVIDE;
11664 94 : break;
11665 120 : case INTRINSIC_MINUS:
11666 120 : alt_op = INTRINSIC_PLUS;
11667 120 : break;
11668 94 : case INTRINSIC_DIVIDE:
11669 94 : alt_op = INTRINSIC_TIMES;
11670 94 : break;
11671 : case INTRINSIC_AND:
11672 : case INTRINSIC_OR:
11673 : break;
11674 43 : case INTRINSIC_EQV:
11675 43 : alt_op = INTRINSIC_NEQV;
11676 43 : break;
11677 43 : case INTRINSIC_NEQV:
11678 43 : alt_op = INTRINSIC_EQV;
11679 43 : break;
11680 1 : default:
11681 1 : gfc_error ("!$OMP ATOMIC assignment operator must be binary "
11682 : "+, *, -, /, .AND., .OR., .EQV. or .NEQV. at %L",
11683 : &stmt_expr2->where);
11684 1 : return;
11685 : }
11686 :
11687 : /* Check for var = var op expr resp. var = expr op var where
11688 : expr doesn't reference var and var op expr is mathematically
11689 : equivalent to var op (expr) resp. expr op var equivalent to
11690 : (expr) op var. We rely here on the fact that the matcher
11691 : for x op1 y op2 z where op1 and op2 have equal precedence
11692 : returns (x op1 y) op2 z. */
11693 1228 : e = stmt_expr2->value.op.op2;
11694 1228 : if (e->expr_type == EXPR_VARIABLE
11695 288 : && e->symtree != NULL
11696 288 : && e->symtree->n.sym == var)
11697 : v = e;
11698 999 : else if ((c = is_conversion (e, false, true)) != NULL
11699 48 : && c->expr_type == EXPR_VARIABLE
11700 48 : && c->symtree != NULL
11701 1047 : && c->symtree->n.sym == var)
11702 : v = c;
11703 : else
11704 : {
11705 951 : gfc_expr **p = NULL, **q;
11706 1049 : for (q = &stmt_expr2->value.op.op1; (e = *q) != NULL; )
11707 1049 : if (e->expr_type == EXPR_VARIABLE
11708 948 : && e->symtree != NULL
11709 948 : && e->symtree->n.sym == var)
11710 : {
11711 : v = e;
11712 : break;
11713 : }
11714 101 : else if ((c = is_conversion (e, false, true)) != NULL)
11715 60 : q = &e->value.function.actual->expr;
11716 41 : else if (e->expr_type != EXPR_OP
11717 41 : || (e->value.op.op != op
11718 15 : && e->value.op.op != alt_op)
11719 38 : || e->rank != 0)
11720 : break;
11721 : else
11722 : {
11723 38 : p = q;
11724 38 : q = &e->value.op.op1;
11725 : }
11726 :
11727 951 : if (v == NULL)
11728 : {
11729 3 : gfc_error ("!$OMP ATOMIC assignment must be var = var op expr "
11730 : "or var = expr op var at %L", &stmt_expr2->where);
11731 3 : return;
11732 : }
11733 :
11734 948 : if (p != NULL)
11735 : {
11736 38 : e = *p;
11737 38 : switch (e->value.op.op)
11738 : {
11739 8 : case INTRINSIC_MINUS:
11740 8 : case INTRINSIC_DIVIDE:
11741 8 : case INTRINSIC_EQV:
11742 8 : case INTRINSIC_NEQV:
11743 8 : gfc_error ("!$OMP ATOMIC var = var op expr not "
11744 : "mathematically equivalent to var = var op "
11745 : "(expr) at %L", &stmt_expr2->where);
11746 8 : break;
11747 : default:
11748 : break;
11749 : }
11750 :
11751 : /* Canonicalize into var = var op (expr). */
11752 38 : *p = e->value.op.op2;
11753 38 : e->value.op.op2 = stmt_expr2;
11754 38 : e->ts = stmt_expr2->ts;
11755 38 : if (stmt->expr2 == stmt_expr2)
11756 26 : stmt->expr2 = stmt_expr2 = e;
11757 : else
11758 12 : stmt->expr2->value.function.actual->expr = stmt_expr2 = e;
11759 :
11760 38 : if (!gfc_compare_types (&stmt_expr2->value.op.op1->ts,
11761 : &stmt_expr2->ts))
11762 : {
11763 24 : for (p = &stmt_expr2->value.op.op1; *p != v;
11764 12 : p = &(*p)->value.function.actual->expr)
11765 : ;
11766 12 : *p = NULL;
11767 12 : gfc_free_expr (stmt_expr2->value.op.op1);
11768 12 : stmt_expr2->value.op.op1 = v;
11769 12 : gfc_convert_type (v, &stmt_expr2->ts, 2);
11770 : }
11771 : }
11772 : }
11773 :
11774 1225 : if (e->rank != 0 || expr_references_sym (stmt->expr2, var, v))
11775 : {
11776 1 : gfc_error ("expr in !$OMP ATOMIC assignment var = var op expr "
11777 : "must be scalar and cannot reference var at %L",
11778 : &stmt_expr2->where);
11779 1 : return;
11780 : }
11781 : }
11782 356 : else if (stmt_expr2->expr_type == EXPR_FUNCTION
11783 355 : && stmt_expr2->value.function.isym != NULL
11784 355 : && stmt_expr2->value.function.esym == NULL
11785 355 : && stmt_expr2->value.function.actual != NULL
11786 355 : && stmt_expr2->value.function.actual->next != NULL)
11787 : {
11788 355 : gfc_actual_arglist *arg, *var_arg;
11789 :
11790 355 : switch (stmt_expr2->value.function.isym->id)
11791 : {
11792 : case GFC_ISYM_MIN:
11793 : case GFC_ISYM_MAX:
11794 : break;
11795 147 : case GFC_ISYM_IAND:
11796 147 : case GFC_ISYM_IOR:
11797 147 : case GFC_ISYM_IEOR:
11798 147 : if (stmt_expr2->value.function.actual->next->next != NULL)
11799 : {
11800 0 : gfc_error ("!$OMP ATOMIC assignment intrinsic IAND, IOR "
11801 : "or IEOR must have two arguments at %L",
11802 : &stmt_expr2->where);
11803 0 : return;
11804 : }
11805 : break;
11806 1 : default:
11807 1 : gfc_error ("!$OMP ATOMIC assignment intrinsic must be "
11808 : "MIN, MAX, IAND, IOR or IEOR at %L",
11809 : &stmt_expr2->where);
11810 1 : return;
11811 : }
11812 :
11813 : var_arg = NULL;
11814 1088 : for (arg = stmt_expr2->value.function.actual; arg; arg = arg->next)
11815 : {
11816 741 : gfc_expr *e = NULL;
11817 741 : if (arg == stmt_expr2->value.function.actual
11818 387 : || (var_arg == NULL && arg->next == NULL))
11819 : {
11820 527 : e = is_conversion (arg->expr, false, true);
11821 527 : if (!e)
11822 514 : e = arg->expr;
11823 527 : if (e->expr_type == EXPR_VARIABLE
11824 453 : && e->symtree != NULL
11825 453 : && e->symtree->n.sym == var)
11826 741 : var_arg = arg;
11827 : }
11828 741 : if ((!var_arg || !e) && expr_references_sym (arg->expr, var, NULL))
11829 : {
11830 7 : gfc_error ("!$OMP ATOMIC intrinsic arguments except one must "
11831 : "not reference %qs at %L",
11832 : var->name, &arg->expr->where);
11833 7 : return;
11834 : }
11835 734 : if (arg->expr->rank != 0)
11836 : {
11837 0 : gfc_error ("!$OMP ATOMIC intrinsic arguments must be scalar "
11838 : "at %L", &arg->expr->where);
11839 0 : return;
11840 : }
11841 : }
11842 :
11843 347 : if (var_arg == NULL)
11844 : {
11845 1 : gfc_error ("First or last !$OMP ATOMIC intrinsic argument must "
11846 : "be %qs at %L", var->name, &stmt_expr2->where);
11847 1 : return;
11848 : }
11849 :
11850 346 : if (var_arg != stmt_expr2->value.function.actual)
11851 : {
11852 : /* Canonicalize, so that var comes first. */
11853 172 : gcc_assert (var_arg->next == NULL);
11854 : for (arg = stmt_expr2->value.function.actual;
11855 185 : arg->next != var_arg; arg = arg->next)
11856 : ;
11857 172 : var_arg->next = stmt_expr2->value.function.actual;
11858 172 : stmt_expr2->value.function.actual = var_arg;
11859 172 : arg->next = NULL;
11860 : }
11861 : }
11862 : else
11863 1 : gfc_error ("!$OMP ATOMIC assignment must have an operator or "
11864 : "intrinsic on right hand side at %L", &stmt_expr2->where);
11865 : return;
11866 :
11867 4 : unexpected:
11868 4 : gfc_error ("unexpected !$OMP ATOMIC expression at %L",
11869 : loc ? loc : &code->loc);
11870 4 : return;
11871 : }
11872 :
11873 :
11874 : static struct fortran_omp_context
11875 : {
11876 : gfc_code *code;
11877 : hash_set<gfc_symbol *> *sharing_clauses;
11878 : hash_set<gfc_symbol *> *private_iterators;
11879 : struct fortran_omp_context *previous;
11880 : bool is_openmp;
11881 : } *omp_current_ctx;
11882 : static gfc_code *omp_current_do_code;
11883 : static int omp_current_do_collapse;
11884 :
11885 : /* Forward declaration for mutually recursive functions. */
11886 : static gfc_code *
11887 : find_nested_loop_in_block (gfc_code *block);
11888 :
11889 : /* Return the first nested DO loop in CHAIN, or NULL if there
11890 : isn't one. Does no error checking on intervening code. */
11891 :
11892 : static gfc_code *
11893 27482 : find_nested_loop_in_chain (gfc_code *chain)
11894 : {
11895 27482 : gfc_code *code;
11896 :
11897 27482 : if (!chain)
11898 : return NULL;
11899 :
11900 31643 : for (code = chain; code; code = code->next)
11901 31222 : switch (code->op)
11902 : {
11903 : case EXEC_DO:
11904 : case EXEC_OMP_TILE:
11905 : case EXEC_OMP_UNROLL:
11906 : return code;
11907 621 : case EXEC_BLOCK:
11908 621 : if (gfc_code *c = find_nested_loop_in_block (code))
11909 : return c;
11910 : break;
11911 : default:
11912 : break;
11913 : }
11914 : return NULL;
11915 : }
11916 :
11917 : /* Return the first nested DO loop in BLOCK, or NULL if there
11918 : isn't one. Does no error checking on intervening code. */
11919 : static gfc_code *
11920 939 : find_nested_loop_in_block (gfc_code *block)
11921 : {
11922 939 : gfc_namespace *ns;
11923 939 : gcc_assert (block->op == EXEC_BLOCK);
11924 939 : ns = block->ext.block.ns;
11925 939 : gcc_assert (ns);
11926 939 : return find_nested_loop_in_chain (ns->code);
11927 : }
11928 :
11929 : void
11930 5425 : gfc_resolve_omp_do_blocks (gfc_code *code, gfc_namespace *ns)
11931 : {
11932 5425 : if (code->block->next && code->block->next->op == EXEC_DO)
11933 : {
11934 5072 : int i;
11935 :
11936 5072 : omp_current_do_code = code->block->next;
11937 5072 : if (code->ext.omp_clauses->orderedc)
11938 142 : omp_current_do_collapse = code->ext.omp_clauses->orderedc;
11939 4930 : else if (code->ext.omp_clauses->collapse)
11940 1121 : omp_current_do_collapse = code->ext.omp_clauses->collapse;
11941 3809 : else if (code->ext.omp_clauses->sizes_list)
11942 175 : omp_current_do_collapse
11943 175 : = gfc_expr_list_len (code->ext.omp_clauses->sizes_list);
11944 : else
11945 3634 : omp_current_do_collapse = 1;
11946 5072 : if (code->ext.omp_clauses->lists[OMP_LIST_REDUCTION_INSCAN])
11947 : {
11948 : /* Checking that there is a matching EXEC_OMP_SCAN in the
11949 : innermost body cannot be deferred to resolve_omp_do because
11950 : we process directives nested in the loop before we get
11951 : there. */
11952 60 : locus *loc
11953 : = &code->ext.omp_clauses->lists[OMP_LIST_REDUCTION_INSCAN]->where;
11954 60 : gfc_code *c;
11955 :
11956 80 : for (i = 1, c = omp_current_do_code;
11957 80 : i < omp_current_do_collapse; i++)
11958 : {
11959 22 : c = find_nested_loop_in_chain (c->block->next);
11960 22 : if (!c || c->op != EXEC_DO || c->block == NULL)
11961 : break;
11962 : }
11963 :
11964 : /* Skip this if we don't have enough nested loops. That
11965 : problem will be diagnosed elsewhere. */
11966 60 : if (c && c->op == EXEC_DO)
11967 : {
11968 58 : gfc_code *block = c->block ? c->block->next : NULL;
11969 58 : if (block && block->op != EXEC_OMP_SCAN)
11970 54 : while (block && block->next
11971 54 : && block->next->op != EXEC_OMP_SCAN)
11972 : block = block->next;
11973 43 : if (!block
11974 46 : || (block->op != EXEC_OMP_SCAN
11975 43 : && (!block->next || block->next->op != EXEC_OMP_SCAN)))
11976 19 : gfc_error ("With INSCAN at %L, expected loop body with "
11977 : "!$OMP SCAN between two "
11978 : "structured block sequences", loc);
11979 : else
11980 : {
11981 39 : if (block->op == EXEC_OMP_SCAN)
11982 3 : gfc_warning (OPT_Wopenmp,
11983 : "!$OMP SCAN at %L with zero executable "
11984 : "statements in preceding structured block "
11985 : "sequence", &block->loc);
11986 39 : if ((block->op == EXEC_OMP_SCAN && !block->next)
11987 38 : || (block->next && block->next->op == EXEC_OMP_SCAN
11988 36 : && !block->next->next))
11989 3 : gfc_warning (OPT_Wopenmp,
11990 : "!$OMP SCAN at %L with zero executable "
11991 : "statements in succeeding structured block "
11992 : "sequence", block->op == EXEC_OMP_SCAN
11993 1 : ? &block->loc : &block->next->loc);
11994 : }
11995 58 : if (block && block->op != EXEC_OMP_SCAN)
11996 43 : block = block->next;
11997 46 : if (block && block->op == EXEC_OMP_SCAN)
11998 : /* Mark 'omp scan' as checked; flag will be unset later. */
11999 39 : block->ext.omp_clauses->if_present = true;
12000 : }
12001 : }
12002 : }
12003 5425 : gfc_resolve_blocks (code->block, ns);
12004 5425 : omp_current_do_collapse = 0;
12005 5425 : omp_current_do_code = NULL;
12006 5425 : }
12007 :
12008 :
12009 : void
12010 6054 : gfc_resolve_omp_parallel_blocks (gfc_code *code, gfc_namespace *ns)
12011 : {
12012 6054 : struct fortran_omp_context ctx;
12013 6054 : gfc_omp_clauses *omp_clauses = code->ext.omp_clauses;
12014 6054 : gfc_omp_namelist *n;
12015 :
12016 6054 : ctx.code = code;
12017 6054 : ctx.sharing_clauses = new hash_set<gfc_symbol *>;
12018 6054 : ctx.private_iterators = new hash_set<gfc_symbol *>;
12019 6054 : ctx.previous = omp_current_ctx;
12020 6054 : ctx.is_openmp = true;
12021 6054 : omp_current_ctx = &ctx;
12022 :
12023 242160 : for (enum gfc_omp_list_type list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
12024 236106 : list = gfc_omp_list_type (list + 1))
12025 236106 : switch (list)
12026 : {
12027 60540 : case OMP_LIST_SHARED:
12028 60540 : case OMP_LIST_PRIVATE:
12029 60540 : case OMP_LIST_FIRSTPRIVATE:
12030 60540 : case OMP_LIST_LASTPRIVATE:
12031 60540 : case OMP_LIST_REDUCTION:
12032 60540 : case OMP_LIST_REDUCTION_INSCAN:
12033 60540 : case OMP_LIST_REDUCTION_TASK:
12034 60540 : case OMP_LIST_IN_REDUCTION:
12035 60540 : case OMP_LIST_TASK_REDUCTION:
12036 60540 : case OMP_LIST_LINEAR:
12037 69531 : for (n = omp_clauses->lists[list]; n; n = n->next)
12038 8991 : ctx.sharing_clauses->add (n->sym);
12039 : break;
12040 : default:
12041 : break;
12042 : }
12043 :
12044 6054 : switch (code->op)
12045 : {
12046 2361 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
12047 2361 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
12048 2361 : case EXEC_OMP_MASKED_TASKLOOP:
12049 2361 : case EXEC_OMP_MASKED_TASKLOOP_SIMD:
12050 2361 : case EXEC_OMP_MASTER_TASKLOOP:
12051 2361 : case EXEC_OMP_MASTER_TASKLOOP_SIMD:
12052 2361 : case EXEC_OMP_PARALLEL_DO:
12053 2361 : case EXEC_OMP_PARALLEL_DO_SIMD:
12054 2361 : case EXEC_OMP_PARALLEL_LOOP:
12055 2361 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
12056 2361 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
12057 2361 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
12058 2361 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
12059 2361 : case EXEC_OMP_TARGET_PARALLEL_DO:
12060 2361 : case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
12061 2361 : case EXEC_OMP_TARGET_PARALLEL_LOOP:
12062 2361 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
12063 2361 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
12064 2361 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
12065 2361 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
12066 2361 : case EXEC_OMP_TARGET_TEAMS_LOOP:
12067 2361 : case EXEC_OMP_TASKLOOP:
12068 2361 : case EXEC_OMP_TASKLOOP_SIMD:
12069 2361 : case EXEC_OMP_TEAMS_DISTRIBUTE:
12070 2361 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
12071 2361 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
12072 2361 : case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
12073 2361 : case EXEC_OMP_TEAMS_LOOP:
12074 2361 : gfc_resolve_omp_do_blocks (code, ns);
12075 2361 : break;
12076 3693 : default:
12077 3693 : gfc_resolve_blocks (code->block, ns);
12078 : }
12079 :
12080 6054 : omp_current_ctx = ctx.previous;
12081 12108 : delete ctx.sharing_clauses;
12082 12108 : delete ctx.private_iterators;
12083 6054 : }
12084 :
12085 :
12086 : /* Save and clear openmp.cc private state. */
12087 :
12088 : void
12089 295052 : gfc_omp_save_and_clear_state (struct gfc_omp_saved_state *state)
12090 : {
12091 295052 : state->ptrs[0] = omp_current_ctx;
12092 295052 : state->ptrs[1] = omp_current_do_code;
12093 295052 : state->ints[0] = omp_current_do_collapse;
12094 295052 : omp_current_ctx = NULL;
12095 295052 : omp_current_do_code = NULL;
12096 295052 : omp_current_do_collapse = 0;
12097 295052 : }
12098 :
12099 :
12100 : /* Restore openmp.cc private state from the saved state. */
12101 :
12102 : void
12103 295051 : gfc_omp_restore_state (struct gfc_omp_saved_state *state)
12104 : {
12105 295051 : omp_current_ctx = (struct fortran_omp_context *) state->ptrs[0];
12106 295051 : omp_current_do_code = (gfc_code *) state->ptrs[1];
12107 295051 : omp_current_do_collapse = state->ints[0];
12108 295051 : }
12109 :
12110 :
12111 : /* Note a DO iterator variable. This is special in !$omp parallel
12112 : construct, where they are predetermined private. */
12113 :
12114 : void
12115 33161 : gfc_resolve_do_iterator (gfc_code *code, gfc_symbol *sym, bool add_clause)
12116 : {
12117 33161 : if (omp_current_ctx == NULL)
12118 : return;
12119 :
12120 13106 : int i = omp_current_do_collapse;
12121 13106 : gfc_code *c = omp_current_do_code;
12122 :
12123 13106 : if (sym->attr.threadprivate)
12124 : return;
12125 :
12126 : /* !$omp do and !$omp parallel do iteration variable is predetermined
12127 : private just in the !$omp do resp. !$omp parallel do construct,
12128 : with no implications for the outer parallel constructs. */
12129 :
12130 17941 : while (i-- >= 1 && c)
12131 : {
12132 9495 : if (code == c)
12133 : return;
12134 4835 : c = find_nested_loop_in_chain (c->block->next);
12135 4835 : if (c && (c->op == EXEC_OMP_TILE || c->op == EXEC_OMP_UNROLL))
12136 : return;
12137 : }
12138 :
12139 : /* An openacc context may represent a data clause. Abort if so. */
12140 8446 : if (!omp_current_ctx->is_openmp && !oacc_is_loop (omp_current_ctx->code))
12141 : return;
12142 :
12143 7468 : if (omp_current_ctx->sharing_clauses->contains (sym))
12144 : return;
12145 :
12146 6466 : if (! omp_current_ctx->private_iterators->add (sym) && add_clause)
12147 : {
12148 6276 : gfc_omp_clauses *omp_clauses = omp_current_ctx->code->ext.omp_clauses;
12149 6276 : gfc_omp_namelist *p;
12150 :
12151 6276 : p = gfc_get_omp_namelist ();
12152 6276 : p->sym = sym;
12153 6276 : p->where = omp_current_ctx->code->loc;
12154 6276 : p->next = omp_clauses->lists[OMP_LIST_PRIVATE];
12155 6276 : omp_clauses->lists[OMP_LIST_PRIVATE] = p;
12156 : }
12157 : }
12158 :
12159 : static void
12160 760 : handle_local_var (gfc_symbol *sym)
12161 : {
12162 760 : if (sym->attr.flavor != FL_VARIABLE
12163 180 : || sym->as != NULL
12164 139 : || (sym->ts.type != BT_INTEGER && sym->ts.type != BT_REAL))
12165 : return;
12166 72 : gfc_resolve_do_iterator (sym->ns->code, sym, false);
12167 : }
12168 :
12169 : void
12170 341841 : gfc_resolve_omp_local_vars (gfc_namespace *ns)
12171 : {
12172 341841 : if (omp_current_ctx)
12173 454 : gfc_traverse_ns (ns, handle_local_var);
12174 341841 : }
12175 :
12176 :
12177 : /* Error checking on intervening code uses a code walker. */
12178 :
12179 : struct icode_error_state
12180 : {
12181 : const char *name;
12182 : bool errorp;
12183 : gfc_code *nested;
12184 : gfc_code *next;
12185 : };
12186 :
12187 : static int
12188 944 : icode_code_error_callback (gfc_code **codep,
12189 : int *walk_subtrees ATTRIBUTE_UNUSED, void *opaque)
12190 : {
12191 944 : gfc_code *code = *codep;
12192 944 : icode_error_state *state = (icode_error_state *)opaque;
12193 :
12194 : /* gfc_code_walker walks down CODE's next chain as well as
12195 : walking things that are actually nested in CODE. We need to
12196 : special-case traversal of outer blocks, so stop immediately if we
12197 : are heading down such a next chain. */
12198 944 : if (code == state->next)
12199 : return 1;
12200 :
12201 647 : switch (code->op)
12202 : {
12203 1 : case EXEC_DO:
12204 1 : case EXEC_DO_WHILE:
12205 1 : case EXEC_DO_CONCURRENT:
12206 1 : gfc_error ("%s cannot contain loop in intervening code at %L",
12207 : state->name, &code->loc);
12208 1 : state->errorp = true;
12209 1 : break;
12210 0 : case EXEC_CYCLE:
12211 0 : case EXEC_EXIT:
12212 : /* Errors have already been diagnosed in match_exit_cycle. */
12213 0 : state->errorp = true;
12214 0 : break;
12215 : case EXEC_OMP_ASSUME:
12216 : case EXEC_OMP_METADIRECTIVE:
12217 : /* Per OpenMP 6.0, some non-executable directives are allowed in
12218 : intervening code. */
12219 : break;
12220 477 : case EXEC_CALL:
12221 : /* Per OpenMP 5.2, the "omp_" prefix is reserved, so we don't have to
12222 : consider the possibility that some locally-bound definition
12223 : overrides the runtime routine. */
12224 477 : if (code->resolved_sym
12225 477 : && omp_runtime_api_procname (code->resolved_sym->name))
12226 : {
12227 1 : gfc_error ("%s cannot contain OpenMP API call in intervening code "
12228 : "at %L",
12229 : state->name, &code->loc);
12230 1 : state->errorp = true;
12231 : }
12232 : break;
12233 168 : default:
12234 168 : if (code->op >= EXEC_OMP_FIRST_OPENMP_EXEC
12235 168 : && code->op <= EXEC_OMP_LAST_OPENMP_EXEC)
12236 : {
12237 2 : gfc_error ("%s cannot contain OpenMP directive in intervening code "
12238 : "at %L",
12239 : state->name, &code->loc);
12240 2 : state->errorp = true;
12241 : }
12242 : }
12243 : return 0;
12244 : }
12245 :
12246 : static int
12247 1081 : icode_expr_error_callback (gfc_expr **expr,
12248 : int *walk_subtrees ATTRIBUTE_UNUSED, void *opaque)
12249 : {
12250 1081 : icode_error_state *state = (icode_error_state *)opaque;
12251 :
12252 1081 : switch ((*expr)->expr_type)
12253 : {
12254 : /* As for EXPR_CALL with "omp_"-prefixed symbols. */
12255 2 : case EXPR_FUNCTION:
12256 2 : {
12257 2 : gfc_symbol *sym = (*expr)->value.function.esym;
12258 2 : if (sym && omp_runtime_api_procname (sym->name))
12259 : {
12260 1 : gfc_error ("%s cannot contain OpenMP API call in intervening code "
12261 : "at %L",
12262 1 : state->name, &((*expr)->where));
12263 1 : state->errorp = true;
12264 : }
12265 : }
12266 :
12267 : break;
12268 : default:
12269 : break;
12270 : }
12271 :
12272 : /* FIXME: The description of canonical loop form in the OpenMP standard
12273 : also says "array expressions" are not permitted in intervening code.
12274 : That term is not defined in either the OpenMP spec or the Fortran
12275 : standard, although the latter uses it informally to refer to any
12276 : expression that is not scalar-valued. It is also apparently not the
12277 : thing GCC internally calls EXPR_ARRAY. It seems the intent of the
12278 : OpenMP restriction is to disallow elemental operations/intrinsics
12279 : (including things that are not expressions, like assignment
12280 : statements) that generate implicit loops over array operands
12281 : (even if the result is a scalar), but even if the spec said
12282 : that there is no list of all the cases that would be forbidden.
12283 : This is OpenMP issue 3326. */
12284 :
12285 1081 : return 0;
12286 : }
12287 :
12288 : static void
12289 267 : diagnose_intervening_code_errors_1 (gfc_code *chain,
12290 : struct icode_error_state *state)
12291 : {
12292 267 : gfc_code *code;
12293 1080 : for (code = chain; code; code = code->next)
12294 : {
12295 813 : if (code == state->nested)
12296 : /* Do not walk the nested loop or its body, we are only
12297 : interested in intervening code. */
12298 : ;
12299 636 : else if (code->op == EXEC_BLOCK
12300 636 : && find_nested_loop_in_block (code) == state->nested)
12301 : /* This block contains the nested loop, recurse on its
12302 : statements. */
12303 : {
12304 90 : gfc_namespace* ns = code->ext.block.ns;
12305 90 : diagnose_intervening_code_errors_1 (ns->code, state);
12306 : }
12307 : else
12308 : /* Treat the whole statement as a unit. */
12309 : {
12310 546 : gfc_code *temp = state->next;
12311 546 : state->next = code->next;
12312 546 : gfc_code_walker (&code, icode_code_error_callback,
12313 : icode_expr_error_callback, state);
12314 546 : state->next = temp;
12315 : }
12316 : }
12317 267 : }
12318 :
12319 : /* Diagnose intervening code errors in BLOCK with nested loop NESTED.
12320 : NAME is the user-friendly name of the OMP directive, used for error
12321 : messages. Returns true if any error was found. */
12322 : static bool
12323 177 : diagnose_intervening_code_errors (gfc_code *chain, const char *name,
12324 : gfc_code *nested)
12325 : {
12326 177 : struct icode_error_state state;
12327 177 : state.name = name;
12328 177 : state.errorp = false;
12329 177 : state.nested = nested;
12330 177 : state.next = NULL;
12331 0 : diagnose_intervening_code_errors_1 (chain, &state);
12332 177 : return state.errorp;
12333 : }
12334 :
12335 : /* Helper function for restructure_intervening_code: wrap CHAIN in
12336 : a marker to indicate that it is a structured block sequence. That
12337 : information will be used later on (in omp-low.cc) for error checking. */
12338 : static gfc_code *
12339 461 : make_structured_block (gfc_code *chain)
12340 : {
12341 461 : gcc_assert (chain);
12342 461 : gfc_namespace *ns = gfc_build_block_ns (gfc_current_ns);
12343 461 : gfc_code *result = gfc_get_code (EXEC_BLOCK);
12344 461 : result->op = EXEC_BLOCK;
12345 461 : result->ext.block.ns = ns;
12346 461 : result->ext.block.assoc = NULL;
12347 461 : result->loc = chain->loc;
12348 461 : ns->omp_structured_block = 1;
12349 461 : ns->code = chain;
12350 461 : return result;
12351 : }
12352 :
12353 : /* Push intervening code surrounding a loop, including nested scopes,
12354 : into the body of the loop. CHAINP is the pointer to the head of
12355 : the next-chain to scan, OUTER_LOOP is the EXEC_DO for the next outer
12356 : loop level, and COLLAPSE is the number of nested loops we need to
12357 : process.
12358 : Note that CHAINP may point at outer_loop->block->next when we
12359 : are scanning the body of a loop, but if there is an intervening block
12360 : CHAINP points into the block's chain rather than its enclosing outer
12361 : loop. This is why OUTER_LOOP is passed separately. */
12362 : static gfc_code *
12363 7175 : restructure_intervening_code (gfc_code **chainp, gfc_code *outer_loop,
12364 : int count)
12365 : {
12366 7175 : gfc_code *code;
12367 7175 : gfc_code *head = *chainp;
12368 7175 : gfc_code *tail = NULL;
12369 7175 : gfc_code *innermost_loop = NULL;
12370 :
12371 7439 : for (code = *chainp; code; code = code->next, chainp = &(*chainp)->next)
12372 : {
12373 7439 : if (code->op == EXEC_DO)
12374 : {
12375 : /* Cut CODE free from its chain, leaving the ends dangling. */
12376 7091 : *chainp = NULL;
12377 7091 : tail = code->next;
12378 7091 : code->next = NULL;
12379 :
12380 7091 : if (count == 1)
12381 : innermost_loop = code;
12382 : else
12383 2090 : innermost_loop
12384 2090 : = restructure_intervening_code (&code->block->next,
12385 : code, count - 1);
12386 : break;
12387 : }
12388 348 : else if (code->op == EXEC_BLOCK
12389 348 : && find_nested_loop_in_block (code))
12390 : {
12391 84 : gfc_namespace *ns = code->ext.block.ns;
12392 :
12393 : /* Cut CODE free from its chain, leaving the ends dangling. */
12394 84 : *chainp = NULL;
12395 84 : tail = code->next;
12396 84 : code->next = NULL;
12397 :
12398 84 : innermost_loop
12399 84 : = restructure_intervening_code (&ns->code, outer_loop,
12400 : count);
12401 :
12402 : /* At this point we have already pulled out the nested loop and
12403 : pointed outer_loop at it, and moved the intervening code that
12404 : was previously in the block into the body of innermost_loop.
12405 : Now we want to move the BLOCK itself so it wraps the entire
12406 : current body of innermost_loop. */
12407 84 : ns->code = innermost_loop->block->next;
12408 84 : innermost_loop->block->next = code;
12409 84 : break;
12410 : }
12411 : }
12412 :
12413 2174 : gcc_assert (innermost_loop);
12414 :
12415 : /* Now we have split the intervening code into two parts:
12416 : head is the start of the part before the loop/block, terminating
12417 : at *chainp, and tail is the part after it. Mark each part as
12418 : a structured block sequence, and splice the two parts around the
12419 : existing body of the innermost loop. */
12420 7175 : if (head != code)
12421 : {
12422 222 : gfc_code *block = make_structured_block (head);
12423 222 : if (innermost_loop->block->next)
12424 221 : gfc_append_code (block, innermost_loop->block->next);
12425 222 : innermost_loop->block->next = block;
12426 : }
12427 7175 : if (tail)
12428 : {
12429 239 : gfc_code *block = make_structured_block (tail);
12430 239 : if (innermost_loop->block->next)
12431 237 : gfc_append_code (innermost_loop->block->next, block);
12432 : else
12433 2 : innermost_loop->block->next = block;
12434 : }
12435 :
12436 : /* For loops, finally splice CODE into OUTER_LOOP. We already handled
12437 : relinking EXEC_BLOCK above. */
12438 7175 : if (code->op == EXEC_DO && outer_loop)
12439 7091 : outer_loop->block->next = code;
12440 :
12441 7175 : return innermost_loop;
12442 : }
12443 :
12444 : /* CODE is an OMP loop construct. Return true if VAR matches an iteration
12445 : variable outer to level DEPTH. */
12446 : static bool
12447 8088 : is_outer_iteration_variable (gfc_code *code, int depth, gfc_symbol *var)
12448 : {
12449 8088 : int i;
12450 8088 : gfc_code *do_code = code;
12451 :
12452 12615 : for (i = 1; i < depth; i++)
12453 : {
12454 5028 : do_code = find_nested_loop_in_chain (do_code->block->next);
12455 5028 : gcc_assert (do_code);
12456 5028 : if (do_code->op == EXEC_OMP_TILE || do_code->op == EXEC_OMP_UNROLL)
12457 : {
12458 51 : --i;
12459 51 : continue;
12460 : }
12461 4977 : gfc_symbol *ivar = do_code->ext.iterator->var->symtree->n.sym;
12462 4977 : if (var == ivar)
12463 : return true;
12464 : }
12465 : return false;
12466 : }
12467 :
12468 : /* Forward declaration for recursive functions. */
12469 : static gfc_code *
12470 : check_nested_loop_in_block (gfc_code *block, gfc_expr *expr, gfc_symbol *sym,
12471 : bool *bad);
12472 :
12473 : /* Like find_nested_loop_in_chain, but additionally check that EXPR
12474 : does not reference any variables bound in intervening EXEC_BLOCKs
12475 : and that SYM is not bound in such intervening blocks. Either EXPR or SYM
12476 : may be null. Sets *BAD to true if either test fails. */
12477 : static gfc_code *
12478 48185 : check_nested_loop_in_chain (gfc_code *chain, gfc_expr *expr, gfc_symbol *sym,
12479 : bool *bad)
12480 : {
12481 51789 : for (gfc_code *code = chain; code; code = code->next)
12482 : {
12483 51501 : if (code->op == EXEC_DO)
12484 : return code;
12485 4123 : else if (code->op == EXEC_OMP_TILE || code->op == EXEC_OMP_UNROLL)
12486 1682 : return check_nested_loop_in_chain (code->block->next, expr, sym, bad);
12487 2441 : else if (code->op == EXEC_BLOCK)
12488 : {
12489 807 : gfc_code *c = check_nested_loop_in_block (code, expr, sym, bad);
12490 807 : if (c)
12491 : return c;
12492 : }
12493 : }
12494 : return NULL;
12495 : }
12496 :
12497 : /* Code walker for block symtrees. It doesn't take any kind of state
12498 : argument, so use a static variable. */
12499 : static struct check_nested_loop_in_block_state_t {
12500 : gfc_expr *expr;
12501 : gfc_symbol *sym;
12502 : bool *bad;
12503 : } check_nested_loop_in_block_state;
12504 :
12505 : static void
12506 766 : check_nested_loop_in_block_symbol (gfc_symbol *sym)
12507 : {
12508 766 : if (sym == check_nested_loop_in_block_state.sym
12509 766 : || (check_nested_loop_in_block_state.expr
12510 567 : && gfc_find_sym_in_expr (sym,
12511 : check_nested_loop_in_block_state.expr)))
12512 5 : *check_nested_loop_in_block_state.bad = true;
12513 766 : }
12514 :
12515 : /* Return the first nested DO loop in BLOCK, or NULL if there
12516 : isn't one. Set *BAD to true if EXPR references any variables in BLOCK, or
12517 : SYM is bound in BLOCK. Either EXPR or SYM may be null. */
12518 : static gfc_code *
12519 807 : check_nested_loop_in_block (gfc_code *block, gfc_expr *expr,
12520 : gfc_symbol *sym, bool *bad)
12521 : {
12522 807 : gfc_namespace *ns;
12523 807 : gcc_assert (block->op == EXEC_BLOCK);
12524 807 : ns = block->ext.block.ns;
12525 807 : gcc_assert (ns);
12526 :
12527 : /* Skip the check if this block doesn't contain the nested loop, or
12528 : if we already know it's bad. */
12529 807 : gfc_code *result = check_nested_loop_in_chain (ns->code, expr, sym, bad);
12530 807 : if (result && !*bad)
12531 : {
12532 519 : check_nested_loop_in_block_state.expr = expr;
12533 519 : check_nested_loop_in_block_state.sym = sym;
12534 519 : check_nested_loop_in_block_state.bad = bad;
12535 519 : gfc_traverse_ns (ns, check_nested_loop_in_block_symbol);
12536 519 : check_nested_loop_in_block_state.expr = NULL;
12537 519 : check_nested_loop_in_block_state.sym = NULL;
12538 519 : check_nested_loop_in_block_state.bad = NULL;
12539 : }
12540 807 : return result;
12541 : }
12542 :
12543 : /* CODE is an OMP loop construct. Return true if EXPR references
12544 : any variables bound in intervening code, to level DEPTH. */
12545 : static bool
12546 22732 : expr_uses_intervening_var (gfc_code *code, int depth, gfc_expr *expr)
12547 : {
12548 22732 : int i;
12549 22732 : gfc_code *do_code = code;
12550 :
12551 58243 : for (i = 0; i < depth; i++)
12552 : {
12553 35514 : bool bad = false;
12554 35514 : do_code = check_nested_loop_in_chain (do_code->block->next,
12555 : expr, NULL, &bad);
12556 35514 : if (bad)
12557 3 : return true;
12558 : }
12559 : return false;
12560 : }
12561 :
12562 : /* CODE is an OMP loop construct. Return true if SYM is bound in
12563 : intervening code, to level DEPTH. */
12564 : static bool
12565 7587 : is_intervening_var (gfc_code *code, int depth, gfc_symbol *sym)
12566 : {
12567 7587 : int i;
12568 7587 : gfc_code *do_code = code;
12569 :
12570 19449 : for (i = 0; i < depth; i++)
12571 : {
12572 11864 : bool bad = false;
12573 11864 : do_code = check_nested_loop_in_chain (do_code->block->next,
12574 : NULL, sym, &bad);
12575 11864 : if (bad)
12576 2 : return true;
12577 : }
12578 : return false;
12579 : }
12580 :
12581 : /* CODE is an OMP loop construct. Return true if EXPR does not reference
12582 : any iteration variables outer to level DEPTH. */
12583 : static bool
12584 23811 : expr_is_invariant (gfc_code *code, int depth, gfc_expr *expr)
12585 : {
12586 23811 : int i;
12587 23811 : gfc_code *do_code = code;
12588 :
12589 37133 : for (i = 1; i < depth; i++)
12590 : {
12591 14388 : do_code = find_nested_loop_in_chain (do_code->block->next);
12592 14388 : gcc_assert (do_code);
12593 14388 : if (do_code->op == EXEC_OMP_TILE || do_code->op == EXEC_OMP_UNROLL)
12594 : {
12595 136 : --i;
12596 136 : continue;
12597 : }
12598 14252 : gfc_symbol *ivar = do_code->ext.iterator->var->symtree->n.sym;
12599 14252 : if (gfc_find_sym_in_expr (ivar, expr))
12600 : return false;
12601 : }
12602 : return true;
12603 : }
12604 :
12605 : /* CODE is an OMP loop construct. Return true if EXPR matches one of the
12606 : canonical forms for a bound expression. It may include references to
12607 : an iteration variable outer to level DEPTH; set OUTER_VARP if so. */
12608 : static bool
12609 15165 : bound_expr_is_canonical (gfc_code *code, int depth, gfc_expr *expr,
12610 : gfc_symbol **outer_varp)
12611 : {
12612 15165 : gfc_expr *expr2 = NULL;
12613 :
12614 : /* Rectangular case. */
12615 15165 : if (depth == 0 || expr_is_invariant (code, depth, expr))
12616 14597 : return true;
12617 :
12618 : /* Any simple variable that didn't pass expr_is_invariant must be
12619 : an outer_var. */
12620 568 : if (expr->expr_type == EXPR_VARIABLE && expr->rank == 0)
12621 : {
12622 63 : *outer_varp = expr->symtree->n.sym;
12623 63 : return true;
12624 : }
12625 :
12626 : /* All other permitted forms are binary operators. */
12627 505 : if (expr->expr_type != EXPR_OP)
12628 : return false;
12629 :
12630 : /* Check for plus/minus a loop invariant expr. */
12631 503 : if (expr->value.op.op == INTRINSIC_PLUS
12632 503 : || expr->value.op.op == INTRINSIC_MINUS)
12633 : {
12634 483 : if (expr_is_invariant (code, depth, expr->value.op.op1))
12635 48 : expr2 = expr->value.op.op2;
12636 435 : else if (expr_is_invariant (code, depth, expr->value.op.op2))
12637 434 : expr2 = expr->value.op.op1;
12638 : else
12639 : return false;
12640 : }
12641 : else
12642 : expr2 = expr;
12643 :
12644 : /* Check for a product with a loop-invariant expr. */
12645 502 : if (expr2->expr_type == EXPR_OP
12646 96 : && expr2->value.op.op == INTRINSIC_TIMES)
12647 : {
12648 96 : if (expr_is_invariant (code, depth, expr2->value.op.op1))
12649 40 : expr2 = expr2->value.op.op2;
12650 56 : else if (expr_is_invariant (code, depth, expr2->value.op.op2))
12651 53 : expr2 = expr2->value.op.op1;
12652 : else
12653 : return false;
12654 : }
12655 :
12656 : /* What's left must be a reference to an outer loop variable. */
12657 499 : if (expr2->expr_type == EXPR_VARIABLE
12658 499 : && expr2->rank == 0
12659 998 : && is_outer_iteration_variable (code, depth, expr2->symtree->n.sym))
12660 : {
12661 499 : *outer_varp = expr2->symtree->n.sym;
12662 499 : return true;
12663 : }
12664 :
12665 : return false;
12666 : }
12667 :
12668 : static void
12669 5425 : resolve_omp_do (gfc_code *code)
12670 : {
12671 5425 : gfc_code *do_code, *next;
12672 5425 : int i, count, non_generated_count;
12673 5425 : gfc_omp_namelist *n;
12674 5425 : gfc_symbol *dovar;
12675 5425 : const char *name;
12676 5425 : bool is_simd = false;
12677 5425 : bool errorp = false;
12678 5425 : bool perfect_nesting_errorp = false;
12679 5425 : bool imperfect = false;
12680 :
12681 5425 : switch (code->op)
12682 : {
12683 : case EXEC_OMP_DISTRIBUTE: name = "!$OMP DISTRIBUTE"; break;
12684 49 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
12685 49 : name = "!$OMP DISTRIBUTE PARALLEL DO";
12686 49 : break;
12687 32 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
12688 32 : name = "!$OMP DISTRIBUTE PARALLEL DO SIMD";
12689 32 : is_simd = true;
12690 32 : break;
12691 50 : case EXEC_OMP_DISTRIBUTE_SIMD:
12692 50 : name = "!$OMP DISTRIBUTE SIMD";
12693 50 : is_simd = true;
12694 50 : break;
12695 1336 : case EXEC_OMP_DO: name = "!$OMP DO"; break;
12696 134 : case EXEC_OMP_DO_SIMD: name = "!$OMP DO SIMD"; is_simd = true; break;
12697 64 : case EXEC_OMP_LOOP: name = "!$OMP LOOP"; break;
12698 1220 : case EXEC_OMP_PARALLEL_DO: name = "!$OMP PARALLEL DO"; break;
12699 304 : case EXEC_OMP_PARALLEL_DO_SIMD:
12700 304 : name = "!$OMP PARALLEL DO SIMD";
12701 304 : is_simd = true;
12702 304 : break;
12703 46 : case EXEC_OMP_PARALLEL_LOOP: name = "!$OMP PARALLEL LOOP"; break;
12704 7 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
12705 7 : name = "!$OMP PARALLEL MASKED TASKLOOP";
12706 7 : break;
12707 10 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
12708 10 : name = "!$OMP PARALLEL MASKED TASKLOOP SIMD";
12709 10 : is_simd = true;
12710 10 : break;
12711 12 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
12712 12 : name = "!$OMP PARALLEL MASTER TASKLOOP";
12713 12 : break;
12714 18 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
12715 18 : name = "!$OMP PARALLEL MASTER TASKLOOP SIMD";
12716 18 : is_simd = true;
12717 18 : break;
12718 8 : case EXEC_OMP_MASKED_TASKLOOP: name = "!$OMP MASKED TASKLOOP"; break;
12719 14 : case EXEC_OMP_MASKED_TASKLOOP_SIMD:
12720 14 : name = "!$OMP MASKED TASKLOOP SIMD";
12721 14 : is_simd = true;
12722 14 : break;
12723 14 : case EXEC_OMP_MASTER_TASKLOOP: name = "!$OMP MASTER TASKLOOP"; break;
12724 19 : case EXEC_OMP_MASTER_TASKLOOP_SIMD:
12725 19 : name = "!$OMP MASTER TASKLOOP SIMD";
12726 19 : is_simd = true;
12727 19 : break;
12728 783 : case EXEC_OMP_SIMD: name = "!$OMP SIMD"; is_simd = true; break;
12729 88 : case EXEC_OMP_TARGET_PARALLEL_DO: name = "!$OMP TARGET PARALLEL DO"; break;
12730 19 : case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
12731 19 : name = "!$OMP TARGET PARALLEL DO SIMD";
12732 19 : is_simd = true;
12733 19 : break;
12734 16 : case EXEC_OMP_TARGET_PARALLEL_LOOP:
12735 16 : name = "!$OMP TARGET PARALLEL LOOP";
12736 16 : break;
12737 33 : case EXEC_OMP_TARGET_SIMD:
12738 33 : name = "!$OMP TARGET SIMD";
12739 33 : is_simd = true;
12740 33 : break;
12741 20 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
12742 20 : name = "!$OMP TARGET TEAMS DISTRIBUTE";
12743 20 : break;
12744 75 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
12745 75 : name = "!$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO";
12746 75 : break;
12747 37 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
12748 37 : name = "!$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD";
12749 37 : is_simd = true;
12750 37 : break;
12751 20 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
12752 20 : name = "!$OMP TARGET TEAMS DISTRIBUTE SIMD";
12753 20 : is_simd = true;
12754 20 : break;
12755 19 : case EXEC_OMP_TARGET_TEAMS_LOOP: name = "!$OMP TARGET TEAMS LOOP"; break;
12756 69 : case EXEC_OMP_TASKLOOP: name = "!$OMP TASKLOOP"; break;
12757 38 : case EXEC_OMP_TASKLOOP_SIMD:
12758 38 : name = "!$OMP TASKLOOP SIMD";
12759 38 : is_simd = true;
12760 38 : break;
12761 20 : case EXEC_OMP_TEAMS_DISTRIBUTE: name = "!$OMP TEAMS DISTRIBUTE"; break;
12762 37 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
12763 37 : name = "!$OMP TEAMS DISTRIBUTE PARALLEL DO";
12764 37 : break;
12765 60 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
12766 60 : name = "!$OMP TEAMS DISTRIBUTE PARALLEL DO SIMD";
12767 60 : is_simd = true;
12768 60 : break;
12769 42 : case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
12770 42 : name = "!$OMP TEAMS DISTRIBUTE SIMD";
12771 42 : is_simd = true;
12772 42 : break;
12773 48 : case EXEC_OMP_TEAMS_LOOP: name = "!$OMP TEAMS LOOP"; break;
12774 195 : case EXEC_OMP_TILE: name = "!$OMP TILE"; break;
12775 415 : case EXEC_OMP_UNROLL: name = "!$OMP UNROLL"; break;
12776 0 : default: gcc_unreachable ();
12777 : }
12778 :
12779 5425 : if (code->ext.omp_clauses)
12780 5425 : resolve_omp_clauses (code, code->ext.omp_clauses, NULL);
12781 :
12782 5425 : if (code->op == EXEC_OMP_TILE && code->ext.omp_clauses->sizes_list == NULL)
12783 0 : gfc_error ("SIZES clause is required on !$OMP TILE construct at %L",
12784 : &code->loc);
12785 :
12786 5425 : do_code = code->block->next;
12787 5425 : if (code->ext.omp_clauses->orderedc)
12788 : count = code->ext.omp_clauses->orderedc;
12789 5281 : else if (code->ext.omp_clauses->sizes_list)
12790 195 : count = gfc_expr_list_len (code->ext.omp_clauses->sizes_list);
12791 : else
12792 : {
12793 5086 : count = code->ext.omp_clauses->collapse;
12794 5086 : if (count <= 0)
12795 : count = 1;
12796 : }
12797 :
12798 5425 : non_generated_count = count;
12799 : /* While the spec defines the loop nest depth independently of the COLLAPSE
12800 : clause, in practice the middle end only pays attention to the COLLAPSE
12801 : depth and treats any further inner loops as the final-loop-body. So
12802 : here we also check canonical loop nest form only for the number of
12803 : outer loops specified by the COLLAPSE clause too. */
12804 8065 : for (i = 1; i <= count; i++)
12805 : {
12806 8065 : gfc_symbol *start_var = NULL, *end_var = NULL;
12807 : /* Parse errors are not recoverable. */
12808 8065 : if (do_code->op == EXEC_DO_WHILE)
12809 : {
12810 6 : gfc_error ("%s cannot be a DO WHILE or DO without loop control "
12811 : "at %L", name, &do_code->loc);
12812 106 : goto fail;
12813 : }
12814 8059 : if (do_code->op == EXEC_DO_CONCURRENT)
12815 : {
12816 4 : gfc_error ("%s cannot be a DO CONCURRENT loop at %L", name,
12817 : &do_code->loc);
12818 4 : goto fail;
12819 : }
12820 8055 : if (do_code->op == EXEC_OMP_TILE || do_code->op == EXEC_OMP_UNROLL)
12821 : {
12822 466 : if (do_code->op == EXEC_OMP_UNROLL)
12823 : {
12824 308 : if (!do_code->ext.omp_clauses->partial)
12825 : {
12826 53 : gfc_error ("Generated loop of UNROLL construct at %L "
12827 : "without PARTIAL clause does not have "
12828 : "canonical form", &do_code->loc);
12829 53 : goto fail;
12830 : }
12831 255 : else if (i != count)
12832 : {
12833 5 : gfc_error ("UNROLL construct at %L with PARTIAL clause "
12834 : "generates just one loop with canonical form "
12835 : "but %d loops are needed",
12836 5 : &do_code->loc, count - i + 1);
12837 5 : goto fail;
12838 : }
12839 : }
12840 158 : else if (do_code->op == EXEC_OMP_TILE)
12841 : {
12842 158 : if (do_code->ext.omp_clauses->sizes_list == NULL)
12843 : /* This should have been diagnosed earlier already. */
12844 0 : return;
12845 158 : int l = gfc_expr_list_len (do_code->ext.omp_clauses->sizes_list);
12846 158 : if (count - i + 1 > l)
12847 : {
12848 14 : gfc_error ("TILE construct at %L generates %d loops "
12849 : "with canonical form but %d loops are needed",
12850 : &do_code->loc, l, count - i + 1);
12851 14 : goto fail;
12852 : }
12853 : }
12854 394 : if (do_code->ext.omp_clauses && do_code->ext.omp_clauses->erroneous)
12855 17 : goto fail;
12856 377 : if (imperfect && !perfect_nesting_errorp)
12857 : {
12858 4 : sorry_at (gfc_get_location (&do_code->loc),
12859 : "Imperfectly nested loop using generated loops");
12860 4 : errorp = true;
12861 : }
12862 377 : if (non_generated_count == count)
12863 329 : non_generated_count = i - 1;
12864 377 : --i;
12865 377 : do_code = do_code->block->next;
12866 377 : continue;
12867 377 : }
12868 7589 : gcc_assert (do_code->op == EXEC_DO);
12869 7589 : if (do_code->ext.iterator->var->ts.type != BT_INTEGER)
12870 : {
12871 3 : gfc_error ("%s iteration variable must be of type integer at %L",
12872 : name, &do_code->loc);
12873 3 : errorp = true;
12874 : }
12875 7589 : dovar = do_code->ext.iterator->var->symtree->n.sym;
12876 7589 : if (dovar->attr.threadprivate)
12877 : {
12878 0 : gfc_error ("%s iteration variable must not be THREADPRIVATE "
12879 : "at %L", name, &do_code->loc);
12880 0 : errorp = true;
12881 : }
12882 7589 : if (code->ext.omp_clauses)
12883 303560 : for (enum gfc_omp_list_type list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
12884 295971 : list = gfc_omp_list_type (list + 1))
12885 97461 : if (!is_simd || code->ext.omp_clauses->collapse > 1
12886 295971 : ? (list != OMP_LIST_PRIVATE && list != OMP_LIST_LASTPRIVATE
12887 254865 : && list != OMP_LIST_ALLOCATE)
12888 41106 : : (list != OMP_LIST_PRIVATE && list != OMP_LIST_LASTPRIVATE
12889 41106 : && list != OMP_LIST_ALLOCATE && list != OMP_LIST_LINEAR))
12890 276535 : for (n = code->ext.omp_clauses->lists[list]; n; n = n->next)
12891 4385 : if (dovar == n->sym)
12892 : {
12893 5 : if (!is_simd || code->ext.omp_clauses->collapse > 1)
12894 4 : gfc_error ("%s iteration variable present on clause "
12895 : "other than PRIVATE, LASTPRIVATE or "
12896 : "ALLOCATE at %L", name, &do_code->loc);
12897 : else
12898 1 : gfc_error ("%s iteration variable present on clause "
12899 : "other than PRIVATE, LASTPRIVATE, ALLOCATE or "
12900 : "LINEAR at %L", name, &do_code->loc);
12901 : errorp = true;
12902 : }
12903 7589 : if (is_outer_iteration_variable (code, i, dovar))
12904 : {
12905 2 : gfc_error ("%s iteration variable used in more than one loop at %L",
12906 : name, &do_code->loc);
12907 2 : errorp = true;
12908 : }
12909 7587 : else if (is_intervening_var (code, i, dovar))
12910 : {
12911 2 : gfc_error ("%s iteration variable at %L is bound in "
12912 : "intervening code",
12913 : name, &do_code->loc);
12914 2 : errorp = true;
12915 : }
12916 7585 : else if (!bound_expr_is_canonical (code, i,
12917 7585 : do_code->ext.iterator->start,
12918 : &start_var))
12919 : {
12920 4 : gfc_error ("%s loop start expression not in canonical form at %L",
12921 : name, &do_code->loc);
12922 4 : errorp = true;
12923 : }
12924 7581 : else if (expr_uses_intervening_var (code, i,
12925 7581 : do_code->ext.iterator->start))
12926 : {
12927 1 : gfc_error ("%s loop start expression at %L uses variable bound in "
12928 : "intervening code",
12929 : name, &do_code->loc);
12930 1 : errorp = true;
12931 : }
12932 7580 : else if (!bound_expr_is_canonical (code, i,
12933 7580 : do_code->ext.iterator->end,
12934 : &end_var))
12935 : {
12936 2 : gfc_error ("%s loop end expression not in canonical form at %L",
12937 : name, &do_code->loc);
12938 2 : errorp = true;
12939 : }
12940 7578 : else if (expr_uses_intervening_var (code, i,
12941 7578 : do_code->ext.iterator->end))
12942 : {
12943 1 : gfc_error ("%s loop end expression at %L uses variable bound in "
12944 : "intervening code",
12945 : name, &do_code->loc);
12946 1 : errorp = true;
12947 : }
12948 7577 : else if (start_var && end_var && start_var != end_var)
12949 : {
12950 1 : gfc_error ("%s loop bounds reference different "
12951 : "iteration variables at %L", name, &do_code->loc);
12952 1 : errorp = true;
12953 : }
12954 7576 : else if (!expr_is_invariant (code, i, do_code->ext.iterator->step))
12955 : {
12956 3 : gfc_error ("%s loop increment not in canonical form at %L",
12957 : name, &do_code->loc);
12958 3 : errorp = true;
12959 : }
12960 7573 : else if (expr_uses_intervening_var (code, i,
12961 7573 : do_code->ext.iterator->step))
12962 : {
12963 1 : gfc_error ("%s loop increment expression at %L uses variable "
12964 : "bound in intervening code",
12965 : name, &do_code->loc);
12966 1 : errorp = true;
12967 : }
12968 7589 : if (start_var || end_var)
12969 : {
12970 528 : code->ext.omp_clauses->non_rectangular = 1;
12971 528 : if (i > non_generated_count)
12972 : {
12973 3 : sorry_at (gfc_get_location (&do_code->loc),
12974 : "Non-rectangular loops from generated loops "
12975 : "unsupported");
12976 3 : errorp = true;
12977 : }
12978 : }
12979 :
12980 : /* Only parse loop body into nested loop and intervening code if
12981 : there are supposed to be more loops in the nest to collapse. */
12982 7589 : if (i == count)
12983 : break;
12984 :
12985 2270 : next = find_nested_loop_in_chain (do_code->block->next);
12986 :
12987 2270 : if (!next)
12988 : {
12989 : /* Parse error, can't recover from this. */
12990 7 : gfc_error ("not enough DO loops for collapsed %s (level %d) at %L",
12991 : name, i, &code->loc);
12992 7 : goto fail;
12993 : }
12994 2263 : else if (next != do_code->block->next
12995 2103 : || (next->next && next->next->op != EXEC_CONTINUE))
12996 : /* Imperfectly nested loop found. */
12997 : {
12998 : /* Only diagnose violation of imperfect nesting constraints once. */
12999 177 : if (!perfect_nesting_errorp)
13000 : {
13001 176 : if (code->ext.omp_clauses->orderedc)
13002 : {
13003 3 : gfc_error ("%s inner loops must be perfectly nested with "
13004 : "ORDERED clause at %L",
13005 : name, &code->loc);
13006 3 : perfect_nesting_errorp = true;
13007 : }
13008 173 : else if (code->ext.omp_clauses->lists[OMP_LIST_REDUCTION_INSCAN])
13009 : {
13010 2 : gfc_error ("%s inner loops must be perfectly nested with "
13011 : "REDUCTION INSCAN clause at %L",
13012 : name, &code->loc);
13013 2 : perfect_nesting_errorp = true;
13014 : }
13015 171 : else if (code->op == EXEC_OMP_TILE)
13016 : {
13017 8 : gfc_error ("%s inner loops must be perfectly nested at %L",
13018 : name, &code->loc);
13019 8 : perfect_nesting_errorp = true;
13020 : }
13021 13 : if (perfect_nesting_errorp)
13022 : errorp = true;
13023 : }
13024 177 : if (diagnose_intervening_code_errors (do_code->block->next,
13025 : name, next))
13026 5 : errorp = true;
13027 : imperfect = true;
13028 : }
13029 2263 : do_code = next;
13030 : }
13031 :
13032 : /* Give up now if we found any constraint violations. */
13033 5319 : if (errorp)
13034 : {
13035 48 : fail:
13036 154 : if (code->ext.omp_clauses)
13037 154 : code->ext.omp_clauses->erroneous = 1;
13038 154 : return;
13039 : }
13040 :
13041 5271 : if (non_generated_count)
13042 5001 : restructure_intervening_code (&code->block->next, code,
13043 : non_generated_count);
13044 : }
13045 :
13046 : /* Resolve the context selector. In particular, SKIP_P is set to true,
13047 : the context can never be matched. */
13048 :
13049 : static void
13050 758 : gfc_resolve_omp_context_selector (gfc_omp_set_selector *oss,
13051 : bool is_metadirective, bool *skip_p)
13052 : {
13053 758 : if (skip_p)
13054 310 : *skip_p = false;
13055 1441 : for (gfc_omp_set_selector *set_selector = oss; set_selector;
13056 683 : set_selector = set_selector->next)
13057 1473 : for (gfc_omp_selector *os = set_selector->trait_selectors; os; os = os->next)
13058 : {
13059 808 : if (os->score)
13060 : {
13061 52 : if (!gfc_resolve_expr (os->score)
13062 52 : || os->score->ts.type != BT_INTEGER
13063 104 : || os->score->rank != 0)
13064 : {
13065 0 : gfc_error ("%<score%> argument must be constant integer "
13066 0 : "expression at %L", &os->score->where);
13067 0 : gfc_free_expr (os->score);
13068 0 : os->score = nullptr;
13069 : }
13070 52 : else if (os->score->expr_type == EXPR_CONSTANT
13071 52 : && mpz_sgn (os->score->value.integer) < 0)
13072 : {
13073 1 : gfc_error ("%<score%> argument must be non-negative at %L",
13074 : &os->score->where);
13075 1 : gfc_free_expr (os->score);
13076 1 : os->score = nullptr;
13077 : }
13078 : }
13079 :
13080 808 : if (os->code == OMP_TRAIT_INVALID)
13081 : break;
13082 790 : enum omp_tp_type property_kind = omp_ts_map[os->code].tp_type;
13083 790 : gfc_omp_trait_property *otp = os->properties;
13084 :
13085 790 : if (!otp)
13086 403 : continue;
13087 387 : switch (property_kind)
13088 : {
13089 139 : case OMP_TRAIT_PROPERTY_DEV_NUM_EXPR:
13090 139 : case OMP_TRAIT_PROPERTY_BOOL_EXPR:
13091 139 : if (!gfc_resolve_expr (otp->expr)
13092 138 : || (property_kind == OMP_TRAIT_PROPERTY_BOOL_EXPR
13093 124 : && otp->expr->ts.type != BT_LOGICAL)
13094 137 : || (property_kind == OMP_TRAIT_PROPERTY_DEV_NUM_EXPR
13095 14 : && otp->expr->ts.type != BT_INTEGER)
13096 137 : || otp->expr->rank != 0
13097 276 : || (!is_metadirective && otp->expr->expr_type != EXPR_CONSTANT))
13098 : {
13099 3 : if (is_metadirective)
13100 : {
13101 0 : if (property_kind == OMP_TRAIT_PROPERTY_BOOL_EXPR)
13102 0 : gfc_error ("property must be a "
13103 : "logical expression at %L",
13104 0 : &otp->expr->where);
13105 : else
13106 0 : gfc_error ("property must be an "
13107 : "integer expression at %L",
13108 0 : &otp->expr->where);
13109 : }
13110 : else
13111 : {
13112 3 : if (property_kind == OMP_TRAIT_PROPERTY_BOOL_EXPR)
13113 2 : gfc_error ("property must be a constant "
13114 : "logical expression at %L",
13115 2 : &otp->expr->where);
13116 : else
13117 1 : gfc_error ("property must be a constant "
13118 : "integer expression at %L",
13119 1 : &otp->expr->where);
13120 : }
13121 : /* Prevent later ICEs. */
13122 3 : gfc_expr *e;
13123 3 : if (property_kind == OMP_TRAIT_PROPERTY_BOOL_EXPR)
13124 2 : e = gfc_get_logical_expr (gfc_default_logical_kind,
13125 2 : &otp->expr->where, true);
13126 : else
13127 1 : e = gfc_get_int_expr (gfc_default_integer_kind,
13128 1 : &otp->expr->where, 0);
13129 3 : gfc_free_expr (otp->expr);
13130 3 : otp->expr = e;
13131 3 : continue;
13132 3 : }
13133 : /* Device number must be conforming, which includes
13134 : omp_initial_device (-1), omp_invalid_device (-4),
13135 : and omp_default_device (-5). */
13136 136 : if (property_kind == OMP_TRAIT_PROPERTY_DEV_NUM_EXPR
13137 14 : && otp->expr->expr_type == EXPR_CONSTANT
13138 5 : && mpz_sgn (otp->expr->value.integer) < 0
13139 3 : && mpz_cmp_si (otp->expr->value.integer, -1) != 0
13140 2 : && mpz_cmp_si (otp->expr->value.integer, -4) != 0
13141 1 : && mpz_cmp_si (otp->expr->value.integer, -5) != 0)
13142 1 : gfc_error ("property must be a conforming device number at %L",
13143 : &otp->expr->where);
13144 : break;
13145 : default:
13146 : break;
13147 : }
13148 : /* This only handles one specific case: User condition.
13149 : FIXME: Handle more cases by calling omp_context_selector_matches;
13150 : unfortunately, we cannot generate the tree here as, e.g., PARM_DECL
13151 : backend decl are not available at this stage - but might be used in,
13152 : e.g. user conditions. See PR122361. */
13153 384 : if (skip_p && otp
13154 138 : && os->code == OMP_TRAIT_USER_CONDITION
13155 81 : && otp->expr->expr_type == EXPR_CONSTANT
13156 14 : && otp->expr->value.logical == false)
13157 12 : *skip_p = true;
13158 : }
13159 758 : }
13160 :
13161 :
13162 : static void
13163 138 : resolve_omp_metadirective (gfc_code *code, gfc_namespace *ns)
13164 : {
13165 138 : gfc_omp_variant *variant = code->ext.omp_variants;
13166 138 : gfc_omp_variant *prev_variant = variant;
13167 :
13168 448 : while (variant)
13169 : {
13170 310 : bool skip;
13171 310 : gfc_resolve_omp_context_selector (variant->selectors, true, &skip);
13172 310 : gfc_code *variant_code = variant->code;
13173 310 : gfc_resolve_code (variant_code, ns);
13174 310 : if (skip)
13175 : {
13176 : /* The following should only be true if an error occurred
13177 : as the 'otherwise' clause should always match. */
13178 12 : if (variant == code->ext.omp_variants && !variant->next)
13179 : break;
13180 12 : gfc_omp_variant *tmp = variant;
13181 12 : if (variant == code->ext.omp_variants)
13182 11 : variant = prev_variant = code->ext.omp_variants = variant->next;
13183 : else
13184 1 : variant = prev_variant->next = variant->next;
13185 12 : gfc_free_omp_set_selector_list (tmp->selectors);
13186 12 : free (tmp);
13187 : }
13188 : else
13189 : {
13190 298 : prev_variant = variant;
13191 298 : variant = variant->next;
13192 : }
13193 : }
13194 : /* Replace metadirective by its body if only 'nothing' remains. */
13195 138 : if (!code->ext.omp_variants->next && code->ext.omp_variants->stmt == ST_NONE)
13196 : {
13197 11 : gfc_code *next = code->next;
13198 11 : gfc_code *inner = code->ext.omp_variants->code;
13199 11 : gfc_free_omp_set_selector_list (code->ext.omp_variants->selectors);
13200 11 : free (code->ext.omp_variants);
13201 11 : *code = *inner;
13202 11 : free (inner);
13203 11 : while (code->next)
13204 : code = code->next;
13205 11 : code->next = next;
13206 : }
13207 138 : }
13208 :
13209 :
13210 : static gfc_statement
13211 63 : omp_code_to_statement (gfc_code *code)
13212 : {
13213 63 : switch (code->op)
13214 : {
13215 : case EXEC_OMP_PARALLEL:
13216 : return ST_OMP_PARALLEL;
13217 0 : case EXEC_OMP_PARALLEL_MASKED:
13218 0 : return ST_OMP_PARALLEL_MASKED;
13219 0 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
13220 0 : return ST_OMP_PARALLEL_MASKED_TASKLOOP;
13221 0 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
13222 0 : return ST_OMP_PARALLEL_MASKED_TASKLOOP_SIMD;
13223 0 : case EXEC_OMP_PARALLEL_MASTER:
13224 0 : return ST_OMP_PARALLEL_MASTER;
13225 0 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
13226 0 : return ST_OMP_PARALLEL_MASTER_TASKLOOP;
13227 0 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
13228 0 : return ST_OMP_PARALLEL_MASTER_TASKLOOP_SIMD;
13229 1 : case EXEC_OMP_PARALLEL_SECTIONS:
13230 1 : return ST_OMP_PARALLEL_SECTIONS;
13231 1 : case EXEC_OMP_SECTIONS:
13232 1 : return ST_OMP_SECTIONS;
13233 1 : case EXEC_OMP_ORDERED:
13234 1 : return ST_OMP_ORDERED;
13235 1 : case EXEC_OMP_CRITICAL:
13236 1 : return ST_OMP_CRITICAL;
13237 0 : case EXEC_OMP_MASKED:
13238 0 : return ST_OMP_MASKED;
13239 0 : case EXEC_OMP_MASKED_TASKLOOP:
13240 0 : return ST_OMP_MASKED_TASKLOOP;
13241 0 : case EXEC_OMP_MASKED_TASKLOOP_SIMD:
13242 0 : return ST_OMP_MASKED_TASKLOOP_SIMD;
13243 1 : case EXEC_OMP_MASTER:
13244 1 : return ST_OMP_MASTER;
13245 0 : case EXEC_OMP_MASTER_TASKLOOP:
13246 0 : return ST_OMP_MASTER_TASKLOOP;
13247 0 : case EXEC_OMP_MASTER_TASKLOOP_SIMD:
13248 0 : return ST_OMP_MASTER_TASKLOOP_SIMD;
13249 1 : case EXEC_OMP_SINGLE:
13250 1 : return ST_OMP_SINGLE;
13251 1 : case EXEC_OMP_TASK:
13252 1 : return ST_OMP_TASK;
13253 1 : case EXEC_OMP_WORKSHARE:
13254 1 : return ST_OMP_WORKSHARE;
13255 1 : case EXEC_OMP_PARALLEL_WORKSHARE:
13256 1 : return ST_OMP_PARALLEL_WORKSHARE;
13257 3 : case EXEC_OMP_DO:
13258 3 : return ST_OMP_DO;
13259 0 : case EXEC_OMP_LOOP:
13260 0 : return ST_OMP_LOOP;
13261 0 : case EXEC_OMP_ALLOCATE:
13262 0 : return ST_OMP_ALLOCATE_EXEC;
13263 0 : case EXEC_OMP_ALLOCATORS:
13264 0 : return ST_OMP_ALLOCATORS;
13265 0 : case EXEC_OMP_ASSUME:
13266 0 : return ST_OMP_ASSUME;
13267 1 : case EXEC_OMP_ATOMIC:
13268 1 : return ST_OMP_ATOMIC;
13269 1 : case EXEC_OMP_BARRIER:
13270 1 : return ST_OMP_BARRIER;
13271 1 : case EXEC_OMP_CANCEL:
13272 1 : return ST_OMP_CANCEL;
13273 1 : case EXEC_OMP_CANCELLATION_POINT:
13274 1 : return ST_OMP_CANCELLATION_POINT;
13275 0 : case EXEC_OMP_ERROR:
13276 0 : return ST_OMP_ERROR;
13277 1 : case EXEC_OMP_FLUSH:
13278 1 : return ST_OMP_FLUSH;
13279 0 : case EXEC_OMP_INTEROP:
13280 0 : return ST_OMP_INTEROP;
13281 1 : case EXEC_OMP_DISTRIBUTE:
13282 1 : return ST_OMP_DISTRIBUTE;
13283 1 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
13284 1 : return ST_OMP_DISTRIBUTE_PARALLEL_DO;
13285 1 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
13286 1 : return ST_OMP_DISTRIBUTE_PARALLEL_DO_SIMD;
13287 1 : case EXEC_OMP_DISTRIBUTE_SIMD:
13288 1 : return ST_OMP_DISTRIBUTE_SIMD;
13289 1 : case EXEC_OMP_DO_SIMD:
13290 1 : return ST_OMP_DO_SIMD;
13291 0 : case EXEC_OMP_SCAN:
13292 0 : return ST_OMP_SCAN;
13293 0 : case EXEC_OMP_SCOPE:
13294 0 : return ST_OMP_SCOPE;
13295 1 : case EXEC_OMP_SIMD:
13296 1 : return ST_OMP_SIMD;
13297 1 : case EXEC_OMP_TARGET:
13298 1 : return ST_OMP_TARGET;
13299 1 : case EXEC_OMP_TARGET_DATA:
13300 1 : return ST_OMP_TARGET_DATA;
13301 1 : case EXEC_OMP_TARGET_ENTER_DATA:
13302 1 : return ST_OMP_TARGET_ENTER_DATA;
13303 1 : case EXEC_OMP_TARGET_EXIT_DATA:
13304 1 : return ST_OMP_TARGET_EXIT_DATA;
13305 1 : case EXEC_OMP_TARGET_PARALLEL:
13306 1 : return ST_OMP_TARGET_PARALLEL;
13307 1 : case EXEC_OMP_TARGET_PARALLEL_DO:
13308 1 : return ST_OMP_TARGET_PARALLEL_DO;
13309 1 : case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
13310 1 : return ST_OMP_TARGET_PARALLEL_DO_SIMD;
13311 0 : case EXEC_OMP_TARGET_PARALLEL_LOOP:
13312 0 : return ST_OMP_TARGET_PARALLEL_LOOP;
13313 1 : case EXEC_OMP_TARGET_SIMD:
13314 1 : return ST_OMP_TARGET_SIMD;
13315 1 : case EXEC_OMP_TARGET_TEAMS:
13316 1 : return ST_OMP_TARGET_TEAMS;
13317 1 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
13318 1 : return ST_OMP_TARGET_TEAMS_DISTRIBUTE;
13319 1 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
13320 1 : return ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO;
13321 1 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
13322 1 : return ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD;
13323 1 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
13324 1 : return ST_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD;
13325 0 : case EXEC_OMP_TARGET_TEAMS_LOOP:
13326 0 : return ST_OMP_TARGET_TEAMS_LOOP;
13327 1 : case EXEC_OMP_TARGET_UPDATE:
13328 1 : return ST_OMP_TARGET_UPDATE;
13329 1 : case EXEC_OMP_TASKGROUP:
13330 1 : return ST_OMP_TASKGROUP;
13331 1 : case EXEC_OMP_TASKLOOP:
13332 1 : return ST_OMP_TASKLOOP;
13333 1 : case EXEC_OMP_TASKLOOP_SIMD:
13334 1 : return ST_OMP_TASKLOOP_SIMD;
13335 1 : case EXEC_OMP_TASKWAIT:
13336 1 : return ST_OMP_TASKWAIT;
13337 1 : case EXEC_OMP_TASKYIELD:
13338 1 : return ST_OMP_TASKYIELD;
13339 1 : case EXEC_OMP_TEAMS:
13340 1 : return ST_OMP_TEAMS;
13341 1 : case EXEC_OMP_TEAMS_DISTRIBUTE:
13342 1 : return ST_OMP_TEAMS_DISTRIBUTE;
13343 1 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
13344 1 : return ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO;
13345 1 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
13346 1 : return ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD;
13347 1 : case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
13348 1 : return ST_OMP_TEAMS_DISTRIBUTE_SIMD;
13349 0 : case EXEC_OMP_TEAMS_LOOP:
13350 0 : return ST_OMP_TEAMS_LOOP;
13351 6 : case EXEC_OMP_PARALLEL_DO:
13352 6 : return ST_OMP_PARALLEL_DO;
13353 1 : case EXEC_OMP_PARALLEL_DO_SIMD:
13354 1 : return ST_OMP_PARALLEL_DO_SIMD;
13355 0 : case EXEC_OMP_PARALLEL_LOOP:
13356 0 : return ST_OMP_PARALLEL_LOOP;
13357 1 : case EXEC_OMP_DEPOBJ:
13358 1 : return ST_OMP_DEPOBJ;
13359 0 : case EXEC_OMP_TILE:
13360 0 : return ST_OMP_TILE;
13361 0 : case EXEC_OMP_UNROLL:
13362 0 : return ST_OMP_UNROLL;
13363 0 : case EXEC_OMP_DISPATCH:
13364 0 : return ST_OMP_DISPATCH;
13365 0 : default:
13366 0 : gcc_unreachable ();
13367 : }
13368 : }
13369 :
13370 : static gfc_statement
13371 63 : oacc_code_to_statement (gfc_code *code)
13372 : {
13373 63 : switch (code->op)
13374 : {
13375 : case EXEC_OACC_PARALLEL:
13376 : return ST_OACC_PARALLEL;
13377 : case EXEC_OACC_KERNELS:
13378 : return ST_OACC_KERNELS;
13379 : case EXEC_OACC_SERIAL:
13380 : return ST_OACC_SERIAL;
13381 : case EXEC_OACC_DATA:
13382 : return ST_OACC_DATA;
13383 : case EXEC_OACC_HOST_DATA:
13384 : return ST_OACC_HOST_DATA;
13385 : case EXEC_OACC_PARALLEL_LOOP:
13386 : return ST_OACC_PARALLEL_LOOP;
13387 : case EXEC_OACC_KERNELS_LOOP:
13388 : return ST_OACC_KERNELS_LOOP;
13389 : case EXEC_OACC_SERIAL_LOOP:
13390 : return ST_OACC_SERIAL_LOOP;
13391 : case EXEC_OACC_LOOP:
13392 : return ST_OACC_LOOP;
13393 : case EXEC_OACC_ATOMIC:
13394 : return ST_OACC_ATOMIC;
13395 : case EXEC_OACC_ROUTINE:
13396 : return ST_OACC_ROUTINE;
13397 : case EXEC_OACC_UPDATE:
13398 : return ST_OACC_UPDATE;
13399 : case EXEC_OACC_WAIT:
13400 : return ST_OACC_WAIT;
13401 : case EXEC_OACC_CACHE:
13402 : return ST_OACC_CACHE;
13403 : case EXEC_OACC_ENTER_DATA:
13404 : return ST_OACC_ENTER_DATA;
13405 : case EXEC_OACC_EXIT_DATA:
13406 : return ST_OACC_EXIT_DATA;
13407 : case EXEC_OACC_DECLARE:
13408 : return ST_OACC_DECLARE;
13409 0 : default:
13410 0 : gcc_unreachable ();
13411 : }
13412 : }
13413 :
13414 : static void
13415 13168 : resolve_oacc_directive_inside_omp_region (gfc_code *code)
13416 : {
13417 13168 : if (omp_current_ctx != NULL && omp_current_ctx->is_openmp)
13418 : {
13419 11 : gfc_statement st = omp_code_to_statement (omp_current_ctx->code);
13420 11 : gfc_statement oacc_st = oacc_code_to_statement (code);
13421 11 : gfc_error ("The %s directive cannot be specified within "
13422 : "a %s region at %L", gfc_ascii_statement (oacc_st),
13423 : gfc_ascii_statement (st), &code->loc);
13424 : }
13425 13168 : }
13426 :
13427 : static void
13428 21194 : resolve_omp_directive_inside_oacc_region (gfc_code *code)
13429 : {
13430 21194 : if (omp_current_ctx != NULL && !omp_current_ctx->is_openmp)
13431 : {
13432 52 : gfc_statement st = oacc_code_to_statement (omp_current_ctx->code);
13433 52 : gfc_statement omp_st = omp_code_to_statement (code);
13434 52 : gfc_error ("The %s directive cannot be specified within "
13435 : "a %s region at %L", gfc_ascii_statement (omp_st),
13436 : gfc_ascii_statement (st), &code->loc);
13437 : }
13438 21194 : }
13439 :
13440 :
13441 : static void
13442 5272 : resolve_oacc_nested_loops (gfc_code *code, gfc_code* do_code, int collapse,
13443 : const char *clause)
13444 : {
13445 5272 : gfc_symbol *dovar;
13446 5272 : gfc_code *c;
13447 5272 : int i;
13448 :
13449 5792 : for (i = 1; i <= collapse; i++)
13450 : {
13451 5792 : if (do_code->op == EXEC_DO_WHILE)
13452 : {
13453 10 : gfc_error ("!$ACC LOOP cannot be a DO WHILE or DO without loop control "
13454 : "at %L", &do_code->loc);
13455 10 : break;
13456 : }
13457 5782 : if (do_code->op == EXEC_DO_CONCURRENT)
13458 : {
13459 3 : gfc_error ("!$ACC LOOP cannot be a DO CONCURRENT loop at %L",
13460 : &do_code->loc);
13461 3 : break;
13462 : }
13463 5779 : gcc_assert (do_code->op == EXEC_DO);
13464 5779 : if (do_code->ext.iterator->var->ts.type != BT_INTEGER)
13465 6 : gfc_error ("!$ACC LOOP iteration variable must be of type integer at %L",
13466 : &do_code->loc);
13467 5779 : dovar = do_code->ext.iterator->var->symtree->n.sym;
13468 5779 : if (i > 1)
13469 : {
13470 518 : gfc_code *do_code2 = code->block->next;
13471 518 : int j;
13472 :
13473 1218 : for (j = 1; j < i; j++)
13474 : {
13475 710 : gfc_symbol *ivar = do_code2->ext.iterator->var->symtree->n.sym;
13476 710 : if (dovar == ivar
13477 710 : || gfc_find_sym_in_expr (ivar, do_code->ext.iterator->start)
13478 701 : || gfc_find_sym_in_expr (ivar, do_code->ext.iterator->end)
13479 1410 : || gfc_find_sym_in_expr (ivar, do_code->ext.iterator->step))
13480 : {
13481 10 : gfc_error ("!$ACC LOOP %s loops don't form rectangular "
13482 : "iteration space at %L", clause, &do_code->loc);
13483 10 : break;
13484 : }
13485 700 : do_code2 = do_code2->block->next;
13486 : }
13487 : }
13488 5779 : if (i == collapse)
13489 : break;
13490 577 : for (c = do_code->next; c; c = c->next)
13491 48 : if (c->op != EXEC_NOP && c->op != EXEC_CONTINUE)
13492 : {
13493 0 : gfc_error ("%s !$ACC LOOP loops not perfectly nested at %L",
13494 : clause, &c->loc);
13495 0 : break;
13496 : }
13497 529 : if (c)
13498 : break;
13499 529 : do_code = do_code->block;
13500 529 : if (do_code->op != EXEC_DO && do_code->op != EXEC_DO_WHILE
13501 0 : && do_code->op != EXEC_DO_CONCURRENT)
13502 : {
13503 0 : gfc_error ("not enough DO loops for %s !$ACC LOOP at %L",
13504 : clause, &code->loc);
13505 0 : break;
13506 : }
13507 529 : do_code = do_code->next;
13508 529 : if (do_code == NULL
13509 522 : || (do_code->op != EXEC_DO && do_code->op != EXEC_DO_WHILE
13510 2 : && do_code->op != EXEC_DO_CONCURRENT))
13511 : {
13512 9 : gfc_error ("not enough DO loops for %s !$ACC LOOP at %L",
13513 : clause, &code->loc);
13514 9 : break;
13515 : }
13516 : }
13517 5272 : }
13518 :
13519 :
13520 : static void
13521 10119 : resolve_oacc_loop_blocks (gfc_code *code)
13522 : {
13523 10119 : if (!oacc_is_loop (code))
13524 : return;
13525 :
13526 5272 : if (code->ext.omp_clauses->tile_list && code->ext.omp_clauses->gang
13527 24 : && code->ext.omp_clauses->worker && code->ext.omp_clauses->vector)
13528 0 : gfc_error ("Tiled loop cannot be parallelized across gangs, workers and "
13529 : "vectors at the same time at %L", &code->loc);
13530 :
13531 5272 : if (code->ext.omp_clauses->tile_list)
13532 : {
13533 : gfc_expr_list *el;
13534 501 : for (el = code->ext.omp_clauses->tile_list; el; el = el->next)
13535 : {
13536 304 : if (el->expr == NULL)
13537 : {
13538 : /* NULL expressions are used to represent '*' arguments.
13539 : Convert those to a 0 expressions. */
13540 113 : el->expr = gfc_get_constant_expr (BT_INTEGER,
13541 : gfc_default_integer_kind,
13542 : &code->loc);
13543 113 : mpz_set_si (el->expr->value.integer, 0);
13544 : }
13545 : else
13546 : {
13547 191 : resolve_positive_int_expr (el->expr, "TILE");
13548 191 : if (el->expr->expr_type != EXPR_CONSTANT)
13549 14 : gfc_error ("TILE requires constant expression at %L",
13550 : &code->loc);
13551 : }
13552 : }
13553 : }
13554 : }
13555 :
13556 :
13557 : void
13558 10119 : gfc_resolve_oacc_blocks (gfc_code *code, gfc_namespace *ns)
13559 : {
13560 10119 : fortran_omp_context ctx;
13561 10119 : gfc_omp_clauses *omp_clauses = code->ext.omp_clauses;
13562 10119 : gfc_omp_namelist *n;
13563 :
13564 10119 : resolve_oacc_loop_blocks (code);
13565 :
13566 10119 : ctx.code = code;
13567 10119 : ctx.sharing_clauses = new hash_set<gfc_symbol *>;
13568 10119 : ctx.private_iterators = new hash_set<gfc_symbol *>;
13569 10119 : ctx.previous = omp_current_ctx;
13570 10119 : ctx.is_openmp = false;
13571 10119 : omp_current_ctx = &ctx;
13572 :
13573 404760 : for (enum gfc_omp_list_type list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
13574 394641 : list = gfc_omp_list_type (list + 1))
13575 394641 : switch (list)
13576 : {
13577 10119 : case OMP_LIST_PRIVATE:
13578 10710 : for (n = omp_clauses->lists[list]; n; n = n->next)
13579 591 : ctx.sharing_clauses->add (n->sym);
13580 : break;
13581 : default:
13582 : break;
13583 : }
13584 :
13585 10119 : gfc_resolve_blocks (code->block, ns);
13586 :
13587 10119 : omp_current_ctx = ctx.previous;
13588 20238 : delete ctx.sharing_clauses;
13589 20238 : delete ctx.private_iterators;
13590 10119 : }
13591 :
13592 :
13593 : static void
13594 5272 : resolve_oacc_loop (gfc_code *code)
13595 : {
13596 5272 : gfc_code *do_code;
13597 5272 : int collapse;
13598 :
13599 5272 : if (code->ext.omp_clauses)
13600 5272 : resolve_omp_clauses (code, code->ext.omp_clauses, NULL, true);
13601 :
13602 5272 : do_code = code->block->next;
13603 5272 : collapse = code->ext.omp_clauses->collapse;
13604 :
13605 : /* Both collapsed and tiled loops are lowered the same way, but are not
13606 : compatible. In gfc_trans_omp_do, the tile is prioritized. */
13607 5272 : if (code->ext.omp_clauses->tile_list)
13608 : {
13609 : int num = 0;
13610 : gfc_expr_list *el;
13611 501 : for (el = code->ext.omp_clauses->tile_list; el; el = el->next)
13612 304 : ++num;
13613 197 : resolve_oacc_nested_loops (code, code->block->next, num, "tiled");
13614 197 : return;
13615 : }
13616 :
13617 5075 : if (collapse <= 0)
13618 : collapse = 1;
13619 5075 : resolve_oacc_nested_loops (code, do_code, collapse, "collapsed");
13620 : }
13621 :
13622 : void
13623 341841 : gfc_resolve_oacc_declare (gfc_namespace *ns)
13624 : {
13625 341841 : enum gfc_omp_list_type list;
13626 341841 : gfc_omp_namelist *n;
13627 341841 : gfc_oacc_declare *oc;
13628 :
13629 341841 : if (ns->oacc_declare == NULL)
13630 : return;
13631 :
13632 290 : for (oc = ns->oacc_declare; oc; oc = oc->next)
13633 : {
13634 6480 : for (list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
13635 6318 : list = gfc_omp_list_type (list + 1))
13636 6574 : for (n = oc->clauses->lists[list]; n; n = n->next)
13637 : {
13638 256 : n->sym->mark = 0;
13639 256 : if (n->sym->attr.flavor != FL_VARIABLE
13640 16 : && (n->sym->attr.flavor != FL_PROCEDURE
13641 8 : || n->sym->result != n->sym))
13642 : {
13643 14 : if (n->sym->attr.flavor != FL_PARAMETER)
13644 : {
13645 8 : gfc_error ("Object %qs is not a variable at %L",
13646 : n->sym->name, &oc->loc);
13647 8 : continue;
13648 : }
13649 : /* Note that OpenACC 3.4 permits name constants, but the
13650 : implementation is permitted to ignore the clause;
13651 : as semantically, device_resident kind of makes sense
13652 : (and the wording with it is a bit odd), the warning
13653 : is suppressed. */
13654 6 : if (list != OMP_LIST_DEVICE_RESIDENT)
13655 5 : gfc_warning (OPT_Wsurprising, "Object %qs at %L is ignored as"
13656 : " parameters need not be copied", n->sym->name,
13657 : &oc->loc);
13658 : }
13659 :
13660 248 : if (n->expr && n->expr->ref->type == REF_ARRAY)
13661 : {
13662 1 : gfc_error ("Array sections: %qs not allowed in"
13663 1 : " !$ACC DECLARE at %L", n->sym->name, &oc->loc);
13664 1 : continue;
13665 : }
13666 : }
13667 :
13668 252 : for (n = oc->clauses->lists[OMP_LIST_DEVICE_RESIDENT]; n; n = n->next)
13669 90 : check_array_not_assumed (n->sym, oc->loc, "DEVICE_RESIDENT");
13670 : }
13671 :
13672 290 : for (oc = ns->oacc_declare; oc; oc = oc->next)
13673 : {
13674 6480 : for (list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
13675 6318 : list = gfc_omp_list_type (list + 1))
13676 6574 : for (n = oc->clauses->lists[list]; n; n = n->next)
13677 : {
13678 256 : if (n->sym->mark)
13679 : {
13680 9 : gfc_error ("Symbol %qs present on multiple clauses at %L",
13681 : n->sym->name, &oc->loc);
13682 9 : continue;
13683 : }
13684 : else
13685 247 : n->sym->mark = 1;
13686 : }
13687 : }
13688 :
13689 290 : for (oc = ns->oacc_declare; oc; oc = oc->next)
13690 : {
13691 6480 : for (list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
13692 6318 : list = gfc_omp_list_type (list + 1))
13693 6574 : for (n = oc->clauses->lists[list]; n; n = n->next)
13694 256 : n->sym->mark = 0;
13695 : }
13696 : }
13697 :
13698 :
13699 : void
13700 341841 : gfc_resolve_oacc_routines (gfc_namespace *ns)
13701 : {
13702 341841 : for (gfc_oacc_routine_name *orn = ns->oacc_routine_names;
13703 341941 : orn;
13704 100 : orn = orn->next)
13705 : {
13706 100 : gfc_symbol *sym = orn->sym;
13707 100 : if (!sym->attr.external
13708 29 : && !sym->attr.function
13709 27 : && !sym->attr.subroutine)
13710 : {
13711 7 : gfc_error ("NAME %qs does not refer to a subroutine or function"
13712 : " in !$ACC ROUTINE ( NAME ) at %L", sym->name, &orn->loc);
13713 7 : continue;
13714 : }
13715 93 : if (!gfc_add_omp_declare_target (&sym->attr, sym->name, &orn->loc))
13716 : {
13717 20 : gfc_error ("NAME %qs invalid"
13718 : " in !$ACC ROUTINE ( NAME ) at %L", sym->name, &orn->loc);
13719 20 : continue;
13720 : }
13721 : }
13722 341841 : }
13723 :
13724 :
13725 : void
13726 13168 : gfc_resolve_oacc_directive (gfc_code *code, gfc_namespace *ns ATTRIBUTE_UNUSED)
13727 : {
13728 13168 : resolve_oacc_directive_inside_omp_region (code);
13729 :
13730 13168 : switch (code->op)
13731 : {
13732 7353 : case EXEC_OACC_PARALLEL:
13733 7353 : case EXEC_OACC_KERNELS:
13734 7353 : case EXEC_OACC_SERIAL:
13735 7353 : case EXEC_OACC_DATA:
13736 7353 : case EXEC_OACC_HOST_DATA:
13737 7353 : case EXEC_OACC_UPDATE:
13738 7353 : case EXEC_OACC_ENTER_DATA:
13739 7353 : case EXEC_OACC_EXIT_DATA:
13740 7353 : case EXEC_OACC_WAIT:
13741 7353 : case EXEC_OACC_CACHE:
13742 7353 : resolve_omp_clauses (code, code->ext.omp_clauses, NULL, true);
13743 7353 : break;
13744 5272 : case EXEC_OACC_PARALLEL_LOOP:
13745 5272 : case EXEC_OACC_KERNELS_LOOP:
13746 5272 : case EXEC_OACC_SERIAL_LOOP:
13747 5272 : case EXEC_OACC_LOOP:
13748 5272 : resolve_oacc_loop (code);
13749 5272 : break;
13750 543 : case EXEC_OACC_ATOMIC:
13751 543 : resolve_omp_atomic (code);
13752 543 : break;
13753 : default:
13754 : break;
13755 : }
13756 13168 : }
13757 :
13758 :
13759 : static void
13760 2179 : resolve_omp_target (gfc_code *code)
13761 : {
13762 : #define GFC_IS_TEAMS_CONSTRUCT(op) \
13763 : (op == EXEC_OMP_TEAMS \
13764 : || op == EXEC_OMP_TEAMS_DISTRIBUTE \
13765 : || op == EXEC_OMP_TEAMS_DISTRIBUTE_SIMD \
13766 : || op == EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO \
13767 : || op == EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD \
13768 : || op == EXEC_OMP_TEAMS_LOOP)
13769 :
13770 2179 : if (!code->ext.omp_clauses->contains_teams_construct)
13771 : return;
13772 203 : gfc_code *c = code->block->next;
13773 203 : if (c->op == EXEC_BLOCK)
13774 30 : c = c->ext.block.ns->code;
13775 203 : if (code->ext.omp_clauses->target_first_st_is_teams_or_meta)
13776 : {
13777 192 : if (c->op == EXEC_OMP_METADIRECTIVE)
13778 : {
13779 15 : struct gfc_omp_variant *mc
13780 : = c->ext.omp_variants;
13781 : /* All mc->(next...->)code should be identical with regards
13782 : to the diagnostic below. */
13783 16 : do
13784 : {
13785 16 : if (mc->stmt != ST_NONE
13786 15 : && GFC_IS_TEAMS_CONSTRUCT (mc->code->op))
13787 : {
13788 14 : if (c->next == NULL && mc->code->next == NULL)
13789 : return;
13790 : c = mc->code;
13791 : break;
13792 : }
13793 2 : mc = mc->next;
13794 : }
13795 2 : while (mc);
13796 : }
13797 177 : else if (GFC_IS_TEAMS_CONSTRUCT (c->op) && c->next == NULL)
13798 : return;
13799 : }
13800 :
13801 31 : while (c && !GFC_IS_TEAMS_CONSTRUCT (c->op))
13802 8 : c = c->next;
13803 23 : if (c)
13804 19 : gfc_error ("!$OMP TARGET region at %L with a nested TEAMS at %L may not "
13805 : "contain any other statement, declaration or directive outside "
13806 : "of the single TEAMS construct", &c->loc, &code->loc);
13807 : else
13808 4 : gfc_error ("!$OMP TARGET region at %L with a nested TEAMS may not "
13809 : "contain any other statement, declaration or directive outside "
13810 : "of the single TEAMS construct", &code->loc);
13811 : #undef GFC_IS_TEAMS_CONSTRUCT
13812 : }
13813 :
13814 : static void
13815 154 : resolve_omp_dispatch (gfc_code *code)
13816 : {
13817 154 : gfc_code *next = code->block->next;
13818 154 : if (next == NULL)
13819 : return;
13820 :
13821 151 : gfc_exec_op op = next->op;
13822 151 : gcc_assert (op == EXEC_CALL || op == EXEC_ASSIGN);
13823 151 : if (op != EXEC_CALL
13824 74 : && (op != EXEC_ASSIGN || next->expr2->expr_type != EXPR_FUNCTION))
13825 3 : gfc_error (
13826 : "%<OMP DISPATCH%> directive at %L must be followed by a procedure "
13827 : "call with optional assignment",
13828 : &code->loc);
13829 :
13830 77 : if ((op == EXEC_CALL && next->resolved_sym != NULL
13831 76 : && next->resolved_sym->attr.proc_pointer)
13832 150 : || (op == EXEC_ASSIGN && gfc_expr_attr (next->expr2).proc_pointer))
13833 1 : gfc_error ("%<OMP DISPATCH%> directive at %L cannot be followed by a "
13834 : "procedure pointer",
13835 : &code->loc);
13836 : }
13837 :
13838 : /* Resolve OpenMP directive clauses and check various requirements
13839 : of each directive. */
13840 :
13841 : void
13842 21194 : gfc_resolve_omp_directive (gfc_code *code, gfc_namespace *ns)
13843 : {
13844 21194 : resolve_omp_directive_inside_oacc_region (code);
13845 :
13846 21194 : if (code->op != EXEC_OMP_ATOMIC)
13847 19040 : gfc_maybe_initialize_eh ();
13848 :
13849 21194 : switch (code->op)
13850 : {
13851 5425 : case EXEC_OMP_DISTRIBUTE:
13852 5425 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
13853 5425 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
13854 5425 : case EXEC_OMP_DISTRIBUTE_SIMD:
13855 5425 : case EXEC_OMP_DO:
13856 5425 : case EXEC_OMP_DO_SIMD:
13857 5425 : case EXEC_OMP_LOOP:
13858 5425 : case EXEC_OMP_PARALLEL_DO:
13859 5425 : case EXEC_OMP_PARALLEL_DO_SIMD:
13860 5425 : case EXEC_OMP_PARALLEL_LOOP:
13861 5425 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
13862 5425 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
13863 5425 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
13864 5425 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
13865 5425 : case EXEC_OMP_MASKED_TASKLOOP:
13866 5425 : case EXEC_OMP_MASKED_TASKLOOP_SIMD:
13867 5425 : case EXEC_OMP_MASTER_TASKLOOP:
13868 5425 : case EXEC_OMP_MASTER_TASKLOOP_SIMD:
13869 5425 : case EXEC_OMP_SIMD:
13870 5425 : case EXEC_OMP_TARGET_PARALLEL_DO:
13871 5425 : case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
13872 5425 : case EXEC_OMP_TARGET_PARALLEL_LOOP:
13873 5425 : case EXEC_OMP_TARGET_SIMD:
13874 5425 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
13875 5425 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
13876 5425 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
13877 5425 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
13878 5425 : case EXEC_OMP_TARGET_TEAMS_LOOP:
13879 5425 : case EXEC_OMP_TASKLOOP:
13880 5425 : case EXEC_OMP_TASKLOOP_SIMD:
13881 5425 : case EXEC_OMP_TEAMS_DISTRIBUTE:
13882 5425 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
13883 5425 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
13884 5425 : case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
13885 5425 : case EXEC_OMP_TEAMS_LOOP:
13886 5425 : case EXEC_OMP_TILE:
13887 5425 : case EXEC_OMP_UNROLL:
13888 5425 : resolve_omp_do (code);
13889 5425 : break;
13890 2179 : case EXEC_OMP_TARGET:
13891 2179 : resolve_omp_target (code);
13892 10228 : gcc_fallthrough ();
13893 10228 : case EXEC_OMP_ALLOCATE:
13894 10228 : case EXEC_OMP_ALLOCATORS:
13895 10228 : case EXEC_OMP_ASSUME:
13896 10228 : case EXEC_OMP_CANCEL:
13897 10228 : case EXEC_OMP_ERROR:
13898 10228 : case EXEC_OMP_INTEROP:
13899 10228 : case EXEC_OMP_MASKED:
13900 10228 : case EXEC_OMP_ORDERED:
13901 10228 : case EXEC_OMP_PARALLEL_WORKSHARE:
13902 10228 : case EXEC_OMP_PARALLEL:
13903 10228 : case EXEC_OMP_PARALLEL_MASKED:
13904 10228 : case EXEC_OMP_PARALLEL_MASTER:
13905 10228 : case EXEC_OMP_PARALLEL_SECTIONS:
13906 10228 : case EXEC_OMP_SCOPE:
13907 10228 : case EXEC_OMP_SECTIONS:
13908 10228 : case EXEC_OMP_SINGLE:
13909 10228 : case EXEC_OMP_TARGET_DATA:
13910 10228 : case EXEC_OMP_TARGET_ENTER_DATA:
13911 10228 : case EXEC_OMP_TARGET_EXIT_DATA:
13912 10228 : case EXEC_OMP_TARGET_PARALLEL:
13913 10228 : case EXEC_OMP_TARGET_TEAMS:
13914 10228 : case EXEC_OMP_TASK:
13915 10228 : case EXEC_OMP_TASKWAIT:
13916 10228 : case EXEC_OMP_TEAMS:
13917 10228 : case EXEC_OMP_WORKSHARE:
13918 10228 : case EXEC_OMP_DEPOBJ:
13919 10228 : if (code->ext.omp_clauses)
13920 10095 : resolve_omp_clauses (code, code->ext.omp_clauses, NULL);
13921 : break;
13922 1718 : case EXEC_OMP_TARGET_UPDATE:
13923 1718 : if (code->ext.omp_clauses)
13924 1718 : resolve_omp_clauses (code, code->ext.omp_clauses, NULL);
13925 1718 : if (code->ext.omp_clauses == NULL
13926 1718 : || (code->ext.omp_clauses->lists[OMP_LIST_TO] == NULL
13927 994 : && code->ext.omp_clauses->lists[OMP_LIST_FROM] == NULL))
13928 0 : gfc_error ("OMP TARGET UPDATE at %L requires at least one TO or "
13929 : "FROM clause", &code->loc);
13930 : break;
13931 2154 : case EXEC_OMP_ATOMIC:
13932 2154 : resolve_omp_clauses (code, code->block->ext.omp_clauses, NULL);
13933 2154 : resolve_omp_atomic (code);
13934 2154 : break;
13935 159 : case EXEC_OMP_CRITICAL:
13936 159 : resolve_omp_clauses (code, code->ext.omp_clauses, NULL);
13937 159 : if (!code->ext.omp_clauses->critical_name
13938 112 : && code->ext.omp_clauses->hint
13939 3 : && code->ext.omp_clauses->hint->ts.type == BT_INTEGER
13940 3 : && code->ext.omp_clauses->hint->expr_type == EXPR_CONSTANT
13941 3 : && mpz_sgn (code->ext.omp_clauses->hint->value.integer) != 0)
13942 1 : gfc_error ("OMP CRITICAL at %L with HINT clause requires a NAME, "
13943 : "except when omp_sync_hint_none is used", &code->loc);
13944 : break;
13945 49 : case EXEC_OMP_SCAN:
13946 : /* Flag is only used to checking, hence, it is unset afterwards. */
13947 49 : if (!code->ext.omp_clauses->if_present)
13948 10 : gfc_error ("Unexpected !$OMP SCAN at %L outside loop construct with "
13949 : "%<inscan%> REDUCTION clause", &code->loc);
13950 49 : code->ext.omp_clauses->if_present = false;
13951 49 : resolve_omp_clauses (code, code->ext.omp_clauses, ns);
13952 49 : break;
13953 154 : case EXEC_OMP_DISPATCH:
13954 154 : if (code->ext.omp_clauses)
13955 154 : resolve_omp_clauses (code, code->ext.omp_clauses, ns);
13956 154 : resolve_omp_dispatch (code);
13957 154 : break;
13958 138 : case EXEC_OMP_METADIRECTIVE:
13959 138 : resolve_omp_metadirective (code, ns);
13960 138 : break;
13961 : default:
13962 : break;
13963 : }
13964 21194 : }
13965 :
13966 : /* Resolve !$omp declare {variant|simd} constructs in NS.
13967 : Note that !$omp declare target is resolved in resolve_symbol. */
13968 :
13969 : void
13970 353613 : gfc_resolve_omp_declare (gfc_namespace *ns)
13971 : {
13972 353613 : gfc_omp_declare_simd *ods;
13973 353849 : for (ods = ns->omp_declare_simd; ods; ods = ods->next)
13974 : {
13975 236 : if (ods->proc_name != NULL
13976 196 : && ods->proc_name != ns->proc_name)
13977 6 : gfc_error ("!$OMP DECLARE SIMD should refer to containing procedure "
13978 : "%qs at %L", ns->proc_name->name, &ods->where);
13979 236 : if (ods->clauses)
13980 218 : resolve_omp_clauses (NULL, ods->clauses, ns);
13981 : }
13982 :
13983 353613 : gfc_omp_declare_variant *odv;
13984 353613 : gfc_omp_namelist *range_begin = NULL;
13985 :
13986 354061 : for (odv = ns->omp_declare_variant; odv; odv = odv->next)
13987 448 : gfc_resolve_omp_context_selector (odv->set_selectors, false, nullptr);
13988 354061 : for (odv = ns->omp_declare_variant; odv; odv = odv->next)
13989 627 : for (gfc_omp_namelist *n = odv->adjust_args_list; n != NULL; n = n->next)
13990 : {
13991 179 : if ((n->expr == NULL
13992 6 : && (range_begin
13993 4 : || n->u.adj_args.range_start
13994 1 : || n->u.adj_args.omp_num_args_plus
13995 1 : || n->u.adj_args.omp_num_args_minus))
13996 174 : || n->u.adj_args.error_p)
13997 : {
13998 : }
13999 173 : else if (range_begin
14000 167 : || n->u.adj_args.range_start
14001 162 : || n->u.adj_args.omp_num_args_plus
14002 162 : || n->u.adj_args.omp_num_args_minus)
14003 : {
14004 11 : if (!n->expr
14005 11 : || !gfc_resolve_expr (n->expr)
14006 11 : || n->expr->expr_type != EXPR_CONSTANT
14007 10 : || n->expr->ts.type != BT_INTEGER
14008 10 : || n->expr->rank != 0
14009 10 : || mpz_sgn (n->expr->value.integer) < 0
14010 20 : || ((n->u.adj_args.omp_num_args_plus
14011 8 : || n->u.adj_args.omp_num_args_minus)
14012 5 : && mpz_sgn (n->expr->value.integer) == 0))
14013 : {
14014 2 : if (n->u.adj_args.omp_num_args_plus
14015 2 : || n->u.adj_args.omp_num_args_minus)
14016 0 : gfc_error ("Expected constant non-negative scalar integer "
14017 : "offset expression at %L", &n->where);
14018 : else
14019 2 : gfc_error ("For range-based %<adjust_args%>, a constant "
14020 : "positive scalar integer expression is required "
14021 : "at %L", &n->where);
14022 : }
14023 : }
14024 162 : else if (n->expr
14025 162 : && n->expr->expr_type == EXPR_CONSTANT
14026 21 : && n->expr->ts.type == BT_INTEGER
14027 20 : && mpz_sgn (n->expr->value.integer) > 0)
14028 : {
14029 : }
14030 142 : else if (!n->expr
14031 142 : || !gfc_resolve_expr (n->expr)
14032 283 : || n->expr->expr_type != EXPR_VARIABLE)
14033 2 : gfc_error ("Expected dummy parameter name or a positive integer "
14034 : "at %L", &n->where);
14035 140 : else if (n->expr->expr_type == EXPR_VARIABLE)
14036 140 : n->sym = n->expr->symtree->n.sym;
14037 :
14038 179 : range_begin = n->u.adj_args.range_start ? n : NULL;
14039 : }
14040 353613 : }
14041 :
14042 : struct omp_udr_callback_data
14043 : {
14044 : gfc_omp_udr *omp_udr;
14045 : bool is_initializer;
14046 : };
14047 :
14048 : static int
14049 3706 : omp_udr_callback (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
14050 : void *data)
14051 : {
14052 3706 : struct omp_udr_callback_data *cd = (struct omp_udr_callback_data *) data;
14053 3706 : if ((*e)->expr_type == EXPR_VARIABLE)
14054 : {
14055 2276 : if (cd->is_initializer)
14056 : {
14057 539 : if ((*e)->symtree->n.sym != cd->omp_udr->omp_priv
14058 140 : && (*e)->symtree->n.sym != cd->omp_udr->omp_orig)
14059 4 : gfc_error ("Variable other than OMP_PRIV or OMP_ORIG used in "
14060 : "INITIALIZER clause of !$OMP DECLARE REDUCTION at %L",
14061 : &(*e)->where);
14062 : }
14063 : else
14064 : {
14065 1737 : if ((*e)->symtree->n.sym != cd->omp_udr->omp_out
14066 619 : && (*e)->symtree->n.sym != cd->omp_udr->omp_in)
14067 6 : gfc_error ("Variable other than OMP_OUT or OMP_IN used in "
14068 : "combiner of !$OMP DECLARE REDUCTION at %L",
14069 : &(*e)->where);
14070 : }
14071 : }
14072 3706 : return 0;
14073 : }
14074 :
14075 : /* Resolve !$omp declare reduction constructs. */
14076 :
14077 : static void
14078 626 : gfc_resolve_omp_udr (gfc_omp_udr *omp_udr)
14079 : {
14080 626 : gfc_actual_arglist *a;
14081 626 : const char *predef_name = NULL;
14082 :
14083 626 : switch (omp_udr->rop)
14084 : {
14085 625 : case OMP_REDUCTION_PLUS:
14086 625 : case OMP_REDUCTION_TIMES:
14087 625 : case OMP_REDUCTION_MINUS:
14088 625 : case OMP_REDUCTION_AND:
14089 625 : case OMP_REDUCTION_OR:
14090 625 : case OMP_REDUCTION_EQV:
14091 625 : case OMP_REDUCTION_NEQV:
14092 625 : case OMP_REDUCTION_MAX:
14093 625 : case OMP_REDUCTION_USER:
14094 625 : break;
14095 1 : default:
14096 1 : gfc_error ("Invalid operator for !$OMP DECLARE REDUCTION %s at %L",
14097 : omp_udr->name, &omp_udr->where);
14098 26 : return;
14099 : }
14100 :
14101 625 : if (gfc_omp_udr_predef (omp_udr->rop, omp_udr->name,
14102 : &omp_udr->ts, &predef_name))
14103 : {
14104 19 : if (predef_name)
14105 19 : gfc_error ("Redefinition of predefined %qs in "
14106 : "!$OMP DECLARE REDUCTION at %L",
14107 : predef_name, &omp_udr->where);
14108 : else
14109 0 : gfc_error ("Redefinition of predefined %qs in "
14110 : "!$OMP DECLARE REDUCTION at %L", omp_udr->name,
14111 : &omp_udr->where);
14112 19 : return;
14113 : }
14114 :
14115 606 : if (omp_udr->ts.type == BT_CHARACTER
14116 62 : && omp_udr->ts.u.cl->length
14117 32 : && omp_udr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
14118 : {
14119 1 : gfc_error ("CHARACTER length in !$OMP DECLARE REDUCTION %qs not "
14120 : "constant at %L", omp_udr->name, &omp_udr->where);
14121 1 : return;
14122 : }
14123 :
14124 605 : struct omp_udr_callback_data cd;
14125 605 : cd.omp_udr = omp_udr;
14126 605 : cd.is_initializer = false;
14127 605 : gfc_code_walker (&omp_udr->combiner_ns->code, gfc_dummy_code_callback,
14128 : omp_udr_callback, &cd);
14129 605 : if (omp_udr->combiner_ns->code->op == EXEC_CALL)
14130 : {
14131 346 : for (a = omp_udr->combiner_ns->code->ext.actual; a; a = a->next)
14132 237 : if (a->expr == NULL)
14133 : break;
14134 110 : if (a)
14135 1 : gfc_error ("Subroutine call with alternate returns in combiner "
14136 : "of !$OMP DECLARE REDUCTION at %L",
14137 : &omp_udr->combiner_ns->code->loc);
14138 : }
14139 605 : if (omp_udr->initializer_ns)
14140 : {
14141 377 : cd.is_initializer = true;
14142 377 : gfc_code_walker (&omp_udr->initializer_ns->code, gfc_dummy_code_callback,
14143 : omp_udr_callback, &cd);
14144 377 : if (omp_udr->initializer_ns->code->op == EXEC_CALL)
14145 : {
14146 377 : for (a = omp_udr->initializer_ns->code->ext.actual; a; a = a->next)
14147 243 : if (a->expr == NULL)
14148 : break;
14149 135 : if (a)
14150 1 : gfc_error ("Subroutine call with alternate returns in "
14151 : "INITIALIZER clause of !$OMP DECLARE REDUCTION "
14152 : "at %L", &omp_udr->initializer_ns->code->loc);
14153 136 : for (a = omp_udr->initializer_ns->code->ext.actual; a; a = a->next)
14154 135 : if (a->expr
14155 135 : && a->expr->expr_type == EXPR_VARIABLE
14156 135 : && a->expr->symtree->n.sym == omp_udr->omp_priv
14157 134 : && a->expr->ref == NULL)
14158 : break;
14159 135 : if (a == NULL)
14160 1 : gfc_error ("One of actual subroutine arguments in INITIALIZER "
14161 : "clause of !$OMP DECLARE REDUCTION must be OMP_PRIV "
14162 : "at %L", &omp_udr->initializer_ns->code->loc);
14163 : }
14164 : }
14165 228 : else if (omp_udr->ts.type == BT_DERIVED
14166 228 : && !gfc_has_default_initializer (omp_udr->ts.u.derived))
14167 : {
14168 4 : gfc_error ("Missing INITIALIZER clause for !$OMP DECLARE REDUCTION "
14169 : "of derived type without default initializer at %L",
14170 : &omp_udr->where);
14171 4 : return;
14172 : }
14173 : }
14174 :
14175 : void
14176 354667 : gfc_resolve_omp_udrs (gfc_symtree *st)
14177 : {
14178 354667 : gfc_omp_udr *omp_udr;
14179 :
14180 354667 : if (st == NULL)
14181 : return;
14182 527 : gfc_resolve_omp_udrs (st->left);
14183 527 : gfc_resolve_omp_udrs (st->right);
14184 1153 : for (omp_udr = st->n.omp_udr; omp_udr; omp_udr = omp_udr->next)
14185 626 : gfc_resolve_omp_udr (omp_udr);
14186 : }
14187 :
14188 : /* Resolve !$omp declare mapper constructs. */
14189 :
14190 : static void
14191 23 : gfc_resolve_omp_udm (gfc_omp_udm *omp_udm)
14192 : {
14193 23 : resolve_omp_clauses (NULL, omp_udm->clauses, omp_udm->mapper_ns);
14194 :
14195 23 : gfc_omp_namelist *n;
14196 25 : for (n = omp_udm->clauses->lists[OMP_LIST_MAP]; n; n = n->next)
14197 23 : if (n->sym == omp_udm->var_sym)
14198 : break;
14199 23 : if (!n)
14200 2 : gfc_error ("At least one %<map%> clause in !$OMP DECLARE MAPPER at %L must "
14201 : "map %qs or an element of it",
14202 2 : &omp_udm->where, omp_udm->var_sym->name);
14203 23 : }
14204 :
14205 : void
14206 353657 : gfc_resolve_omp_udms (gfc_symtree *st)
14207 : {
14208 353657 : gfc_omp_udm *omp_udm;
14209 :
14210 353657 : if (st == NULL)
14211 : return;
14212 22 : gfc_resolve_omp_udms (st->left);
14213 22 : gfc_resolve_omp_udms (st->right);
14214 45 : for (omp_udm = st->n.omp_udm; omp_udm; omp_udm = omp_udm->next)
14215 23 : gfc_resolve_omp_udm (omp_udm);
14216 : }
|