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 55276 : gfc_match_omp_eos (void)
135 : {
136 55276 : locus old_loc;
137 55276 : char c;
138 :
139 55276 : old_loc = gfc_current_locus;
140 55276 : gfc_gobble_whitespace ();
141 :
142 55276 : if (gfc_matching_omp_context_selector)
143 : {
144 269 : if (gfc_peek_ascii_char () == ')')
145 : return MATCH_YES;
146 : }
147 : else
148 : {
149 55007 : c = gfc_next_ascii_char ();
150 55007 : 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 53298 : case '\n':
159 53298 : return MATCH_YES;
160 : }
161 : }
162 :
163 1710 : gfc_current_locus = old_loc;
164 1710 : return MATCH_NO;
165 : }
166 :
167 : match
168 13157 : gfc_match_omp_eos_error (void)
169 : {
170 13157 : 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 61384 : gfc_free_omp_clauses (gfc_omp_clauses *c)
182 : {
183 61384 : if (c == NULL)
184 : return;
185 :
186 34555 : gfc_free_expr (c->if_expr);
187 380105 : for (int i = 0; i < OMP_IF_LAST; i++)
188 345550 : gfc_free_expr (c->if_exprs[i]);
189 34555 : gfc_free_expr (c->self_expr);
190 34555 : gfc_free_expr (c->final_expr);
191 34555 : gfc_free_expr (c->num_threads);
192 34555 : gfc_free_expr (c->chunk_size);
193 34555 : gfc_free_expr (c->safelen_expr);
194 34555 : gfc_free_expr (c->simdlen_expr);
195 34555 : gfc_free_expr (c->num_teams_lower);
196 34555 : gfc_free_expr (c->num_teams_upper);
197 34555 : gfc_free_expr (c->device);
198 34555 : gfc_free_expr (c->dyn_groupprivate);
199 34555 : gfc_free_expr (c->thread_limit);
200 34555 : gfc_free_expr (c->dist_chunk_size);
201 34555 : gfc_free_expr (c->grainsize);
202 34555 : gfc_free_expr (c->hint);
203 34555 : gfc_free_expr (c->num_tasks);
204 34555 : gfc_free_expr (c->priority);
205 34555 : gfc_free_expr (c->detach);
206 34555 : gfc_free_expr (c->novariants);
207 34555 : gfc_free_expr (c->nocontext);
208 34555 : gfc_free_expr (c->async_expr);
209 34555 : gfc_free_expr (c->gang_num_expr);
210 34555 : gfc_free_expr (c->gang_static_expr);
211 34555 : gfc_free_expr (c->worker_expr);
212 34555 : gfc_free_expr (c->vector_expr);
213 34555 : gfc_free_expr (c->num_gangs_expr);
214 34555 : gfc_free_expr (c->num_workers_expr);
215 34555 : gfc_free_expr (c->vector_length_expr);
216 1382200 : for (enum gfc_omp_list_type t = OMP_LIST_FIRST; t < OMP_LIST_NUM;
217 1347645 : t = gfc_omp_list_type (t + 1))
218 1347645 : gfc_free_omp_namelist (c->lists[t], t);
219 34555 : gfc_free_expr_list (c->wait_list);
220 34555 : gfc_free_expr_list (c->tile_list);
221 34555 : gfc_free_expr_list (c->sizes_list);
222 34555 : free (const_cast<char *> (c->critical_name));
223 34555 : 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 34555 : 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 104612 : gfc_free_expr_list (gfc_expr_list *list)
255 : {
256 104612 : gfc_expr_list *n;
257 :
258 106015 : for (; list; list = n)
259 : {
260 1403 : n = list->next;
261 1403 : free (list);
262 : }
263 104612 : }
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 525405 : gfc_free_omp_declare_simd_list (gfc_omp_declare_simd *list)
279 : {
280 525641 : 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 525405 : }
287 :
288 : static void
289 727 : gfc_free_omp_trait_property_list (gfc_omp_trait_property *list)
290 : {
291 1134 : 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 727 : }
313 :
314 : static void
315 599 : gfc_free_omp_selector_list (gfc_omp_selector *list)
316 : {
317 1326 : while (list)
318 : {
319 727 : gfc_omp_selector *current = list;
320 727 : list = list->next;
321 727 : gfc_free_omp_trait_property_list (current->properties);
322 727 : free (current);
323 : }
324 599 : }
325 :
326 : static void
327 668 : gfc_free_omp_set_selector_list (gfc_omp_set_selector *list)
328 : {
329 1267 : while (list)
330 : {
331 599 : gfc_omp_set_selector *current = list;
332 599 : list = list->next;
333 599 : gfc_free_omp_selector_list (current->trait_selectors);
334 599 : free (current);
335 : }
336 668 : }
337 :
338 : /* Free an !$omp declare variant construct list. */
339 :
340 : void
341 525405 : gfc_free_omp_declare_variant_list (gfc_omp_declare_variant *list)
342 : {
343 525859 : while (list)
344 : {
345 454 : gfc_omp_declare_variant *current = list;
346 454 : list = list->next;
347 454 : gfc_free_omp_set_selector_list (current->set_selectors);
348 454 : gfc_free_omp_namelist (current->adjust_args_list, OMP_LIST_NONE);
349 454 : free (current);
350 : }
351 525405 : }
352 :
353 : /* Free an !$omp declare reduction. */
354 :
355 : void
356 1118 : gfc_free_omp_udr (gfc_omp_udr *omp_udr)
357 : {
358 1118 : if (omp_udr)
359 : {
360 607 : gfc_free_omp_udr (omp_udr->next);
361 607 : gfc_free_namespace (omp_udr->combiner_ns);
362 607 : if (omp_udr->initializer_ns)
363 377 : gfc_free_namespace (omp_udr->initializer_ns);
364 607 : free (omp_udr);
365 : }
366 1118 : }
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 13 : gfc_free_omp_udm (gfc_omp_udm *omp_udm)
386 : {
387 13 : if (omp_udm)
388 : {
389 6 : gfc_free_omp_udm (omp_udm->next);
390 6 : gfc_free_namespace (omp_udm->mapper_ns);
391 6 : free (omp_udm);
392 : }
393 13 : }
394 :
395 : static gfc_omp_udr *
396 4710 : gfc_find_omp_udr (gfc_namespace *ns, const char *name, gfc_typespec *ts)
397 : {
398 4710 : gfc_symtree *st;
399 :
400 4710 : if (ns == NULL)
401 467 : ns = gfc_current_ns;
402 5658 : do
403 : {
404 5658 : gfc_omp_udr *omp_udr;
405 :
406 5658 : st = gfc_find_symtree (ns->omp_udr_root, name);
407 5658 : if (st != NULL)
408 : {
409 934 : for (omp_udr = st->n.omp_udr; omp_udr; omp_udr = omp_udr->next)
410 934 : if (ts == NULL)
411 : return omp_udr;
412 567 : else if (gfc_compare_types (&omp_udr->ts, ts))
413 : {
414 479 : 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 443 : 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 31592 : 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 31592 : gfc_omp_namelist *head, *tail, *p;
457 31592 : locus old_loc, cur_loc;
458 31592 : char n[GFC_MAX_SYMBOL_LEN+1];
459 31592 : gfc_symbol *sym;
460 31592 : match m;
461 31592 : gfc_symtree *st;
462 :
463 31592 : head = tail = NULL;
464 :
465 31592 : old_loc = gfc_current_locus;
466 31592 : if (has_all_memory)
467 708 : *has_all_memory = false;
468 31592 : m = gfc_match (str);
469 31592 : if (m != MATCH_YES)
470 : return m;
471 :
472 38296 : for (;;)
473 : {
474 38296 : gfc_gobble_whitespace ();
475 38296 : cur_loc = gfc_current_locus;
476 :
477 38296 : m = gfc_match_name (n);
478 38296 : 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 38019 : if (m == MATCH_YES)
501 : {
502 38019 : gfc_symtree *st;
503 38019 : if ((m = gfc_get_ha_sym_tree (n, &st) ? MATCH_ERROR : MATCH_YES)
504 : == MATCH_YES)
505 38019 : sym = st->n.sym;
506 : }
507 38273 : switch (m)
508 : {
509 38019 : case MATCH_YES:
510 38019 : gfc_expr *expr;
511 38019 : expr = NULL;
512 38019 : gfc_gobble_whitespace ();
513 23399 : if ((allow_sections && gfc_peek_ascii_char () == '(')
514 57116 : || (allow_derived && gfc_peek_ascii_char () == '%'))
515 : {
516 6530 : gfc_current_locus = cur_loc;
517 6530 : m = gfc_match_variable (&expr, 0);
518 6530 : switch (m)
519 : {
520 4 : case MATCH_ERROR:
521 12 : goto cleanup;
522 0 : case MATCH_NO:
523 0 : goto syntax;
524 6526 : default:
525 6526 : break;
526 : }
527 6526 : 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 38010 : gfc_set_sym_referenced (sym);
535 38010 : p = gfc_get_omp_namelist ();
536 38010 : if (head == NULL)
537 : head = tail = p;
538 10113 : else if (reverse_order)
539 : {
540 57 : p->next = head;
541 57 : head = p;
542 : }
543 : else
544 : {
545 10056 : tail->next = p;
546 10056 : tail = tail->next;
547 : }
548 38010 : p->sym = sym;
549 38010 : p->expr = expr;
550 38010 : p->where = gfc_get_location_range (NULL, 0, &cur_loc, 1,
551 : &gfc_current_locus);
552 38010 : 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 specificed implicitly via the named "
557 : "common block", sym->name, &cur_loc,
558 3 : sym->common_head->name);
559 3 : goto cleanup;
560 : }
561 38007 : goto next_item;
562 254 : case MATCH_NO:
563 254 : break;
564 0 : case MATCH_ERROR:
565 0 : goto cleanup;
566 : }
567 :
568 254 : if (!allow_common)
569 10 : 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 38251 : if (end_colon && gfc_match_char (':') == MATCH_YES)
607 : {
608 793 : *end_colon = true;
609 793 : break;
610 : }
611 37458 : if (gfc_match_char (')') == MATCH_YES)
612 : break;
613 10182 : if (gfc_match_char (',') != MATCH_YES)
614 19 : goto syntax;
615 : }
616 :
617 38076 : while (*list)
618 10007 : list = &(*list)->next;
619 :
620 28069 : *list = head;
621 28069 : if (headp)
622 22200 : *headp = list;
623 : return MATCH_YES;
624 :
625 48 : syntax:
626 48 : gfc_error ("Syntax error in OpenMP variable list at %C");
627 :
628 64 : cleanup:
629 64 : gfc_free_omp_namelist (head, OMP_LIST_NONE);
630 64 : gfc_current_locus = old_loc;
631 64 : 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 362 : gfc_match_omp_to_link (const char *str, gfc_omp_namelist **list)
639 : {
640 362 : gfc_omp_namelist *head, *tail, *p;
641 362 : locus old_loc, cur_loc;
642 362 : char n[GFC_MAX_SYMBOL_LEN+1];
643 362 : gfc_symbol *sym;
644 362 : match m;
645 362 : gfc_symtree *st;
646 :
647 362 : head = tail = NULL;
648 :
649 362 : old_loc = gfc_current_locus;
650 :
651 362 : m = gfc_match (str);
652 362 : if (m != MATCH_YES)
653 : return m;
654 :
655 548 : for (;;)
656 : {
657 548 : cur_loc = gfc_current_locus;
658 548 : m = gfc_match_symbol (&sym, 1);
659 548 : switch (m)
660 : {
661 507 : case MATCH_YES:
662 507 : p = gfc_get_omp_namelist ();
663 507 : if (head == NULL)
664 : head = tail = p;
665 : else
666 : {
667 194 : tail->next = p;
668 194 : tail = tail->next;
669 : }
670 507 : tail->sym = sym;
671 507 : tail->where = cur_loc;
672 507 : 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 548 : next_item:
703 548 : if (gfc_match_char (')') == MATCH_YES)
704 : break;
705 198 : if (gfc_match_char (',') != MATCH_YES)
706 0 : goto syntax;
707 : }
708 :
709 361 : while (*list)
710 11 : list = &(*list)->next;
711 :
712 350 : *list = head;
713 350 : 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 819 : match_omp_oacc_expr_list (const char *str, gfc_expr_list **list,
838 : bool allow_asterisk, bool is_omp)
839 : {
840 819 : gfc_expr_list *head, *tail, *p;
841 819 : locus old_loc;
842 819 : gfc_expr *expr;
843 819 : match m;
844 :
845 819 : head = tail = NULL;
846 :
847 819 : old_loc = gfc_current_locus;
848 :
849 819 : m = gfc_match (str);
850 819 : 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 32195 : omp_mask::omp_mask (omp_mask1 m) : mask1 (((uint64_t) 1) << m), mask2 (0)
1229 : {
1230 : }
1231 :
1232 2206 : omp_mask::omp_mask (omp_mask2 m) : mask1 (0), mask2 (((uint64_t) 1) << m)
1233 : {
1234 : }
1235 :
1236 33094 : omp_mask::omp_mask (uint64_t m1, uint64_t m2) : mask1 (m1), mask2 (m2)
1237 : {
1238 : }
1239 :
1240 : omp_mask
1241 32143 : omp_mask::operator| (omp_mask1 m) const
1242 : {
1243 32143 : return omp_mask (mask1 | (((uint64_t) 1) << m), mask2);
1244 : }
1245 :
1246 : omp_mask
1247 16779 : omp_mask::operator| (omp_mask2 m) const
1248 : {
1249 16779 : return omp_mask (mask1, mask2 | (((uint64_t) 1) << m));
1250 : }
1251 :
1252 : omp_mask
1253 4357 : omp_mask::operator| (omp_mask m) const
1254 : {
1255 4357 : return omp_mask (mask1 | m.mask1, mask2 | m.mask2);
1256 : }
1257 :
1258 : omp_mask
1259 2018 : omp_mask::operator& (const omp_inv_mask &m) const
1260 : {
1261 2018 : return omp_mask (mask1 & ~m.mask1, mask2 & ~m.mask2);
1262 : }
1263 :
1264 : bool
1265 125439 : omp_mask::operator& (omp_mask1 m) const
1266 : {
1267 125439 : return (mask1 & (((uint64_t) 1) << m)) != 0;
1268 : }
1269 :
1270 : bool
1271 88268 : omp_mask::operator& (omp_mask2 m) const
1272 : {
1273 88268 : return (mask2 & (((uint64_t) 1) << m)) != 0;
1274 : }
1275 :
1276 : omp_inv_mask
1277 2018 : omp_mask::operator~ () const
1278 : {
1279 2018 : return omp_inv_mask (*this);
1280 : }
1281 :
1282 2018 : 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 1114 : gfc_match_iterator (gfc_namespace **ns, bool permit_var)
1309 : {
1310 1114 : locus old_loc = gfc_current_locus;
1311 :
1312 1114 : if (gfc_match ("iterator ( ") != MATCH_YES)
1313 : return MATCH_NO;
1314 :
1315 80 : gfc_typespec ts;
1316 80 : gfc_symbol *last = NULL;
1317 80 : gfc_expr *begin, *end, *step;
1318 80 : *ns = gfc_build_block_ns (gfc_current_ns);
1319 86 : char name[GFC_MAX_SYMBOL_LEN + 1];
1320 92 : while (true)
1321 : {
1322 86 : locus prev_loc = gfc_current_locus;
1323 86 : if (gfc_match_type_spec (&ts) == MATCH_YES
1324 86 : && 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 81 : ts.type = BT_INTEGER;
1336 81 : ts.kind = gfc_default_integer_kind;
1337 81 : gfc_current_locus = prev_loc;
1338 : }
1339 84 : prev_loc = gfc_current_locus;
1340 84 : if (gfc_match_name (name) != MATCH_YES)
1341 : {
1342 4 : gfc_error ("Expected identifier at %C");
1343 4 : goto failed;
1344 : }
1345 80 : 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 78 : gfc_symbol *sym = gfc_new_symbol (name, *ns);
1352 78 : if (last)
1353 4 : last->tlink = sym;
1354 : else
1355 74 : (*ns)->omp_affinity_iterators = sym;
1356 78 : last = sym;
1357 78 : sym->declared_at = prev_loc;
1358 78 : sym->ts = ts;
1359 78 : sym->attr.flavor = FL_VARIABLE;
1360 78 : sym->attr.artificial = 1;
1361 78 : sym->attr.referenced = 1;
1362 78 : sym->refs++;
1363 78 : gfc_symtree *st = gfc_new_symtree (&(*ns)->sym_root, name);
1364 78 : st->n.sym = sym;
1365 :
1366 78 : prev_loc = gfc_current_locus;
1367 78 : if (gfc_match (" = ") != MATCH_YES)
1368 3 : goto failed;
1369 75 : permit_var = false;
1370 75 : begin = end = step = NULL;
1371 75 : if (gfc_match ("%e : ", &begin) != MATCH_YES
1372 75 : || 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 72 : 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 67 : gfc_expr *e = gfc_get_expr ();
1391 67 : e->where = prev_loc;
1392 67 : e->expr_type = EXPR_ARRAY;
1393 67 : e->ts = ts;
1394 67 : e->rank = 1;
1395 67 : e->shape = gfc_get_shape (1);
1396 116 : mpz_init_set_ui (e->shape[0], step ? 3 : 2);
1397 67 : gfc_constructor_append_expr (&e->value.constructor, begin, &begin->where);
1398 67 : gfc_constructor_append_expr (&e->value.constructor, end, &end->where);
1399 67 : if (step)
1400 18 : gfc_constructor_append_expr (&e->value.constructor, step, &step->where);
1401 67 : sym->value = e;
1402 :
1403 67 : if (gfc_match (") ") == MATCH_YES)
1404 : break;
1405 6 : if (gfc_match (", ") != MATCH_YES)
1406 0 : goto failed;
1407 6 : }
1408 61 : 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 1715 : gfc_match_motion_var_list (const char *str, gfc_omp_namelist **list,
1436 : gfc_omp_namelist ***headp)
1437 : {
1438 1715 : match m = gfc_match (str);
1439 1715 : if (m != MATCH_YES)
1440 : return m;
1441 :
1442 1715 : match m_present = gfc_match (" present : ");
1443 :
1444 1715 : m = gfc_match_omp_variable_list ("", list, false, NULL, headp, true, true);
1445 1715 : if (m != MATCH_YES)
1446 : return m;
1447 1715 : if (m_present == MATCH_YES)
1448 : {
1449 5 : gfc_omp_namelist *n;
1450 10 : for (n = **headp; n; n = n->next)
1451 5 : n->u.present_modifier = true;
1452 : }
1453 : return MATCH_YES;
1454 : }
1455 :
1456 : /* reduction ( reduction-modifier, reduction-operator : variable-list )
1457 : in_reduction ( reduction-operator : variable-list )
1458 : task_reduction ( reduction-operator : variable-list ) */
1459 :
1460 : static match
1461 4357 : gfc_match_omp_clause_reduction (char pc, gfc_omp_clauses *c, bool openacc,
1462 : bool allow_derived, bool openmp_target = false)
1463 : {
1464 4357 : if (pc == 'r' && gfc_match ("reduction ( ") != MATCH_YES)
1465 : return MATCH_NO;
1466 4357 : else if (pc == 'i' && gfc_match ("in_reduction ( ") != MATCH_YES)
1467 : return MATCH_NO;
1468 4245 : else if (pc == 't' && gfc_match ("task_reduction ( ") != MATCH_YES)
1469 : return MATCH_NO;
1470 :
1471 4245 : locus old_loc = gfc_current_locus;
1472 4245 : enum gfc_omp_list_type list_idx = OMP_LIST_NONE;
1473 :
1474 4245 : if (pc == 'r' && !openacc)
1475 : {
1476 2118 : if (gfc_match ("inscan") == MATCH_YES)
1477 : list_idx = OMP_LIST_REDUCTION_INSCAN;
1478 2048 : else if (gfc_match ("task") == MATCH_YES)
1479 : list_idx = OMP_LIST_REDUCTION_TASK;
1480 1943 : else if (gfc_match ("default") == MATCH_YES)
1481 : list_idx = OMP_LIST_REDUCTION;
1482 231 : if (list_idx != OMP_LIST_NONE && gfc_match (", ") != MATCH_YES)
1483 : {
1484 1 : gfc_error ("Comma expected at %C");
1485 1 : gfc_current_locus = old_loc;
1486 1 : return MATCH_NO;
1487 : }
1488 2117 : if (list_idx == OMP_LIST_NONE)
1489 3831 : list_idx = OMP_LIST_REDUCTION;
1490 : }
1491 2127 : else if (pc == 'i')
1492 : list_idx = OMP_LIST_IN_REDUCTION;
1493 2009 : else if (pc == 't')
1494 : list_idx = OMP_LIST_TASK_REDUCTION;
1495 : else
1496 3831 : list_idx = OMP_LIST_REDUCTION;
1497 :
1498 4244 : gfc_omp_reduction_op rop = OMP_REDUCTION_NONE;
1499 4244 : char buffer[GFC_MAX_SYMBOL_LEN + 3];
1500 4244 : if (gfc_match_char ('+') == MATCH_YES)
1501 : rop = OMP_REDUCTION_PLUS;
1502 2223 : else if (gfc_match_char ('*') == MATCH_YES)
1503 : rop = OMP_REDUCTION_TIMES;
1504 1991 : else if (gfc_match_char ('-') == MATCH_YES)
1505 : {
1506 171 : if (!openacc)
1507 16 : gfc_warning (OPT_Wdeprecated_openmp,
1508 : "%<-%> operator at %C for reductions deprecated in "
1509 : "OpenMP 5.2");
1510 : rop = OMP_REDUCTION_MINUS;
1511 : }
1512 1820 : else if (gfc_match (".and.") == MATCH_YES)
1513 : rop = OMP_REDUCTION_AND;
1514 1714 : else if (gfc_match (".or.") == MATCH_YES)
1515 : rop = OMP_REDUCTION_OR;
1516 929 : else if (gfc_match (".eqv.") == MATCH_YES)
1517 : rop = OMP_REDUCTION_EQV;
1518 831 : else if (gfc_match (".neqv.") == MATCH_YES)
1519 : rop = OMP_REDUCTION_NEQV;
1520 736 : if (rop != OMP_REDUCTION_NONE)
1521 3508 : snprintf (buffer, sizeof buffer, "operator %s",
1522 : gfc_op2string ((gfc_intrinsic_op) rop));
1523 736 : else if (gfc_match_defined_op_name (buffer + 1, 1) == MATCH_YES)
1524 : {
1525 38 : buffer[0] = '.';
1526 38 : strcat (buffer, ".");
1527 : }
1528 698 : else if (gfc_match_name (buffer) == MATCH_YES)
1529 : {
1530 697 : gfc_symbol *sym;
1531 697 : const char *n = buffer;
1532 :
1533 697 : gfc_find_symbol (buffer, NULL, 1, &sym);
1534 697 : if (sym != NULL)
1535 : {
1536 216 : if (sym->attr.intrinsic)
1537 139 : n = sym->name;
1538 77 : else if ((sym->attr.flavor != FL_UNKNOWN
1539 75 : && sym->attr.flavor != FL_PROCEDURE)
1540 75 : || sym->attr.external
1541 64 : || sym->attr.generic
1542 64 : || sym->attr.entry
1543 64 : || sym->attr.result
1544 64 : || sym->attr.dummy
1545 64 : || sym->attr.subroutine
1546 63 : || sym->attr.pointer
1547 63 : || sym->attr.target
1548 63 : || sym->attr.cray_pointer
1549 63 : || sym->attr.cray_pointee
1550 63 : || (sym->attr.proc != PROC_UNKNOWN
1551 1 : && sym->attr.proc != PROC_INTRINSIC)
1552 62 : || sym->attr.if_source != IFSRC_UNKNOWN
1553 62 : || sym == sym->ns->proc_name)
1554 : {
1555 : sym = NULL;
1556 : n = NULL;
1557 : }
1558 : else
1559 62 : n = sym->name;
1560 : }
1561 201 : if (n == NULL)
1562 : rop = OMP_REDUCTION_NONE;
1563 682 : else if (strcmp (n, "max") == 0)
1564 : rop = OMP_REDUCTION_MAX;
1565 517 : else if (strcmp (n, "min") == 0)
1566 : rop = OMP_REDUCTION_MIN;
1567 376 : else if (strcmp (n, "iand") == 0)
1568 : rop = OMP_REDUCTION_IAND;
1569 321 : else if (strcmp (n, "ior") == 0)
1570 : rop = OMP_REDUCTION_IOR;
1571 255 : else if (strcmp (n, "ieor") == 0)
1572 : rop = OMP_REDUCTION_IEOR;
1573 : if (rop != OMP_REDUCTION_NONE
1574 477 : && sym != NULL
1575 200 : && ! sym->attr.intrinsic
1576 61 : && ! sym->attr.use_assoc
1577 61 : && ((sym->attr.flavor == FL_UNKNOWN
1578 2 : && !gfc_add_flavor (&sym->attr, FL_PROCEDURE,
1579 : sym->name, NULL))
1580 61 : || !gfc_add_intrinsic (&sym->attr, NULL)))
1581 : rop = OMP_REDUCTION_NONE;
1582 : }
1583 : else
1584 1 : buffer[0] = '\0';
1585 4244 : gfc_omp_udr *udr = (buffer[0] ? gfc_find_omp_udr (gfc_current_ns, buffer, NULL)
1586 : : NULL);
1587 4244 : gfc_omp_namelist **head = NULL;
1588 4244 : if (rop == OMP_REDUCTION_NONE && udr)
1589 250 : rop = OMP_REDUCTION_USER;
1590 :
1591 4244 : if (gfc_match_omp_variable_list (" :", &c->lists[list_idx], false, NULL,
1592 : &head, openacc, allow_derived) != MATCH_YES)
1593 : {
1594 9 : gfc_current_locus = old_loc;
1595 9 : return MATCH_NO;
1596 : }
1597 4235 : gfc_omp_namelist *n;
1598 4235 : if (rop == OMP_REDUCTION_NONE)
1599 : {
1600 6 : n = *head;
1601 6 : *head = NULL;
1602 6 : gfc_error_now ("!$OMP DECLARE REDUCTION %s not found at %L",
1603 : buffer, &old_loc);
1604 6 : gfc_free_omp_namelist (n, OMP_LIST_NONE);
1605 : }
1606 : else
1607 9110 : for (n = *head; n; n = n->next)
1608 : {
1609 4881 : n->u.reduction_op = rop;
1610 4881 : if (udr)
1611 : {
1612 473 : n->u2.udr = gfc_get_omp_namelist_udr ();
1613 473 : n->u2.udr->udr = udr;
1614 : }
1615 4881 : if (openmp_target && list_idx == OMP_LIST_IN_REDUCTION)
1616 : {
1617 40 : gfc_omp_namelist *p = gfc_get_omp_namelist (), **tl;
1618 40 : p->sym = n->sym;
1619 40 : p->where = n->where;
1620 40 : p->u.map.op = OMP_MAP_ALWAYS_TOFROM;
1621 :
1622 40 : tl = &c->lists[OMP_LIST_MAP];
1623 52 : while (*tl)
1624 12 : tl = &((*tl)->next);
1625 40 : *tl = p;
1626 40 : p->next = NULL;
1627 : }
1628 : }
1629 : return MATCH_YES;
1630 : }
1631 :
1632 : static match
1633 40 : gfc_omp_absent_contains_clause (gfc_omp_assumptions **assume, bool is_absent)
1634 : {
1635 40 : if (*assume == NULL)
1636 15 : *assume = gfc_get_omp_assumptions ();
1637 62 : do
1638 : {
1639 51 : gfc_statement st = ST_NONE;
1640 51 : gfc_gobble_whitespace ();
1641 51 : locus old_loc = gfc_current_locus;
1642 51 : char c = gfc_peek_ascii_char ();
1643 51 : enum gfc_omp_directive_kind kind
1644 : = GFC_OMP_DIR_DECLARATIVE; /* Silence warning. */
1645 1585 : for (size_t i = 0; i < ARRAY_SIZE (gfc_omp_directives); i++)
1646 : {
1647 1585 : if (gfc_omp_directives[i].name[0] > c)
1648 : break;
1649 1534 : if (gfc_omp_directives[i].name[0] != c)
1650 1182 : continue;
1651 352 : if (gfc_match (gfc_omp_directives[i].name) == MATCH_YES)
1652 : {
1653 51 : st = gfc_omp_directives[i].st;
1654 51 : kind = gfc_omp_directives[i].kind;
1655 : }
1656 : }
1657 51 : gfc_gobble_whitespace ();
1658 51 : c = gfc_peek_ascii_char ();
1659 51 : if (st == ST_NONE || (c != ',' && c != ')'))
1660 : {
1661 0 : if (st == ST_NONE)
1662 0 : gfc_error ("Unknown directive at %L", &old_loc);
1663 : else
1664 0 : gfc_error ("Invalid combined or composite directive at %L",
1665 : &old_loc);
1666 4 : return MATCH_ERROR;
1667 : }
1668 51 : if (kind == GFC_OMP_DIR_DECLARATIVE
1669 51 : || kind == GFC_OMP_DIR_INFORMATIONAL
1670 : || kind == GFC_OMP_DIR_META)
1671 : {
1672 5 : gfc_error ("Invalid %qs directive at %L in %s clause: declarative, "
1673 : "informational, and meta directives not permitted",
1674 : gfc_ascii_statement (st, true), &old_loc,
1675 : is_absent ? "ABSENT" : "CONTAINS");
1676 4 : return MATCH_ERROR;
1677 : }
1678 47 : if (is_absent)
1679 : {
1680 : /* Use exponential allocation; equivalent to pow2p(x). */
1681 33 : int i = (*assume)->n_absent;
1682 33 : int size = ((i == 0) ? 4
1683 10 : : pow2p_hwi (i) == 1 ? i*2 : 0);
1684 8 : if (size != 0)
1685 31 : (*assume)->absent = XRESIZEVEC (gfc_statement,
1686 : (*assume)->absent, size);
1687 33 : (*assume)->absent[(*assume)->n_absent++] = st;
1688 : }
1689 : else
1690 : {
1691 14 : int i = (*assume)->n_contains;
1692 14 : int size = ((i == 0) ? 4
1693 4 : : pow2p_hwi (i) == 1 ? i*2 : 0);
1694 4 : if (size != 0)
1695 14 : (*assume)->contains = XRESIZEVEC (gfc_statement,
1696 : (*assume)->contains, size);
1697 14 : (*assume)->contains[(*assume)->n_contains++] = st;
1698 : }
1699 47 : gfc_gobble_whitespace ();
1700 47 : if (gfc_match(",") == MATCH_YES)
1701 11 : continue;
1702 36 : if (gfc_match(")") == MATCH_YES)
1703 : break;
1704 0 : gfc_error ("Expected %<,%> or %<)%> at %C");
1705 0 : return MATCH_ERROR;
1706 : }
1707 : while (true);
1708 :
1709 36 : return MATCH_YES;
1710 : }
1711 :
1712 : /* Check 'check' argument for duplicated statements in absent and/or contains
1713 : clauses. If 'merge', merge them from check to 'merge'. */
1714 :
1715 : static match
1716 43 : omp_verify_merge_absent_contains (gfc_statement st, gfc_omp_assumptions *check,
1717 : gfc_omp_assumptions *merge, locus *loc)
1718 : {
1719 43 : if (check == NULL)
1720 : return MATCH_YES;
1721 43 : bitmap_head absent_head, contains_head;
1722 43 : bitmap_obstack_initialize (NULL);
1723 43 : bitmap_initialize (&absent_head, &bitmap_default_obstack);
1724 43 : bitmap_initialize (&contains_head, &bitmap_default_obstack);
1725 :
1726 43 : match m = MATCH_YES;
1727 76 : for (int i = 0; i < check->n_absent; i++)
1728 33 : if (!bitmap_set_bit (&absent_head, check->absent[i]))
1729 : {
1730 2 : gfc_error ("%qs directive mentioned multiple times in %s clause in %s "
1731 : "directive at %L",
1732 2 : gfc_ascii_statement (check->absent[i], true),
1733 : "ABSENT", gfc_ascii_statement (st), loc);
1734 2 : m = MATCH_ERROR;
1735 : }
1736 57 : for (int i = 0; i < check->n_contains; i++)
1737 : {
1738 14 : if (!bitmap_set_bit (&contains_head, check->contains[i]))
1739 : {
1740 2 : gfc_error ("%qs directive mentioned multiple times in %s clause in %s "
1741 : "directive at %L",
1742 2 : gfc_ascii_statement (check->contains[i], true),
1743 : "CONTAINS", gfc_ascii_statement (st), loc);
1744 2 : m = MATCH_ERROR;
1745 : }
1746 14 : if (bitmap_bit_p (&absent_head, check->contains[i]))
1747 : {
1748 2 : gfc_error ("%qs directive mentioned both times in ABSENT and CONTAINS "
1749 : "clauses in %s directive at %L",
1750 2 : gfc_ascii_statement (check->absent[i], true),
1751 : gfc_ascii_statement (st), loc);
1752 2 : m = MATCH_ERROR;
1753 : }
1754 : }
1755 :
1756 43 : if (m == MATCH_ERROR)
1757 : return MATCH_ERROR;
1758 37 : if (merge == NULL)
1759 : return MATCH_YES;
1760 2 : if (merge->absent == NULL && check->absent)
1761 : {
1762 1 : merge->n_absent = check->n_absent;
1763 1 : merge->absent = check->absent;
1764 1 : check->absent = NULL;
1765 : }
1766 1 : else if (merge->absent && check->absent)
1767 : {
1768 0 : check->absent = XRESIZEVEC (gfc_statement, check->absent,
1769 : merge->n_absent + check->n_absent);
1770 0 : for (int i = 0; i < merge->n_absent; i++)
1771 0 : if (!bitmap_bit_p (&absent_head, merge->absent[i]))
1772 0 : check->absent[check->n_absent++] = merge->absent[i];
1773 0 : free (merge->absent);
1774 0 : merge->absent = check->absent;
1775 0 : merge->n_absent = check->n_absent;
1776 0 : check->absent = NULL;
1777 : }
1778 2 : if (merge->contains == NULL && check->contains)
1779 : {
1780 0 : merge->n_contains = check->n_contains;
1781 0 : merge->contains = check->contains;
1782 0 : check->contains = NULL;
1783 : }
1784 2 : else if (merge->contains && check->contains)
1785 : {
1786 0 : check->contains = XRESIZEVEC (gfc_statement, check->contains,
1787 : merge->n_contains + check->n_contains);
1788 0 : for (int i = 0; i < merge->n_contains; i++)
1789 0 : if (!bitmap_bit_p (&contains_head, merge->contains[i]))
1790 0 : check->contains[check->n_contains++] = merge->contains[i];
1791 0 : free (merge->contains);
1792 0 : merge->contains = check->contains;
1793 0 : merge->n_contains = check->n_contains;
1794 0 : check->contains = NULL;
1795 : }
1796 : return MATCH_YES;
1797 : }
1798 :
1799 : /* OpenMP 5.0
1800 : uses_allocators ( allocator-list )
1801 :
1802 : allocator:
1803 : predefined-allocator
1804 : variable ( traits-array )
1805 :
1806 : OpenMP 5.2 deprecated, 6.0 deleted: 'variable ( traits-array )'
1807 :
1808 : OpenMP 5.2:
1809 : uses_allocators ( [modifier-list :] allocator-list )
1810 :
1811 : OpenMP 6.0:
1812 : uses_allocators ( [modifier-list :] allocator-list [; ...])
1813 :
1814 : allocator:
1815 : variable or predefined-allocator
1816 : modifier:
1817 : traits ( traits-array )
1818 : memspace ( mem-space-handle ) */
1819 :
1820 : static match
1821 56 : gfc_match_omp_clause_uses_allocators (gfc_omp_clauses *c)
1822 : {
1823 60 : parse_next:
1824 60 : gfc_symbol *memspace_sym = NULL;
1825 60 : gfc_symbol *traits_sym = NULL;
1826 60 : gfc_omp_namelist *head = NULL;
1827 60 : gfc_omp_namelist *p, *tail, **list;
1828 60 : int ntraits, nmemspace;
1829 60 : bool has_modifiers;
1830 60 : locus old_loc, cur_loc;
1831 :
1832 60 : gfc_gobble_whitespace ();
1833 60 : old_loc = gfc_current_locus;
1834 60 : ntraits = nmemspace = 0;
1835 92 : do
1836 : {
1837 76 : cur_loc = gfc_current_locus;
1838 76 : if (gfc_match ("traits ( %S ) ", &traits_sym) == MATCH_YES)
1839 24 : ntraits++;
1840 52 : else if (gfc_match ("memspace ( %S ) ", &memspace_sym) == MATCH_YES)
1841 23 : nmemspace++;
1842 76 : if (ntraits > 1 || nmemspace > 1)
1843 : {
1844 2 : gfc_error ("Duplicate %s modifier at %L in USES_ALLOCATORS clause",
1845 : ntraits > 1 ? "TRAITS" : "MEMSPACE", &cur_loc);
1846 2 : return MATCH_ERROR;
1847 : }
1848 74 : if (gfc_match (", ") == MATCH_YES)
1849 16 : continue;
1850 58 : if (gfc_match (": ") != MATCH_YES)
1851 : {
1852 : /* Assume no modifier. */
1853 31 : memspace_sym = traits_sym = NULL;
1854 31 : gfc_current_locus = old_loc;
1855 31 : break;
1856 : }
1857 : break;
1858 : } while (true);
1859 :
1860 85 : has_modifiers = traits_sym != NULL || memspace_sym != NULL;
1861 150 : do
1862 : {
1863 104 : p = gfc_get_omp_namelist ();
1864 104 : p->where = gfc_current_locus;
1865 104 : if (head == NULL)
1866 : head = tail = p;
1867 : else
1868 : {
1869 46 : tail->next = p;
1870 46 : tail = tail->next;
1871 : }
1872 104 : if (gfc_match ("%S ", &p->sym) != MATCH_YES)
1873 0 : goto error;
1874 104 : if (!has_modifiers)
1875 : {
1876 72 : if (gfc_match ("( %S ) ", &p->u2.traits_sym) == MATCH_YES)
1877 17 : gfc_warning (OPT_Wdeprecated_openmp,
1878 : "The specification of arguments to "
1879 : "%<uses_allocators%> at %L where each item is of "
1880 : "the form %<allocator(traits)%> is deprecated since "
1881 : "OpenMP 5.2; instead use %<uses_allocators(traits(%s"
1882 17 : "): %s)%>", &p->where, p->u2.traits_sym->name,
1883 17 : p->sym->name);
1884 : }
1885 32 : else if (gfc_peek_ascii_char () == '(')
1886 : {
1887 0 : gfc_error ("Unexpected %<(%> at %C");
1888 0 : goto error;
1889 : }
1890 : else
1891 : {
1892 32 : p->u.memspace_sym = memspace_sym;
1893 32 : p->u2.traits_sym = traits_sym;
1894 : }
1895 104 : gfc_gobble_whitespace ();
1896 104 : const char c = gfc_peek_ascii_char ();
1897 104 : if (c == ';' || c == ')')
1898 : break;
1899 48 : if (c != ',')
1900 : {
1901 2 : gfc_error ("Expected %<,%>, %<)%> or %<;%> at %C");
1902 2 : goto error;
1903 : }
1904 46 : gfc_match_char (',');
1905 46 : gfc_gobble_whitespace ();
1906 46 : } while (true);
1907 :
1908 56 : list = &c->lists[OMP_LIST_USES_ALLOCATORS];
1909 74 : while (*list)
1910 18 : list = &(*list)->next;
1911 56 : *list = head;
1912 :
1913 56 : if (gfc_match_char (';') == MATCH_YES)
1914 4 : goto parse_next;
1915 :
1916 52 : gfc_match_char (')');
1917 52 : return MATCH_YES;
1918 :
1919 2 : error:
1920 2 : gfc_free_omp_namelist (head, OMP_LIST_USES_ALLOCATORS);
1921 2 : return MATCH_ERROR;
1922 : }
1923 :
1924 :
1925 : /* Match the 'prefer_type' modifier of the interop 'init' clause:
1926 : with either OpenMP 5.1's
1927 : prefer_type ( <const-int-expr|string literal> [, ...]
1928 : or
1929 : prefer_type ( '{' <fr(...) | attr (...)>, ...] '}' [, '{' ... '}' ] )
1930 : where 'fr' takes a constant expression or a string literal
1931 : and 'attr takes a list of string literals, starting with 'ompx_')
1932 :
1933 : For the foreign runtime identifiers, string values are converted to
1934 : their integer value; unknown string or integer values are set to
1935 : GOMP_INTEROP_IFR_KNOWN.
1936 :
1937 : Data format:
1938 : For the foreign runtime identifiers, string values are converted to
1939 : their integer value; unknown string or integer values are set to 0.
1940 :
1941 : Each item (a) GOMP_INTEROP_IFR_SEPARATOR
1942 : (b) for any 'fr', its integer value.
1943 : Note: Spec only permits 1 'fr' entry (6.0; changed after TR13)
1944 : (c) GOMP_INTEROP_IFR_SEPARATOR
1945 : (d) list of \0-terminated non-empty strings for 'attr'
1946 : (e) '\0'
1947 : Tailing '\0'. */
1948 :
1949 : static match
1950 82 : gfc_match_omp_prefer_type (char **type_str, int *type_str_len)
1951 : {
1952 82 : gfc_expr *e;
1953 82 : std::string type_string, attr_string;
1954 : /* New syntax. */
1955 82 : if (gfc_peek_ascii_char () == '{')
1956 115 : do
1957 : {
1958 85 : attr_string.clear ();
1959 85 : type_string += (char) GOMP_INTEROP_IFR_SEPARATOR;
1960 85 : if (gfc_match ("{ ") != MATCH_YES)
1961 : {
1962 1 : gfc_error ("Expected %<{%> at %C");
1963 1 : return MATCH_ERROR;
1964 : }
1965 : bool fr_found = false;
1966 148 : do
1967 : {
1968 116 : if (gfc_match ("fr ( ") == MATCH_YES)
1969 : {
1970 62 : if (fr_found)
1971 : {
1972 1 : gfc_error ("Duplicated %<fr%> preference-selector-name "
1973 : "at %C");
1974 1 : return MATCH_ERROR;
1975 : }
1976 61 : fr_found = true;
1977 61 : do
1978 : {
1979 61 : bool found_literal = false;
1980 61 : match m = MATCH_YES;
1981 61 : if (gfc_match_literal_constant (&e, false) == MATCH_YES)
1982 : found_literal = true;
1983 : else
1984 12 : m = gfc_match_expr (&e);
1985 12 : if (m != MATCH_YES
1986 61 : || !gfc_resolve_expr (e)
1987 61 : || e->rank != 0
1988 60 : || e->expr_type != EXPR_CONSTANT
1989 59 : || (e->ts.type != BT_INTEGER
1990 43 : && (!found_literal || e->ts.type != BT_CHARACTER))
1991 58 : || (e->ts.type == BT_INTEGER
1992 16 : && !mpz_fits_sint_p (e->value.integer))
1993 70 : || (e->ts.type == BT_CHARACTER
1994 42 : && (e->ts.kind != gfc_default_character_kind
1995 41 : || e->value.character.length == 0)))
1996 : {
1997 5 : gfc_error ("Expected constant scalar integer expression"
1998 : " or non-empty default-kind character "
1999 5 : "literal at %L", &e->where);
2000 5 : gfc_free_expr (e);
2001 5 : return MATCH_ERROR;
2002 : }
2003 56 : gfc_gobble_whitespace ();
2004 56 : int val;
2005 56 : if (e->ts.type == BT_INTEGER)
2006 : {
2007 16 : val = mpz_get_si (e->value.integer);
2008 16 : if (val < 1 || val > GOMP_INTEROP_IFR_LAST)
2009 : {
2010 0 : gfc_warning_now (OPT_Wopenmp,
2011 : "Unknown foreign runtime "
2012 : "identifier %qd at %L",
2013 : val, &e->where);
2014 0 : val = GOMP_INTEROP_IFR_UNKNOWN;
2015 : }
2016 : }
2017 : else
2018 : {
2019 40 : char *str = XALLOCAVEC (char,
2020 : e->value.character.length+1);
2021 229 : for (int i = 0; i < e->value.character.length + 1; i++)
2022 189 : str[i] = e->value.character.string[i];
2023 40 : if (memchr (str, '\0', e->value.character.length) != 0)
2024 : {
2025 0 : gfc_error ("Unexpected null character in character "
2026 : "literal at %L", &e->where);
2027 0 : return MATCH_ERROR;
2028 : }
2029 40 : val = omp_get_fr_id_from_name (str);
2030 40 : if (val == GOMP_INTEROP_IFR_UNKNOWN)
2031 2 : gfc_warning_now (OPT_Wopenmp,
2032 : "Unknown foreign runtime identifier "
2033 2 : "%qs at %L", str, &e->where);
2034 : }
2035 :
2036 56 : type_string += (char) val;
2037 56 : if (gfc_match (") ") == MATCH_YES)
2038 : break;
2039 4 : gfc_error ("Expected %<)%> at %C");
2040 4 : return MATCH_ERROR;
2041 : }
2042 : while (true);
2043 : }
2044 54 : else if (gfc_match ("attr ( ") == MATCH_YES)
2045 : {
2046 60 : do
2047 : {
2048 57 : if (gfc_match_literal_constant (&e, false) != MATCH_YES
2049 56 : || !gfc_resolve_expr (e)
2050 56 : || e->expr_type != EXPR_CONSTANT
2051 56 : || e->rank != 0
2052 56 : || e->ts.type != BT_CHARACTER
2053 113 : || e->ts.kind != gfc_default_character_kind)
2054 : {
2055 1 : gfc_error ("Expected default-kind character literal "
2056 1 : "at %L", &e->where);
2057 1 : gfc_free_expr (e);
2058 1 : return MATCH_ERROR;
2059 : }
2060 56 : gfc_gobble_whitespace ();
2061 56 : char *str = XALLOCAVEC (char, e->value.character.length+1);
2062 564 : for (int i = 0; i < e->value.character.length + 1; i++)
2063 508 : str[i] = e->value.character.string[i];
2064 56 : if (!startswith (str, "ompx_"))
2065 : {
2066 1 : gfc_error ("Character literal at %L must start with "
2067 : "%<ompx_%>", &e->where);
2068 1 : gfc_free_expr (e);
2069 1 : return MATCH_ERROR;
2070 : }
2071 55 : if (memchr (str, '\0', e->value.character.length) != 0
2072 55 : || memchr (str, ',', e->value.character.length) != 0)
2073 : {
2074 1 : gfc_error ("Unexpected null or %<,%> character in "
2075 : "character literal at %L", &e->where);
2076 1 : return MATCH_ERROR;
2077 : }
2078 54 : attr_string += str;
2079 54 : attr_string += '\0';
2080 54 : if (gfc_match (", ") == MATCH_YES)
2081 3 : continue;
2082 51 : if (gfc_match (") ") == MATCH_YES)
2083 : break;
2084 0 : gfc_error ("Expected %<,%> or %<)%> at %C");
2085 0 : return MATCH_ERROR;
2086 3 : }
2087 : while (true);
2088 : }
2089 : else
2090 : {
2091 0 : gfc_error ("Expected %<fr(%> or %<attr(%> at %C");
2092 0 : return MATCH_ERROR;
2093 : }
2094 103 : if (gfc_match (", ") == MATCH_YES)
2095 32 : continue;
2096 71 : if (gfc_match ("} ") == MATCH_YES)
2097 : break;
2098 2 : gfc_error ("Expected %<,%> or %<}%> at %C");
2099 2 : return MATCH_ERROR;
2100 32 : }
2101 : while (true);
2102 69 : type_string += (char) GOMP_INTEROP_IFR_SEPARATOR;
2103 69 : type_string += attr_string;
2104 69 : type_string += '\0';
2105 69 : if (gfc_match (", ") == MATCH_YES)
2106 30 : continue;
2107 39 : if (gfc_match (") ") == MATCH_YES)
2108 : break;
2109 1 : gfc_error ("Expected %<,%> or %<)%> at %C");
2110 1 : return MATCH_ERROR;
2111 30 : }
2112 : while (true);
2113 : else
2114 75 : do
2115 : {
2116 51 : type_string += (char) GOMP_INTEROP_IFR_SEPARATOR;
2117 51 : bool found_literal = false;
2118 51 : match m = MATCH_YES;
2119 51 : if (gfc_match_literal_constant (&e, false) == MATCH_YES)
2120 : found_literal = true;
2121 : else
2122 19 : m = gfc_match_expr (&e);
2123 19 : if (m != MATCH_YES
2124 51 : || !gfc_resolve_expr (e)
2125 51 : || e->rank != 0
2126 50 : || e->expr_type != EXPR_CONSTANT
2127 49 : || (e->ts.type != BT_INTEGER
2128 28 : && (!found_literal || e->ts.type != BT_CHARACTER))
2129 48 : || (e->ts.type == BT_INTEGER
2130 21 : && !mpz_fits_sint_p (e->value.integer))
2131 67 : || (e->ts.type == BT_CHARACTER
2132 27 : && (e->ts.kind != gfc_default_character_kind
2133 27 : || e->value.character.length == 0)))
2134 : {
2135 3 : gfc_error ("Expected constant scalar integer expression or "
2136 3 : "non-empty default-kind character literal at %L", &e->where);
2137 3 : gfc_free_expr (e);
2138 3 : return MATCH_ERROR;
2139 : }
2140 48 : gfc_gobble_whitespace ();
2141 48 : int val;
2142 48 : if (e->ts.type == BT_INTEGER)
2143 : {
2144 21 : val = mpz_get_si (e->value.integer);
2145 21 : if (val < 1 || val > GOMP_INTEROP_IFR_LAST)
2146 : {
2147 3 : gfc_warning_now (OPT_Wopenmp,
2148 : "Unknown foreign runtime identifier %qd at %L",
2149 : val, &e->where);
2150 3 : val = 0;
2151 : }
2152 : }
2153 : else
2154 : {
2155 27 : char *str = XALLOCAVEC (char, e->value.character.length+1);
2156 169 : for (int i = 0; i < e->value.character.length + 1; i++)
2157 142 : str[i] = e->value.character.string[i];
2158 27 : if (memchr (str, '\0', e->value.character.length) != 0)
2159 : {
2160 0 : gfc_error ("Unexpected null character in character "
2161 : "literal at %L", &e->where);
2162 0 : return MATCH_ERROR;
2163 : }
2164 27 : val = omp_get_fr_id_from_name (str);
2165 27 : if (val == GOMP_INTEROP_IFR_UNKNOWN)
2166 5 : gfc_warning_now (OPT_Wopenmp,
2167 : "Unknown foreign runtime identifier %qs at %L",
2168 5 : str, &e->where);
2169 : }
2170 48 : type_string += (char) val;
2171 48 : type_string += (char) GOMP_INTEROP_IFR_SEPARATOR;
2172 48 : type_string += '\0';
2173 48 : gfc_free_expr (e);
2174 48 : if (gfc_match (", ") == MATCH_YES)
2175 24 : continue;
2176 24 : if (gfc_match (") ") == MATCH_YES)
2177 : break;
2178 2 : gfc_error ("Expected %<,%> or %<)%> at %C");
2179 2 : return MATCH_ERROR;
2180 24 : }
2181 : while (true);
2182 60 : type_string += '\0';
2183 60 : *type_str_len = type_string.length();
2184 60 : *type_str = XNEWVEC (char, type_string.length ());
2185 60 : memcpy (*type_str, type_string.data (), type_string.length ());
2186 60 : return MATCH_YES;
2187 82 : }
2188 :
2189 :
2190 : /* Match OpenMP 5.1's 'init'-clause modifiers, used by the 'init' clause of
2191 : the 'interop' directive and the 'append_args' directive of 'declare variant'.
2192 : [prefer_type(...)][,][<target|targetsync>, ...])
2193 :
2194 : If is_init_clause, the modifier parsing ends with a ':'.
2195 : If not is_init_clause (i.e. append_args), the parsing ends with ')'. */
2196 :
2197 : static match
2198 164 : gfc_parser_omp_clause_init_modifiers (bool &target, bool &targetsync,
2199 : char **type_str, int &type_str_len,
2200 : bool is_init_clause)
2201 : {
2202 164 : target = false;
2203 164 : targetsync = false;
2204 164 : *type_str = NULL;
2205 164 : type_str_len = 0;
2206 286 : match m;
2207 :
2208 286 : do
2209 : {
2210 286 : if (gfc_match ("prefer_type ( ") == MATCH_YES)
2211 : {
2212 83 : if (*type_str)
2213 : {
2214 1 : gfc_error ("Duplicate %<prefer_type%> modifier at %C");
2215 1 : return MATCH_ERROR;
2216 : }
2217 82 : m = gfc_match_omp_prefer_type (type_str, &type_str_len);
2218 82 : if (m != MATCH_YES)
2219 : return m;
2220 60 : if (gfc_match (", ") == MATCH_YES)
2221 14 : continue;
2222 46 : if (is_init_clause)
2223 : {
2224 24 : if (gfc_match (": ") == MATCH_YES)
2225 : break;
2226 0 : gfc_error ("Expected %<,%> or %<:%> at %C");
2227 : }
2228 : else
2229 : {
2230 22 : if (gfc_match (") ") == MATCH_YES)
2231 : break;
2232 0 : gfc_error ("Expected %<,%> or %<)%> at %C");
2233 : }
2234 0 : return MATCH_ERROR;
2235 : }
2236 :
2237 203 : if (gfc_match ("prefer_type ") == MATCH_YES)
2238 : {
2239 2 : gfc_error ("Expected %<(%> after %<prefer_type%> at %C");
2240 2 : return MATCH_ERROR;
2241 : }
2242 :
2243 201 : if (gfc_match ("targetsync ") == MATCH_YES)
2244 : {
2245 57 : if (targetsync)
2246 : {
2247 3 : gfc_error ("Duplicate %<targetsync%> at %C");
2248 3 : return MATCH_ERROR;
2249 : }
2250 54 : targetsync = true;
2251 54 : if (gfc_match (", ") == MATCH_YES)
2252 13 : continue;
2253 41 : if (!is_init_clause)
2254 : {
2255 23 : if (gfc_match (") ") == MATCH_YES)
2256 : break;
2257 0 : gfc_error ("Expected %<,%> or %<)%> at %C");
2258 0 : return MATCH_ERROR;
2259 : }
2260 18 : if (gfc_match (": ") == MATCH_YES)
2261 : break;
2262 1 : gfc_error ("Expected %<,%> or %<:%> at %C");
2263 1 : return MATCH_ERROR;
2264 : }
2265 144 : if (gfc_match ("target ") == MATCH_YES)
2266 : {
2267 135 : if (target)
2268 : {
2269 3 : gfc_error ("Duplicate %<target%> at %C");
2270 3 : return MATCH_ERROR;
2271 : }
2272 132 : target = true;
2273 132 : if (gfc_match (", ") == MATCH_YES)
2274 95 : continue;
2275 37 : if (!is_init_clause)
2276 : {
2277 11 : if (gfc_match (") ") == MATCH_YES)
2278 : break;
2279 0 : gfc_error ("Expected %<,%> or %<)%> at %C");
2280 0 : return MATCH_ERROR;
2281 : }
2282 26 : if (gfc_match (": ") == MATCH_YES)
2283 : break;
2284 1 : gfc_error ("Expected %<,%> or %<:%> at %C");
2285 1 : return MATCH_ERROR;
2286 : }
2287 9 : gfc_error ("Expected %<prefer_type%>, %<target%>, or %<targetsync%> "
2288 : "at %C");
2289 9 : return MATCH_ERROR;
2290 : }
2291 : while (true);
2292 :
2293 122 : if (!target && !targetsync)
2294 : {
2295 4 : gfc_error ("Missing required %<target%> and/or %<targetsync%> "
2296 : "modifier at %C");
2297 4 : return MATCH_ERROR;
2298 : }
2299 : return MATCH_YES;
2300 : }
2301 :
2302 : /* Match OpenMP 5.1's 'init' clause for 'interop' objects:
2303 : init([prefer_type(...)][,][<target|targetsync>, ...] :] interop-obj-list) */
2304 :
2305 : static match
2306 108 : gfc_match_omp_init (gfc_omp_namelist **list)
2307 : {
2308 108 : bool target, targetsync;
2309 108 : char *type_str = NULL;
2310 108 : int type_str_len;
2311 108 : if (gfc_parser_omp_clause_init_modifiers (target, targetsync, &type_str,
2312 : type_str_len, true) == MATCH_ERROR)
2313 : return MATCH_ERROR;
2314 :
2315 64 : gfc_omp_namelist **head = NULL;
2316 64 : if (gfc_match_omp_variable_list ("", list, false, NULL, &head) != MATCH_YES)
2317 : return MATCH_ERROR;
2318 147 : for (gfc_omp_namelist *n = *head; n; n = n->next)
2319 : {
2320 84 : n->u.init.target = target;
2321 84 : n->u.init.targetsync = targetsync;
2322 84 : n->u.init.len = type_str_len;
2323 84 : n->u2.init_interop = type_str;
2324 : }
2325 : return MATCH_YES;
2326 : }
2327 :
2328 :
2329 : /* Match with duplicate check. Matches 'name'. If expr != NULL, it
2330 : then matches '(expr)', otherwise, if open_parens is true,
2331 : it matches a ' ( ' after 'name'.
2332 : dupl_message requires '%qs %L' - and is used by
2333 : gfc_match_dupl_memorder and gfc_match_dupl_atomic. */
2334 :
2335 : static match
2336 22380 : gfc_match_dupl_check (bool not_dupl, const char *name, bool open_parens = false,
2337 : gfc_expr **expr = NULL, const char *dupl_msg = NULL)
2338 : {
2339 22380 : match m;
2340 22380 : char c;
2341 22380 : locus old_loc = gfc_current_locus;
2342 22380 : if ((m = gfc_match (name)) != MATCH_YES)
2343 : return m;
2344 : /* Ensure that no partial string is matched. */
2345 17417 : if (gfc_current_form == FORM_FREE
2346 16919 : && gfc_match_eos () != MATCH_YES
2347 30200 : && ((c = gfc_peek_ascii_char ()) == '_' || ISALNUM (c)))
2348 : {
2349 8 : gfc_current_locus = old_loc;
2350 8 : return MATCH_NO;
2351 : }
2352 17409 : if (!not_dupl)
2353 : {
2354 44 : if (dupl_msg)
2355 2 : gfc_error (dupl_msg, name, &old_loc);
2356 : else
2357 42 : gfc_error ("Duplicated %qs clause at %L", name, &old_loc);
2358 44 : return MATCH_ERROR;
2359 : }
2360 17365 : if (open_parens || expr)
2361 : {
2362 9475 : if (gfc_match (" ( ") != MATCH_YES)
2363 : {
2364 22 : gfc_error ("Expected %<(%> after %qs at %C", name);
2365 22 : return MATCH_ERROR;
2366 : }
2367 9453 : if (expr)
2368 : {
2369 4419 : if (gfc_match ("%e )", expr) != MATCH_YES)
2370 : {
2371 9 : gfc_error ("Invalid expression after %<%s(%> at %C", name);
2372 9 : return MATCH_ERROR;
2373 : }
2374 : }
2375 : }
2376 : return MATCH_YES;
2377 : }
2378 :
2379 : static match
2380 211 : gfc_match_dupl_memorder (bool not_dupl, const char *name)
2381 : {
2382 0 : return gfc_match_dupl_check (not_dupl, name, false, NULL,
2383 : "Duplicated memory-order clause: unexpected %s "
2384 0 : "clause at %L");
2385 : }
2386 :
2387 : static match
2388 1175 : gfc_match_dupl_atomic (bool not_dupl, const char *name)
2389 : {
2390 0 : return gfc_match_dupl_check (not_dupl, name, false, NULL,
2391 : "Duplicated atomic clause: unexpected %s "
2392 0 : "clause at %L");
2393 : }
2394 :
2395 :
2396 : /* Search upwards though namespace NS and its parents to find an
2397 : !$omp declare mapper named MAPPER_ID, for typespec TS. */
2398 :
2399 : gfc_omp_udm *
2400 7295 : gfc_find_omp_udm (gfc_namespace *ns, const char *mapper_id, gfc_typespec *ts)
2401 : {
2402 7295 : gfc_symtree *st;
2403 :
2404 7295 : if (ns == NULL)
2405 0 : ns = gfc_current_ns;
2406 :
2407 11371 : do
2408 : {
2409 11371 : gfc_omp_udm *omp_udm;
2410 :
2411 11371 : st = gfc_find_symtree (ns->omp_udm_root, mapper_id);
2412 :
2413 11371 : if (st != NULL)
2414 : {
2415 8 : for (omp_udm = st->n.omp_udm; omp_udm; omp_udm = omp_udm->next)
2416 6 : if (gfc_compare_types (&omp_udm->ts, ts))
2417 : return omp_udm;
2418 : }
2419 :
2420 : /* Don't escape an interface block. */
2421 11367 : if (ns && !ns->has_import_set
2422 11367 : && ns->proc_name && ns->proc_name->attr.if_source == IFSRC_IFBODY)
2423 : break;
2424 :
2425 11367 : ns = ns->parent;
2426 : }
2427 11367 : while (ns != NULL);
2428 :
2429 : return NULL;
2430 : }
2431 :
2432 :
2433 : /* Match OpenMP and OpenACC directive clauses. MASK is a bitmask of
2434 : clauses that are allowed for a particular directive. */
2435 :
2436 : static match
2437 34401 : gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
2438 : bool first = true, bool needs_space = true,
2439 : bool openacc = false, bool openmp_target = false,
2440 : gfc_omp_map_op default_map_op = OMP_MAP_TOFROM)
2441 : {
2442 34401 : bool error = false;
2443 34401 : gfc_omp_clauses *c = gfc_get_omp_clauses ();
2444 34401 : locus old_loc;
2445 : /* Determine whether we're dealing with an OpenACC directive that permits
2446 : derived type member accesses. This in particular disallows
2447 : "!$acc declare" from using such accesses, because it's not clear if/how
2448 : that should work. */
2449 34401 : bool allow_derived = (openacc
2450 34401 : && ((mask & OMP_CLAUSE_ATTACH)
2451 5933 : || (mask & OMP_CLAUSE_DETACH)));
2452 :
2453 34401 : gcc_checking_assert (OMP_MASK1_LAST <= 64 && OMP_MASK2_LAST <= 64);
2454 34401 : *cp = NULL;
2455 126543 : while (1)
2456 : {
2457 80472 : match m = MATCH_NO;
2458 59841 : if ((first || (m = gfc_match_char (',')) != MATCH_YES)
2459 139957 : && (needs_space && gfc_match_space () != MATCH_YES))
2460 : break;
2461 75912 : needs_space = false;
2462 75912 : first = false;
2463 75912 : gfc_gobble_whitespace ();
2464 75912 : bool end_colon;
2465 75912 : gfc_omp_namelist **head;
2466 75912 : old_loc = gfc_current_locus;
2467 75912 : char pc = gfc_peek_ascii_char ();
2468 75912 : if (pc == '\n' && m == MATCH_YES)
2469 : {
2470 1 : gfc_error ("Clause expected at %C after trailing comma");
2471 1 : goto error;
2472 : }
2473 75911 : switch (pc)
2474 : {
2475 1312 : case 'a':
2476 1312 : end_colon = false;
2477 1312 : head = NULL;
2478 1336 : if ((mask & OMP_CLAUSE_ASSUMPTIONS)
2479 1312 : && gfc_match ("absent ( ") == MATCH_YES)
2480 : {
2481 27 : if (gfc_omp_absent_contains_clause (&c->assume, true)
2482 : != MATCH_YES)
2483 3 : goto error;
2484 24 : continue;
2485 : }
2486 1285 : if ((mask & OMP_CLAUSE_ALIGNED)
2487 1285 : && gfc_match_omp_variable_list ("aligned (",
2488 : &c->lists[OMP_LIST_ALIGNED],
2489 : false, &end_colon,
2490 : &head) == MATCH_YES)
2491 : {
2492 112 : gfc_expr *alignment = NULL;
2493 112 : gfc_omp_namelist *n;
2494 :
2495 112 : if (end_colon && gfc_match (" %e )", &alignment) != MATCH_YES)
2496 : {
2497 0 : gfc_free_omp_namelist (*head, OMP_LIST_ALIGNED);
2498 0 : gfc_current_locus = old_loc;
2499 0 : *head = NULL;
2500 0 : break;
2501 : }
2502 268 : for (n = *head; n; n = n->next)
2503 156 : if (n->next && alignment)
2504 42 : n->expr = gfc_copy_expr (alignment);
2505 : else
2506 114 : n->expr = alignment;
2507 112 : continue;
2508 112 : }
2509 1183 : if ((mask & OMP_CLAUSE_MEMORDER)
2510 1190 : && (m = gfc_match_dupl_memorder ((c->memorder
2511 17 : == OMP_MEMORDER_UNSET),
2512 : "acq_rel")) != MATCH_NO)
2513 : {
2514 10 : if (m == MATCH_ERROR)
2515 0 : goto error;
2516 10 : c->memorder = OMP_MEMORDER_ACQ_REL;
2517 10 : continue;
2518 : }
2519 1170 : if ((mask & OMP_CLAUSE_MEMORDER)
2520 1170 : && (m = gfc_match_dupl_memorder ((c->memorder
2521 7 : == OMP_MEMORDER_UNSET),
2522 : "acquire")) != MATCH_NO)
2523 : {
2524 7 : if (m == MATCH_ERROR)
2525 0 : goto error;
2526 7 : c->memorder = OMP_MEMORDER_ACQUIRE;
2527 7 : continue;
2528 : }
2529 1156 : if ((mask & OMP_CLAUSE_AFFINITY)
2530 1156 : && gfc_match ("affinity ( ") == MATCH_YES)
2531 : {
2532 41 : gfc_namespace *ns_iter = NULL, *ns_curr = gfc_current_ns;
2533 41 : m = gfc_match_iterator (&ns_iter, true);
2534 41 : if (m == MATCH_ERROR)
2535 : break;
2536 31 : if (m == MATCH_YES && gfc_match (" : ") != MATCH_YES)
2537 : {
2538 1 : gfc_error ("Expected %<:%> at %C");
2539 1 : break;
2540 : }
2541 30 : if (ns_iter)
2542 18 : gfc_current_ns = ns_iter;
2543 30 : head = NULL;
2544 30 : m = gfc_match_omp_variable_list ("", &c->lists[OMP_LIST_AFFINITY],
2545 : false, NULL, &head, true);
2546 30 : gfc_current_ns = ns_curr;
2547 30 : if (m == MATCH_ERROR)
2548 : break;
2549 27 : if (ns_iter)
2550 : {
2551 45 : for (gfc_omp_namelist *n = *head; n; n = n->next)
2552 : {
2553 27 : n->u2.ns = ns_iter;
2554 27 : ns_iter->refs++;
2555 : }
2556 : }
2557 27 : continue;
2558 27 : }
2559 1115 : if ((mask & OMP_CLAUSE_ALLOCATE)
2560 1115 : && gfc_match ("allocate ( ") == MATCH_YES)
2561 : {
2562 279 : gfc_expr *allocator = NULL;
2563 279 : gfc_expr *align = NULL;
2564 279 : old_loc = gfc_current_locus;
2565 279 : if ((m = gfc_match ("allocator ( %e )", &allocator)) == MATCH_YES)
2566 50 : gfc_match (" , align ( %e )", &align);
2567 229 : else if ((m = gfc_match ("align ( %e )", &align)) == MATCH_YES)
2568 29 : gfc_match (" , allocator ( %e )", &allocator);
2569 :
2570 279 : if (m == MATCH_YES)
2571 : {
2572 79 : if (gfc_match (" : ") != MATCH_YES)
2573 : {
2574 5 : gfc_error ("Expected %<:%> at %C");
2575 8 : goto error;
2576 : }
2577 : }
2578 : else
2579 : {
2580 200 : m = gfc_match_expr (&allocator);
2581 200 : if (m == MATCH_YES && gfc_match (" : ") != MATCH_YES)
2582 : {
2583 : /* If no ":" then there is no allocator, we backtrack
2584 : and read the variable list. */
2585 101 : gfc_free_expr (allocator);
2586 101 : allocator = NULL;
2587 101 : gfc_current_locus = old_loc;
2588 : }
2589 : }
2590 274 : gfc_omp_namelist **head = NULL;
2591 274 : m = gfc_match_omp_variable_list ("", &c->lists[OMP_LIST_ALLOCATE],
2592 : true, NULL, &head);
2593 :
2594 274 : if (m != MATCH_YES)
2595 : {
2596 3 : gfc_free_expr (allocator);
2597 3 : gfc_free_expr (align);
2598 3 : gfc_error ("Expected variable list at %C");
2599 3 : goto error;
2600 : }
2601 :
2602 725 : for (gfc_omp_namelist *n = *head; n; n = n->next)
2603 : {
2604 454 : n->u2.allocator = allocator;
2605 454 : n->u.align = (align) ? gfc_copy_expr (align) : NULL;
2606 : }
2607 271 : gfc_free_expr (align);
2608 271 : continue;
2609 271 : }
2610 896 : if ((mask & OMP_CLAUSE_AT)
2611 836 : && (m = gfc_match_dupl_check (c->at == OMP_AT_UNSET, "at", true))
2612 : != MATCH_NO)
2613 : {
2614 66 : if (m == MATCH_ERROR)
2615 2 : goto error;
2616 64 : if (gfc_match ("compilation )") == MATCH_YES)
2617 15 : c->at = OMP_AT_COMPILATION;
2618 49 : else if (gfc_match ("execution )") == MATCH_YES)
2619 45 : c->at = OMP_AT_EXECUTION;
2620 : else
2621 : {
2622 4 : gfc_error ("Expected COMPILATION or EXECUTION in AT clause "
2623 : "at %C");
2624 4 : goto error;
2625 : }
2626 60 : continue;
2627 : }
2628 1413 : if ((mask & OMP_CLAUSE_ASYNC)
2629 770 : && (m = gfc_match_dupl_check (!c->async, "async")) != MATCH_NO)
2630 : {
2631 643 : if (m == MATCH_ERROR)
2632 0 : goto error;
2633 643 : c->async = true;
2634 643 : m = gfc_match (" ( %e )", &c->async_expr);
2635 643 : if (m == MATCH_ERROR)
2636 : {
2637 0 : gfc_current_locus = old_loc;
2638 0 : break;
2639 : }
2640 643 : else if (m == MATCH_NO)
2641 : {
2642 133 : c->async_expr
2643 133 : = gfc_get_constant_expr (BT_INTEGER,
2644 : gfc_default_integer_kind,
2645 : &gfc_current_locus);
2646 133 : mpz_set_si (c->async_expr->value.integer, GOMP_ASYNC_NOVAL);
2647 : }
2648 643 : continue;
2649 : }
2650 190 : if ((mask & OMP_CLAUSE_AUTO)
2651 127 : && (m = gfc_match_dupl_check (!c->par_auto, "auto"))
2652 : != MATCH_NO)
2653 : {
2654 63 : if (m == MATCH_ERROR)
2655 0 : goto error;
2656 63 : c->par_auto = true;
2657 63 : continue;
2658 : }
2659 125 : if ((mask & OMP_CLAUSE_ATTACH)
2660 62 : && gfc_match ("attach ( ") == MATCH_YES
2661 125 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
2662 : OMP_MAP_ATTACH, false,
2663 : allow_derived))
2664 61 : continue;
2665 : break;
2666 36 : case 'b':
2667 70 : if ((mask & OMP_CLAUSE_BIND)
2668 36 : && (m = gfc_match_dupl_check (c->bind == OMP_BIND_UNSET, "bind",
2669 : true)) != MATCH_NO)
2670 : {
2671 36 : if (m == MATCH_ERROR)
2672 1 : goto error;
2673 35 : if (gfc_match ("teams )") == MATCH_YES)
2674 11 : c->bind = OMP_BIND_TEAMS;
2675 24 : else if (gfc_match ("parallel )") == MATCH_YES)
2676 15 : c->bind = OMP_BIND_PARALLEL;
2677 9 : else if (gfc_match ("thread )") == MATCH_YES)
2678 8 : c->bind = OMP_BIND_THREAD;
2679 : else
2680 : {
2681 1 : gfc_error ("Expected TEAMS, PARALLEL or THREAD as binding in "
2682 : "BIND at %C");
2683 1 : break;
2684 : }
2685 34 : continue;
2686 : }
2687 : break;
2688 7110 : case 'c':
2689 7383 : if ((mask & OMP_CLAUSE_CAPTURE)
2690 7110 : && (m = gfc_match_dupl_check (!c->capture, "capture"))
2691 : != MATCH_NO)
2692 : {
2693 274 : if (m == MATCH_ERROR)
2694 1 : goto error;
2695 273 : c->capture = true;
2696 273 : continue;
2697 : }
2698 6836 : if (mask & OMP_CLAUSE_COLLAPSE)
2699 : {
2700 1996 : gfc_expr *cexpr = NULL;
2701 1996 : if ((m = gfc_match_dupl_check (!c->collapse, "collapse", true,
2702 : &cexpr)) != MATCH_NO)
2703 : {
2704 1506 : int collapse;
2705 1506 : if (m == MATCH_ERROR)
2706 0 : goto error;
2707 1506 : if (gfc_extract_int (cexpr, &collapse, -1))
2708 4 : collapse = 1;
2709 1502 : else if (collapse <= 0)
2710 : {
2711 8 : gfc_error_now ("COLLAPSE clause argument not constant "
2712 : "positive integer at %C");
2713 8 : collapse = 1;
2714 : }
2715 1506 : gfc_free_expr (cexpr);
2716 1506 : c->collapse = collapse;
2717 1506 : continue;
2718 1506 : }
2719 : }
2720 5496 : if ((mask & OMP_CLAUSE_COMPARE)
2721 5330 : && (m = gfc_match_dupl_check (!c->compare, "compare"))
2722 : != MATCH_NO)
2723 : {
2724 167 : if (m == MATCH_ERROR)
2725 1 : goto error;
2726 166 : c->compare = true;
2727 166 : continue;
2728 : }
2729 5175 : if ((mask & OMP_CLAUSE_ASSUMPTIONS)
2730 5163 : && gfc_match ("contains ( ") == MATCH_YES)
2731 : {
2732 13 : if (gfc_omp_absent_contains_clause (&c->assume, false)
2733 : != MATCH_YES)
2734 1 : goto error;
2735 12 : continue;
2736 : }
2737 7266 : if ((mask & OMP_CLAUSE_COPY)
2738 3723 : && gfc_match ("copy ( ") == MATCH_YES
2739 7267 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
2740 : OMP_MAP_TOFROM, true,
2741 : allow_derived))
2742 2116 : continue;
2743 3034 : if (mask & OMP_CLAUSE_COPYIN)
2744 : {
2745 2628 : if (openacc)
2746 : {
2747 2529 : if (gfc_match ("copyin ( ") == MATCH_YES)
2748 : {
2749 1458 : bool readonly = gfc_match ("readonly : ") == MATCH_YES;
2750 1458 : head = NULL;
2751 1458 : if (gfc_match_omp_variable_list ("",
2752 : &c->lists[OMP_LIST_MAP],
2753 : true, NULL, &head, true,
2754 : allow_derived)
2755 : == MATCH_YES)
2756 : {
2757 1452 : gfc_omp_namelist *n;
2758 3349 : for (n = *head; n; n = n->next)
2759 : {
2760 1897 : n->u.map.op = OMP_MAP_TO;
2761 1897 : n->u.map.readonly = readonly;
2762 : }
2763 1452 : continue;
2764 1452 : }
2765 : }
2766 : }
2767 99 : else if (gfc_match_omp_variable_list ("copyin (",
2768 : &c->lists[OMP_LIST_COPYIN],
2769 : true) == MATCH_YES)
2770 97 : continue;
2771 : }
2772 2556 : if ((mask & OMP_CLAUSE_COPYOUT)
2773 1216 : && gfc_match ("copyout ( ") == MATCH_YES
2774 2556 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
2775 : OMP_MAP_FROM, true, allow_derived))
2776 1071 : continue;
2777 498 : if ((mask & OMP_CLAUSE_COPYPRIVATE)
2778 414 : && gfc_match_omp_variable_list ("copyprivate (",
2779 : &c->lists[OMP_LIST_COPYPRIVATE],
2780 : true) == MATCH_YES)
2781 84 : continue;
2782 651 : if ((mask & OMP_CLAUSE_CREATE)
2783 328 : && gfc_match ("create ( ") == MATCH_YES
2784 651 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
2785 : OMP_MAP_ALLOC, true, allow_derived))
2786 321 : continue;
2787 : break;
2788 3739 : case 'd':
2789 3739 : if ((mask & OMP_CLAUSE_DEFAULTMAP)
2790 3739 : && gfc_match ("defaultmap ( ") == MATCH_YES)
2791 : {
2792 180 : enum gfc_omp_defaultmap behavior;
2793 180 : gfc_omp_defaultmap_category category
2794 : = OMP_DEFAULTMAP_CAT_UNCATEGORIZED;
2795 180 : if (gfc_match ("alloc ") == MATCH_YES)
2796 : behavior = OMP_DEFAULTMAP_ALLOC;
2797 174 : else if (gfc_match ("tofrom ") == MATCH_YES)
2798 : behavior = OMP_DEFAULTMAP_TOFROM;
2799 142 : else if (gfc_match ("to ") == MATCH_YES)
2800 : behavior = OMP_DEFAULTMAP_TO;
2801 132 : else if (gfc_match ("from ") == MATCH_YES)
2802 : behavior = OMP_DEFAULTMAP_FROM;
2803 129 : else if (gfc_match ("firstprivate ") == MATCH_YES)
2804 : behavior = OMP_DEFAULTMAP_FIRSTPRIVATE;
2805 94 : else if (gfc_match ("present ") == MATCH_YES)
2806 : behavior = OMP_DEFAULTMAP_PRESENT;
2807 90 : else if (gfc_match ("none ") == MATCH_YES)
2808 : behavior = OMP_DEFAULTMAP_NONE;
2809 10 : else if (gfc_match ("default ") == MATCH_YES)
2810 : behavior = OMP_DEFAULTMAP_DEFAULT;
2811 : else
2812 : {
2813 1 : gfc_error ("Expected ALLOC, TO, FROM, TOFROM, FIRSTPRIVATE, "
2814 : "PRESENT, NONE or DEFAULT at %C");
2815 1 : break;
2816 : }
2817 179 : if (')' == gfc_peek_ascii_char ())
2818 : ;
2819 102 : else if (gfc_match (": ") != MATCH_YES)
2820 : break;
2821 : else
2822 : {
2823 102 : if (gfc_match ("scalar ") == MATCH_YES)
2824 : category = OMP_DEFAULTMAP_CAT_SCALAR;
2825 67 : else if (gfc_match ("aggregate ") == MATCH_YES)
2826 : category = OMP_DEFAULTMAP_CAT_AGGREGATE;
2827 43 : else if (gfc_match ("allocatable ") == MATCH_YES)
2828 : category = OMP_DEFAULTMAP_CAT_ALLOCATABLE;
2829 31 : else if (gfc_match ("pointer ") == MATCH_YES)
2830 : category = OMP_DEFAULTMAP_CAT_POINTER;
2831 14 : else if (gfc_match ("all ") == MATCH_YES)
2832 : category = OMP_DEFAULTMAP_CAT_ALL;
2833 : else
2834 : {
2835 1 : gfc_error ("Expected SCALAR, AGGREGATE, ALLOCATABLE, "
2836 : "POINTER or ALL at %C");
2837 1 : break;
2838 : }
2839 : }
2840 1193 : for (int i = 0; i < OMP_DEFAULTMAP_CAT_NUM; ++i)
2841 : {
2842 1028 : if (i != category
2843 1028 : && category != OMP_DEFAULTMAP_CAT_UNCATEGORIZED
2844 486 : && category != OMP_DEFAULTMAP_CAT_ALL
2845 486 : && i != OMP_DEFAULTMAP_CAT_UNCATEGORIZED
2846 341 : && i != OMP_DEFAULTMAP_CAT_ALL)
2847 254 : continue;
2848 774 : if (c->defaultmap[i] != OMP_DEFAULTMAP_UNSET)
2849 : {
2850 13 : const char *pcategory = NULL;
2851 13 : switch (i)
2852 : {
2853 : case OMP_DEFAULTMAP_CAT_UNCATEGORIZED: break;
2854 : case OMP_DEFAULTMAP_CAT_ALL: pcategory = "ALL"; break;
2855 1 : case OMP_DEFAULTMAP_CAT_SCALAR: pcategory = "SCALAR"; break;
2856 2 : case OMP_DEFAULTMAP_CAT_AGGREGATE:
2857 2 : pcategory = "AGGREGATE";
2858 2 : break;
2859 1 : case OMP_DEFAULTMAP_CAT_ALLOCATABLE:
2860 1 : pcategory = "ALLOCATABLE";
2861 1 : break;
2862 2 : case OMP_DEFAULTMAP_CAT_POINTER:
2863 2 : pcategory = "POINTER";
2864 2 : break;
2865 : default: gcc_unreachable ();
2866 : }
2867 6 : if (i == OMP_DEFAULTMAP_CAT_UNCATEGORIZED)
2868 4 : gfc_error ("DEFAULTMAP at %C but prior DEFAULTMAP with "
2869 : "unspecified category");
2870 : else
2871 9 : gfc_error ("DEFAULTMAP at %C but prior DEFAULTMAP for "
2872 : "category %s", pcategory);
2873 13 : goto error;
2874 : }
2875 : }
2876 165 : c->defaultmap[category] = behavior;
2877 165 : if (gfc_match (")") != MATCH_YES)
2878 : break;
2879 165 : continue;
2880 165 : }
2881 4526 : if ((mask & OMP_CLAUSE_DEFAULT)
2882 3559 : && (m = gfc_match_dupl_check (c->default_sharing
2883 : == OMP_DEFAULT_UNKNOWN, "default",
2884 : true)) != MATCH_NO)
2885 : {
2886 1012 : if (m == MATCH_ERROR)
2887 6 : goto error;
2888 1006 : if (gfc_match ("none") == MATCH_YES)
2889 596 : c->default_sharing = OMP_DEFAULT_NONE;
2890 410 : else if (openacc)
2891 : {
2892 225 : if (gfc_match ("present") == MATCH_YES)
2893 195 : c->default_sharing = OMP_DEFAULT_PRESENT;
2894 : }
2895 : else
2896 : {
2897 185 : if (gfc_match ("firstprivate") == MATCH_YES)
2898 8 : c->default_sharing = OMP_DEFAULT_FIRSTPRIVATE;
2899 177 : else if (gfc_match ("private") == MATCH_YES)
2900 24 : c->default_sharing = OMP_DEFAULT_PRIVATE;
2901 153 : else if (gfc_match ("shared") == MATCH_YES)
2902 153 : c->default_sharing = OMP_DEFAULT_SHARED;
2903 : }
2904 1006 : if (c->default_sharing == OMP_DEFAULT_UNKNOWN)
2905 : {
2906 30 : if (openacc)
2907 30 : gfc_error ("Expected NONE or PRESENT in DEFAULT clause "
2908 : "at %C");
2909 : else
2910 0 : gfc_error ("Expected NONE, FIRSTPRIVATE, PRIVATE or SHARED "
2911 : "in DEFAULT clause at %C");
2912 30 : goto error;
2913 : }
2914 976 : if (gfc_match (" )") != MATCH_YES)
2915 9 : goto error;
2916 967 : continue;
2917 : }
2918 2855 : if ((mask & OMP_CLAUSE_DELETE)
2919 345 : && gfc_match ("delete ( ") == MATCH_YES
2920 2855 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
2921 : OMP_MAP_RELEASE, true,
2922 : allow_derived))
2923 308 : continue;
2924 : /* DOACROSS: match 'doacross' and 'depend' with sink/source.
2925 : DEPEND: match 'depend' but not sink/source. */
2926 2239 : m = MATCH_NO;
2927 2239 : if (((mask & OMP_CLAUSE_DOACROSS)
2928 383 : && gfc_match ("doacross ( ") == MATCH_YES)
2929 2595 : || (((mask & OMP_CLAUSE_DEPEND) || (mask & OMP_CLAUSE_DOACROSS))
2930 1598 : && (m = gfc_match ("depend ( ")) == MATCH_YES))
2931 : {
2932 1100 : bool has_omp_all_memory;
2933 1100 : bool is_depend = m == MATCH_YES;
2934 1100 : gfc_namespace *ns_iter = NULL, *ns_curr = gfc_current_ns;
2935 1100 : match m_it = MATCH_NO;
2936 1100 : if (is_depend)
2937 1073 : m_it = gfc_match_iterator (&ns_iter, false);
2938 1073 : if (m_it == MATCH_ERROR)
2939 : break;
2940 1095 : if (m_it == MATCH_YES && gfc_match (" , ") != MATCH_YES)
2941 : break;
2942 1095 : m = MATCH_YES;
2943 1095 : gfc_omp_depend_doacross_op depend_op = OMP_DEPEND_OUT;
2944 1095 : if (gfc_match ("inoutset") == MATCH_YES)
2945 : depend_op = OMP_DEPEND_INOUTSET;
2946 1083 : else if (gfc_match ("inout") == MATCH_YES)
2947 : depend_op = OMP_DEPEND_INOUT;
2948 991 : else if (gfc_match ("in") == MATCH_YES)
2949 : depend_op = OMP_DEPEND_IN;
2950 704 : else if (gfc_match ("out") == MATCH_YES)
2951 : depend_op = OMP_DEPEND_OUT;
2952 442 : else if (gfc_match ("mutexinoutset") == MATCH_YES)
2953 : depend_op = OMP_DEPEND_MUTEXINOUTSET;
2954 424 : else if (gfc_match ("depobj") == MATCH_YES)
2955 : depend_op = OMP_DEPEND_DEPOBJ;
2956 387 : else if (gfc_match ("source") == MATCH_YES)
2957 : {
2958 143 : if (m_it == MATCH_YES)
2959 : {
2960 1 : gfc_error ("ITERATOR may not be combined with SOURCE "
2961 : "at %C");
2962 17 : goto error;
2963 : }
2964 142 : if (!(mask & OMP_CLAUSE_DOACROSS))
2965 : {
2966 1 : gfc_error ("SOURCE at %C not permitted as dependence-type"
2967 : " for this directive");
2968 1 : goto error;
2969 : }
2970 141 : if (c->doacross_source)
2971 : {
2972 0 : gfc_error ("Duplicated clause with SOURCE dependence-type"
2973 : " at %C");
2974 0 : goto error;
2975 : }
2976 141 : gfc_gobble_whitespace ();
2977 141 : m = gfc_match (": ");
2978 141 : if (m != MATCH_YES && !is_depend)
2979 : {
2980 1 : gfc_error ("Expected %<:%> at %C");
2981 1 : goto error;
2982 : }
2983 140 : if (gfc_match (")") != MATCH_YES
2984 146 : && !(m == MATCH_YES
2985 6 : && gfc_match ("omp_cur_iteration )") == MATCH_YES))
2986 : {
2987 2 : gfc_error ("Expected %<)%> or %<omp_cur_iteration)%> "
2988 : "at %C");
2989 2 : goto error;
2990 : }
2991 138 : if (is_depend)
2992 130 : gfc_warning (OPT_Wdeprecated_openmp,
2993 : "%<source%> modifier with %<depend%> clause "
2994 : "at %L deprecated since OpenMP 5.2, use with "
2995 : "%<doacross%>", &old_loc);
2996 138 : c->doacross_source = true;
2997 138 : c->depend_source = is_depend;
2998 1078 : continue;
2999 : }
3000 244 : else if (gfc_match ("sink ") == MATCH_YES)
3001 : {
3002 244 : if (!(mask & OMP_CLAUSE_DOACROSS))
3003 : {
3004 2 : gfc_error ("SINK at %C not permitted as dependence-type "
3005 : "for this directive");
3006 2 : goto error;
3007 : }
3008 242 : if (gfc_match (": ") != MATCH_YES)
3009 : {
3010 1 : gfc_error ("Expected %<:%> at %C");
3011 1 : goto error;
3012 : }
3013 241 : if (m_it == MATCH_YES)
3014 : {
3015 0 : gfc_error ("ITERATOR may not be combined with SINK "
3016 : "at %C");
3017 0 : goto error;
3018 : }
3019 241 : if (is_depend)
3020 226 : gfc_warning (OPT_Wdeprecated_openmp,
3021 : "%<sink%> modifier with %<depend%> clause at "
3022 : "%L deprecated since OpenMP 5.2, use with "
3023 : "%<doacross%>", &old_loc);
3024 241 : m = gfc_match_omp_doacross_sink (&c->lists[OMP_LIST_DEPEND],
3025 : is_depend);
3026 241 : if (m == MATCH_YES)
3027 238 : continue;
3028 3 : goto error;
3029 : }
3030 : else
3031 : m = MATCH_NO;
3032 708 : if (!(mask & OMP_CLAUSE_DEPEND))
3033 : {
3034 0 : gfc_error ("Expected dependence-type SINK or SOURCE at %C");
3035 0 : goto error;
3036 : }
3037 708 : head = NULL;
3038 708 : if (ns_iter)
3039 40 : gfc_current_ns = ns_iter;
3040 708 : if (m == MATCH_YES)
3041 708 : m = gfc_match_omp_variable_list (" : ",
3042 : &c->lists[OMP_LIST_DEPEND],
3043 : false, NULL, &head, true,
3044 : false, &has_omp_all_memory);
3045 708 : if (m != MATCH_YES)
3046 2 : goto error;
3047 706 : gfc_current_ns = ns_curr;
3048 706 : if (has_omp_all_memory && depend_op != OMP_DEPEND_INOUT
3049 21 : && depend_op != OMP_DEPEND_OUT)
3050 : {
3051 4 : gfc_error ("%<omp_all_memory%> used with DEPEND kind "
3052 : "other than OUT or INOUT at %C");
3053 4 : goto error;
3054 : }
3055 702 : gfc_omp_namelist *n;
3056 1435 : for (n = *head; n; n = n->next)
3057 : {
3058 733 : n->u.depend_doacross_op = depend_op;
3059 733 : n->u2.ns = ns_iter;
3060 733 : if (ns_iter)
3061 39 : ns_iter->refs++;
3062 : }
3063 702 : continue;
3064 702 : }
3065 1160 : if ((mask & OMP_CLAUSE_DESTROY)
3066 1139 : && gfc_match_omp_variable_list ("destroy (",
3067 : &c->lists[OMP_LIST_DESTROY],
3068 : true) == MATCH_YES)
3069 21 : continue;
3070 1244 : if ((mask & OMP_CLAUSE_DETACH)
3071 164 : && !openacc
3072 127 : && !c->detach
3073 1244 : && gfc_match_omp_detach (&c->detach) == MATCH_YES)
3074 126 : continue;
3075 1029 : if ((mask & OMP_CLAUSE_DETACH)
3076 38 : && openacc
3077 37 : && gfc_match ("detach ( ") == MATCH_YES
3078 1029 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
3079 : OMP_MAP_DETACH, false,
3080 : allow_derived))
3081 37 : continue;
3082 991 : if ((mask & OMP_CLAUSE_DEVICEPTR)
3083 87 : && gfc_match ("deviceptr ( ") == MATCH_YES
3084 993 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
3085 : OMP_MAP_FORCE_DEVICEPTR, false,
3086 : allow_derived))
3087 36 : continue;
3088 1010 : if ((mask & OMP_CLAUSE_DEVICE_TYPE)
3089 919 : && gfc_match_dupl_check (c->device_type == OMP_DEVICE_TYPE_UNSET,
3090 : "device_type", true) == MATCH_YES)
3091 : {
3092 92 : if (gfc_match ("host") == MATCH_YES)
3093 32 : c->device_type = OMP_DEVICE_TYPE_HOST;
3094 60 : else if (gfc_match ("nohost") == MATCH_YES)
3095 21 : c->device_type = OMP_DEVICE_TYPE_NOHOST;
3096 39 : else if (gfc_match ("any") == MATCH_YES)
3097 38 : c->device_type = OMP_DEVICE_TYPE_ANY;
3098 : else
3099 : {
3100 1 : gfc_error ("Expected HOST, NOHOST or ANY at %C");
3101 1 : break;
3102 : }
3103 91 : if (gfc_match (" )") != MATCH_YES)
3104 : break;
3105 91 : continue;
3106 : }
3107 875 : if ((mask & OMP_CLAUSE_DEVICE_RESIDENT)
3108 876 : && gfc_match_omp_variable_list
3109 49 : ("device_resident (",
3110 : &c->lists[OMP_LIST_DEVICE_RESIDENT], true) == MATCH_YES)
3111 48 : continue;
3112 1091 : if ((mask & OMP_CLAUSE_DEVICE)
3113 703 : && openacc
3114 314 : && gfc_match ("device ( ") == MATCH_YES
3115 1092 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
3116 : OMP_MAP_FORCE_TO, true,
3117 : /* allow_derived = */ true))
3118 312 : continue;
3119 467 : if ((mask & OMP_CLAUSE_DEVICE)
3120 391 : && !openacc
3121 856 : && ((m = gfc_match_dupl_check (!c->device, "device", true))
3122 : != MATCH_NO))
3123 : {
3124 349 : if (m == MATCH_ERROR)
3125 0 : goto error;
3126 349 : c->ancestor = false;
3127 349 : if (gfc_match ("device_num : ") == MATCH_YES)
3128 : {
3129 18 : if (gfc_match ("%e )", &c->device) != MATCH_YES)
3130 : {
3131 1 : gfc_error ("Expected integer expression at %C");
3132 1 : break;
3133 : }
3134 : }
3135 331 : else if (gfc_match ("ancestor : ") == MATCH_YES)
3136 : {
3137 45 : bool has_requires = false;
3138 45 : c->ancestor = true;
3139 82 : for (gfc_namespace *ns = gfc_current_ns; ns; ns = ns->parent)
3140 80 : if (ns->omp_requires & OMP_REQ_REVERSE_OFFLOAD)
3141 : {
3142 : has_requires = true;
3143 : break;
3144 : }
3145 45 : if (!has_requires)
3146 : {
3147 2 : gfc_error ("%<ancestor%> device modifier not "
3148 : "preceded by %<requires%> directive "
3149 : "with %<reverse_offload%> clause at %C");
3150 5 : break;
3151 : }
3152 43 : locus old_loc2 = gfc_current_locus;
3153 43 : if (gfc_match ("%e )", &c->device) == MATCH_YES)
3154 : {
3155 43 : int device = 0;
3156 43 : if (!gfc_extract_int (c->device, &device) && device != 1)
3157 : {
3158 1 : gfc_current_locus = old_loc2;
3159 1 : gfc_error ("the %<device%> clause expression must "
3160 : "evaluate to %<1%> at %C");
3161 1 : break;
3162 : }
3163 : }
3164 : else
3165 : {
3166 0 : gfc_error ("Expected integer expression at %C");
3167 0 : break;
3168 : }
3169 : }
3170 286 : else if (gfc_match ("%e )", &c->device) != MATCH_YES)
3171 : {
3172 13 : gfc_error ("Expected integer expression or a single device-"
3173 : "modifier %<device_num%> or %<ancestor%> at %C");
3174 13 : break;
3175 : }
3176 332 : continue;
3177 332 : }
3178 118 : if ((mask & OMP_CLAUSE_DIST_SCHEDULE)
3179 97 : && c->dist_sched_kind == OMP_SCHED_NONE
3180 215 : && gfc_match ("dist_schedule ( static") == MATCH_YES)
3181 : {
3182 97 : m = MATCH_NO;
3183 97 : c->dist_sched_kind = OMP_SCHED_STATIC;
3184 97 : m = gfc_match (" , %e )", &c->dist_chunk_size);
3185 97 : if (m != MATCH_YES)
3186 14 : m = gfc_match_char (')');
3187 14 : if (m != MATCH_YES)
3188 : {
3189 0 : c->dist_sched_kind = OMP_SCHED_NONE;
3190 0 : gfc_current_locus = old_loc;
3191 : }
3192 : else
3193 97 : continue;
3194 : }
3195 32 : if ((mask & OMP_CLAUSE_DYN_GROUPPRIVATE)
3196 21 : && gfc_match_dupl_check (!c->dyn_groupprivate,
3197 : "dyn_groupprivate", true) == MATCH_YES)
3198 : {
3199 12 : if (gfc_match ("fallback ( abort ) : ") == MATCH_YES)
3200 1 : c->fallback = OMP_FALLBACK_ABORT;
3201 11 : else if (gfc_match ("fallback ( default_mem ) : ") == MATCH_YES)
3202 1 : c->fallback = OMP_FALLBACK_DEFAULT_MEM;
3203 10 : else if (gfc_match ("fallback ( null ) : ") == MATCH_YES)
3204 1 : c->fallback = OMP_FALLBACK_NULL;
3205 12 : if (gfc_match_expr (&c->dyn_groupprivate) != MATCH_YES)
3206 0 : return MATCH_ERROR;
3207 12 : if (gfc_match (" )") != MATCH_YES)
3208 1 : goto error;
3209 11 : continue;
3210 : }
3211 : break;
3212 90 : case 'e':
3213 90 : if ((mask & OMP_CLAUSE_ENTER))
3214 : {
3215 90 : m = gfc_match_omp_to_link ("enter (", &c->lists[OMP_LIST_ENTER]);
3216 90 : if (m == MATCH_ERROR)
3217 0 : goto error;
3218 90 : if (m == MATCH_YES)
3219 90 : continue;
3220 : }
3221 : break;
3222 2283 : case 'f':
3223 2332 : if ((mask & OMP_CLAUSE_FAIL)
3224 2283 : && (m = gfc_match_dupl_check (c->fail == OMP_MEMORDER_UNSET,
3225 : "fail", true)) != MATCH_NO)
3226 : {
3227 58 : if (m == MATCH_ERROR)
3228 3 : goto error;
3229 55 : if (gfc_match ("seq_cst") == MATCH_YES)
3230 6 : c->fail = OMP_MEMORDER_SEQ_CST;
3231 49 : else if (gfc_match ("acquire") == MATCH_YES)
3232 14 : c->fail = OMP_MEMORDER_ACQUIRE;
3233 35 : else if (gfc_match ("relaxed") == MATCH_YES)
3234 30 : c->fail = OMP_MEMORDER_RELAXED;
3235 : else
3236 : {
3237 5 : gfc_error ("Expected SEQ_CST, ACQUIRE or RELAXED at %C");
3238 5 : break;
3239 : }
3240 50 : if (gfc_match (" )") != MATCH_YES)
3241 1 : goto error;
3242 49 : continue;
3243 : }
3244 2268 : if ((mask & OMP_CLAUSE_FILTER)
3245 2225 : && (m = gfc_match_dupl_check (!c->filter, "filter", true,
3246 : &c->filter)) != MATCH_NO)
3247 : {
3248 44 : if (m == MATCH_ERROR)
3249 1 : goto error;
3250 43 : continue;
3251 : }
3252 2245 : if ((mask & OMP_CLAUSE_FINAL)
3253 2181 : && (m = gfc_match_dupl_check (!c->final_expr, "final", true,
3254 : &c->final_expr)) != MATCH_NO)
3255 : {
3256 64 : if (m == MATCH_ERROR)
3257 0 : goto error;
3258 64 : continue;
3259 : }
3260 2143 : if ((mask & OMP_CLAUSE_FINALIZE)
3261 2117 : && (m = gfc_match_dupl_check (!c->finalize, "finalize"))
3262 : != MATCH_NO)
3263 : {
3264 26 : if (m == MATCH_ERROR)
3265 0 : goto error;
3266 26 : c->finalize = true;
3267 26 : continue;
3268 : }
3269 3105 : if ((mask & OMP_CLAUSE_FIRSTPRIVATE)
3270 2091 : && gfc_match_omp_variable_list ("firstprivate (",
3271 : &c->lists[OMP_LIST_FIRSTPRIVATE],
3272 : true) == MATCH_YES)
3273 1014 : continue;
3274 2076 : if ((mask & OMP_CLAUSE_FROM)
3275 1077 : && gfc_match_motion_var_list ("from (", &c->lists[OMP_LIST_FROM],
3276 : &head) == MATCH_YES)
3277 999 : continue;
3278 143 : if ((mask & OMP_CLAUSE_FULL)
3279 78 : && (m = gfc_match_dupl_check (!c->full, "full")) != MATCH_NO)
3280 : {
3281 65 : if (m == MATCH_ERROR)
3282 0 : goto error;
3283 65 : c->full = true;
3284 65 : continue;
3285 : }
3286 : break;
3287 1231 : case 'g':
3288 2423 : if ((mask & OMP_CLAUSE_GANG)
3289 1231 : && (m = gfc_match_dupl_check (!c->gang, "gang")) != MATCH_NO)
3290 : {
3291 1197 : if (m == MATCH_ERROR)
3292 0 : goto error;
3293 1197 : c->gang = true;
3294 1197 : m = match_oacc_clause_gwv (c, GOMP_DIM_GANG);
3295 1197 : if (m == MATCH_ERROR)
3296 : {
3297 5 : gfc_current_locus = old_loc;
3298 5 : break;
3299 : }
3300 1192 : continue;
3301 : }
3302 68 : if ((mask & OMP_CLAUSE_GRAINSIZE)
3303 34 : && (m = gfc_match_dupl_check (!c->grainsize, "grainsize", true))
3304 : != MATCH_NO)
3305 : {
3306 34 : if (m == MATCH_ERROR)
3307 0 : goto error;
3308 34 : if (gfc_match ("strict : ") == MATCH_YES)
3309 1 : c->grainsize_strict = true;
3310 34 : if (gfc_match (" %e )", &c->grainsize) != MATCH_YES)
3311 0 : goto error;
3312 34 : continue;
3313 : }
3314 : break;
3315 465 : case 'h':
3316 513 : if ((mask & OMP_CLAUSE_HAS_DEVICE_ADDR)
3317 513 : && gfc_match_omp_variable_list
3318 48 : ("has_device_addr (", &c->lists[OMP_LIST_HAS_DEVICE_ADDR],
3319 : false, NULL, NULL, true) == MATCH_YES)
3320 48 : continue;
3321 460 : if ((mask & OMP_CLAUSE_HINT)
3322 417 : && (m = gfc_match_dupl_check (!c->hint, "hint", true, &c->hint))
3323 : != MATCH_NO)
3324 : {
3325 43 : if (m == MATCH_ERROR)
3326 0 : goto error;
3327 43 : continue;
3328 : }
3329 374 : if ((mask & OMP_CLAUSE_ASSUMPTIONS)
3330 374 : && gfc_match ("holds ( ") == MATCH_YES)
3331 : {
3332 19 : gfc_expr *e;
3333 19 : if (gfc_match ("%e )", &e) != MATCH_YES)
3334 0 : goto error;
3335 19 : if (c->assume == NULL)
3336 12 : c->assume = gfc_get_omp_assumptions ();
3337 19 : gfc_expr_list *el = XCNEW (gfc_expr_list);
3338 19 : el->expr = e;
3339 19 : el->next = c->assume->holds;
3340 19 : c->assume->holds = el;
3341 19 : continue;
3342 19 : }
3343 709 : if ((mask & OMP_CLAUSE_HOST)
3344 355 : && gfc_match ("host ( ") == MATCH_YES
3345 710 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
3346 : OMP_MAP_FORCE_FROM, true,
3347 : /* allow_derived = */ true))
3348 354 : continue;
3349 : break;
3350 2119 : case 'i':
3351 2142 : if ((mask & OMP_CLAUSE_IF_PRESENT)
3352 2119 : && (m = gfc_match_dupl_check (!c->if_present, "if_present"))
3353 : != MATCH_NO)
3354 : {
3355 23 : if (m == MATCH_ERROR)
3356 0 : goto error;
3357 23 : c->if_present = true;
3358 23 : continue;
3359 : }
3360 2096 : if ((mask & OMP_CLAUSE_IF)
3361 2096 : && (m = gfc_match_dupl_check (!c->if_expr, "if", true))
3362 : != MATCH_NO)
3363 : {
3364 1347 : if (m == MATCH_ERROR)
3365 12 : goto error;
3366 1335 : if (!openacc)
3367 : {
3368 : /* This should match the enum gfc_omp_if_kind order. */
3369 : static const char *ifs[OMP_IF_LAST] = {
3370 : "cancel : %e )",
3371 : "parallel : %e )",
3372 : "simd : %e )",
3373 : "task : %e )",
3374 : "taskloop : %e )",
3375 : "target : %e )",
3376 : "target data : %e )",
3377 : "target update : %e )",
3378 : "target enter data : %e )",
3379 : "target exit data : %e )" };
3380 : int i;
3381 4841 : for (i = 0; i < OMP_IF_LAST; i++)
3382 4443 : if (c->if_exprs[i] == NULL
3383 4443 : && gfc_match (ifs[i], &c->if_exprs[i]) == MATCH_YES)
3384 : break;
3385 536 : if (i < OMP_IF_LAST)
3386 138 : continue;
3387 : }
3388 1197 : if (gfc_match (" %e )", &c->if_expr) == MATCH_YES)
3389 1192 : continue;
3390 5 : goto error;
3391 : }
3392 866 : if ((mask & OMP_CLAUSE_IN_REDUCTION)
3393 749 : && gfc_match_omp_clause_reduction (pc, c, openacc, allow_derived,
3394 : openmp_target) == MATCH_YES)
3395 117 : continue;
3396 657 : if ((mask & OMP_CLAUSE_INBRANCH)
3397 632 : && (m = gfc_match_dupl_check (!c->inbranch && !c->notinbranch,
3398 : "inbranch")) != MATCH_NO)
3399 : {
3400 25 : if (m == MATCH_ERROR)
3401 0 : goto error;
3402 25 : c->inbranch = true;
3403 25 : continue;
3404 : }
3405 849 : if ((mask & OMP_CLAUSE_INDEPENDENT)
3406 607 : && (m = gfc_match_dupl_check (!c->independent, "independent"))
3407 : != MATCH_NO)
3408 : {
3409 242 : if (m == MATCH_ERROR)
3410 0 : goto error;
3411 242 : c->independent = true;
3412 242 : continue;
3413 : }
3414 365 : if ((mask & OMP_CLAUSE_INDIRECT)
3415 365 : && (m = gfc_match_dupl_check (!c->indirect, "indirect"))
3416 : != MATCH_NO)
3417 : {
3418 61 : if (m == MATCH_ERROR)
3419 5 : goto error;
3420 60 : gfc_expr *indirect_expr = NULL;
3421 60 : m = gfc_match (" ( %e )", &indirect_expr);
3422 60 : if (m == MATCH_YES)
3423 : {
3424 13 : if (!gfc_resolve_expr (indirect_expr)
3425 13 : || indirect_expr->ts.type != BT_LOGICAL
3426 23 : || indirect_expr->expr_type != EXPR_CONSTANT)
3427 : {
3428 4 : gfc_error ("INDIRECT clause at %C requires a constant "
3429 : "logical expression");
3430 4 : gfc_free_expr (indirect_expr);
3431 4 : goto error;
3432 : }
3433 9 : c->indirect = indirect_expr->value.logical;
3434 9 : gfc_free_expr (indirect_expr);
3435 : }
3436 : else
3437 47 : c->indirect = 1;
3438 56 : continue;
3439 56 : }
3440 304 : if ((mask & OMP_CLAUSE_INIT)
3441 304 : && gfc_match ("init ( ") == MATCH_YES)
3442 : {
3443 108 : m = gfc_match_omp_init (&c->lists[OMP_LIST_INIT]);
3444 108 : if (m == MATCH_YES)
3445 63 : continue;
3446 45 : goto error;
3447 : }
3448 196 : if ((mask & OMP_CLAUSE_INTEROP)
3449 196 : && (m = gfc_match_dupl_check (!c->lists[OMP_LIST_INTEROP],
3450 : "interop", true)) != MATCH_NO)
3451 : {
3452 : /* Note: the interop objects are saved in reverse order to match
3453 : the order in C/C++. */
3454 125 : if (m == MATCH_YES
3455 63 : && (gfc_match_omp_variable_list ("",
3456 : &c->lists[OMP_LIST_INTEROP],
3457 : false, NULL, NULL, false,
3458 : false, NULL, false, true)
3459 : == MATCH_YES))
3460 62 : continue;
3461 1 : goto error;
3462 : }
3463 253 : if ((mask & OMP_CLAUSE_IS_DEVICE_PTR)
3464 253 : && gfc_match_omp_variable_list
3465 120 : ("is_device_ptr (",
3466 : &c->lists[OMP_LIST_IS_DEVICE_PTR], false) == MATCH_YES)
3467 120 : continue;
3468 : break;
3469 2334 : case 'l':
3470 2334 : if ((mask & OMP_CLAUSE_LASTPRIVATE)
3471 2334 : && gfc_match ("lastprivate ( ") == MATCH_YES)
3472 : {
3473 1431 : bool conditional = gfc_match ("conditional : ") == MATCH_YES;
3474 1431 : head = NULL;
3475 1431 : if (gfc_match_omp_variable_list ("",
3476 : &c->lists[OMP_LIST_LASTPRIVATE],
3477 : false, NULL, &head) == MATCH_YES)
3478 : {
3479 1431 : gfc_omp_namelist *n;
3480 3737 : for (n = *head; n; n = n->next)
3481 2306 : n->u.lastprivate_conditional = conditional;
3482 1431 : continue;
3483 1431 : }
3484 0 : gfc_current_locus = old_loc;
3485 0 : break;
3486 : }
3487 903 : end_colon = false;
3488 903 : head = NULL;
3489 903 : if ((mask & OMP_CLAUSE_LINEAR)
3490 903 : && gfc_match ("linear (") == MATCH_YES)
3491 : {
3492 836 : bool old_linear_modifier = false;
3493 836 : gfc_omp_linear_op linear_op = OMP_LINEAR_DEFAULT;
3494 836 : gfc_expr *step = NULL;
3495 836 : locus saved_loc = gfc_current_locus;
3496 :
3497 836 : if (gfc_match_omp_variable_list (" ref (",
3498 : &c->lists[OMP_LIST_LINEAR],
3499 : false, NULL, &head)
3500 : == MATCH_YES)
3501 : {
3502 : linear_op = OMP_LINEAR_REF;
3503 : old_linear_modifier = true;
3504 : }
3505 808 : else if (gfc_match_omp_variable_list (" val (",
3506 : &c->lists[OMP_LIST_LINEAR],
3507 : false, NULL, &head)
3508 : == MATCH_YES)
3509 : {
3510 : linear_op = OMP_LINEAR_VAL;
3511 : old_linear_modifier = true;
3512 : }
3513 797 : else if (gfc_match_omp_variable_list (" uval (",
3514 : &c->lists[OMP_LIST_LINEAR],
3515 : false, NULL, &head)
3516 : == MATCH_YES)
3517 : {
3518 : linear_op = OMP_LINEAR_UVAL;
3519 : old_linear_modifier = true;
3520 : }
3521 788 : else if (gfc_match_omp_variable_list ("",
3522 : &c->lists[OMP_LIST_LINEAR],
3523 : false, &end_colon, &head)
3524 : == MATCH_YES)
3525 : linear_op = OMP_LINEAR_DEFAULT;
3526 : else
3527 : {
3528 2 : gfc_current_locus = old_loc;
3529 2 : break;
3530 : }
3531 : if (linear_op != OMP_LINEAR_DEFAULT)
3532 : {
3533 48 : if (gfc_match (" :") == MATCH_YES)
3534 31 : end_colon = true;
3535 17 : else if (gfc_match (" )") != MATCH_YES)
3536 : {
3537 0 : gfc_free_omp_namelist (*head, OMP_LIST_LINEAR);
3538 0 : gfc_current_locus = old_loc;
3539 0 : *head = NULL;
3540 0 : break;
3541 : }
3542 : }
3543 834 : gfc_gobble_whitespace ();
3544 834 : if (old_linear_modifier && end_colon)
3545 : {
3546 31 : if (gfc_match (" %e )", &step) != MATCH_YES)
3547 : {
3548 1 : gfc_free_omp_namelist (*head, OMP_LIST_LINEAR);
3549 1 : gfc_current_locus = old_loc;
3550 1 : *head = NULL;
3551 5 : goto error;
3552 : }
3553 : }
3554 833 : if (old_linear_modifier)
3555 : {
3556 47 : char var_names[512]{};
3557 47 : int count, offset = 0;
3558 106 : for (gfc_omp_namelist *n = *head; n; n = n->next)
3559 : {
3560 59 : if (!n->next)
3561 47 : count = snprintf (var_names + offset,
3562 47 : sizeof (var_names) - offset,
3563 47 : "%s", n->sym->name);
3564 : else
3565 12 : count = snprintf (var_names + offset,
3566 12 : sizeof (var_names) - offset,
3567 12 : "%s, ", n->sym->name);
3568 59 : if (count < 0 || count >= ((int)sizeof (var_names))
3569 59 : - offset)
3570 : {
3571 0 : snprintf (var_names, 512, "%s, ..., ",
3572 0 : (*head)->sym->name);
3573 0 : while (n->next)
3574 : n = n->next;
3575 0 : offset = strlen (var_names);
3576 0 : snprintf (var_names + offset,
3577 0 : sizeof (var_names) - offset,
3578 0 : "%s", n->sym->name);
3579 0 : break;
3580 : }
3581 59 : offset += count;
3582 : }
3583 47 : char *var_names_for_warn = var_names;
3584 47 : const char *op_name;
3585 47 : switch (linear_op)
3586 : {
3587 : case OMP_LINEAR_REF: op_name = "ref"; break;
3588 10 : case OMP_LINEAR_VAL: op_name = "val"; break;
3589 9 : case OMP_LINEAR_UVAL: op_name = "uval"; break;
3590 0 : default: gcc_unreachable ();
3591 : }
3592 47 : gfc_warning (OPT_Wdeprecated_openmp,
3593 : "Specification of the list items as "
3594 : "arguments to the modifiers at %L is "
3595 : "deprecated; since OpenMP 5.2, use "
3596 : "%<linear(%s : %s%s)%>", &saved_loc,
3597 : var_names_for_warn, op_name,
3598 47 : step == nullptr ? "" : ", step(...)");
3599 : }
3600 786 : else if (end_colon)
3601 : {
3602 713 : bool has_error = false;
3603 : bool has_modifiers = false;
3604 : bool has_step = false;
3605 713 : bool duplicate_step = false;
3606 713 : bool duplicate_mod = false;
3607 713 : while (true)
3608 : {
3609 713 : old_loc = gfc_current_locus;
3610 713 : bool close_paren = gfc_match ("val )") == MATCH_YES;
3611 713 : if (close_paren || gfc_match ("val , ") == MATCH_YES)
3612 : {
3613 17 : if (linear_op != OMP_LINEAR_DEFAULT)
3614 : {
3615 : duplicate_mod = true;
3616 : break;
3617 : }
3618 16 : linear_op = OMP_LINEAR_VAL;
3619 16 : has_modifiers = true;
3620 16 : if (close_paren)
3621 : break;
3622 10 : continue;
3623 : }
3624 696 : close_paren = gfc_match ("uval )") == MATCH_YES;
3625 696 : if (close_paren || gfc_match ("uval , ") == MATCH_YES)
3626 : {
3627 7 : if (linear_op != OMP_LINEAR_DEFAULT)
3628 : {
3629 : duplicate_mod = true;
3630 : break;
3631 : }
3632 7 : linear_op = OMP_LINEAR_UVAL;
3633 7 : has_modifiers = true;
3634 7 : if (close_paren)
3635 : break;
3636 2 : continue;
3637 : }
3638 689 : close_paren = gfc_match ("ref )") == MATCH_YES;
3639 689 : if (close_paren || gfc_match ("ref , ") == MATCH_YES)
3640 : {
3641 16 : if (linear_op != OMP_LINEAR_DEFAULT)
3642 : {
3643 : duplicate_mod = true;
3644 : break;
3645 : }
3646 15 : linear_op = OMP_LINEAR_REF;
3647 15 : has_modifiers = true;
3648 15 : if (close_paren)
3649 : break;
3650 7 : continue;
3651 : }
3652 673 : close_paren = (gfc_match ("step ( %e ) )", &step)
3653 : == MATCH_YES);
3654 684 : if (close_paren
3655 673 : || gfc_match ("step ( %e ) , ", &step) == MATCH_YES)
3656 : {
3657 38 : if (has_step)
3658 : {
3659 : duplicate_step = true;
3660 : break;
3661 : }
3662 37 : has_modifiers = has_step = true;
3663 37 : if (close_paren)
3664 : break;
3665 11 : continue;
3666 : }
3667 635 : if (!has_modifiers
3668 635 : && gfc_match ("%e )", &step) == MATCH_YES)
3669 : {
3670 635 : if ((step->expr_type == EXPR_FUNCTION
3671 634 : || step->expr_type == EXPR_VARIABLE)
3672 31 : && strcmp (step->symtree->name, "step") == 0)
3673 : {
3674 1 : gfc_current_locus = old_loc;
3675 1 : gfc_match ("step (");
3676 1 : has_error = true;
3677 : }
3678 : break;
3679 : }
3680 : has_error = true;
3681 : break;
3682 : }
3683 49 : if (duplicate_mod || duplicate_step)
3684 : {
3685 3 : gfc_error ("Multiple %qs modifiers specified at %C",
3686 : duplicate_mod ? "linear" : "step");
3687 3 : has_error = true;
3688 : }
3689 683 : if (has_error)
3690 : {
3691 4 : gfc_free_omp_namelist (*head, OMP_LIST_LINEAR);
3692 4 : *head = NULL;
3693 4 : goto error;
3694 : }
3695 : }
3696 829 : if (step == NULL)
3697 : {
3698 130 : step = gfc_get_constant_expr (BT_INTEGER,
3699 : gfc_default_integer_kind,
3700 : &old_loc);
3701 130 : mpz_set_si (step->value.integer, 1);
3702 : }
3703 829 : (*head)->expr = step;
3704 829 : if (linear_op != OMP_LINEAR_DEFAULT || old_linear_modifier)
3705 176 : for (gfc_omp_namelist *n = *head; n; n = n->next)
3706 : {
3707 94 : n->u.linear.op = linear_op;
3708 94 : n->u.linear.old_modifier = old_linear_modifier;
3709 : }
3710 829 : continue;
3711 829 : }
3712 71 : if ((mask & OMP_CLAUSE_LINK)
3713 67 : && openacc
3714 75 : && (gfc_match_oacc_clause_link ("link (",
3715 : &c->lists[OMP_LIST_LINK])
3716 : == MATCH_YES))
3717 4 : continue;
3718 110 : else if ((mask & OMP_CLAUSE_LINK)
3719 63 : && !openacc
3720 122 : && (gfc_match_omp_to_link ("link (",
3721 : &c->lists[OMP_LIST_LINK])
3722 : == MATCH_YES))
3723 47 : continue;
3724 28 : if ((mask & OMP_CLAUSE_LOCAL)
3725 16 : && (gfc_match_omp_to_link ("local (", &c->lists[OMP_LIST_LOCAL])
3726 : == MATCH_YES))
3727 12 : continue;
3728 : break;
3729 5832 : case 'm':
3730 5832 : if ((mask & OMP_CLAUSE_MAP)
3731 5832 : && gfc_match ("map ( ") == MATCH_YES)
3732 : {
3733 5740 : locus old_loc2 = gfc_current_locus;
3734 5740 : int always_modifier = 0;
3735 5740 : int close_modifier = 0;
3736 5740 : int present_modifier = 0;
3737 5740 : int mapper_modifier = 0;
3738 5740 : locus second_always_locus = old_loc2;
3739 5740 : locus second_close_locus = old_loc2;
3740 5740 : locus second_mapper_locus = old_loc2;
3741 5740 : locus second_present_locus = old_loc2;
3742 5740 : char mapper_id[GFC_MAX_SYMBOL_LEN + 1] = { '\0' };
3743 :
3744 6310 : for (;;)
3745 : {
3746 6025 : locus current_locus = gfc_current_locus;
3747 6025 : if (gfc_match ("always ") == MATCH_YES)
3748 : {
3749 148 : if (always_modifier++ == 1)
3750 5 : second_always_locus = current_locus;
3751 : }
3752 5877 : else if (gfc_match ("close ") == MATCH_YES)
3753 : {
3754 69 : if (close_modifier++ == 1)
3755 5 : second_close_locus = current_locus;
3756 : }
3757 5808 : else if (gfc_match ("present ") == MATCH_YES)
3758 : {
3759 67 : if (present_modifier++ == 1)
3760 4 : second_present_locus = current_locus;
3761 : }
3762 5741 : else if (gfc_match ("mapper ( ") == MATCH_YES)
3763 : {
3764 1 : if (mapper_modifier++ == 1)
3765 0 : second_mapper_locus = current_locus;
3766 1 : m = gfc_match (" %n ) ", mapper_id);
3767 1 : if (m != MATCH_YES)
3768 0 : goto error;
3769 : }
3770 : else
3771 : break;
3772 285 : if (gfc_match (", ") != MATCH_YES)
3773 62 : gfc_warning (OPT_Wdeprecated_openmp,
3774 : "The specification of modifiers without "
3775 : "comma separators for the %<map%> clause "
3776 : "at %C has been deprecated since "
3777 : "OpenMP 5.2");
3778 285 : }
3779 :
3780 5740 : gfc_omp_map_op map_op = default_map_op;
3781 5740 : int always_present_modifier
3782 5740 : = always_modifier && present_modifier;
3783 :
3784 5740 : if (gfc_match ("alloc : ") == MATCH_YES)
3785 799 : map_op = (present_modifier ? OMP_MAP_PRESENT_ALLOC
3786 : : OMP_MAP_ALLOC);
3787 4941 : else if (gfc_match ("tofrom : ") == MATCH_YES)
3788 948 : map_op = (always_present_modifier ? OMP_MAP_ALWAYS_PRESENT_TOFROM
3789 944 : : present_modifier ? OMP_MAP_PRESENT_TOFROM
3790 939 : : always_modifier ? OMP_MAP_ALWAYS_TOFROM
3791 : : OMP_MAP_TOFROM);
3792 3993 : else if (gfc_match ("to : ") == MATCH_YES)
3793 1772 : map_op = (always_present_modifier ? OMP_MAP_ALWAYS_PRESENT_TO
3794 1766 : : present_modifier ? OMP_MAP_PRESENT_TO
3795 1754 : : always_modifier ? OMP_MAP_ALWAYS_TO
3796 : : OMP_MAP_TO);
3797 2221 : else if (gfc_match ("from : ") == MATCH_YES)
3798 1616 : map_op = (always_present_modifier ? OMP_MAP_ALWAYS_PRESENT_FROM
3799 1612 : : present_modifier ? OMP_MAP_PRESENT_FROM
3800 1607 : : always_modifier ? OMP_MAP_ALWAYS_FROM
3801 : : OMP_MAP_FROM);
3802 605 : else if (gfc_match ("release : ") == MATCH_YES)
3803 : map_op = OMP_MAP_RELEASE;
3804 552 : else if (gfc_match ("delete : ") == MATCH_YES)
3805 : map_op = OMP_MAP_DELETE;
3806 : else
3807 : {
3808 475 : gfc_current_locus = old_loc2;
3809 475 : always_modifier = 0;
3810 475 : close_modifier = 0;
3811 475 : mapper_modifier = 0;
3812 : }
3813 :
3814 1552 : if (always_modifier > 1)
3815 : {
3816 5 : gfc_error ("too many %<always%> modifiers at %L",
3817 : &second_always_locus);
3818 21 : break;
3819 : }
3820 5735 : if (close_modifier > 1)
3821 : {
3822 4 : gfc_error ("too many %<close%> modifiers at %L",
3823 : &second_close_locus);
3824 4 : break;
3825 : }
3826 5731 : if (present_modifier > 1)
3827 : {
3828 4 : gfc_error ("too many %<present%> modifiers at %L",
3829 : &second_present_locus);
3830 4 : break;
3831 : }
3832 5727 : if (mapper_modifier > 1)
3833 : {
3834 0 : gfc_error ("too many %<mapper%> modifiers at %L",
3835 : &second_mapper_locus);
3836 0 : break;
3837 : }
3838 :
3839 5727 : head = NULL;
3840 5727 : if (gfc_match_omp_variable_list ("", &c->lists[OMP_LIST_MAP],
3841 : false, NULL, &head,
3842 : true, true) == MATCH_YES)
3843 : {
3844 5724 : gfc_omp_namelist *n;
3845 13019 : for (n = *head; n; n = n->next)
3846 : {
3847 7295 : n->u.map.op = map_op;
3848 :
3849 7295 : gfc_typespec *ts;
3850 7295 : if (n->expr)
3851 2383 : ts = &n->expr->ts;
3852 : else
3853 4912 : ts = &n->sym->ts;
3854 :
3855 7295 : gfc_omp_udm *udm
3856 7295 : = gfc_find_omp_udm (gfc_current_ns, mapper_id, ts);
3857 7295 : if (udm)
3858 : {
3859 4 : n->u2.udm.udm = udm;
3860 : }
3861 : }
3862 5724 : continue;
3863 5724 : }
3864 3 : gfc_current_locus = old_loc;
3865 3 : break;
3866 : }
3867 126 : if ((mask & OMP_CLAUSE_MERGEABLE)
3868 92 : && (m = gfc_match_dupl_check (!c->mergeable, "mergeable"))
3869 : != MATCH_NO)
3870 : {
3871 34 : if (m == MATCH_ERROR)
3872 0 : goto error;
3873 34 : c->mergeable = true;
3874 34 : continue;
3875 : }
3876 111 : if ((mask & OMP_CLAUSE_MESSAGE)
3877 58 : && (m = gfc_match_dupl_check (!c->message, "message", true,
3878 : &c->message)) != MATCH_NO)
3879 : {
3880 58 : if (m == MATCH_ERROR)
3881 5 : goto error;
3882 53 : continue;
3883 : }
3884 : break;
3885 2910 : case 'n':
3886 2962 : if ((mask & OMP_CLAUSE_NO_CREATE)
3887 1343 : && gfc_match ("no_create ( ") == MATCH_YES
3888 2962 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
3889 : OMP_MAP_IF_PRESENT, true,
3890 : allow_derived))
3891 52 : continue;
3892 2859 : if ((mask & OMP_CLAUSE_ASSUMPTIONS)
3893 2884 : && (m = gfc_match_dupl_check (!c->assume
3894 26 : || !c->assume->no_openmp_constructs,
3895 : "no_openmp_constructs")) != MATCH_NO)
3896 : {
3897 2 : if (m == MATCH_ERROR)
3898 1 : goto error;
3899 1 : if (c->assume == NULL)
3900 0 : c->assume = gfc_get_omp_assumptions ();
3901 1 : c->assume->no_openmp_constructs = true;
3902 1 : continue;
3903 : }
3904 2869 : if ((mask & OMP_CLAUSE_ASSUMPTIONS)
3905 2880 : && (m = gfc_match_dupl_check (!c->assume
3906 24 : || !c->assume->no_openmp_routines,
3907 : "no_openmp_routines")) != MATCH_NO)
3908 : {
3909 13 : if (m == MATCH_ERROR)
3910 0 : goto error;
3911 13 : if (c->assume == NULL)
3912 12 : c->assume = gfc_get_omp_assumptions ();
3913 13 : c->assume->no_openmp_routines = true;
3914 13 : continue;
3915 : }
3916 2847 : if ((mask & OMP_CLAUSE_ASSUMPTIONS)
3917 2853 : && (m = gfc_match_dupl_check (!c->assume || !c->assume->no_openmp,
3918 : "no_openmp")) != MATCH_NO)
3919 : {
3920 4 : if (m == MATCH_ERROR)
3921 0 : goto error;
3922 4 : if (c->assume == NULL)
3923 4 : c->assume = gfc_get_omp_assumptions ();
3924 4 : c->assume->no_openmp = true;
3925 4 : continue;
3926 : }
3927 2845 : if ((mask & OMP_CLAUSE_ASSUMPTIONS)
3928 2846 : && (m = gfc_match_dupl_check (!c->assume
3929 7 : || !c->assume->no_parallelism,
3930 : "no_parallelism")) != MATCH_NO)
3931 : {
3932 6 : if (m == MATCH_ERROR)
3933 0 : goto error;
3934 6 : if (c->assume == NULL)
3935 6 : c->assume = gfc_get_omp_assumptions ();
3936 6 : c->assume->no_parallelism = true;
3937 6 : continue;
3938 : }
3939 :
3940 2843 : if ((mask & OMP_CLAUSE_NOVARIANTS)
3941 2833 : && (m = gfc_match_dupl_check (!c->novariants, "novariants", true,
3942 : &c->novariants))
3943 : != MATCH_NO)
3944 : {
3945 12 : if (m == MATCH_ERROR)
3946 2 : goto error;
3947 10 : continue;
3948 : }
3949 2834 : if ((mask & OMP_CLAUSE_NOCONTEXT)
3950 2821 : && (m = gfc_match_dupl_check (!c->nocontext, "nocontext", true,
3951 : &c->nocontext))
3952 : != MATCH_NO)
3953 : {
3954 15 : if (m == MATCH_ERROR)
3955 2 : goto error;
3956 13 : continue;
3957 : }
3958 2820 : if ((mask & OMP_CLAUSE_NOGROUP)
3959 2806 : && (m = gfc_match_dupl_check (!c->nogroup, "nogroup"))
3960 : != MATCH_NO)
3961 : {
3962 14 : if (m == MATCH_ERROR)
3963 0 : goto error;
3964 14 : c->nogroup = true;
3965 14 : continue;
3966 : }
3967 2942 : if ((mask & OMP_CLAUSE_NOHOST)
3968 2792 : && (m = gfc_match_dupl_check (!c->nohost, "nohost")) != MATCH_NO)
3969 : {
3970 151 : if (m == MATCH_ERROR)
3971 1 : goto error;
3972 150 : c->nohost = true;
3973 150 : continue;
3974 : }
3975 2683 : if ((mask & OMP_CLAUSE_NOTEMPORAL)
3976 2641 : && gfc_match_omp_variable_list ("nontemporal (",
3977 : &c->lists[OMP_LIST_NONTEMPORAL],
3978 : true) == MATCH_YES)
3979 42 : continue;
3980 2623 : if ((mask & OMP_CLAUSE_NOTINBRANCH)
3981 2600 : && (m = gfc_match_dupl_check (!c->notinbranch && !c->inbranch,
3982 : "notinbranch")) != MATCH_NO)
3983 : {
3984 25 : if (m == MATCH_ERROR)
3985 1 : goto error;
3986 24 : c->notinbranch = true;
3987 24 : continue;
3988 : }
3989 2703 : if ((mask & OMP_CLAUSE_NOWAIT)
3990 2574 : && (m = gfc_match_dupl_check (!c->nowait, "nowait")) != MATCH_NO)
3991 : {
3992 132 : if (m == MATCH_ERROR)
3993 3 : goto error;
3994 129 : c->nowait = true;
3995 129 : continue;
3996 : }
3997 3124 : if ((mask & OMP_CLAUSE_NUM_GANGS)
3998 2442 : && (m = gfc_match_dupl_check (!c->num_gangs_expr, "num_gangs",
3999 : true)) != MATCH_NO)
4000 : {
4001 686 : if (m == MATCH_ERROR)
4002 2 : goto error;
4003 684 : if (gfc_match (" %e )", &c->num_gangs_expr) != MATCH_YES)
4004 2 : goto error;
4005 682 : continue;
4006 : }
4007 1782 : if ((mask & OMP_CLAUSE_NUM_TASKS)
4008 1756 : && (m = gfc_match_dupl_check (!c->num_tasks, "num_tasks", true))
4009 : != MATCH_NO)
4010 : {
4011 26 : if (m == MATCH_ERROR)
4012 0 : goto error;
4013 26 : if (gfc_match ("strict : ") == MATCH_YES)
4014 1 : c->num_tasks_strict = true;
4015 26 : if (gfc_match (" %e )", &c->num_tasks) != MATCH_YES)
4016 0 : goto error;
4017 26 : continue;
4018 : }
4019 1857 : if ((mask & OMP_CLAUSE_NUM_TEAMS)
4020 1730 : && (m = gfc_match_dupl_check (!c->num_teams_upper, "num_teams",
4021 : true)) != MATCH_NO)
4022 : {
4023 127 : if (m == MATCH_ERROR)
4024 0 : goto error;
4025 127 : if (gfc_match ("%e ", &c->num_teams_upper) != MATCH_YES)
4026 0 : goto error;
4027 127 : if (gfc_peek_ascii_char () == ':')
4028 : {
4029 21 : c->num_teams_lower = c->num_teams_upper;
4030 21 : c->num_teams_upper = NULL;
4031 21 : if (gfc_match (": %e ", &c->num_teams_upper) != MATCH_YES)
4032 0 : goto error;
4033 : }
4034 127 : if (gfc_match (") ") != MATCH_YES)
4035 0 : goto error;
4036 127 : continue;
4037 : }
4038 2565 : if ((mask & OMP_CLAUSE_NUM_THREADS)
4039 1603 : && (m = gfc_match_dupl_check (!c->num_threads, "num_threads", true,
4040 : &c->num_threads)) != MATCH_NO)
4041 : {
4042 962 : if (m == MATCH_ERROR)
4043 0 : goto error;
4044 962 : continue;
4045 : }
4046 1240 : if ((mask & OMP_CLAUSE_NUM_WORKERS)
4047 641 : && (m = gfc_match_dupl_check (!c->num_workers_expr, "num_workers",
4048 : true, &c->num_workers_expr))
4049 : != MATCH_NO)
4050 : {
4051 603 : if (m == MATCH_ERROR)
4052 4 : goto error;
4053 599 : continue;
4054 : }
4055 : break;
4056 591 : case 'o':
4057 591 : if ((mask & OMP_CLAUSE_ORDERED)
4058 591 : && (m = gfc_match_dupl_check (!c->ordered, "ordered"))
4059 : != MATCH_NO)
4060 : {
4061 343 : if (m == MATCH_ERROR)
4062 0 : goto error;
4063 343 : gfc_expr *cexpr = NULL;
4064 343 : m = gfc_match (" ( %e )", &cexpr);
4065 :
4066 343 : c->ordered = true;
4067 343 : if (m == MATCH_YES)
4068 : {
4069 144 : int ordered = 0;
4070 144 : if (gfc_extract_int (cexpr, &ordered, -1))
4071 0 : ordered = 0;
4072 144 : else if (ordered <= 0)
4073 : {
4074 0 : gfc_error_now ("ORDERED clause argument not"
4075 : " constant positive integer at %C");
4076 0 : ordered = 0;
4077 : }
4078 144 : c->orderedc = ordered;
4079 144 : gfc_free_expr (cexpr);
4080 144 : continue;
4081 144 : }
4082 :
4083 199 : continue;
4084 199 : }
4085 482 : if ((mask & OMP_CLAUSE_ORDER)
4086 248 : && (m = gfc_match_dupl_check (!c->order_concurrent, "order", true))
4087 : != MATCH_NO)
4088 : {
4089 247 : if (m == MATCH_ERROR)
4090 10 : goto error;
4091 237 : if (gfc_match (" reproducible : concurrent )") == MATCH_YES)
4092 55 : c->order_reproducible = true;
4093 182 : else if (gfc_match (" concurrent )") == MATCH_YES)
4094 : ;
4095 50 : else if (gfc_match (" unconstrained : concurrent )") == MATCH_YES)
4096 47 : c->order_unconstrained = true;
4097 : else
4098 : {
4099 3 : gfc_error ("Expected ORDER(CONCURRENT) at %C "
4100 : "with optional %<reproducible%> or "
4101 : "%<unconstrained%> modifier");
4102 3 : goto error;
4103 : }
4104 234 : c->order_concurrent = true;
4105 234 : continue;
4106 : }
4107 : break;
4108 3101 : case 'p':
4109 3101 : if (mask & OMP_CLAUSE_PARTIAL)
4110 : {
4111 276 : if ((m = gfc_match_dupl_check (!c->partial, "partial"))
4112 : != MATCH_NO)
4113 : {
4114 276 : int expr;
4115 276 : if (m == MATCH_ERROR)
4116 0 : goto error;
4117 :
4118 276 : c->partial = -1;
4119 :
4120 276 : gfc_expr *cexpr = NULL;
4121 276 : m = gfc_match (" ( %e )", &cexpr);
4122 276 : if (m == MATCH_NO)
4123 : ;
4124 251 : else if (m == MATCH_YES
4125 251 : && !gfc_extract_int (cexpr, &expr, -1)
4126 502 : && expr > 0)
4127 247 : c->partial = expr;
4128 : else
4129 4 : gfc_error_now ("PARTIAL clause argument not constant "
4130 : "positive integer at %C");
4131 276 : gfc_free_expr (cexpr);
4132 276 : continue;
4133 276 : }
4134 : }
4135 2894 : if ((mask & OMP_CLAUSE_COPY)
4136 877 : && gfc_match ("pcopy ( ") == MATCH_YES
4137 2895 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4138 : OMP_MAP_TOFROM, true, allow_derived))
4139 69 : continue;
4140 2830 : if ((mask & OMP_CLAUSE_COPYIN)
4141 1910 : && gfc_match ("pcopyin ( ") == MATCH_YES
4142 2830 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4143 : OMP_MAP_TO, true, allow_derived))
4144 74 : continue;
4145 2755 : if ((mask & OMP_CLAUSE_COPYOUT)
4146 735 : && gfc_match ("pcopyout ( ") == MATCH_YES
4147 2755 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4148 : OMP_MAP_FROM, true, allow_derived))
4149 73 : continue;
4150 2624 : if ((mask & OMP_CLAUSE_CREATE)
4151 672 : && gfc_match ("pcreate ( ") == MATCH_YES
4152 2624 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4153 : OMP_MAP_ALLOC, true, allow_derived))
4154 15 : continue;
4155 3010 : if ((mask & OMP_CLAUSE_PRESENT)
4156 647 : && gfc_match ("present ( ") == MATCH_YES
4157 3012 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4158 : OMP_MAP_FORCE_PRESENT, false,
4159 : allow_derived))
4160 416 : continue;
4161 2201 : if ((mask & OMP_CLAUSE_COPY)
4162 231 : && gfc_match ("present_or_copy ( ") == MATCH_YES
4163 2201 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4164 : OMP_MAP_TOFROM, true,
4165 : allow_derived))
4166 23 : continue;
4167 2195 : if ((mask & OMP_CLAUSE_COPYIN)
4168 1309 : && gfc_match ("present_or_copyin ( ") == MATCH_YES
4169 2195 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4170 : OMP_MAP_TO, true, allow_derived))
4171 40 : continue;
4172 2150 : if ((mask & OMP_CLAUSE_COPYOUT)
4173 173 : && gfc_match ("present_or_copyout ( ") == MATCH_YES
4174 2150 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4175 : OMP_MAP_FROM, true, allow_derived))
4176 35 : continue;
4177 2108 : if ((mask & OMP_CLAUSE_CREATE)
4178 143 : && gfc_match ("present_or_create ( ") == MATCH_YES
4179 2108 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4180 : OMP_MAP_ALLOC, true, allow_derived))
4181 28 : continue;
4182 2086 : if ((mask & OMP_CLAUSE_PRIORITY)
4183 2052 : && (m = gfc_match_dupl_check (!c->priority, "priority", true,
4184 : &c->priority)) != MATCH_NO)
4185 : {
4186 34 : if (m == MATCH_ERROR)
4187 0 : goto error;
4188 34 : continue;
4189 : }
4190 3959 : if ((mask & OMP_CLAUSE_PRIVATE)
4191 2018 : && gfc_match_omp_variable_list ("private (",
4192 : &c->lists[OMP_LIST_PRIVATE],
4193 : true) == MATCH_YES)
4194 1941 : continue;
4195 141 : if ((mask & OMP_CLAUSE_PROC_BIND)
4196 141 : && (m = gfc_match_dupl_check ((c->proc_bind
4197 64 : == OMP_PROC_BIND_UNKNOWN),
4198 : "proc_bind", true)) != MATCH_NO)
4199 : {
4200 64 : if (m == MATCH_ERROR)
4201 0 : goto error;
4202 64 : if (gfc_match ("primary )") == MATCH_YES)
4203 1 : c->proc_bind = OMP_PROC_BIND_PRIMARY;
4204 63 : else if (gfc_match ("master )") == MATCH_YES)
4205 : {
4206 9 : gfc_warning (OPT_Wdeprecated_openmp,
4207 : "%<master%> affinity policy at %C deprecated "
4208 : "since OpenMP 5.1, use %<primary%>");
4209 9 : c->proc_bind = OMP_PROC_BIND_MASTER;
4210 : }
4211 54 : else if (gfc_match ("spread )") == MATCH_YES)
4212 53 : c->proc_bind = OMP_PROC_BIND_SPREAD;
4213 1 : else if (gfc_match ("close )") == MATCH_YES)
4214 1 : c->proc_bind = OMP_PROC_BIND_CLOSE;
4215 : else
4216 0 : goto error;
4217 64 : continue;
4218 : }
4219 : break;
4220 4580 : case 'r':
4221 5070 : if ((mask & OMP_CLAUSE_ATOMIC)
4222 4580 : && (m = gfc_match_dupl_atomic ((c->atomic_op
4223 : == GFC_OMP_ATOMIC_UNSET),
4224 : "read")) != MATCH_NO)
4225 : {
4226 490 : if (m == MATCH_ERROR)
4227 0 : goto error;
4228 490 : c->atomic_op = GFC_OMP_ATOMIC_READ;
4229 490 : continue;
4230 : }
4231 8143 : if ((mask & OMP_CLAUSE_REDUCTION)
4232 4090 : && gfc_match_omp_clause_reduction (pc, c, openacc,
4233 : allow_derived) == MATCH_YES)
4234 4053 : continue;
4235 47 : if ((mask & OMP_CLAUSE_MEMORDER)
4236 65 : && (m = gfc_match_dupl_memorder ((c->memorder
4237 28 : == OMP_MEMORDER_UNSET),
4238 : "relaxed")) != MATCH_NO)
4239 : {
4240 10 : if (m == MATCH_ERROR)
4241 0 : goto error;
4242 10 : c->memorder = OMP_MEMORDER_RELAXED;
4243 10 : continue;
4244 : }
4245 44 : if ((mask & OMP_CLAUSE_MEMORDER)
4246 45 : && (m = gfc_match_dupl_memorder ((c->memorder
4247 18 : == OMP_MEMORDER_UNSET),
4248 : "release")) != MATCH_NO)
4249 : {
4250 18 : if (m == MATCH_ERROR)
4251 1 : goto error;
4252 17 : c->memorder = OMP_MEMORDER_RELEASE;
4253 17 : continue;
4254 : }
4255 : break;
4256 3036 : case 's':
4257 3129 : if ((mask & OMP_CLAUSE_SAFELEN)
4258 3036 : && (m = gfc_match_dupl_check (!c->safelen_expr, "safelen",
4259 : true, &c->safelen_expr))
4260 : != MATCH_NO)
4261 : {
4262 93 : if (m == MATCH_ERROR)
4263 0 : goto error;
4264 93 : continue;
4265 : }
4266 2943 : if ((mask & OMP_CLAUSE_SCHEDULE)
4267 2943 : && (m = gfc_match_dupl_check (c->sched_kind == OMP_SCHED_NONE,
4268 : "schedule", true)) != MATCH_NO)
4269 : {
4270 809 : if (m == MATCH_ERROR)
4271 0 : goto error;
4272 809 : int nmodifiers = 0;
4273 809 : locus old_loc2 = gfc_current_locus;
4274 827 : do
4275 : {
4276 818 : if (gfc_match ("simd") == MATCH_YES)
4277 : {
4278 18 : c->sched_simd = true;
4279 18 : nmodifiers++;
4280 : }
4281 800 : else if (gfc_match ("monotonic") == MATCH_YES)
4282 : {
4283 30 : c->sched_monotonic = true;
4284 30 : nmodifiers++;
4285 : }
4286 770 : else if (gfc_match ("nonmonotonic") == MATCH_YES)
4287 : {
4288 35 : c->sched_nonmonotonic = true;
4289 35 : nmodifiers++;
4290 : }
4291 : else
4292 : {
4293 735 : if (nmodifiers)
4294 0 : gfc_current_locus = old_loc2;
4295 : break;
4296 : }
4297 92 : if (nmodifiers == 1
4298 83 : && gfc_match (" , ") == MATCH_YES)
4299 9 : continue;
4300 74 : else if (gfc_match (" : ") == MATCH_YES)
4301 : break;
4302 0 : gfc_current_locus = old_loc2;
4303 0 : break;
4304 : }
4305 : while (1);
4306 809 : if (gfc_match ("static") == MATCH_YES)
4307 425 : c->sched_kind = OMP_SCHED_STATIC;
4308 384 : else if (gfc_match ("dynamic") == MATCH_YES)
4309 164 : c->sched_kind = OMP_SCHED_DYNAMIC;
4310 220 : else if (gfc_match ("guided") == MATCH_YES)
4311 127 : c->sched_kind = OMP_SCHED_GUIDED;
4312 93 : else if (gfc_match ("runtime") == MATCH_YES)
4313 85 : c->sched_kind = OMP_SCHED_RUNTIME;
4314 8 : else if (gfc_match ("auto") == MATCH_YES)
4315 8 : c->sched_kind = OMP_SCHED_AUTO;
4316 809 : if (c->sched_kind != OMP_SCHED_NONE)
4317 : {
4318 809 : m = MATCH_NO;
4319 809 : if (c->sched_kind != OMP_SCHED_RUNTIME
4320 809 : && c->sched_kind != OMP_SCHED_AUTO)
4321 716 : m = gfc_match (" , %e )", &c->chunk_size);
4322 716 : if (m != MATCH_YES)
4323 299 : m = gfc_match_char (')');
4324 299 : if (m != MATCH_YES)
4325 0 : c->sched_kind = OMP_SCHED_NONE;
4326 : }
4327 809 : if (c->sched_kind != OMP_SCHED_NONE)
4328 809 : continue;
4329 : else
4330 0 : gfc_current_locus = old_loc;
4331 : }
4332 2317 : if ((mask & OMP_CLAUSE_SELF)
4333 335 : && !(mask & OMP_CLAUSE_HOST) /* OpenACC compute construct */
4334 2374 : && (m = gfc_match_dupl_check (!c->self_expr, "self"))
4335 : != MATCH_NO)
4336 : {
4337 186 : if (m == MATCH_ERROR)
4338 3 : goto error;
4339 183 : m = gfc_match (" ( %e )", &c->self_expr);
4340 183 : if (m == MATCH_ERROR)
4341 : {
4342 0 : gfc_current_locus = old_loc;
4343 0 : break;
4344 : }
4345 183 : else if (m == MATCH_NO)
4346 9 : c->self_expr = gfc_get_logical_expr (gfc_default_logical_kind,
4347 : NULL, true);
4348 183 : continue;
4349 : }
4350 2042 : if ((mask & OMP_CLAUSE_SELF)
4351 149 : && (mask & OMP_CLAUSE_HOST) /* OpenACC 'update' directive */
4352 95 : && gfc_match ("self ( ") == MATCH_YES
4353 2043 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4354 : OMP_MAP_FORCE_FROM, true,
4355 : /* allow_derived = */ true))
4356 94 : continue;
4357 2202 : if ((mask & OMP_CLAUSE_SEQ)
4358 1854 : && (m = gfc_match_dupl_check (!c->seq, "seq")) != MATCH_NO)
4359 : {
4360 348 : if (m == MATCH_ERROR)
4361 0 : goto error;
4362 348 : c->seq = true;
4363 348 : continue;
4364 : }
4365 1647 : if ((mask & OMP_CLAUSE_MEMORDER)
4366 1647 : && (m = gfc_match_dupl_memorder ((c->memorder
4367 141 : == OMP_MEMORDER_UNSET),
4368 : "seq_cst")) != MATCH_NO)
4369 : {
4370 141 : if (m == MATCH_ERROR)
4371 0 : goto error;
4372 141 : c->memorder = OMP_MEMORDER_SEQ_CST;
4373 141 : continue;
4374 : }
4375 2340 : if ((mask & OMP_CLAUSE_SHARED)
4376 1365 : && gfc_match_omp_variable_list ("shared (",
4377 : &c->lists[OMP_LIST_SHARED],
4378 : true) == MATCH_YES)
4379 975 : continue;
4380 508 : if ((mask & OMP_CLAUSE_SIMDLEN)
4381 390 : && (m = gfc_match_dupl_check (!c->simdlen_expr, "simdlen", true,
4382 : &c->simdlen_expr)) != MATCH_NO)
4383 : {
4384 118 : if (m == MATCH_ERROR)
4385 0 : goto error;
4386 118 : continue;
4387 : }
4388 294 : if ((mask & OMP_CLAUSE_SIMD)
4389 272 : && (m = gfc_match_dupl_check (!c->simd, "simd")) != MATCH_NO)
4390 : {
4391 22 : if (m == MATCH_ERROR)
4392 0 : goto error;
4393 22 : c->simd = true;
4394 22 : continue;
4395 : }
4396 289 : if ((mask & OMP_CLAUSE_SEVERITY)
4397 250 : && (m = gfc_match_dupl_check (!c->severity, "severity", true))
4398 : != MATCH_NO)
4399 : {
4400 45 : if (m == MATCH_ERROR)
4401 2 : goto error;
4402 43 : if (gfc_match ("fatal )") == MATCH_YES)
4403 10 : c->severity = OMP_SEVERITY_FATAL;
4404 33 : else if (gfc_match ("warning )") == MATCH_YES)
4405 29 : c->severity = OMP_SEVERITY_WARNING;
4406 : else
4407 : {
4408 4 : gfc_error ("Expected FATAL or WARNING in SEVERITY clause "
4409 : "at %C");
4410 4 : goto error;
4411 : }
4412 39 : continue;
4413 : }
4414 205 : if ((mask & OMP_CLAUSE_SIZES)
4415 205 : && ((m = gfc_match_dupl_check (!c->sizes_list, "sizes"))
4416 : != MATCH_NO))
4417 : {
4418 203 : if (m == MATCH_ERROR)
4419 0 : goto error;
4420 203 : m = match_omp_oacc_expr_list (" (", &c->sizes_list, false, true);
4421 203 : if (m == MATCH_ERROR)
4422 7 : goto error;
4423 196 : if (m == MATCH_YES)
4424 195 : continue;
4425 1 : gfc_error ("Expected %<(%> after %qs at %C", "sizes");
4426 1 : goto error;
4427 : }
4428 : break;
4429 1203 : case 't':
4430 1268 : if ((mask & OMP_CLAUSE_TASK_REDUCTION)
4431 1203 : && gfc_match_omp_clause_reduction (pc, c, openacc,
4432 : allow_derived) == MATCH_YES)
4433 65 : continue;
4434 1210 : if ((mask & OMP_CLAUSE_THREAD_LIMIT)
4435 1138 : && (m = gfc_match_dupl_check (!c->thread_limit, "thread_limit",
4436 : true, &c->thread_limit))
4437 : != MATCH_NO)
4438 : {
4439 72 : if (m == MATCH_ERROR)
4440 0 : goto error;
4441 72 : continue;
4442 : }
4443 1079 : if ((mask & OMP_CLAUSE_THREADS)
4444 1066 : && (m = gfc_match_dupl_check (!c->threads, "threads"))
4445 : != MATCH_NO)
4446 : {
4447 13 : if (m == MATCH_ERROR)
4448 0 : goto error;
4449 13 : c->threads = true;
4450 13 : continue;
4451 : }
4452 1250 : if ((mask & OMP_CLAUSE_TILE)
4453 221 : && !c->tile_list
4454 1274 : && match_omp_oacc_expr_list ("tile (", &c->tile_list,
4455 : true, false) == MATCH_YES)
4456 197 : continue;
4457 856 : if ((mask & OMP_CLAUSE_TO) && (mask & OMP_CLAUSE_LINK))
4458 : {
4459 : /* Declare target: 'to' is an alias for 'enter';
4460 : 'to' is deprecated since 5.2. */
4461 116 : m = gfc_match_omp_to_link ("to (", &c->lists[OMP_LIST_TO]);
4462 116 : if (m == MATCH_ERROR)
4463 0 : goto error;
4464 116 : if (m == MATCH_YES)
4465 : {
4466 116 : gfc_warning (OPT_Wdeprecated_openmp,
4467 : "%<to%> clause with %<declare target%> at %L "
4468 : "deprecated since OpenMP 5.2, use %<enter%>",
4469 : &old_loc);
4470 116 : continue;
4471 : }
4472 : }
4473 1456 : else if ((mask & OMP_CLAUSE_TO)
4474 740 : && gfc_match_motion_var_list ("to (", &c->lists[OMP_LIST_TO],
4475 : &head) == MATCH_YES)
4476 716 : continue;
4477 : break;
4478 1516 : case 'u':
4479 1574 : if ((mask & OMP_CLAUSE_UNIFORM)
4480 1516 : && gfc_match_omp_variable_list ("uniform (",
4481 : &c->lists[OMP_LIST_UNIFORM],
4482 : false) == MATCH_YES)
4483 58 : continue;
4484 1599 : if ((mask & OMP_CLAUSE_UNTIED)
4485 1458 : && (m = gfc_match_dupl_check (!c->untied, "untied")) != MATCH_NO)
4486 : {
4487 141 : if (m == MATCH_ERROR)
4488 0 : goto error;
4489 141 : c->untied = true;
4490 141 : continue;
4491 : }
4492 1561 : if ((mask & OMP_CLAUSE_ATOMIC)
4493 1317 : && (m = gfc_match_dupl_atomic ((c->atomic_op
4494 : == GFC_OMP_ATOMIC_UNSET),
4495 : "update")) != MATCH_NO)
4496 : {
4497 245 : if (m == MATCH_ERROR)
4498 1 : goto error;
4499 244 : c->atomic_op = GFC_OMP_ATOMIC_UPDATE;
4500 244 : continue;
4501 : }
4502 1094 : if ((mask & OMP_CLAUSE_USE)
4503 1072 : && gfc_match_omp_variable_list ("use (",
4504 : &c->lists[OMP_LIST_USE],
4505 : true) == MATCH_YES)
4506 22 : continue;
4507 1110 : if ((mask & OMP_CLAUSE_USE_DEVICE)
4508 1050 : && gfc_match_omp_variable_list ("use_device (",
4509 : &c->lists[OMP_LIST_USE_DEVICE],
4510 : true) == MATCH_YES)
4511 60 : continue;
4512 1153 : if ((mask & OMP_CLAUSE_USE_DEVICE_PTR)
4513 1918 : && gfc_match_omp_variable_list
4514 928 : ("use_device_ptr (",
4515 : &c->lists[OMP_LIST_USE_DEVICE_PTR], false) == MATCH_YES)
4516 163 : continue;
4517 1592 : if ((mask & OMP_CLAUSE_USE_DEVICE_ADDR)
4518 1592 : && gfc_match_omp_variable_list
4519 765 : ("use_device_addr (", &c->lists[OMP_LIST_USE_DEVICE_ADDR],
4520 : false, NULL, NULL, true) == MATCH_YES)
4521 765 : continue;
4522 114 : if ((mask & OMP_CLAUSE_USES_ALLOCATORS)
4523 62 : && (gfc_match ("uses_allocators ( ") == MATCH_YES))
4524 : {
4525 56 : if (gfc_match_omp_clause_uses_allocators (c) != MATCH_YES)
4526 4 : goto error;
4527 52 : continue;
4528 : }
4529 : break;
4530 1570 : case 'v':
4531 : /* VECTOR_LENGTH must be matched before VECTOR, because the latter
4532 : doesn't unconditionally match '('. */
4533 2139 : if ((mask & OMP_CLAUSE_VECTOR_LENGTH)
4534 1570 : && (m = gfc_match_dupl_check (!c->vector_length_expr,
4535 : "vector_length", true,
4536 : &c->vector_length_expr))
4537 : != MATCH_NO)
4538 : {
4539 573 : if (m == MATCH_ERROR)
4540 4 : goto error;
4541 569 : continue;
4542 : }
4543 1989 : if ((mask & OMP_CLAUSE_VECTOR)
4544 997 : && (m = gfc_match_dupl_check (!c->vector, "vector")) != MATCH_NO)
4545 : {
4546 995 : if (m == MATCH_ERROR)
4547 0 : goto error;
4548 995 : c->vector = true;
4549 995 : m = match_oacc_clause_gwv (c, GOMP_DIM_VECTOR);
4550 995 : if (m == MATCH_ERROR)
4551 3 : goto error;
4552 992 : continue;
4553 : }
4554 : break;
4555 1482 : case 'w':
4556 1482 : if ((mask & OMP_CLAUSE_WAIT)
4557 1482 : && gfc_match ("wait") == MATCH_YES)
4558 : {
4559 192 : m = match_omp_oacc_expr_list (" (", &c->wait_list, false, false);
4560 192 : if (m == MATCH_ERROR)
4561 9 : goto error;
4562 183 : else if (m == MATCH_NO)
4563 : {
4564 47 : gfc_expr *expr
4565 47 : = gfc_get_constant_expr (BT_INTEGER,
4566 : gfc_default_integer_kind,
4567 : &gfc_current_locus);
4568 47 : mpz_set_si (expr->value.integer, GOMP_ASYNC_NOVAL);
4569 47 : gfc_expr_list **expr_list = &c->wait_list;
4570 56 : while (*expr_list)
4571 9 : expr_list = &(*expr_list)->next;
4572 47 : *expr_list = gfc_get_expr_list ();
4573 47 : (*expr_list)->expr = expr;
4574 47 : needs_space = true;
4575 : }
4576 183 : continue;
4577 183 : }
4578 1303 : if ((mask & OMP_CLAUSE_WEAK)
4579 1290 : && (m = gfc_match_dupl_check (!c->weak, "weak"))
4580 : != MATCH_NO)
4581 : {
4582 14 : if (m == MATCH_ERROR)
4583 1 : goto error;
4584 13 : c->weak = true;
4585 13 : continue;
4586 : }
4587 2137 : if ((mask & OMP_CLAUSE_WORKER)
4588 1276 : && (m = gfc_match_dupl_check (!c->worker, "worker")) != MATCH_NO)
4589 : {
4590 864 : if (m == MATCH_ERROR)
4591 0 : goto error;
4592 864 : c->worker = true;
4593 864 : m = match_oacc_clause_gwv (c, GOMP_DIM_WORKER);
4594 864 : if (m == MATCH_ERROR)
4595 3 : goto error;
4596 861 : continue;
4597 : }
4598 824 : if ((mask & OMP_CLAUSE_ATOMIC)
4599 412 : && (m = gfc_match_dupl_atomic ((c->atomic_op
4600 : == GFC_OMP_ATOMIC_UNSET),
4601 : "write")) != MATCH_NO)
4602 : {
4603 412 : if (m == MATCH_ERROR)
4604 0 : goto error;
4605 412 : c->atomic_op = GFC_OMP_ATOMIC_WRITE;
4606 412 : continue;
4607 : }
4608 : break;
4609 : }
4610 : break;
4611 46071 : }
4612 :
4613 34401 : end:
4614 34146 : if (error || gfc_match_omp_eos () != MATCH_YES)
4615 : {
4616 523 : if (!gfc_error_flag_test ())
4617 138 : gfc_error ("Failed to match clause at %C");
4618 523 : gfc_free_omp_clauses (c);
4619 523 : return MATCH_ERROR;
4620 : }
4621 :
4622 33878 : *cp = c;
4623 33878 : return MATCH_YES;
4624 :
4625 255 : error:
4626 255 : error = true;
4627 255 : goto end;
4628 : }
4629 :
4630 :
4631 : #define OACC_PARALLEL_CLAUSES \
4632 : (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_NUM_GANGS \
4633 : | OMP_CLAUSE_NUM_WORKERS | OMP_CLAUSE_VECTOR_LENGTH | OMP_CLAUSE_REDUCTION \
4634 : | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT \
4635 : | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT \
4636 : | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE \
4637 : | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH \
4638 : | OMP_CLAUSE_SELF)
4639 : #define OACC_KERNELS_CLAUSES \
4640 : (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_NUM_GANGS \
4641 : | OMP_CLAUSE_NUM_WORKERS | OMP_CLAUSE_VECTOR_LENGTH | OMP_CLAUSE_DEVICEPTR \
4642 : | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT \
4643 : | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT \
4644 : | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH \
4645 : | OMP_CLAUSE_SELF)
4646 : #define OACC_SERIAL_CLAUSES \
4647 : (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_REDUCTION \
4648 : | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT \
4649 : | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT \
4650 : | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE \
4651 : | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH \
4652 : | OMP_CLAUSE_SELF)
4653 : #define OACC_DATA_CLAUSES \
4654 : (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_COPY \
4655 : | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_CREATE \
4656 : | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT | OMP_CLAUSE_ATTACH \
4657 : | OMP_CLAUSE_DEFAULT)
4658 : #define OACC_LOOP_CLAUSES \
4659 : (omp_mask (OMP_CLAUSE_COLLAPSE) | OMP_CLAUSE_GANG | OMP_CLAUSE_WORKER \
4660 : | OMP_CLAUSE_VECTOR | OMP_CLAUSE_SEQ | OMP_CLAUSE_INDEPENDENT \
4661 : | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_AUTO \
4662 : | OMP_CLAUSE_TILE)
4663 : #define OACC_PARALLEL_LOOP_CLAUSES \
4664 : (OACC_LOOP_CLAUSES | OACC_PARALLEL_CLAUSES)
4665 : #define OACC_KERNELS_LOOP_CLAUSES \
4666 : (OACC_LOOP_CLAUSES | OACC_KERNELS_CLAUSES)
4667 : #define OACC_SERIAL_LOOP_CLAUSES \
4668 : (OACC_LOOP_CLAUSES | OACC_SERIAL_CLAUSES)
4669 : #define OACC_HOST_DATA_CLAUSES \
4670 : (omp_mask (OMP_CLAUSE_USE_DEVICE) \
4671 : | OMP_CLAUSE_IF \
4672 : | OMP_CLAUSE_IF_PRESENT)
4673 : #define OACC_DECLARE_CLAUSES \
4674 : (omp_mask (OMP_CLAUSE_COPY) | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT \
4675 : | OMP_CLAUSE_CREATE | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_DEVICE_RESIDENT \
4676 : | OMP_CLAUSE_PRESENT \
4677 : | OMP_CLAUSE_LINK)
4678 : #define OACC_UPDATE_CLAUSES \
4679 : (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_HOST \
4680 : | OMP_CLAUSE_DEVICE | OMP_CLAUSE_WAIT | OMP_CLAUSE_IF_PRESENT \
4681 : | OMP_CLAUSE_SELF)
4682 : #define OACC_ENTER_DATA_CLAUSES \
4683 : (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_WAIT \
4684 : | OMP_CLAUSE_COPYIN | OMP_CLAUSE_CREATE | OMP_CLAUSE_ATTACH)
4685 : #define OACC_EXIT_DATA_CLAUSES \
4686 : (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_WAIT \
4687 : | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_DELETE | OMP_CLAUSE_FINALIZE \
4688 : | OMP_CLAUSE_DETACH)
4689 : #define OACC_WAIT_CLAUSES \
4690 : omp_mask (OMP_CLAUSE_ASYNC) | OMP_CLAUSE_IF
4691 : #define OACC_ROUTINE_CLAUSES \
4692 : (omp_mask (OMP_CLAUSE_GANG) | OMP_CLAUSE_WORKER | OMP_CLAUSE_VECTOR \
4693 : | OMP_CLAUSE_SEQ \
4694 : | OMP_CLAUSE_NOHOST)
4695 :
4696 :
4697 : static match
4698 11804 : match_acc (gfc_exec_op op, const omp_mask mask)
4699 : {
4700 11804 : gfc_omp_clauses *c;
4701 11804 : if (gfc_match_omp_clauses (&c, mask, false, false, true) != MATCH_YES)
4702 : return MATCH_ERROR;
4703 11599 : new_st.op = op;
4704 11599 : new_st.ext.omp_clauses = c;
4705 11599 : return MATCH_YES;
4706 : }
4707 :
4708 : match
4709 1378 : gfc_match_oacc_parallel_loop (void)
4710 : {
4711 1378 : return match_acc (EXEC_OACC_PARALLEL_LOOP, OACC_PARALLEL_LOOP_CLAUSES);
4712 : }
4713 :
4714 :
4715 : match
4716 2974 : gfc_match_oacc_parallel (void)
4717 : {
4718 2974 : return match_acc (EXEC_OACC_PARALLEL, OACC_PARALLEL_CLAUSES);
4719 : }
4720 :
4721 :
4722 : match
4723 129 : gfc_match_oacc_kernels_loop (void)
4724 : {
4725 129 : return match_acc (EXEC_OACC_KERNELS_LOOP, OACC_KERNELS_LOOP_CLAUSES);
4726 : }
4727 :
4728 :
4729 : match
4730 906 : gfc_match_oacc_kernels (void)
4731 : {
4732 906 : return match_acc (EXEC_OACC_KERNELS, OACC_KERNELS_CLAUSES);
4733 : }
4734 :
4735 :
4736 : match
4737 230 : gfc_match_oacc_serial_loop (void)
4738 : {
4739 230 : return match_acc (EXEC_OACC_SERIAL_LOOP, OACC_SERIAL_LOOP_CLAUSES);
4740 : }
4741 :
4742 :
4743 : match
4744 359 : gfc_match_oacc_serial (void)
4745 : {
4746 359 : return match_acc (EXEC_OACC_SERIAL, OACC_SERIAL_CLAUSES);
4747 : }
4748 :
4749 :
4750 : match
4751 689 : gfc_match_oacc_data (void)
4752 : {
4753 689 : return match_acc (EXEC_OACC_DATA, OACC_DATA_CLAUSES);
4754 : }
4755 :
4756 :
4757 : match
4758 65 : gfc_match_oacc_host_data (void)
4759 : {
4760 65 : return match_acc (EXEC_OACC_HOST_DATA, OACC_HOST_DATA_CLAUSES);
4761 : }
4762 :
4763 :
4764 : match
4765 3585 : gfc_match_oacc_loop (void)
4766 : {
4767 3585 : return match_acc (EXEC_OACC_LOOP, OACC_LOOP_CLAUSES);
4768 : }
4769 :
4770 :
4771 : match
4772 178 : gfc_match_oacc_declare (void)
4773 : {
4774 178 : gfc_omp_clauses *c;
4775 178 : gfc_omp_namelist *n;
4776 178 : gfc_namespace *ns = gfc_current_ns;
4777 178 : gfc_oacc_declare *new_oc;
4778 178 : bool module_var = false;
4779 178 : locus where = gfc_current_locus;
4780 :
4781 178 : if (gfc_match_omp_clauses (&c, OACC_DECLARE_CLAUSES, false, false, true)
4782 : != MATCH_YES)
4783 : return MATCH_ERROR;
4784 :
4785 262 : for (n = c->lists[OMP_LIST_DEVICE_RESIDENT]; n != NULL; n = n->next)
4786 90 : n->sym->attr.oacc_declare_device_resident = 1;
4787 :
4788 192 : for (n = c->lists[OMP_LIST_LINK]; n != NULL; n = n->next)
4789 20 : n->sym->attr.oacc_declare_link = 1;
4790 :
4791 318 : for (n = c->lists[OMP_LIST_MAP]; n != NULL; n = n->next)
4792 : {
4793 156 : gfc_symbol *s = n->sym;
4794 :
4795 156 : if (gfc_current_ns->proc_name
4796 156 : && gfc_current_ns->proc_name->attr.flavor == FL_MODULE)
4797 : {
4798 52 : if (n->u.map.op != OMP_MAP_ALLOC && n->u.map.op != OMP_MAP_TO)
4799 : {
4800 6 : gfc_error ("Invalid clause in module with !$ACC DECLARE at %L",
4801 : &where);
4802 6 : return MATCH_ERROR;
4803 : }
4804 :
4805 : module_var = true;
4806 : }
4807 :
4808 150 : if (s->attr.use_assoc)
4809 : {
4810 0 : gfc_error ("Variable is USE-associated with !$ACC DECLARE at %L",
4811 : &where);
4812 0 : return MATCH_ERROR;
4813 : }
4814 :
4815 150 : if ((s->result == s && s->ns->contained != gfc_current_ns)
4816 150 : || ((s->attr.flavor == FL_UNKNOWN || s->attr.flavor == FL_VARIABLE)
4817 135 : && s->ns != gfc_current_ns))
4818 : {
4819 2 : gfc_error ("Variable %qs shall be declared in the same scoping unit "
4820 : "as !$ACC DECLARE at %L", s->name, &where);
4821 2 : return MATCH_ERROR;
4822 : }
4823 :
4824 148 : if ((s->attr.dimension || s->attr.codimension)
4825 76 : && s->attr.dummy && s->as->type != AS_EXPLICIT)
4826 : {
4827 2 : gfc_error ("Assumed-size dummy array with !$ACC DECLARE at %L",
4828 : &where);
4829 2 : return MATCH_ERROR;
4830 : }
4831 :
4832 146 : switch (n->u.map.op)
4833 : {
4834 49 : case OMP_MAP_FORCE_ALLOC:
4835 49 : case OMP_MAP_ALLOC:
4836 49 : s->attr.oacc_declare_create = 1;
4837 49 : break;
4838 :
4839 63 : case OMP_MAP_FORCE_TO:
4840 63 : case OMP_MAP_TO:
4841 63 : s->attr.oacc_declare_copyin = 1;
4842 63 : break;
4843 :
4844 1 : case OMP_MAP_FORCE_DEVICEPTR:
4845 1 : s->attr.oacc_declare_deviceptr = 1;
4846 1 : break;
4847 :
4848 : default:
4849 : break;
4850 : }
4851 : }
4852 :
4853 162 : new_oc = gfc_get_oacc_declare ();
4854 162 : new_oc->next = ns->oacc_declare;
4855 162 : new_oc->module_var = module_var;
4856 162 : new_oc->clauses = c;
4857 162 : new_oc->loc = gfc_current_locus;
4858 162 : ns->oacc_declare = new_oc;
4859 :
4860 162 : return MATCH_YES;
4861 : }
4862 :
4863 :
4864 : match
4865 760 : gfc_match_oacc_update (void)
4866 : {
4867 760 : gfc_omp_clauses *c;
4868 760 : locus here = gfc_current_locus;
4869 :
4870 760 : if (gfc_match_omp_clauses (&c, OACC_UPDATE_CLAUSES, false, false, true)
4871 : != MATCH_YES)
4872 : return MATCH_ERROR;
4873 :
4874 756 : if (!c->lists[OMP_LIST_MAP])
4875 : {
4876 1 : gfc_error ("%<acc update%> must contain at least one "
4877 : "%<device%> or %<host%> or %<self%> clause at %L", &here);
4878 1 : return MATCH_ERROR;
4879 : }
4880 :
4881 755 : new_st.op = EXEC_OACC_UPDATE;
4882 755 : new_st.ext.omp_clauses = c;
4883 755 : return MATCH_YES;
4884 : }
4885 :
4886 :
4887 : match
4888 877 : gfc_match_oacc_enter_data (void)
4889 : {
4890 877 : return match_acc (EXEC_OACC_ENTER_DATA, OACC_ENTER_DATA_CLAUSES);
4891 : }
4892 :
4893 :
4894 : match
4895 612 : gfc_match_oacc_exit_data (void)
4896 : {
4897 612 : return match_acc (EXEC_OACC_EXIT_DATA, OACC_EXIT_DATA_CLAUSES);
4898 : }
4899 :
4900 :
4901 : match
4902 203 : gfc_match_oacc_wait (void)
4903 : {
4904 203 : gfc_omp_clauses *c = gfc_get_omp_clauses ();
4905 203 : gfc_expr_list *wait_list = NULL, *el;
4906 203 : bool space = true;
4907 203 : match m;
4908 :
4909 203 : m = match_omp_oacc_expr_list (" (", &wait_list, true, false);
4910 203 : if (m == MATCH_ERROR)
4911 : return m;
4912 197 : else if (m == MATCH_YES)
4913 126 : space = false;
4914 :
4915 197 : if (gfc_match_omp_clauses (&c, OACC_WAIT_CLAUSES, space, space, true)
4916 : == MATCH_ERROR)
4917 : return MATCH_ERROR;
4918 :
4919 184 : if (wait_list)
4920 261 : for (el = wait_list; el; el = el->next)
4921 : {
4922 140 : if (el->expr == NULL)
4923 : {
4924 2 : gfc_error ("Invalid argument to !$ACC WAIT at %C");
4925 2 : return MATCH_ERROR;
4926 : }
4927 :
4928 138 : if (!gfc_resolve_expr (el->expr)
4929 138 : || el->expr->ts.type != BT_INTEGER || el->expr->rank != 0)
4930 : {
4931 3 : gfc_error ("WAIT clause at %L requires a scalar INTEGER expression",
4932 3 : &el->expr->where);
4933 :
4934 3 : return MATCH_ERROR;
4935 : }
4936 : }
4937 179 : c->wait_list = wait_list;
4938 179 : new_st.op = EXEC_OACC_WAIT;
4939 179 : new_st.ext.omp_clauses = c;
4940 179 : return MATCH_YES;
4941 : }
4942 :
4943 :
4944 : match
4945 97 : gfc_match_oacc_cache (void)
4946 : {
4947 97 : bool readonly = false;
4948 97 : gfc_omp_clauses *c = gfc_get_omp_clauses ();
4949 : /* The OpenACC cache directive explicitly only allows "array elements or
4950 : subarrays", which we're currently not checking here. Either check this
4951 : after the call of gfc_match_omp_variable_list, or add something like a
4952 : only_sections variant next to its allow_sections parameter. */
4953 97 : match m = gfc_match (" ( ");
4954 97 : if (m != MATCH_YES)
4955 : {
4956 0 : gfc_free_omp_clauses(c);
4957 0 : return m;
4958 : }
4959 :
4960 97 : if (gfc_match ("readonly : ") == MATCH_YES)
4961 8 : readonly = true;
4962 :
4963 97 : gfc_omp_namelist **head = NULL;
4964 97 : m = gfc_match_omp_variable_list ("", &c->lists[OMP_LIST_CACHE], true,
4965 : NULL, &head, true);
4966 97 : if (m != MATCH_YES)
4967 : {
4968 2 : gfc_free_omp_clauses(c);
4969 2 : return m;
4970 : }
4971 :
4972 95 : if (readonly)
4973 24 : for (gfc_omp_namelist *n = *head; n; n = n->next)
4974 16 : n->u.map.readonly = true;
4975 :
4976 95 : if (gfc_current_state() != COMP_DO
4977 56 : && gfc_current_state() != COMP_DO_CONCURRENT)
4978 : {
4979 2 : gfc_error ("ACC CACHE directive must be inside of loop %C");
4980 2 : gfc_free_omp_clauses(c);
4981 2 : return MATCH_ERROR;
4982 : }
4983 :
4984 93 : new_st.op = EXEC_OACC_CACHE;
4985 93 : new_st.ext.omp_clauses = c;
4986 93 : return MATCH_YES;
4987 : }
4988 :
4989 : /* Determine the OpenACC 'routine' directive's level of parallelism. */
4990 :
4991 : static oacc_routine_lop
4992 734 : gfc_oacc_routine_lop (gfc_omp_clauses *clauses)
4993 : {
4994 734 : oacc_routine_lop ret = OACC_ROUTINE_LOP_SEQ;
4995 :
4996 734 : if (clauses)
4997 : {
4998 584 : unsigned n_lop_clauses = 0;
4999 :
5000 584 : if (clauses->gang)
5001 : {
5002 164 : ++n_lop_clauses;
5003 164 : ret = OACC_ROUTINE_LOP_GANG;
5004 : }
5005 584 : if (clauses->worker)
5006 : {
5007 114 : ++n_lop_clauses;
5008 114 : ret = OACC_ROUTINE_LOP_WORKER;
5009 : }
5010 584 : if (clauses->vector)
5011 : {
5012 116 : ++n_lop_clauses;
5013 116 : ret = OACC_ROUTINE_LOP_VECTOR;
5014 : }
5015 584 : if (clauses->seq)
5016 : {
5017 206 : ++n_lop_clauses;
5018 206 : ret = OACC_ROUTINE_LOP_SEQ;
5019 : }
5020 :
5021 584 : if (n_lop_clauses > 1)
5022 47 : ret = OACC_ROUTINE_LOP_ERROR;
5023 : }
5024 :
5025 734 : return ret;
5026 : }
5027 :
5028 : match
5029 698 : gfc_match_oacc_routine (void)
5030 : {
5031 698 : locus old_loc;
5032 698 : match m;
5033 698 : gfc_intrinsic_sym *isym = NULL;
5034 698 : gfc_symbol *sym = NULL;
5035 698 : gfc_omp_clauses *c = NULL;
5036 698 : gfc_oacc_routine_name *n = NULL;
5037 698 : oacc_routine_lop lop = OACC_ROUTINE_LOP_NONE;
5038 698 : bool nohost;
5039 :
5040 698 : old_loc = gfc_current_locus;
5041 :
5042 698 : m = gfc_match (" (");
5043 :
5044 698 : if (gfc_current_ns->proc_name
5045 696 : && gfc_current_ns->proc_name->attr.if_source == IFSRC_IFBODY
5046 90 : && m == MATCH_YES)
5047 : {
5048 3 : gfc_error ("Only the !$ACC ROUTINE form without "
5049 : "list is allowed in interface block at %C");
5050 3 : goto cleanup;
5051 : }
5052 :
5053 608 : if (m == MATCH_YES)
5054 : {
5055 295 : char buffer[GFC_MAX_SYMBOL_LEN + 1];
5056 :
5057 295 : m = gfc_match_name (buffer);
5058 295 : if (m == MATCH_YES)
5059 : {
5060 294 : gfc_symtree *st = NULL;
5061 :
5062 : /* First look for an intrinsic symbol. */
5063 294 : isym = gfc_find_function (buffer);
5064 294 : if (!isym)
5065 294 : isym = gfc_find_subroutine (buffer);
5066 : /* If no intrinsic symbol found, search the current namespace. */
5067 294 : if (!isym)
5068 276 : st = gfc_find_symtree (gfc_current_ns->sym_root, buffer);
5069 276 : if (st)
5070 : {
5071 270 : sym = st->n.sym;
5072 : /* If the name in a 'routine' directive refers to the containing
5073 : subroutine or function, then make sure that we'll later handle
5074 : this accordingly. */
5075 270 : if (gfc_current_ns->proc_name != NULL
5076 270 : && strcmp (sym->name, gfc_current_ns->proc_name->name) == 0)
5077 294 : sym = NULL;
5078 : }
5079 :
5080 294 : if (isym == NULL && st == NULL)
5081 : {
5082 6 : gfc_error ("Invalid NAME %qs in !$ACC ROUTINE ( NAME ) at %C",
5083 : buffer);
5084 6 : gfc_current_locus = old_loc;
5085 9 : return MATCH_ERROR;
5086 : }
5087 : }
5088 : else
5089 : {
5090 1 : gfc_error ("Syntax error in !$ACC ROUTINE ( NAME ) at %C");
5091 1 : gfc_current_locus = old_loc;
5092 1 : return MATCH_ERROR;
5093 : }
5094 :
5095 288 : if (gfc_match_char (')') != MATCH_YES)
5096 : {
5097 2 : gfc_error ("Syntax error in !$ACC ROUTINE ( NAME ) at %C, expecting"
5098 : " %<)%> after NAME");
5099 2 : gfc_current_locus = old_loc;
5100 2 : return MATCH_ERROR;
5101 : }
5102 : }
5103 :
5104 686 : if (gfc_match_omp_eos () != MATCH_YES
5105 686 : && (gfc_match_omp_clauses (&c, OACC_ROUTINE_CLAUSES, false, false, true)
5106 : != MATCH_YES))
5107 : return MATCH_ERROR;
5108 :
5109 683 : lop = gfc_oacc_routine_lop (c);
5110 683 : if (lop == OACC_ROUTINE_LOP_ERROR)
5111 : {
5112 47 : gfc_error ("Multiple loop axes specified for routine at %C");
5113 47 : goto cleanup;
5114 : }
5115 636 : nohost = c ? c->nohost : false;
5116 :
5117 636 : if (isym != NULL)
5118 : {
5119 : /* Diagnose any OpenACC 'routine' directive that doesn't match the
5120 : (implicit) one with a 'seq' clause. */
5121 16 : if (c && (c->gang || c->worker || c->vector))
5122 : {
5123 10 : gfc_error ("Intrinsic symbol specified in !$ACC ROUTINE ( NAME )"
5124 : " at %C marked with incompatible GANG, WORKER, or VECTOR"
5125 : " clause");
5126 10 : goto cleanup;
5127 : }
5128 : /* ..., and no 'nohost' clause. */
5129 6 : if (nohost)
5130 : {
5131 2 : gfc_error ("Intrinsic symbol specified in !$ACC ROUTINE ( NAME )"
5132 : " at %C marked with incompatible NOHOST clause");
5133 2 : goto cleanup;
5134 : }
5135 : }
5136 620 : else if (sym != NULL)
5137 : {
5138 151 : bool add = true;
5139 :
5140 : /* For a repeated OpenACC 'routine' directive, diagnose if it doesn't
5141 : match the first one. */
5142 151 : for (gfc_oacc_routine_name *n_p = gfc_current_ns->oacc_routine_names;
5143 346 : n_p;
5144 195 : n_p = n_p->next)
5145 235 : if (n_p->sym == sym)
5146 : {
5147 51 : add = false;
5148 51 : bool nohost_p = n_p->clauses ? n_p->clauses->nohost : false;
5149 51 : if (lop != gfc_oacc_routine_lop (n_p->clauses)
5150 51 : || nohost != nohost_p)
5151 : {
5152 40 : gfc_error ("!$ACC ROUTINE already applied at %C");
5153 40 : goto cleanup;
5154 : }
5155 : }
5156 :
5157 111 : if (add)
5158 : {
5159 100 : sym->attr.oacc_routine_lop = lop;
5160 100 : sym->attr.oacc_routine_nohost = nohost;
5161 :
5162 100 : n = gfc_get_oacc_routine_name ();
5163 100 : n->sym = sym;
5164 100 : n->clauses = c;
5165 100 : n->next = gfc_current_ns->oacc_routine_names;
5166 100 : n->loc = old_loc;
5167 100 : gfc_current_ns->oacc_routine_names = n;
5168 : }
5169 : }
5170 469 : else if (gfc_current_ns->proc_name)
5171 : {
5172 : /* For a repeated OpenACC 'routine' directive, diagnose if it doesn't
5173 : match the first one. */
5174 468 : oacc_routine_lop lop_p = gfc_current_ns->proc_name->attr.oacc_routine_lop;
5175 468 : bool nohost_p = gfc_current_ns->proc_name->attr.oacc_routine_nohost;
5176 468 : if (lop_p != OACC_ROUTINE_LOP_NONE
5177 86 : && (lop != lop_p
5178 86 : || nohost != nohost_p))
5179 : {
5180 56 : gfc_error ("!$ACC ROUTINE already applied at %C");
5181 56 : goto cleanup;
5182 : }
5183 :
5184 412 : if (!gfc_add_omp_declare_target (&gfc_current_ns->proc_name->attr,
5185 : gfc_current_ns->proc_name->name,
5186 : &old_loc))
5187 1 : goto cleanup;
5188 411 : gfc_current_ns->proc_name->attr.oacc_routine_lop = lop;
5189 411 : gfc_current_ns->proc_name->attr.oacc_routine_nohost = nohost;
5190 : }
5191 : else
5192 : /* Something has gone wrong, possibly a syntax error. */
5193 1 : goto cleanup;
5194 :
5195 526 : if (gfc_pure (NULL) && c && (c->gang || c->worker || c->vector))
5196 : {
5197 6 : gfc_error ("!$ACC ROUTINE with GANG, WORKER, or VECTOR clause is not "
5198 : "permitted in PURE procedure at %C");
5199 6 : goto cleanup;
5200 : }
5201 :
5202 :
5203 520 : if (n)
5204 100 : n->clauses = c;
5205 420 : else if (gfc_current_ns->oacc_routine)
5206 0 : gfc_current_ns->oacc_routine_clauses = c;
5207 :
5208 520 : new_st.op = EXEC_OACC_ROUTINE;
5209 520 : new_st.ext.omp_clauses = c;
5210 520 : return MATCH_YES;
5211 :
5212 166 : cleanup:
5213 166 : gfc_current_locus = old_loc;
5214 166 : return MATCH_ERROR;
5215 : }
5216 :
5217 :
5218 : #define OMP_PARALLEL_CLAUSES \
5219 : (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
5220 : | OMP_CLAUSE_SHARED | OMP_CLAUSE_COPYIN | OMP_CLAUSE_REDUCTION \
5221 : | OMP_CLAUSE_IF | OMP_CLAUSE_NUM_THREADS | OMP_CLAUSE_DEFAULT \
5222 : | OMP_CLAUSE_PROC_BIND | OMP_CLAUSE_ALLOCATE)
5223 : #define OMP_DECLARE_SIMD_CLAUSES \
5224 : (omp_mask (OMP_CLAUSE_SIMDLEN) | OMP_CLAUSE_LINEAR \
5225 : | OMP_CLAUSE_UNIFORM | OMP_CLAUSE_ALIGNED | OMP_CLAUSE_INBRANCH \
5226 : | OMP_CLAUSE_NOTINBRANCH)
5227 : #define OMP_DO_CLAUSES \
5228 : (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
5229 : | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION \
5230 : | OMP_CLAUSE_SCHEDULE | OMP_CLAUSE_ORDERED | OMP_CLAUSE_COLLAPSE \
5231 : | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ORDER | OMP_CLAUSE_ALLOCATE \
5232 : | OMP_CLAUSE_NOWAIT)
5233 : #define OMP_LOOP_CLAUSES \
5234 : (omp_mask (OMP_CLAUSE_BIND) | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_ORDER \
5235 : | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION)
5236 :
5237 : #define OMP_SCOPE_CLAUSES \
5238 : (omp_mask (OMP_CLAUSE_PRIVATE) |OMP_CLAUSE_FIRSTPRIVATE \
5239 : | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT)
5240 : #define OMP_SECTIONS_CLAUSES \
5241 : (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
5242 : | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION \
5243 : | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT)
5244 : #define OMP_SIMD_CLAUSES \
5245 : (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_LASTPRIVATE \
5246 : | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_SAFELEN \
5247 : | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ALIGNED | OMP_CLAUSE_SIMDLEN \
5248 : | OMP_CLAUSE_IF | OMP_CLAUSE_ORDER | OMP_CLAUSE_NOTEMPORAL)
5249 : #define OMP_TASK_CLAUSES \
5250 : (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
5251 : | OMP_CLAUSE_SHARED | OMP_CLAUSE_IF | OMP_CLAUSE_DEFAULT \
5252 : | OMP_CLAUSE_UNTIED | OMP_CLAUSE_FINAL | OMP_CLAUSE_MERGEABLE \
5253 : | OMP_CLAUSE_DEPEND | OMP_CLAUSE_PRIORITY | OMP_CLAUSE_IN_REDUCTION \
5254 : | OMP_CLAUSE_DETACH | OMP_CLAUSE_AFFINITY | OMP_CLAUSE_ALLOCATE)
5255 : #define OMP_TASKLOOP_CLAUSES \
5256 : (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
5257 : | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_IF \
5258 : | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_UNTIED | OMP_CLAUSE_FINAL \
5259 : | OMP_CLAUSE_MERGEABLE | OMP_CLAUSE_PRIORITY | OMP_CLAUSE_GRAINSIZE \
5260 : | OMP_CLAUSE_NUM_TASKS | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_NOGROUP \
5261 : | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_IN_REDUCTION | OMP_CLAUSE_ALLOCATE)
5262 : #define OMP_TASKGROUP_CLAUSES \
5263 : (omp_mask (OMP_CLAUSE_TASK_REDUCTION) | OMP_CLAUSE_ALLOCATE)
5264 : #define OMP_TARGET_CLAUSES \
5265 : (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF \
5266 : | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_PRIVATE \
5267 : | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_DEFAULTMAP \
5268 : | OMP_CLAUSE_IS_DEVICE_PTR | OMP_CLAUSE_IN_REDUCTION \
5269 : | OMP_CLAUSE_THREAD_LIMIT | OMP_CLAUSE_ALLOCATE \
5270 : | OMP_CLAUSE_HAS_DEVICE_ADDR | OMP_CLAUSE_USES_ALLOCATORS \
5271 : | OMP_CLAUSE_DYN_GROUPPRIVATE | OMP_CLAUSE_DEVICE_TYPE)
5272 : #define OMP_TARGET_DATA_CLAUSES \
5273 : (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF \
5274 : | OMP_CLAUSE_USE_DEVICE_PTR | OMP_CLAUSE_USE_DEVICE_ADDR)
5275 : #define OMP_TARGET_ENTER_DATA_CLAUSES \
5276 : (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF \
5277 : | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT)
5278 : #define OMP_TARGET_EXIT_DATA_CLAUSES \
5279 : (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF \
5280 : | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT)
5281 : #define OMP_TARGET_UPDATE_CLAUSES \
5282 : (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_IF | OMP_CLAUSE_TO \
5283 : | OMP_CLAUSE_FROM | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT)
5284 : #define OMP_TEAMS_CLAUSES \
5285 : (omp_mask (OMP_CLAUSE_NUM_TEAMS) | OMP_CLAUSE_THREAD_LIMIT \
5286 : | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE \
5287 : | OMP_CLAUSE_SHARED | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_ALLOCATE)
5288 : #define OMP_DISTRIBUTE_CLAUSES \
5289 : (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
5290 : | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_DIST_SCHEDULE \
5291 : | OMP_CLAUSE_ORDER | OMP_CLAUSE_ALLOCATE)
5292 : #define OMP_SINGLE_CLAUSES \
5293 : (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
5294 : | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_COPYPRIVATE)
5295 : #define OMP_ORDERED_CLAUSES \
5296 : (omp_mask (OMP_CLAUSE_THREADS) | OMP_CLAUSE_SIMD)
5297 : #define OMP_DECLARE_TARGET_CLAUSES \
5298 : (omp_mask (OMP_CLAUSE_ENTER) | OMP_CLAUSE_LINK | OMP_CLAUSE_DEVICE_TYPE \
5299 : | OMP_CLAUSE_TO | OMP_CLAUSE_INDIRECT | OMP_CLAUSE_LOCAL)
5300 : #define OMP_ATOMIC_CLAUSES \
5301 : (omp_mask (OMP_CLAUSE_ATOMIC) | OMP_CLAUSE_CAPTURE | OMP_CLAUSE_HINT \
5302 : | OMP_CLAUSE_MEMORDER | OMP_CLAUSE_COMPARE | OMP_CLAUSE_FAIL \
5303 : | OMP_CLAUSE_WEAK)
5304 : #define OMP_MASKED_CLAUSES \
5305 : (omp_mask (OMP_CLAUSE_FILTER))
5306 : #define OMP_ERROR_CLAUSES \
5307 : (omp_mask (OMP_CLAUSE_AT) | OMP_CLAUSE_MESSAGE | OMP_CLAUSE_SEVERITY)
5308 : #define OMP_WORKSHARE_CLAUSES \
5309 : omp_mask (OMP_CLAUSE_NOWAIT)
5310 : #define OMP_UNROLL_CLAUSES \
5311 : (omp_mask (OMP_CLAUSE_FULL) | OMP_CLAUSE_PARTIAL)
5312 : #define OMP_TILE_CLAUSES \
5313 : (omp_mask (OMP_CLAUSE_SIZES))
5314 : #define OMP_ALLOCATORS_CLAUSES \
5315 : omp_mask (OMP_CLAUSE_ALLOCATE)
5316 : #define OMP_INTEROP_CLAUSES \
5317 : (omp_mask (OMP_CLAUSE_DEPEND) | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_DEVICE \
5318 : | OMP_CLAUSE_INIT | OMP_CLAUSE_DESTROY | OMP_CLAUSE_USE)
5319 : #define OMP_DISPATCH_CLAUSES \
5320 : (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOVARIANTS \
5321 : | OMP_CLAUSE_NOCONTEXT | OMP_CLAUSE_IS_DEVICE_PTR | OMP_CLAUSE_NOWAIT \
5322 : | OMP_CLAUSE_HAS_DEVICE_ADDR | OMP_CLAUSE_INTEROP)
5323 :
5324 :
5325 : static match
5326 17067 : match_omp (gfc_exec_op op, const omp_mask mask)
5327 : {
5328 17067 : gfc_omp_clauses *c;
5329 17067 : if (gfc_match_omp_clauses (&c, mask, true, true, false,
5330 : op == EXEC_OMP_TARGET) != MATCH_YES)
5331 : return MATCH_ERROR;
5332 16819 : new_st.op = op;
5333 16819 : new_st.ext.omp_clauses = c;
5334 16819 : return MATCH_YES;
5335 : }
5336 :
5337 : /* Handles both declarative and (deprecated) executable ALLOCATE directive;
5338 : accepts optional list (for executable) and common blocks.
5339 : If no variables have been provided, the single omp namelist has sym == NULL.
5340 :
5341 : Note that the executable ALLOCATE directive permits structure elements only
5342 : in OpenMP 5.0 and 5.1 but not longer in 5.2. See also the comment on the
5343 : 'omp allocators' directive below. The accidental change was reverted for
5344 : OpenMP TR12, permitting them again. See also gfc_match_omp_allocators.
5345 :
5346 : Hence, structure elements are rejected for now, also to make resolving
5347 : OMP_LIST_ALLOCATE simpler (check for duplicates, same symbol in
5348 : Fortran allocate stmt). TODO: Permit structure elements. */
5349 :
5350 : match
5351 274 : gfc_match_omp_allocate (void)
5352 : {
5353 274 : match m;
5354 274 : bool first = true;
5355 274 : gfc_omp_namelist *vars = NULL;
5356 274 : gfc_expr *align = NULL;
5357 274 : gfc_expr *allocator = NULL;
5358 274 : locus loc = gfc_current_locus;
5359 :
5360 274 : m = gfc_match_omp_variable_list (" (", &vars, true, NULL, NULL, true, true,
5361 : NULL, true);
5362 :
5363 274 : if (m == MATCH_ERROR)
5364 : return m;
5365 :
5366 502 : while (true)
5367 : {
5368 502 : gfc_gobble_whitespace ();
5369 502 : if (gfc_match_omp_eos () == MATCH_YES)
5370 : break;
5371 234 : if (!first)
5372 28 : gfc_match (", ");
5373 234 : first = false;
5374 234 : if ((m = gfc_match_dupl_check (!align, "align", true, &align))
5375 : != MATCH_NO)
5376 : {
5377 62 : if (m == MATCH_ERROR)
5378 1 : goto error;
5379 61 : continue;
5380 : }
5381 172 : if ((m = gfc_match_dupl_check (!allocator, "allocator",
5382 : true, &allocator)) != MATCH_NO)
5383 : {
5384 171 : if (m == MATCH_ERROR)
5385 1 : goto error;
5386 170 : continue;
5387 : }
5388 1 : gfc_error ("Expected ALIGN or ALLOCATOR clause at %C");
5389 1 : return MATCH_ERROR;
5390 : }
5391 541 : for (gfc_omp_namelist *n = vars; n; n = n->next)
5392 276 : if (n->expr)
5393 : {
5394 3 : if ((n->expr->ref && n->expr->ref->type == REF_COMPONENT)
5395 3 : || (n->expr->ref->next && n->expr->ref->type == REF_COMPONENT))
5396 1 : gfc_error ("Sorry, structure-element list item at %L in ALLOCATE "
5397 : "directive is not yet supported", &n->expr->where);
5398 : else
5399 2 : gfc_error ("Unexpected expression as list item at %L in ALLOCATE "
5400 : "directive", &n->expr->where);
5401 :
5402 3 : gfc_free_omp_namelist (vars, OMP_LIST_ALLOCATE);
5403 3 : goto error;
5404 : }
5405 :
5406 265 : new_st.op = EXEC_OMP_ALLOCATE;
5407 265 : new_st.ext.omp_clauses = gfc_get_omp_clauses ();
5408 265 : if (vars == NULL)
5409 : {
5410 27 : vars = gfc_get_omp_namelist ();
5411 27 : vars->where = loc;
5412 27 : vars->u.align = align;
5413 27 : vars->u2.allocator = allocator;
5414 27 : new_st.ext.omp_clauses->lists[OMP_LIST_ALLOCATE] = vars;
5415 : }
5416 : else
5417 : {
5418 238 : new_st.ext.omp_clauses->lists[OMP_LIST_ALLOCATE] = vars;
5419 511 : for (; vars; vars = vars->next)
5420 : {
5421 273 : vars->u.align = (align) ? gfc_copy_expr (align) : NULL;
5422 273 : vars->u2.allocator = allocator;
5423 : }
5424 238 : gfc_free_expr (align);
5425 : }
5426 : return MATCH_YES;
5427 :
5428 5 : error:
5429 5 : gfc_free_expr (align);
5430 5 : gfc_free_expr (allocator);
5431 5 : return MATCH_ERROR;
5432 : }
5433 :
5434 : /* In line with OpenMP 5.2 derived-type components are rejected.
5435 : See also comment before gfc_match_omp_allocate. */
5436 :
5437 : match
5438 26 : gfc_match_omp_allocators (void)
5439 : {
5440 26 : return match_omp (EXEC_OMP_ALLOCATORS, OMP_ALLOCATORS_CLAUSES);
5441 : }
5442 :
5443 :
5444 : match
5445 23 : gfc_match_omp_assume (void)
5446 : {
5447 23 : gfc_omp_clauses *c;
5448 23 : locus loc = gfc_current_locus;
5449 23 : if ((gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_ASSUMPTIONS))
5450 : != MATCH_YES)
5451 23 : || (omp_verify_merge_absent_contains (ST_OMP_ASSUME, c->assume, NULL,
5452 : &loc) != MATCH_YES))
5453 7 : return MATCH_ERROR;
5454 16 : new_st.op = EXEC_OMP_ASSUME;
5455 16 : new_st.ext.omp_clauses = c;
5456 16 : return MATCH_YES;
5457 : }
5458 :
5459 :
5460 : match
5461 28 : gfc_match_omp_assumes (void)
5462 : {
5463 28 : gfc_omp_clauses *c;
5464 28 : locus loc = gfc_current_locus;
5465 28 : if (!gfc_current_ns->proc_name
5466 27 : || (gfc_current_ns->proc_name->attr.flavor != FL_MODULE
5467 23 : && !gfc_current_ns->proc_name->attr.subroutine
5468 10 : && !gfc_current_ns->proc_name->attr.function))
5469 : {
5470 2 : gfc_error ("!$OMP ASSUMES at %C must be in the specification part of a "
5471 : "subprogram or module");
5472 2 : return MATCH_ERROR;
5473 : }
5474 26 : if ((gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_ASSUMPTIONS))
5475 : != MATCH_YES)
5476 50 : || (omp_verify_merge_absent_contains (ST_OMP_ASSUMES, c->assume,
5477 24 : gfc_current_ns->omp_assumes, &loc)
5478 : != MATCH_YES))
5479 5 : return MATCH_ERROR;
5480 21 : if (gfc_current_ns->omp_assumes == NULL)
5481 : {
5482 19 : gfc_current_ns->omp_assumes = c->assume;
5483 19 : c->assume = NULL;
5484 : }
5485 2 : else if (gfc_current_ns->omp_assumes && c->assume)
5486 : {
5487 2 : gfc_current_ns->omp_assumes->no_openmp |= c->assume->no_openmp;
5488 2 : gfc_current_ns->omp_assumes->no_openmp_routines
5489 2 : |= c->assume->no_openmp_routines;
5490 2 : gfc_current_ns->omp_assumes->no_openmp_constructs
5491 2 : |= c->assume->no_openmp_constructs;
5492 2 : gfc_current_ns->omp_assumes->no_parallelism |= c->assume->no_parallelism;
5493 2 : if (gfc_current_ns->omp_assumes->holds && c->assume->holds)
5494 : {
5495 : gfc_expr_list *el = gfc_current_ns->omp_assumes->holds;
5496 1 : for ( ; el->next ; el = el->next)
5497 : ;
5498 1 : el->next = c->assume->holds;
5499 1 : }
5500 1 : else if (c->assume->holds)
5501 0 : gfc_current_ns->omp_assumes->holds = c->assume->holds;
5502 2 : c->assume->holds = NULL;
5503 : }
5504 21 : gfc_free_omp_clauses (c);
5505 21 : return MATCH_YES;
5506 : }
5507 :
5508 :
5509 : match
5510 162 : gfc_match_omp_critical (void)
5511 : {
5512 162 : char n[GFC_MAX_SYMBOL_LEN+1];
5513 162 : gfc_omp_clauses *c = NULL;
5514 :
5515 162 : if (gfc_match (" ( %n )", n) != MATCH_YES)
5516 115 : n[0] = '\0';
5517 :
5518 162 : if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_HINT),
5519 162 : /* first = */ n[0] == '\0') != MATCH_YES)
5520 : return MATCH_ERROR;
5521 :
5522 160 : new_st.op = EXEC_OMP_CRITICAL;
5523 160 : new_st.ext.omp_clauses = c;
5524 160 : if (n[0])
5525 47 : c->critical_name = xstrdup (n);
5526 : return MATCH_YES;
5527 : }
5528 :
5529 :
5530 : match
5531 160 : gfc_match_omp_end_critical (void)
5532 : {
5533 160 : char n[GFC_MAX_SYMBOL_LEN+1];
5534 :
5535 160 : if (gfc_match (" ( %n )", n) != MATCH_YES)
5536 113 : n[0] = '\0';
5537 160 : if (gfc_match_omp_eos () != MATCH_YES)
5538 : {
5539 1 : gfc_error ("Unexpected junk after $OMP CRITICAL statement at %C");
5540 1 : return MATCH_ERROR;
5541 : }
5542 :
5543 159 : new_st.op = EXEC_OMP_END_CRITICAL;
5544 159 : new_st.ext.omp_name = n[0] ? xstrdup (n) : NULL;
5545 159 : return MATCH_YES;
5546 : }
5547 :
5548 : /* depobj(depobj) depend(dep-type:loc)|destroy|update(dep-type)
5549 : dep-type = in/out/inout/mutexinoutset/depobj/source/sink
5550 : depend: !source, !sink
5551 : update: !source, !sink, !depobj
5552 : locator = exactly one list item .*/
5553 : match
5554 125 : gfc_match_omp_depobj (void)
5555 : {
5556 125 : gfc_omp_clauses *c = NULL;
5557 125 : gfc_expr *depobj;
5558 :
5559 125 : if (gfc_match (" ( %v ) ", &depobj) != MATCH_YES)
5560 : {
5561 2 : gfc_error ("Expected %<( depobj )%> at %C");
5562 2 : return MATCH_ERROR;
5563 : }
5564 123 : if (gfc_match ("update ( ") == MATCH_YES)
5565 : {
5566 12 : c = gfc_get_omp_clauses ();
5567 12 : if (gfc_match ("inoutset )") == MATCH_YES)
5568 2 : c->depobj_update = OMP_DEPEND_INOUTSET;
5569 10 : else if (gfc_match ("inout )") == MATCH_YES)
5570 1 : c->depobj_update = OMP_DEPEND_INOUT;
5571 9 : else if (gfc_match ("in )") == MATCH_YES)
5572 2 : c->depobj_update = OMP_DEPEND_IN;
5573 7 : else if (gfc_match ("out )") == MATCH_YES)
5574 2 : c->depobj_update = OMP_DEPEND_OUT;
5575 5 : else if (gfc_match ("mutexinoutset )") == MATCH_YES)
5576 2 : c->depobj_update = OMP_DEPEND_MUTEXINOUTSET;
5577 : else
5578 : {
5579 3 : gfc_error ("Expected IN, OUT, INOUT, INOUTSET or MUTEXINOUTSET "
5580 : "followed by %<)%> at %C");
5581 3 : goto error;
5582 : }
5583 : }
5584 111 : else if (gfc_match ("destroy ") == MATCH_YES)
5585 : {
5586 16 : gfc_expr *destroyobj = NULL;
5587 16 : c = gfc_get_omp_clauses ();
5588 16 : c->destroy = true;
5589 :
5590 16 : if (gfc_match (" ( %v ) ", &destroyobj) == MATCH_YES)
5591 : {
5592 3 : if (destroyobj->symtree != depobj->symtree)
5593 2 : gfc_warning (OPT_Wopenmp, "The same depend object should be used as"
5594 : " DEPOBJ argument at %L and as DESTROY argument at %L",
5595 : &depobj->where, &destroyobj->where);
5596 3 : gfc_free_expr (destroyobj);
5597 : }
5598 : }
5599 95 : else if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_DEPEND), true, false)
5600 : != MATCH_YES)
5601 2 : goto error;
5602 :
5603 118 : if (c->depobj_update == OMP_DEPEND_UNSET && !c->destroy)
5604 : {
5605 93 : if (!c->doacross_source && !c->lists[OMP_LIST_DEPEND])
5606 : {
5607 1 : gfc_error ("Expected DEPEND, UPDATE, or DESTROY clause at %C");
5608 1 : goto error;
5609 : }
5610 92 : if (c->lists[OMP_LIST_DEPEND]->u.depend_doacross_op == OMP_DEPEND_DEPOBJ)
5611 : {
5612 1 : gfc_error ("DEPEND clause at %L of OMP DEPOBJ construct shall not "
5613 : "have dependence-type DEPOBJ",
5614 : c->lists[OMP_LIST_DEPEND]
5615 : ? &c->lists[OMP_LIST_DEPEND]->where : &gfc_current_locus);
5616 1 : goto error;
5617 : }
5618 91 : if (c->lists[OMP_LIST_DEPEND]->next)
5619 : {
5620 1 : gfc_error ("DEPEND clause at %L of OMP DEPOBJ construct shall have "
5621 : "only a single locator",
5622 : &c->lists[OMP_LIST_DEPEND]->next->where);
5623 1 : goto error;
5624 : }
5625 : }
5626 :
5627 115 : c->depobj = depobj;
5628 115 : new_st.op = EXEC_OMP_DEPOBJ;
5629 115 : new_st.ext.omp_clauses = c;
5630 115 : return MATCH_YES;
5631 :
5632 8 : error:
5633 8 : gfc_free_expr (depobj);
5634 8 : gfc_free_omp_clauses (c);
5635 8 : return MATCH_ERROR;
5636 : }
5637 :
5638 : match
5639 160 : gfc_match_omp_dispatch (void)
5640 : {
5641 160 : return match_omp (EXEC_OMP_DISPATCH, OMP_DISPATCH_CLAUSES);
5642 : }
5643 :
5644 : match
5645 57 : gfc_match_omp_distribute (void)
5646 : {
5647 57 : return match_omp (EXEC_OMP_DISTRIBUTE, OMP_DISTRIBUTE_CLAUSES);
5648 : }
5649 :
5650 :
5651 : match
5652 44 : gfc_match_omp_distribute_parallel_do (void)
5653 : {
5654 44 : return match_omp (EXEC_OMP_DISTRIBUTE_PARALLEL_DO,
5655 44 : (OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
5656 44 : | OMP_DO_CLAUSES)
5657 44 : & ~(omp_mask (OMP_CLAUSE_ORDERED)
5658 44 : | OMP_CLAUSE_LINEAR | OMP_CLAUSE_NOWAIT));
5659 : }
5660 :
5661 :
5662 : match
5663 34 : gfc_match_omp_distribute_parallel_do_simd (void)
5664 : {
5665 34 : return match_omp (EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD,
5666 34 : (OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
5667 34 : | OMP_DO_CLAUSES | OMP_SIMD_CLAUSES)
5668 34 : & ~(omp_mask (OMP_CLAUSE_ORDERED) | OMP_CLAUSE_NOWAIT));
5669 : }
5670 :
5671 :
5672 : match
5673 52 : gfc_match_omp_distribute_simd (void)
5674 : {
5675 52 : return match_omp (EXEC_OMP_DISTRIBUTE_SIMD,
5676 52 : OMP_DISTRIBUTE_CLAUSES | OMP_SIMD_CLAUSES);
5677 : }
5678 :
5679 :
5680 : match
5681 1252 : gfc_match_omp_do (void)
5682 : {
5683 1252 : return match_omp (EXEC_OMP_DO, OMP_DO_CLAUSES);
5684 : }
5685 :
5686 :
5687 : match
5688 137 : gfc_match_omp_do_simd (void)
5689 : {
5690 137 : return match_omp (EXEC_OMP_DO_SIMD, OMP_DO_CLAUSES | OMP_SIMD_CLAUSES);
5691 : }
5692 :
5693 :
5694 : match
5695 70 : gfc_match_omp_loop (void)
5696 : {
5697 70 : return match_omp (EXEC_OMP_LOOP, OMP_LOOP_CLAUSES);
5698 : }
5699 :
5700 :
5701 : match
5702 35 : gfc_match_omp_teams_loop (void)
5703 : {
5704 35 : return match_omp (EXEC_OMP_TEAMS_LOOP, OMP_TEAMS_CLAUSES | OMP_LOOP_CLAUSES);
5705 : }
5706 :
5707 :
5708 : match
5709 18 : gfc_match_omp_target_teams_loop (void)
5710 : {
5711 18 : return match_omp (EXEC_OMP_TARGET_TEAMS_LOOP,
5712 18 : OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES | OMP_LOOP_CLAUSES);
5713 : }
5714 :
5715 :
5716 : match
5717 31 : gfc_match_omp_parallel_loop (void)
5718 : {
5719 31 : return match_omp (EXEC_OMP_PARALLEL_LOOP,
5720 31 : OMP_PARALLEL_CLAUSES | OMP_LOOP_CLAUSES);
5721 : }
5722 :
5723 :
5724 : match
5725 16 : gfc_match_omp_target_parallel_loop (void)
5726 : {
5727 16 : return match_omp (EXEC_OMP_TARGET_PARALLEL_LOOP,
5728 16 : (OMP_TARGET_CLAUSES | OMP_PARALLEL_CLAUSES
5729 16 : | OMP_LOOP_CLAUSES));
5730 : }
5731 :
5732 :
5733 : match
5734 101 : gfc_match_omp_error (void)
5735 : {
5736 101 : locus loc = gfc_current_locus;
5737 101 : match m = match_omp (EXEC_OMP_ERROR, OMP_ERROR_CLAUSES);
5738 101 : if (m != MATCH_YES)
5739 : return m;
5740 :
5741 82 : gfc_omp_clauses *c = new_st.ext.omp_clauses;
5742 82 : if (c->severity == OMP_SEVERITY_UNSET)
5743 45 : c->severity = OMP_SEVERITY_FATAL;
5744 82 : if (new_st.ext.omp_clauses->at == OMP_AT_EXECUTION)
5745 : return MATCH_YES;
5746 37 : if (c->message
5747 37 : && (!gfc_resolve_expr (c->message)
5748 16 : || c->message->ts.type != BT_CHARACTER
5749 14 : || c->message->ts.kind != gfc_default_character_kind
5750 13 : || c->message->rank != 0))
5751 : {
5752 4 : gfc_error ("MESSAGE clause at %L requires a scalar default-kind "
5753 : "CHARACTER expression",
5754 4 : &new_st.ext.omp_clauses->message->where);
5755 4 : return MATCH_ERROR;
5756 : }
5757 33 : if (c->message && !gfc_is_constant_expr (c->message))
5758 : {
5759 2 : gfc_error ("Constant character expression required in MESSAGE clause "
5760 2 : "at %L", &new_st.ext.omp_clauses->message->where);
5761 2 : return MATCH_ERROR;
5762 : }
5763 31 : if (c->message)
5764 : {
5765 10 : const char *msg = G_("$OMP ERROR encountered at %L: %s");
5766 10 : gcc_assert (c->message->expr_type == EXPR_CONSTANT);
5767 10 : gfc_charlen_t slen = c->message->value.character.length;
5768 10 : int i = gfc_validate_kind (BT_CHARACTER, gfc_default_character_kind,
5769 : false);
5770 10 : size_t size = slen * gfc_character_kinds[i].bit_size / 8;
5771 10 : unsigned char *s = XCNEWVAR (unsigned char, size + 1);
5772 10 : gfc_encode_character (gfc_default_character_kind, slen,
5773 10 : c->message->value.character.string,
5774 : (unsigned char *) s, size);
5775 10 : s[size] = '\0';
5776 10 : if (c->severity == OMP_SEVERITY_WARNING)
5777 6 : gfc_warning_now (0, msg, &loc, s);
5778 : else
5779 4 : gfc_error_now (msg, &loc, s);
5780 10 : free (s);
5781 : }
5782 : else
5783 : {
5784 21 : const char *msg = G_("$OMP ERROR encountered at %L");
5785 21 : if (c->severity == OMP_SEVERITY_WARNING)
5786 7 : gfc_warning_now (0, msg, &loc);
5787 : else
5788 14 : gfc_error_now (msg, &loc);
5789 : }
5790 : return MATCH_YES;
5791 : }
5792 :
5793 : match
5794 86 : gfc_match_omp_flush (void)
5795 : {
5796 86 : gfc_omp_namelist *list = NULL;
5797 86 : gfc_omp_clauses *c = NULL;
5798 86 : gfc_gobble_whitespace ();
5799 86 : enum gfc_omp_memorder mo = OMP_MEMORDER_UNSET;
5800 86 : if (gfc_match_omp_eos () == MATCH_NO && gfc_peek_ascii_char () != '(')
5801 : {
5802 14 : if (gfc_match ("seq_cst") == MATCH_YES)
5803 : mo = OMP_MEMORDER_SEQ_CST;
5804 11 : else if (gfc_match ("acq_rel") == MATCH_YES)
5805 : mo = OMP_MEMORDER_ACQ_REL;
5806 8 : else if (gfc_match ("release") == MATCH_YES)
5807 : mo = OMP_MEMORDER_RELEASE;
5808 5 : else if (gfc_match ("acquire") == MATCH_YES)
5809 : mo = OMP_MEMORDER_ACQUIRE;
5810 : else
5811 : {
5812 2 : gfc_error ("Expected SEQ_CST, AQC_REL, RELEASE, or ACQUIRE at %C");
5813 2 : return MATCH_ERROR;
5814 : }
5815 12 : c = gfc_get_omp_clauses ();
5816 12 : c->memorder = mo;
5817 : }
5818 84 : gfc_match_omp_variable_list (" (", &list, true);
5819 84 : if (list && mo != OMP_MEMORDER_UNSET)
5820 : {
5821 4 : gfc_error ("List specified together with memory order clause in FLUSH "
5822 : "directive at %C");
5823 4 : gfc_free_omp_namelist (list, OMP_LIST_NONE);
5824 4 : gfc_free_omp_clauses (c);
5825 4 : return MATCH_ERROR;
5826 : }
5827 80 : if (gfc_match_omp_eos () != MATCH_YES)
5828 : {
5829 0 : gfc_error ("Unexpected junk after $OMP FLUSH statement at %C");
5830 0 : gfc_free_omp_namelist (list, OMP_LIST_NONE);
5831 0 : gfc_free_omp_clauses (c);
5832 0 : return MATCH_ERROR;
5833 : }
5834 80 : new_st.op = EXEC_OMP_FLUSH;
5835 80 : new_st.ext.omp_namelist = list;
5836 80 : new_st.ext.omp_clauses = c;
5837 80 : return MATCH_YES;
5838 : }
5839 :
5840 :
5841 : match
5842 188 : gfc_match_omp_declare_simd (void)
5843 : {
5844 188 : locus where = gfc_current_locus;
5845 188 : gfc_symbol *proc_name;
5846 188 : gfc_omp_clauses *c;
5847 188 : gfc_omp_declare_simd *ods;
5848 188 : bool needs_space = false;
5849 :
5850 188 : switch (gfc_match (" ( "))
5851 : {
5852 144 : case MATCH_YES:
5853 144 : if (gfc_match_symbol (&proc_name, /* host assoc = */ true) != MATCH_YES
5854 144 : || gfc_match (" ) ") != MATCH_YES)
5855 0 : return MATCH_ERROR;
5856 : break;
5857 44 : case MATCH_NO: proc_name = NULL; needs_space = true; break;
5858 : case MATCH_ERROR: return MATCH_ERROR;
5859 : }
5860 :
5861 188 : if (gfc_match_omp_clauses (&c, OMP_DECLARE_SIMD_CLAUSES, true,
5862 : needs_space) != MATCH_YES)
5863 : return MATCH_ERROR;
5864 :
5865 183 : if (gfc_current_ns->is_block_data)
5866 : {
5867 1 : gfc_free_omp_clauses (c);
5868 1 : return MATCH_YES;
5869 : }
5870 :
5871 182 : ods = gfc_get_omp_declare_simd ();
5872 182 : ods->where = where;
5873 182 : ods->proc_name = proc_name;
5874 182 : ods->clauses = c;
5875 182 : ods->next = gfc_current_ns->omp_declare_simd;
5876 182 : gfc_current_ns->omp_declare_simd = ods;
5877 182 : return MATCH_YES;
5878 : }
5879 :
5880 :
5881 : /* Find a matching "!$omp declare mapper" for typespec TS in symtree ST. */
5882 :
5883 : gfc_omp_udm *
5884 8 : gfc_omp_udm_find (gfc_symtree *st, gfc_typespec *ts)
5885 : {
5886 8 : gfc_omp_udm *omp_udm;
5887 :
5888 8 : if (st == NULL)
5889 : return NULL;
5890 :
5891 2 : for (omp_udm = st->n.omp_udm; omp_udm; omp_udm = omp_udm->next)
5892 2 : if ((omp_udm->ts.type == BT_DERIVED || omp_udm->ts.type == BT_CLASS)
5893 2 : && (ts->type == BT_DERIVED || ts->type == BT_CLASS)
5894 2 : && strcmp (omp_udm->ts.u.derived->name, ts->u.derived->name) == 0)
5895 : return omp_udm;
5896 :
5897 : return NULL;
5898 : }
5899 :
5900 :
5901 : /* Match !$omp declare mapper([ mapper-identifier : ] type :: var) clauses-list */
5902 :
5903 : match
5904 18 : gfc_match_omp_declare_mapper (void)
5905 : {
5906 18 : match m;
5907 18 : gfc_typespec ts;
5908 18 : char mapper_id[GFC_MAX_SYMBOL_LEN + 1];
5909 18 : char var[GFC_MAX_SYMBOL_LEN + 1];
5910 18 : gfc_namespace *mapper_ns = NULL;
5911 18 : gfc_symtree *var_st;
5912 18 : gfc_symtree *st;
5913 18 : gfc_omp_udm *omp_udm = NULL, *prev_udm = NULL;
5914 18 : locus where = gfc_current_locus;
5915 :
5916 18 : if (gfc_match_char ('(') != MATCH_YES)
5917 : {
5918 1 : gfc_error ("Expected %<(%> at %C");
5919 1 : return MATCH_ERROR;
5920 : }
5921 :
5922 17 : locus old_locus = gfc_current_locus;
5923 :
5924 17 : m = gfc_match (" %n : ", mapper_id);
5925 :
5926 17 : if (m == MATCH_ERROR)
5927 : return MATCH_ERROR;
5928 :
5929 : /* As a special case, a mapper named "default" and an unnamed mapper are
5930 : both the default mapper for a given type. */
5931 17 : if (strcmp (mapper_id, "default") == 0)
5932 0 : mapper_id[0] = '\0';
5933 :
5934 17 : if (gfc_peek_ascii_char () == ':')
5935 : {
5936 : /* If we see '::', the user did not name the mapper, and instead we just
5937 : saw the type. So backtrack and try parsing as a type instead. */
5938 6 : mapper_id[0] = '\0';
5939 6 : gfc_current_locus = old_locus;
5940 : }
5941 17 : old_locus = gfc_current_locus;
5942 :
5943 17 : m = gfc_match_type_spec (&ts);
5944 17 : if (m != MATCH_YES)
5945 : {
5946 4 : gfc_error ("Expected either a type name at %L or a map-type "
5947 : "identifier, a colon, or a type name", &old_locus);
5948 4 : return MATCH_ERROR;
5949 : }
5950 :
5951 13 : if (ts.type != BT_DERIVED)
5952 : {
5953 1 : gfc_error ("!$OMP DECLARE MAPPER with non-derived type at %L", &old_locus);
5954 1 : return MATCH_ERROR;
5955 : }
5956 :
5957 12 : if (gfc_match (" :: ") != MATCH_YES)
5958 : {
5959 0 : gfc_error ("Expected %<::%> at %C");
5960 0 : return MATCH_ERROR;
5961 : }
5962 :
5963 12 : if (gfc_match_name (var) != MATCH_YES)
5964 : {
5965 1 : gfc_error ("Expected variable name at %C");
5966 1 : return MATCH_ERROR;
5967 : }
5968 :
5969 11 : if (gfc_match_char (')') != MATCH_YES)
5970 : {
5971 2 : gfc_error ("Expected %<)%> at %C");
5972 2 : return MATCH_ERROR;
5973 : }
5974 :
5975 9 : st = gfc_find_symtree (gfc_current_ns->omp_udm_root, mapper_id);
5976 :
5977 : /* Now we need to set up a new namespace, and create a new sym_tree for our
5978 : dummy variable so we can use it in the following list of mapping
5979 : clauses. */
5980 :
5981 9 : gfc_current_ns = mapper_ns = gfc_get_namespace (gfc_current_ns, 1);
5982 9 : mapper_ns->proc_name = mapper_ns->parent->proc_name;
5983 9 : mapper_ns->omp_udm_ns = 1;
5984 :
5985 9 : gfc_get_sym_tree (var, mapper_ns, &var_st, false);
5986 9 : var_st->n.sym->ts = ts;
5987 9 : var_st->n.sym->attr.omp_udm_artificial_var = 1;
5988 9 : var_st->n.sym->attr.flavor = FL_VARIABLE;
5989 9 : gfc_commit_symbols ();
5990 :
5991 9 : gfc_omp_clauses *clauses = NULL;
5992 :
5993 9 : m = gfc_match_omp_clauses (&clauses, omp_mask (OMP_CLAUSE_MAP), true, true,
5994 : false, false, OMP_MAP_UNSET);
5995 9 : if (m != MATCH_YES)
5996 1 : goto failure;
5997 :
5998 8 : omp_udm = gfc_get_omp_udm ();
5999 8 : omp_udm->next = NULL;
6000 8 : omp_udm->where = where;
6001 8 : omp_udm->mapper_id = gfc_get_string ("%s", mapper_id);
6002 8 : omp_udm->ts = ts;
6003 8 : omp_udm->var_sym = var_st->n.sym;
6004 8 : omp_udm->mapper_ns = mapper_ns;
6005 8 : omp_udm->clauses = clauses;
6006 :
6007 8 : gfc_current_ns = mapper_ns->parent;
6008 :
6009 8 : prev_udm = gfc_omp_udm_find (st, &ts);
6010 8 : if (prev_udm)
6011 : {
6012 2 : if (mapper_id[0])
6013 1 : gfc_error ("Redefinition of !$OMP DECLARE MAPPER at %L for type %qs with id %qs",
6014 : &where, gfc_typename (&ts), mapper_id);
6015 : else
6016 1 : gfc_error ("Redefinition of !$OMP DECLARE MAPPER at %L for type %qs",
6017 : &where, gfc_typename (&ts));
6018 2 : inform (gfc_get_location (&prev_udm->where),
6019 : "Previous !$OMP DECLARE MAPPER here");
6020 2 : return MATCH_ERROR;
6021 : }
6022 6 : else if (st)
6023 : {
6024 0 : omp_udm->next = st->n.omp_udm;
6025 0 : st->n.omp_udm = omp_udm;
6026 : }
6027 : else
6028 : {
6029 6 : st = gfc_new_symtree (&gfc_current_ns->omp_udm_root, mapper_id);
6030 6 : st->n.omp_udm = omp_udm;
6031 : }
6032 :
6033 : return MATCH_YES;
6034 :
6035 1 : failure:
6036 1 : if (mapper_ns)
6037 1 : gfc_current_ns = mapper_ns->parent;
6038 1 : gfc_free_omp_udm (omp_udm);
6039 :
6040 1 : return MATCH_ERROR;
6041 : }
6042 :
6043 :
6044 : static bool
6045 877 : match_udr_expr (gfc_symtree *omp_sym1, gfc_symtree *omp_sym2)
6046 : {
6047 877 : match m;
6048 877 : locus old_loc = gfc_current_locus;
6049 877 : char sname[GFC_MAX_SYMBOL_LEN + 1];
6050 877 : gfc_symbol *sym;
6051 877 : gfc_namespace *ns = gfc_current_ns;
6052 877 : gfc_expr *lvalue = NULL, *rvalue = NULL;
6053 877 : gfc_symtree *st;
6054 877 : gfc_actual_arglist *arglist;
6055 :
6056 877 : m = gfc_match (" %v =", &lvalue);
6057 877 : if (m != MATCH_YES)
6058 200 : gfc_current_locus = old_loc;
6059 : else
6060 : {
6061 677 : m = gfc_match (" %e )", &rvalue);
6062 677 : if (m == MATCH_YES)
6063 : {
6064 675 : ns->code = gfc_get_code (EXEC_ASSIGN);
6065 675 : ns->code->expr1 = lvalue;
6066 675 : ns->code->expr2 = rvalue;
6067 675 : ns->code->loc = old_loc;
6068 675 : return true;
6069 : }
6070 :
6071 2 : gfc_current_locus = old_loc;
6072 2 : gfc_free_expr (lvalue);
6073 : }
6074 :
6075 202 : m = gfc_match (" %n", sname);
6076 202 : if (m != MATCH_YES)
6077 : return false;
6078 :
6079 202 : if (strcmp (sname, omp_sym1->name) == 0
6080 200 : || strcmp (sname, omp_sym2->name) == 0)
6081 : return false;
6082 :
6083 200 : gfc_current_ns = ns->parent;
6084 200 : if (gfc_get_ha_sym_tree (sname, &st))
6085 : return false;
6086 :
6087 200 : sym = st->n.sym;
6088 200 : if (sym->attr.flavor != FL_PROCEDURE
6089 72 : && sym->attr.flavor != FL_UNKNOWN)
6090 : return false;
6091 :
6092 199 : if (!sym->attr.generic
6093 189 : && !sym->attr.subroutine
6094 71 : && !sym->attr.function)
6095 : {
6096 71 : if (!(sym->attr.external && !sym->attr.referenced))
6097 : {
6098 : /* ...create a symbol in this scope... */
6099 71 : if (sym->ns != gfc_current_ns
6100 71 : && gfc_get_sym_tree (sname, NULL, &st, false) == 1)
6101 : return false;
6102 :
6103 71 : if (sym != st->n.sym)
6104 71 : sym = st->n.sym;
6105 : }
6106 :
6107 : /* ...and then to try to make the symbol into a subroutine. */
6108 71 : if (!gfc_add_subroutine (&sym->attr, sym->name, NULL))
6109 : return false;
6110 : }
6111 :
6112 199 : gfc_set_sym_referenced (sym);
6113 199 : gfc_gobble_whitespace ();
6114 199 : if (gfc_peek_ascii_char () != '(')
6115 : return false;
6116 :
6117 195 : gfc_current_ns = ns;
6118 195 : m = gfc_match_actual_arglist (1, &arglist);
6119 195 : if (m != MATCH_YES)
6120 : return false;
6121 :
6122 195 : if (gfc_match_char (')') != MATCH_YES)
6123 : return false;
6124 :
6125 195 : ns->code = gfc_get_code (EXEC_CALL);
6126 195 : ns->code->symtree = st;
6127 195 : ns->code->ext.actual = arglist;
6128 195 : ns->code->loc = old_loc;
6129 195 : return true;
6130 : }
6131 :
6132 : static bool
6133 1156 : gfc_omp_udr_predef (gfc_omp_reduction_op rop, const char *name,
6134 : gfc_typespec *ts, const char **n)
6135 : {
6136 1156 : if (!gfc_numeric_ts (ts) && ts->type != BT_LOGICAL)
6137 : return false;
6138 :
6139 648 : switch (rop)
6140 : {
6141 21 : case OMP_REDUCTION_PLUS:
6142 21 : case OMP_REDUCTION_MINUS:
6143 21 : case OMP_REDUCTION_TIMES:
6144 21 : return ts->type != BT_LOGICAL;
6145 8 : case OMP_REDUCTION_AND:
6146 8 : case OMP_REDUCTION_OR:
6147 8 : case OMP_REDUCTION_EQV:
6148 8 : case OMP_REDUCTION_NEQV:
6149 8 : return ts->type == BT_LOGICAL;
6150 618 : case OMP_REDUCTION_USER:
6151 618 : if (name[0] != '.' && (ts->type == BT_INTEGER || ts->type == BT_REAL))
6152 : {
6153 546 : gfc_symbol *sym;
6154 :
6155 546 : gfc_find_symbol (name, NULL, 1, &sym);
6156 546 : if (sym != NULL)
6157 : {
6158 93 : if (sym->attr.intrinsic)
6159 0 : *n = sym->name;
6160 93 : else if ((sym->attr.flavor != FL_UNKNOWN
6161 81 : && sym->attr.flavor != FL_PROCEDURE)
6162 69 : || sym->attr.external
6163 54 : || sym->attr.generic
6164 54 : || sym->attr.entry
6165 54 : || sym->attr.result
6166 54 : || sym->attr.dummy
6167 54 : || sym->attr.subroutine
6168 50 : || sym->attr.pointer
6169 50 : || sym->attr.target
6170 50 : || sym->attr.cray_pointer
6171 50 : || sym->attr.cray_pointee
6172 50 : || (sym->attr.proc != PROC_UNKNOWN
6173 0 : && sym->attr.proc != PROC_INTRINSIC)
6174 50 : || sym->attr.if_source != IFSRC_UNKNOWN
6175 50 : || sym == sym->ns->proc_name)
6176 43 : *n = NULL;
6177 : else
6178 50 : *n = sym->name;
6179 : }
6180 : else
6181 453 : *n = name;
6182 546 : if (*n
6183 503 : && (strcmp (*n, "max") == 0 || strcmp (*n, "min") == 0))
6184 54 : return true;
6185 510 : else if (*n
6186 467 : && ts->type == BT_INTEGER
6187 383 : && (strcmp (*n, "iand") == 0
6188 377 : || strcmp (*n, "ior") == 0
6189 371 : || strcmp (*n, "ieor") == 0))
6190 : return true;
6191 : }
6192 : break;
6193 : default:
6194 : break;
6195 : }
6196 : return false;
6197 : }
6198 :
6199 : gfc_omp_udr *
6200 639 : gfc_omp_udr_find (gfc_symtree *st, gfc_typespec *ts)
6201 : {
6202 639 : gfc_omp_udr *omp_udr;
6203 :
6204 639 : if (st == NULL)
6205 : return NULL;
6206 :
6207 250 : for (omp_udr = st->n.omp_udr; omp_udr; omp_udr = omp_udr->next)
6208 154 : if (omp_udr->ts.type == ts->type
6209 89 : || ((omp_udr->ts.type == BT_DERIVED || omp_udr->ts.type == BT_CLASS)
6210 0 : && (ts->type == BT_DERIVED || ts->type == BT_CLASS)))
6211 : {
6212 65 : if (omp_udr->ts.type == BT_DERIVED || omp_udr->ts.type == BT_CLASS)
6213 : {
6214 12 : if (strcmp (omp_udr->ts.u.derived->name, ts->u.derived->name) == 0)
6215 : return omp_udr;
6216 : }
6217 53 : else if (omp_udr->ts.kind == ts->kind)
6218 : {
6219 19 : if (omp_udr->ts.type == BT_CHARACTER)
6220 : {
6221 17 : if (omp_udr->ts.u.cl->length == NULL
6222 15 : || ts->u.cl->length == NULL)
6223 : return omp_udr;
6224 15 : if (omp_udr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
6225 : return omp_udr;
6226 15 : if (ts->u.cl->length->expr_type != EXPR_CONSTANT)
6227 : return omp_udr;
6228 15 : if (omp_udr->ts.u.cl->length->ts.type != BT_INTEGER)
6229 : return omp_udr;
6230 15 : if (ts->u.cl->length->ts.type != BT_INTEGER)
6231 : return omp_udr;
6232 15 : if (gfc_compare_expr (omp_udr->ts.u.cl->length,
6233 : ts->u.cl->length, INTRINSIC_EQ) != 0)
6234 15 : continue;
6235 : }
6236 2 : return omp_udr;
6237 : }
6238 : }
6239 : return NULL;
6240 : }
6241 :
6242 : match
6243 532 : gfc_match_omp_declare_reduction (void)
6244 : {
6245 532 : match m;
6246 532 : gfc_intrinsic_op op;
6247 532 : char name[GFC_MAX_SYMBOL_LEN + 3];
6248 532 : auto_vec<gfc_typespec, 5> tss;
6249 532 : gfc_typespec ts;
6250 532 : unsigned int i;
6251 532 : gfc_symtree *st;
6252 532 : locus where = gfc_current_locus;
6253 532 : locus end_loc = gfc_current_locus;
6254 532 : bool end_loc_set = false;
6255 532 : gfc_omp_reduction_op rop = OMP_REDUCTION_NONE;
6256 :
6257 532 : if (gfc_match_char ('(') != MATCH_YES)
6258 : return MATCH_ERROR;
6259 :
6260 530 : m = gfc_match (" %o : ", &op);
6261 530 : if (m == MATCH_ERROR)
6262 : return MATCH_ERROR;
6263 530 : if (m == MATCH_YES)
6264 : {
6265 117 : snprintf (name, sizeof name, "operator %s", gfc_op2string (op));
6266 117 : rop = (gfc_omp_reduction_op) op;
6267 : }
6268 : else
6269 : {
6270 413 : m = gfc_match_defined_op_name (name + 1, 1);
6271 413 : if (m == MATCH_ERROR)
6272 : return MATCH_ERROR;
6273 413 : if (m == MATCH_YES)
6274 : {
6275 41 : name[0] = '.';
6276 41 : strcat (name, ".");
6277 41 : if (gfc_match (" : ") != MATCH_YES)
6278 : return MATCH_ERROR;
6279 : }
6280 : else
6281 : {
6282 372 : if (gfc_match (" %n : ", name) != MATCH_YES)
6283 : return MATCH_ERROR;
6284 : }
6285 : rop = OMP_REDUCTION_USER;
6286 : }
6287 :
6288 529 : m = gfc_match_type_spec (&ts);
6289 529 : if (m != MATCH_YES)
6290 : return MATCH_ERROR;
6291 : /* Treat len=: the same as len=*. */
6292 528 : if (ts.type == BT_CHARACTER)
6293 61 : ts.deferred = false;
6294 528 : tss.safe_push (ts);
6295 :
6296 1093 : while (gfc_match_char (',') == MATCH_YES)
6297 : {
6298 37 : m = gfc_match_type_spec (&ts);
6299 37 : if (m != MATCH_YES)
6300 : return MATCH_ERROR;
6301 37 : tss.safe_push (ts);
6302 : }
6303 528 : if (gfc_match_char (':') != MATCH_YES)
6304 : return MATCH_ERROR;
6305 :
6306 527 : st = gfc_find_symtree (gfc_current_ns->omp_udr_root, name);
6307 1084 : for (i = 0; i < tss.length (); i++)
6308 : {
6309 564 : gfc_symtree *omp_out, *omp_in;
6310 564 : gfc_symtree *omp_priv = NULL, *omp_orig = NULL;
6311 564 : gfc_namespace *combiner_ns, *initializer_ns = NULL;
6312 564 : gfc_omp_udr *prev_udr, *omp_udr;
6313 564 : const char *predef_name = NULL;
6314 :
6315 564 : omp_udr = gfc_get_omp_udr ();
6316 564 : omp_udr->name = gfc_get_string ("%s", name);
6317 564 : omp_udr->rop = rop;
6318 564 : omp_udr->ts = tss[i];
6319 564 : omp_udr->where = where;
6320 :
6321 564 : gfc_current_ns = combiner_ns = gfc_get_namespace (gfc_current_ns, 1);
6322 564 : combiner_ns->proc_name = combiner_ns->parent->proc_name;
6323 :
6324 564 : gfc_get_sym_tree ("omp_out", combiner_ns, &omp_out, false);
6325 564 : gfc_get_sym_tree ("omp_in", combiner_ns, &omp_in, false);
6326 564 : combiner_ns->omp_udr_ns = 1;
6327 564 : omp_out->n.sym->ts = tss[i];
6328 564 : omp_in->n.sym->ts = tss[i];
6329 564 : omp_out->n.sym->attr.omp_udr_artificial_var = 1;
6330 564 : omp_in->n.sym->attr.omp_udr_artificial_var = 1;
6331 564 : omp_out->n.sym->attr.flavor = FL_VARIABLE;
6332 564 : omp_in->n.sym->attr.flavor = FL_VARIABLE;
6333 564 : gfc_commit_symbols ();
6334 564 : omp_udr->combiner_ns = combiner_ns;
6335 564 : omp_udr->omp_out = omp_out->n.sym;
6336 564 : omp_udr->omp_in = omp_in->n.sym;
6337 :
6338 564 : locus old_loc = gfc_current_locus;
6339 :
6340 564 : if (!match_udr_expr (omp_out, omp_in))
6341 : {
6342 4 : syntax:
6343 7 : gfc_current_locus = old_loc;
6344 7 : gfc_current_ns = combiner_ns->parent;
6345 7 : gfc_undo_symbols ();
6346 7 : gfc_free_omp_udr (omp_udr);
6347 7 : return MATCH_ERROR;
6348 : }
6349 :
6350 560 : if (gfc_match (" initializer ( ") == MATCH_YES)
6351 : {
6352 313 : gfc_current_ns = combiner_ns->parent;
6353 313 : initializer_ns = gfc_get_namespace (gfc_current_ns, 1);
6354 313 : gfc_current_ns = initializer_ns;
6355 313 : initializer_ns->proc_name = initializer_ns->parent->proc_name;
6356 :
6357 313 : gfc_get_sym_tree ("omp_priv", initializer_ns, &omp_priv, false);
6358 313 : gfc_get_sym_tree ("omp_orig", initializer_ns, &omp_orig, false);
6359 313 : initializer_ns->omp_udr_ns = 1;
6360 313 : omp_priv->n.sym->ts = tss[i];
6361 313 : omp_orig->n.sym->ts = tss[i];
6362 313 : omp_priv->n.sym->attr.omp_udr_artificial_var = 1;
6363 313 : omp_orig->n.sym->attr.omp_udr_artificial_var = 1;
6364 313 : omp_priv->n.sym->attr.flavor = FL_VARIABLE;
6365 313 : omp_orig->n.sym->attr.flavor = FL_VARIABLE;
6366 313 : gfc_commit_symbols ();
6367 313 : omp_udr->initializer_ns = initializer_ns;
6368 313 : omp_udr->omp_priv = omp_priv->n.sym;
6369 313 : omp_udr->omp_orig = omp_orig->n.sym;
6370 :
6371 313 : if (!match_udr_expr (omp_priv, omp_orig))
6372 3 : goto syntax;
6373 : }
6374 :
6375 557 : gfc_current_ns = combiner_ns->parent;
6376 557 : if (!end_loc_set)
6377 : {
6378 520 : end_loc_set = true;
6379 520 : end_loc = gfc_current_locus;
6380 : }
6381 557 : gfc_current_locus = old_loc;
6382 :
6383 557 : prev_udr = gfc_omp_udr_find (st, &tss[i]);
6384 557 : if (gfc_omp_udr_predef (rop, name, &tss[i], &predef_name)
6385 : /* Don't error on !$omp declare reduction (min : integer : ...)
6386 : just yet, there could be integer :: min afterwards,
6387 : making it valid. When the UDR is resolved, we'll get
6388 : to it again. */
6389 557 : && (rop != OMP_REDUCTION_USER || name[0] == '.'))
6390 : {
6391 29 : if (predef_name)
6392 0 : gfc_error_now ("Redefinition of predefined %s "
6393 : "!$OMP DECLARE REDUCTION at %L",
6394 : predef_name, &where);
6395 : else
6396 29 : gfc_error_now ("Redefinition of predefined "
6397 : "!$OMP DECLARE REDUCTION at %L", &where);
6398 : }
6399 528 : else if (prev_udr)
6400 : {
6401 6 : gfc_error_now ("Redefinition of !$OMP DECLARE REDUCTION at %L",
6402 : &where);
6403 6 : gfc_error_now ("Previous !$OMP DECLARE REDUCTION at %L",
6404 : &prev_udr->where);
6405 : }
6406 522 : else if (st)
6407 : {
6408 96 : omp_udr->next = st->n.omp_udr;
6409 96 : st->n.omp_udr = omp_udr;
6410 : }
6411 : else
6412 : {
6413 426 : st = gfc_new_symtree (&gfc_current_ns->omp_udr_root, name);
6414 426 : st->n.omp_udr = omp_udr;
6415 : }
6416 : }
6417 :
6418 520 : if (end_loc_set)
6419 : {
6420 520 : gfc_current_locus = end_loc;
6421 520 : if (gfc_match_omp_eos () != MATCH_YES)
6422 : {
6423 1 : gfc_error ("Unexpected junk after !$OMP DECLARE REDUCTION at %C");
6424 1 : gfc_current_locus = where;
6425 1 : return MATCH_ERROR;
6426 : }
6427 :
6428 : return MATCH_YES;
6429 : }
6430 0 : gfc_clear_error ();
6431 0 : return MATCH_ERROR;
6432 532 : }
6433 :
6434 :
6435 : match
6436 471 : gfc_match_omp_declare_target (void)
6437 : {
6438 471 : locus old_loc;
6439 471 : match m;
6440 471 : gfc_omp_clauses *c = NULL;
6441 471 : enum gfc_omp_list_type list;
6442 471 : gfc_omp_namelist *n;
6443 471 : gfc_symbol *s;
6444 :
6445 471 : old_loc = gfc_current_locus;
6446 :
6447 471 : if (gfc_current_ns->proc_name
6448 471 : && gfc_match_omp_eos () == MATCH_YES)
6449 : {
6450 138 : if (!gfc_add_omp_declare_target (&gfc_current_ns->proc_name->attr,
6451 138 : gfc_current_ns->proc_name->name,
6452 : &old_loc))
6453 0 : goto cleanup;
6454 : return MATCH_YES;
6455 : }
6456 :
6457 333 : if (gfc_current_ns->proc_name
6458 333 : && gfc_current_ns->proc_name->attr.if_source == IFSRC_IFBODY)
6459 : {
6460 2 : gfc_error ("Only the !$OMP DECLARE TARGET form without "
6461 : "clauses is allowed in interface block at %C");
6462 2 : goto cleanup;
6463 : }
6464 :
6465 331 : m = gfc_match (" (");
6466 331 : if (m == MATCH_YES)
6467 : {
6468 85 : c = gfc_get_omp_clauses ();
6469 85 : gfc_current_locus = old_loc;
6470 85 : m = gfc_match_omp_to_link (" (", &c->lists[OMP_LIST_ENTER]);
6471 85 : if (m != MATCH_YES)
6472 0 : goto syntax;
6473 85 : if (gfc_match_omp_eos () != MATCH_YES)
6474 : {
6475 0 : gfc_error ("Unexpected junk after !$OMP DECLARE TARGET at %C");
6476 0 : goto cleanup;
6477 : }
6478 : }
6479 246 : else if (gfc_match_omp_clauses (&c, OMP_DECLARE_TARGET_CLAUSES) != MATCH_YES)
6480 : return MATCH_ERROR;
6481 :
6482 325 : gfc_buffer_error (false);
6483 :
6484 325 : static const enum gfc_omp_list_type to_enter_link_lists[]
6485 : = { OMP_LIST_TO, OMP_LIST_ENTER, OMP_LIST_LINK, OMP_LIST_LOCAL };
6486 1625 : for (size_t listn = 0; listn < ARRAY_SIZE (to_enter_link_lists)
6487 1625 : && (list = to_enter_link_lists[listn], true); ++listn)
6488 1844 : for (n = c->lists[list]; n; n = n->next)
6489 544 : if (n->sym)
6490 503 : n->sym->mark = 0;
6491 41 : else if (n->u.common->head)
6492 41 : n->u.common->head->mark = 0;
6493 :
6494 325 : if (c->device_type == OMP_DEVICE_TYPE_UNSET)
6495 257 : c->device_type = OMP_DEVICE_TYPE_ANY;
6496 1300 : for (size_t listn = 0; listn < ARRAY_SIZE (to_enter_link_lists)
6497 1625 : && (list = to_enter_link_lists[listn], true); ++listn)
6498 1844 : for (n = c->lists[list]; n; n = n->next)
6499 544 : if (n->sym)
6500 : {
6501 503 : if (n->sym->attr.in_common)
6502 1 : gfc_error_now ("OMP DECLARE TARGET variable at %L is an "
6503 : "element of a COMMON block", &n->where);
6504 502 : else if (n->sym->attr.omp_groupprivate && list != OMP_LIST_LOCAL)
6505 12 : gfc_error_now ("List item %qs at %L not appear in the %qs clause "
6506 : "as it was previously specified in a GROUPPRIVATE "
6507 : "directive", n->sym->name, &n->where,
6508 : list == OMP_LIST_LINK
6509 5 : ? "link" : list == OMP_LIST_TO ? "to" : "enter");
6510 495 : else if (n->sym->mark)
6511 9 : gfc_error_now ("Variable at %L mentioned multiple times in "
6512 : "clauses of the same OMP DECLARE TARGET directive",
6513 : &n->where);
6514 486 : else if ((n->sym->attr.omp_declare_target_link
6515 481 : || n->sym->attr.omp_declare_target_local)
6516 : && list != OMP_LIST_LINK
6517 7 : && list != OMP_LIST_LOCAL)
6518 1 : gfc_error_now ("OMP DECLARE TARGET variable at %L previously "
6519 : "mentioned in %s clause and later in %s clause",
6520 : &n->where,
6521 : n->sym->attr.omp_declare_target_link ? "LINK"
6522 : : "LOCAL",
6523 : list == OMP_LIST_TO ? "TO" : "ENTER");
6524 485 : else if (n->sym->attr.omp_declare_target
6525 14 : && (list == OMP_LIST_LINK || list == OMP_LIST_LOCAL))
6526 1 : gfc_error_now ("OMP DECLARE TARGET variable at %L previously "
6527 : "mentioned in TO or ENTER clause and later in "
6528 : "%s clause", &n->where,
6529 : list == OMP_LIST_LINK ? "LINK" : "LOCAL");
6530 : else
6531 : {
6532 484 : if (list == OMP_LIST_TO || list == OMP_LIST_ENTER)
6533 445 : gfc_add_omp_declare_target (&n->sym->attr, n->sym->name,
6534 : &n->sym->declared_at);
6535 484 : if (list == OMP_LIST_LINK)
6536 30 : gfc_add_omp_declare_target_link (&n->sym->attr, n->sym->name,
6537 30 : &n->sym->declared_at);
6538 484 : if (list == OMP_LIST_LOCAL)
6539 9 : gfc_add_omp_declare_target_local (&n->sym->attr, n->sym->name,
6540 9 : &n->sym->declared_at);
6541 : }
6542 503 : if (n->sym->attr.omp_device_type != OMP_DEVICE_TYPE_UNSET
6543 36 : && n->sym->attr.omp_device_type != c->device_type)
6544 : {
6545 12 : const char *dt = "any";
6546 12 : if (n->sym->attr.omp_device_type == OMP_DEVICE_TYPE_NOHOST)
6547 : dt = "nohost";
6548 8 : else if (n->sym->attr.omp_device_type == OMP_DEVICE_TYPE_HOST)
6549 4 : dt = "host";
6550 12 : if (n->sym->attr.omp_groupprivate)
6551 1 : gfc_error_now ("List item %qs at %L set in previous OMP "
6552 : "GROUPPRIVATE directive to the different "
6553 : "DEVICE_TYPE %qs", n->sym->name, &n->where, dt);
6554 : else
6555 11 : gfc_error_now ("List item %qs at %L set in previous OMP "
6556 : "DECLARE TARGET directive to the different "
6557 : "DEVICE_TYPE %qs", n->sym->name, &n->where, dt);
6558 : }
6559 503 : n->sym->attr.omp_device_type = c->device_type;
6560 503 : if (c->indirect && c->device_type != OMP_DEVICE_TYPE_ANY)
6561 : {
6562 1 : gfc_error_now ("DEVICE_TYPE must be ANY when used with INDIRECT "
6563 : "at %L", &n->where);
6564 1 : c->indirect = 0;
6565 : }
6566 503 : n->sym->attr.omp_declare_target_indirect = c->indirect;
6567 503 : if (list == OMP_LIST_LINK && c->device_type == OMP_DEVICE_TYPE_NOHOST)
6568 3 : gfc_error_now ("List item %qs at %L set with NOHOST specified may "
6569 : "not appear in a LINK clause", n->sym->name,
6570 : &n->where);
6571 503 : n->sym->mark = 1;
6572 : }
6573 : else /* common block */
6574 : {
6575 41 : if (n->u.common->omp_groupprivate && list != OMP_LIST_LOCAL)
6576 7 : gfc_error_now ("Common block %</%s/%> at %L not appear in the %qs "
6577 : "clause as it was previously specified in a "
6578 : "GROUPPRIVATE directive",
6579 7 : n->u.common->name, &n->where,
6580 : list == OMP_LIST_LINK
6581 5 : ? "link" : list == OMP_LIST_TO ? "to" : "enter");
6582 34 : else if (n->u.common->head && n->u.common->head->mark)
6583 4 : gfc_error_now ("Common block %</%s/%> at %L mentioned multiple "
6584 : "times in clauses of the same OMP DECLARE TARGET "
6585 4 : "directive", n->u.common->name, &n->where);
6586 30 : else if ((n->u.common->omp_declare_target_link
6587 26 : || n->u.common->omp_declare_target_local)
6588 : && list != OMP_LIST_LINK
6589 6 : && list != OMP_LIST_LOCAL)
6590 2 : gfc_error_now ("Common block %</%s/%> at %L previously mentioned "
6591 : "in %s clause and later in %s clause",
6592 1 : n->u.common->name, &n->where,
6593 : n->u.common->omp_declare_target_link ? "LINK"
6594 : : "LOCAL",
6595 : list == OMP_LIST_TO ? "TO" : "ENTER");
6596 29 : else if (n->u.common->omp_declare_target
6597 4 : && (list == OMP_LIST_LINK || list == OMP_LIST_LOCAL))
6598 1 : gfc_error_now ("Common block %</%s/%> at %L previously mentioned "
6599 : "in TO or ENTER clause and later in %s clause",
6600 1 : n->u.common->name, &n->where,
6601 : list == OMP_LIST_LINK ? "LINK" : "LOCAL");
6602 41 : if (n->u.common->omp_device_type != OMP_DEVICE_TYPE_UNSET
6603 21 : && n->u.common->omp_device_type != c->device_type)
6604 : {
6605 1 : const char *dt = "any";
6606 1 : if (n->u.common->omp_device_type == OMP_DEVICE_TYPE_NOHOST)
6607 : dt = "nohost";
6608 0 : else if (n->u.common->omp_device_type == OMP_DEVICE_TYPE_HOST)
6609 0 : dt = "host";
6610 1 : if (n->u.common->omp_groupprivate)
6611 1 : gfc_error_now ("Common block %</%s/%> at %L set in previous OMP "
6612 : "GROUPPRIVATE directive to the different "
6613 1 : "DEVICE_TYPE %qs", n->u.common->name, &n->where,
6614 : dt);
6615 : else
6616 0 : gfc_error_now ("Common block %</%s/%> at %L set in previous OMP "
6617 : "DECLARE TARGET directive to the different "
6618 0 : "DEVICE_TYPE %qs", n->u.common->name, &n->where,
6619 : dt);
6620 : }
6621 41 : n->u.common->omp_device_type = c->device_type;
6622 :
6623 41 : if (c->indirect && c->device_type != OMP_DEVICE_TYPE_ANY)
6624 : {
6625 0 : gfc_error_now ("DEVICE_TYPE must be ANY when used with INDIRECT "
6626 : "at %L", &n->where);
6627 0 : c->indirect = 0;
6628 : }
6629 41 : if (list == OMP_LIST_LINK && c->device_type == OMP_DEVICE_TYPE_NOHOST)
6630 1 : gfc_error_now ("Common block %</%s/%> at %L set with NOHOST "
6631 : "specified may not appear in a LINK clause",
6632 1 : n->u.common->name, &n->where);
6633 :
6634 41 : if (list == OMP_LIST_TO || list == OMP_LIST_ENTER)
6635 21 : n->u.common->omp_declare_target = 1;
6636 41 : if (list == OMP_LIST_LINK)
6637 15 : n->u.common->omp_declare_target_link = 1;
6638 41 : if (list == OMP_LIST_LOCAL)
6639 5 : n->u.common->omp_declare_target_local = 1;
6640 :
6641 110 : for (s = n->u.common->head; s; s = s->common_next)
6642 : {
6643 69 : s->mark = 1;
6644 69 : if (list == OMP_LIST_TO || list == OMP_LIST_ENTER)
6645 33 : gfc_add_omp_declare_target (&s->attr, s->name, &n->where);
6646 69 : if (list == OMP_LIST_LINK)
6647 31 : gfc_add_omp_declare_target_link (&s->attr, s->name, &n->where);
6648 69 : if (list == OMP_LIST_LOCAL)
6649 5 : gfc_add_omp_declare_target_local (&s->attr, s->name, &n->where);
6650 69 : s->attr.omp_device_type = c->device_type;
6651 69 : s->attr.omp_declare_target_indirect = c->indirect;
6652 : }
6653 : }
6654 325 : if ((c->device_type || c->indirect)
6655 325 : && !c->lists[OMP_LIST_ENTER]
6656 151 : && !c->lists[OMP_LIST_TO]
6657 47 : && !c->lists[OMP_LIST_LINK]
6658 10 : && !c->lists[OMP_LIST_LOCAL])
6659 2 : gfc_warning_now (OPT_Wopenmp,
6660 : "OMP DECLARE TARGET directive at %L with only "
6661 : "DEVICE_TYPE or INDIRECT clauses is ignored",
6662 : &old_loc);
6663 :
6664 325 : gfc_buffer_error (true);
6665 :
6666 325 : if (c)
6667 325 : gfc_free_omp_clauses (c);
6668 325 : return MATCH_YES;
6669 :
6670 0 : syntax:
6671 0 : gfc_error ("Syntax error in !$OMP DECLARE TARGET list at %C");
6672 :
6673 2 : cleanup:
6674 2 : gfc_current_locus = old_loc;
6675 2 : if (c)
6676 0 : gfc_free_omp_clauses (c);
6677 : return MATCH_ERROR;
6678 : }
6679 :
6680 : /* Skip over and ignore trait-property-extensions.
6681 :
6682 : trait-property-extension :
6683 : trait-property-name
6684 : identifier (trait-property-extension[, trait-property-extension[, ...]])
6685 : constant integer expression
6686 : */
6687 :
6688 : static match gfc_ignore_trait_property_extension_list (void);
6689 :
6690 : static match
6691 7 : gfc_ignore_trait_property_extension (void)
6692 : {
6693 7 : char buf[GFC_MAX_SYMBOL_LEN + 1];
6694 7 : gfc_expr *expr;
6695 :
6696 : /* Identifier form of trait-property name, possibly followed by
6697 : a list of (recursive) trait-property-extensions. */
6698 7 : if (gfc_match_name (buf) == MATCH_YES)
6699 : {
6700 0 : if (gfc_match (" (") == MATCH_YES)
6701 0 : return gfc_ignore_trait_property_extension_list ();
6702 : return MATCH_YES;
6703 : }
6704 :
6705 : /* Literal constant. */
6706 7 : if (gfc_match_literal_constant (&expr, 0) == MATCH_YES)
6707 : return MATCH_YES;
6708 :
6709 : /* FIXME: constant integer expressions. */
6710 0 : gfc_error ("Expected trait-property-extension at %C");
6711 0 : return MATCH_ERROR;
6712 : }
6713 :
6714 : static match
6715 5 : gfc_ignore_trait_property_extension_list (void)
6716 : {
6717 9 : while (1)
6718 : {
6719 7 : if (gfc_ignore_trait_property_extension () != MATCH_YES)
6720 : return MATCH_ERROR;
6721 7 : if (gfc_match (" ,") == MATCH_YES)
6722 2 : continue;
6723 5 : if (gfc_match (" )") == MATCH_YES)
6724 : return MATCH_YES;
6725 0 : gfc_error ("expected %<)%> at %C");
6726 0 : return MATCH_ERROR;
6727 : }
6728 : }
6729 :
6730 :
6731 : match
6732 110 : gfc_match_omp_interop (void)
6733 : {
6734 110 : return match_omp (EXEC_OMP_INTEROP, OMP_INTEROP_CLAUSES);
6735 : }
6736 :
6737 :
6738 : /* OpenMP 5.0:
6739 :
6740 : trait-selector:
6741 : trait-selector-name[([trait-score:]trait-property[,trait-property[,...]])]
6742 :
6743 : trait-score:
6744 : score(score-expression) */
6745 :
6746 : static match
6747 637 : gfc_match_omp_context_selector (gfc_omp_set_selector *oss)
6748 : {
6749 775 : do
6750 : {
6751 775 : char selector[GFC_MAX_SYMBOL_LEN + 1];
6752 :
6753 775 : if (gfc_match_name (selector) != MATCH_YES)
6754 : {
6755 2 : gfc_error ("expected trait selector name at %C");
6756 39 : return MATCH_ERROR;
6757 : }
6758 :
6759 773 : gfc_omp_selector *os = gfc_get_omp_selector ();
6760 773 : if (oss->code == OMP_TRAIT_SET_CONSTRUCT
6761 335 : && !strcmp (selector, "do"))
6762 48 : os->code = OMP_TRAIT_CONSTRUCT_FOR;
6763 725 : else if (oss->code == OMP_TRAIT_SET_CONSTRUCT
6764 287 : && !strcmp (selector, "for"))
6765 1 : os->code = OMP_TRAIT_INVALID;
6766 : else
6767 724 : os->code = omp_lookup_ts_code (oss->code, selector);
6768 773 : os->next = oss->trait_selectors;
6769 773 : oss->trait_selectors = os;
6770 :
6771 773 : if (os->code == OMP_TRAIT_INVALID)
6772 : {
6773 18 : gfc_warning (OPT_Wopenmp,
6774 : "unknown selector %qs for context selector set %qs "
6775 : "at %C",
6776 18 : selector, omp_tss_map[oss->code]);
6777 18 : if (gfc_match (" (") == MATCH_YES
6778 18 : && gfc_ignore_trait_property_extension_list () != MATCH_YES)
6779 : return MATCH_ERROR;
6780 18 : if (gfc_match (" ,") == MATCH_YES)
6781 1 : continue;
6782 598 : break;
6783 : }
6784 :
6785 755 : enum omp_tp_type property_kind = omp_ts_map[os->code].tp_type;
6786 755 : bool allow_score = omp_ts_map[os->code].allow_score;
6787 :
6788 755 : if (gfc_match (" (") == MATCH_YES)
6789 : {
6790 431 : if (property_kind == OMP_TRAIT_PROPERTY_NONE)
6791 : {
6792 6 : gfc_error ("selector %qs does not accept any properties at %C",
6793 : selector);
6794 6 : return MATCH_ERROR;
6795 : }
6796 :
6797 425 : if (gfc_match (" score") == MATCH_YES)
6798 : {
6799 63 : if (!allow_score)
6800 : {
6801 10 : gfc_error ("%<score%> cannot be specified in traits "
6802 : "in the %qs trait-selector-set at %C",
6803 10 : omp_tss_map[oss->code]);
6804 10 : return MATCH_ERROR;
6805 : }
6806 53 : if (gfc_match (" (") != MATCH_YES)
6807 : {
6808 0 : gfc_error ("expected %<(%> at %C");
6809 0 : return MATCH_ERROR;
6810 : }
6811 53 : if (gfc_match_expr (&os->score) != MATCH_YES)
6812 : return MATCH_ERROR;
6813 :
6814 52 : if (gfc_match (" )") != MATCH_YES)
6815 : {
6816 0 : gfc_error ("expected %<)%> at %C");
6817 0 : return MATCH_ERROR;
6818 : }
6819 :
6820 52 : if (gfc_match (" :") != MATCH_YES)
6821 : {
6822 0 : gfc_error ("expected : at %C");
6823 0 : return MATCH_ERROR;
6824 : }
6825 : }
6826 :
6827 414 : gfc_omp_trait_property *otp = gfc_get_omp_trait_property ();
6828 414 : otp->property_kind = property_kind;
6829 414 : otp->next = os->properties;
6830 414 : os->properties = otp;
6831 :
6832 414 : switch (property_kind)
6833 : {
6834 25 : case OMP_TRAIT_PROPERTY_ID:
6835 25 : {
6836 25 : char buf[GFC_MAX_SYMBOL_LEN + 1];
6837 25 : if (gfc_match_name (buf) == MATCH_YES)
6838 : {
6839 24 : otp->name = XNEWVEC (char, strlen (buf) + 1);
6840 24 : strcpy (otp->name, buf);
6841 : }
6842 : else
6843 : {
6844 1 : gfc_error ("expected identifier at %C");
6845 1 : free (otp);
6846 1 : os->properties = nullptr;
6847 1 : return MATCH_ERROR;
6848 : }
6849 : }
6850 24 : break;
6851 290 : case OMP_TRAIT_PROPERTY_NAME_LIST:
6852 343 : do
6853 : {
6854 290 : char buf[GFC_MAX_SYMBOL_LEN + 1];
6855 290 : if (gfc_match_name (buf) == MATCH_YES)
6856 : {
6857 170 : otp->name = XNEWVEC (char, strlen (buf) + 1);
6858 170 : strcpy (otp->name, buf);
6859 170 : otp->is_name = true;
6860 : }
6861 120 : else if (gfc_match_literal_constant (&otp->expr, 0)
6862 : != MATCH_YES
6863 120 : || otp->expr->ts.type != BT_CHARACTER)
6864 : {
6865 5 : gfc_error ("expected identifier or string literal "
6866 : "at %C");
6867 5 : free (otp);
6868 5 : os->properties = nullptr;
6869 5 : return MATCH_ERROR;
6870 : }
6871 :
6872 285 : if (gfc_match (" ,") == MATCH_YES)
6873 : {
6874 53 : otp = gfc_get_omp_trait_property ();
6875 53 : otp->property_kind = property_kind;
6876 53 : otp->next = os->properties;
6877 53 : os->properties = otp;
6878 : }
6879 : else
6880 : break;
6881 53 : }
6882 : while (1);
6883 232 : break;
6884 137 : case OMP_TRAIT_PROPERTY_DEV_NUM_EXPR:
6885 137 : case OMP_TRAIT_PROPERTY_BOOL_EXPR:
6886 137 : if (gfc_match_expr (&otp->expr) != MATCH_YES)
6887 : {
6888 3 : gfc_error ("expected expression at %C");
6889 3 : free (otp);
6890 3 : os->properties = nullptr;
6891 3 : return MATCH_ERROR;
6892 : }
6893 : break;
6894 15 : case OMP_TRAIT_PROPERTY_CLAUSE_LIST:
6895 15 : {
6896 15 : if (os->code == OMP_TRAIT_CONSTRUCT_SIMD)
6897 : {
6898 15 : gfc_matching_omp_context_selector = true;
6899 15 : if (gfc_match_omp_clauses (&otp->clauses,
6900 15 : OMP_DECLARE_SIMD_CLAUSES,
6901 : true, false, false)
6902 : != MATCH_YES)
6903 : {
6904 1 : gfc_matching_omp_context_selector = false;
6905 1 : gfc_error ("expected simd clause at %C");
6906 1 : return MATCH_ERROR;
6907 : }
6908 14 : gfc_matching_omp_context_selector = false;
6909 : }
6910 0 : else if (os->code == OMP_TRAIT_IMPLEMENTATION_REQUIRES)
6911 : {
6912 : /* FIXME: The "requires" selector was added in OpenMP 5.1.
6913 : Currently only the now-deprecated syntax
6914 : from OpenMP 5.0 is supported.
6915 : TODO: When implementing, update modules.cc as well. */
6916 0 : sorry_at (gfc_get_location (&gfc_current_locus),
6917 : "%<requires%> selector is not supported yet");
6918 0 : return MATCH_ERROR;
6919 : }
6920 : else
6921 0 : gcc_unreachable ();
6922 14 : break;
6923 : }
6924 0 : default:
6925 0 : gcc_unreachable ();
6926 : }
6927 :
6928 404 : if (gfc_match (" )") != MATCH_YES)
6929 : {
6930 2 : gfc_error ("expected %<)%> at %C");
6931 2 : return MATCH_ERROR;
6932 : }
6933 : }
6934 324 : else if (property_kind != OMP_TRAIT_PROPERTY_NONE
6935 324 : && property_kind != OMP_TRAIT_PROPERTY_CLAUSE_LIST
6936 8 : && property_kind != OMP_TRAIT_PROPERTY_EXTENSION)
6937 : {
6938 8 : if (gfc_match (" (") != MATCH_YES)
6939 : {
6940 8 : gfc_error ("expected %<(%> at %C");
6941 8 : return MATCH_ERROR;
6942 : }
6943 : }
6944 :
6945 718 : if (gfc_match (" ,") != MATCH_YES)
6946 : break;
6947 : }
6948 : while (1);
6949 :
6950 598 : return MATCH_YES;
6951 : }
6952 :
6953 : /* OpenMP 5.0:
6954 :
6955 : trait-set-selector[,trait-set-selector[,...]]
6956 :
6957 : trait-set-selector:
6958 : trait-set-selector-name = { trait-selector[, trait-selector[, ...]] }
6959 :
6960 : trait-set-selector-name:
6961 : constructor
6962 : device
6963 : implementation
6964 : user */
6965 :
6966 : static match
6967 577 : gfc_match_omp_context_selector_specification (gfc_omp_set_selector **oss_head)
6968 : {
6969 713 : do
6970 : {
6971 645 : match m;
6972 645 : char buf[GFC_MAX_SYMBOL_LEN + 1];
6973 645 : enum omp_tss_code set = OMP_TRAIT_SET_INVALID;
6974 :
6975 645 : m = gfc_match_name (buf);
6976 645 : if (m == MATCH_YES)
6977 643 : set = omp_lookup_tss_code (buf);
6978 :
6979 643 : if (set == OMP_TRAIT_SET_INVALID)
6980 : {
6981 5 : gfc_error ("expected context selector set name at %C");
6982 47 : return MATCH_ERROR;
6983 : }
6984 :
6985 640 : m = gfc_match (" =");
6986 640 : if (m != MATCH_YES)
6987 : {
6988 1 : gfc_error ("expected %<=%> at %C");
6989 1 : return MATCH_ERROR;
6990 : }
6991 :
6992 639 : m = gfc_match (" {");
6993 639 : if (m != MATCH_YES)
6994 : {
6995 2 : gfc_error ("expected %<{%> at %C");
6996 2 : return MATCH_ERROR;
6997 : }
6998 :
6999 637 : gfc_omp_set_selector *oss = gfc_get_omp_set_selector ();
7000 637 : oss->next = *oss_head;
7001 637 : oss->code = set;
7002 637 : *oss_head = oss;
7003 :
7004 637 : if (gfc_match_omp_context_selector (oss) != MATCH_YES)
7005 : return MATCH_ERROR;
7006 :
7007 598 : m = gfc_match (" }");
7008 598 : if (m != MATCH_YES)
7009 : {
7010 0 : gfc_error ("expected %<}%> at %C");
7011 0 : return MATCH_ERROR;
7012 : }
7013 :
7014 598 : m = gfc_match (" ,");
7015 598 : if (m != MATCH_YES)
7016 : break;
7017 68 : }
7018 : while (1);
7019 :
7020 530 : return MATCH_YES;
7021 : }
7022 :
7023 :
7024 : match
7025 419 : gfc_match_omp_declare_variant (void)
7026 : {
7027 419 : char buf[GFC_MAX_SYMBOL_LEN + 1];
7028 :
7029 419 : if (gfc_match (" (") != MATCH_YES)
7030 : {
7031 2 : gfc_error ("expected %<(%> at %C");
7032 2 : return MATCH_ERROR;
7033 : }
7034 :
7035 417 : gfc_symtree *base_proc_st, *variant_proc_st;
7036 417 : if (gfc_match_name (buf) != MATCH_YES)
7037 : {
7038 2 : gfc_error ("expected name at %C");
7039 2 : return MATCH_ERROR;
7040 : }
7041 :
7042 415 : if (gfc_get_ha_sym_tree (buf, &base_proc_st))
7043 : return MATCH_ERROR;
7044 :
7045 415 : if (gfc_match (" :") == MATCH_YES)
7046 : {
7047 16 : if (gfc_match_name (buf) != MATCH_YES)
7048 : {
7049 0 : gfc_error ("expected variant name at %C");
7050 0 : return MATCH_ERROR;
7051 : }
7052 :
7053 16 : if (gfc_get_ha_sym_tree (buf, &variant_proc_st))
7054 : return MATCH_ERROR;
7055 : }
7056 : else
7057 : {
7058 : /* Base procedure not specified. */
7059 399 : variant_proc_st = base_proc_st;
7060 399 : base_proc_st = NULL;
7061 : }
7062 :
7063 415 : gfc_omp_declare_variant *odv;
7064 415 : odv = gfc_get_omp_declare_variant ();
7065 415 : odv->where = gfc_current_locus;
7066 415 : odv->variant_proc_symtree = variant_proc_st;
7067 415 : odv->adjust_args_list = NULL;
7068 415 : odv->base_proc_symtree = base_proc_st;
7069 415 : odv->next = NULL;
7070 415 : odv->error_p = false;
7071 :
7072 : /* Add the new declare variant to the end of the list. */
7073 415 : gfc_omp_declare_variant **prev_next = &gfc_current_ns->omp_declare_variant;
7074 555 : while (*prev_next)
7075 140 : prev_next = &((*prev_next)->next);
7076 415 : *prev_next = odv;
7077 :
7078 415 : if (gfc_match (" )") != MATCH_YES)
7079 : {
7080 1 : gfc_error ("expected %<)%> at %C");
7081 1 : return MATCH_ERROR;
7082 : }
7083 :
7084 414 : bool has_match = false, has_adjust_args = false, has_append_args = false;
7085 414 : bool error_p = false;
7086 414 : locus adjust_args_loc;
7087 414 : locus append_args_loc;
7088 :
7089 414 : gfc_gobble_whitespace ();
7090 414 : gfc_match_char (',');
7091 632 : for (;;)
7092 : {
7093 523 : gfc_gobble_whitespace ();
7094 :
7095 523 : enum clause
7096 : {
7097 : clause_match,
7098 : clause_adjust_args,
7099 : clause_append_args
7100 : } ccode;
7101 :
7102 523 : if (gfc_match ("match") == MATCH_YES)
7103 : ccode = clause_match;
7104 119 : else if (gfc_match ("adjust_args") == MATCH_YES)
7105 : {
7106 517 : ccode = clause_adjust_args;
7107 : adjust_args_loc = gfc_current_locus;
7108 : }
7109 38 : else if (gfc_match ("append_args") == MATCH_YES)
7110 : {
7111 517 : ccode = clause_append_args;
7112 : append_args_loc = gfc_current_locus;
7113 : }
7114 : else
7115 : {
7116 : error_p = true;
7117 : break;
7118 : }
7119 :
7120 517 : if (gfc_match (" ( ") != MATCH_YES)
7121 : {
7122 1 : gfc_error ("expected %<(%> at %C");
7123 1 : return MATCH_ERROR;
7124 : }
7125 :
7126 516 : if (ccode == clause_match)
7127 : {
7128 403 : if (has_match)
7129 : {
7130 1 : gfc_error ("%qs clause at %L specified more than once",
7131 : "match", &gfc_current_locus);
7132 1 : return MATCH_ERROR;
7133 : }
7134 402 : has_match = true;
7135 402 : if (gfc_match_omp_context_selector_specification (&odv->set_selectors)
7136 : != MATCH_YES)
7137 : return MATCH_ERROR;
7138 362 : if (gfc_match (" )") != MATCH_YES)
7139 : {
7140 0 : gfc_error ("expected %<)%> at %C");
7141 0 : return MATCH_ERROR;
7142 : }
7143 : }
7144 113 : else if (ccode == clause_adjust_args)
7145 : {
7146 81 : has_adjust_args = true;
7147 81 : bool need_device_ptr_p = false;
7148 81 : bool need_device_addr_p = false;
7149 81 : if (gfc_match ("nothing ") == MATCH_YES)
7150 : ;
7151 58 : else if (gfc_match ("need_device_ptr ") == MATCH_YES)
7152 : need_device_ptr_p = true;
7153 9 : else if (gfc_match ("need_device_addr ") == MATCH_YES)
7154 : need_device_addr_p = true;
7155 : else
7156 : {
7157 2 : gfc_error ("expected %<nothing%>, %<need_device_ptr%> or "
7158 : "%<need_device_addr%> at %C");
7159 2 : return MATCH_ERROR;
7160 : }
7161 79 : if (gfc_match (": ") != MATCH_YES)
7162 : {
7163 1 : gfc_error ("expected %<:%> at %C");
7164 1 : return MATCH_ERROR;
7165 : }
7166 : gfc_omp_namelist *tail = NULL;
7167 : bool need_range = false, have_range = false;
7168 125 : while (true)
7169 : {
7170 125 : gfc_omp_namelist *p = gfc_get_omp_namelist ();
7171 125 : p->where = gfc_current_locus;
7172 125 : p->u.adj_args.need_ptr = need_device_ptr_p;
7173 125 : p->u.adj_args.need_addr = need_device_addr_p;
7174 125 : if (tail)
7175 : {
7176 47 : tail->next = p;
7177 47 : tail = tail->next;
7178 : }
7179 : else
7180 : {
7181 78 : gfc_omp_namelist **q = &odv->adjust_args_list;
7182 78 : if (*q)
7183 : {
7184 50 : for (; (*q)->next; q = &(*q)->next)
7185 : ;
7186 28 : (*q)->next = p;
7187 : }
7188 : else
7189 50 : *q = p;
7190 : tail = p;
7191 : }
7192 125 : if (gfc_match (": ") == MATCH_YES)
7193 : {
7194 2 : if (have_range)
7195 : {
7196 0 : gfc_error ("unexpected %<:%> at %C");
7197 2 : return MATCH_ERROR;
7198 : }
7199 2 : p->u.adj_args.range_start = have_range = true;
7200 2 : need_range = false;
7201 49 : continue;
7202 : }
7203 123 : if (have_range && gfc_match (", ") == MATCH_YES)
7204 : {
7205 1 : have_range = false;
7206 1 : continue;
7207 : }
7208 122 : if (have_range && gfc_match (") ") == MATCH_YES)
7209 : break;
7210 121 : locus saved_loc = gfc_current_locus;
7211 :
7212 : /* Without ranges, only arg names or integer literals permitted;
7213 : handle literals here as gfc_match_expr simplifies the expr. */
7214 121 : if (gfc_match_literal_constant (&p->expr, true) == MATCH_YES)
7215 : {
7216 17 : gfc_gobble_whitespace ();
7217 17 : char c = gfc_peek_ascii_char ();
7218 17 : if (c != ')' && c != ',' && c != ':')
7219 : {
7220 1 : gfc_free_expr (p->expr);
7221 1 : p->expr = NULL;
7222 1 : gfc_current_locus = saved_loc;
7223 : }
7224 : }
7225 121 : if (!p->expr && gfc_match ("omp_num_args") == MATCH_YES)
7226 : {
7227 6 : if (!have_range)
7228 3 : p->u.adj_args.range_start = need_range = true;
7229 : else
7230 : need_range = false;
7231 :
7232 6 : locus saved_loc2 = gfc_current_locus;
7233 6 : gfc_gobble_whitespace ();
7234 6 : char c = gfc_peek_ascii_char ();
7235 6 : if (c == '+' || c == '-')
7236 : {
7237 5 : if (gfc_match ("+ %e", &p->expr) == MATCH_YES)
7238 1 : p->u.adj_args.omp_num_args_plus = true;
7239 4 : else if (gfc_match ("- %e", &p->expr) == MATCH_YES)
7240 4 : p->u.adj_args.omp_num_args_minus = true;
7241 0 : else if (!gfc_error_check ())
7242 : {
7243 0 : gfc_error ("expected constant integer expression "
7244 : "at %C");
7245 0 : p->u.adj_args.error_p = true;
7246 0 : return MATCH_ERROR;
7247 : }
7248 5 : p->where = gfc_get_location_range (&saved_loc, 1,
7249 : &saved_loc, 1,
7250 : &gfc_current_locus);
7251 : }
7252 : else
7253 : {
7254 1 : p->where = gfc_get_location_range (&saved_loc, 1,
7255 : &saved_loc, 1,
7256 : &saved_loc2);
7257 1 : p->u.adj_args.omp_num_args_plus = true;
7258 : }
7259 : }
7260 115 : else if (!p->expr)
7261 : {
7262 99 : match m = gfc_match_expr (&p->expr);
7263 99 : if (m != MATCH_YES)
7264 : {
7265 1 : gfc_error ("expected dummy parameter name, "
7266 : "%<omp_num_args%> or constant positive integer"
7267 : " at %C");
7268 1 : p->u.adj_args.error_p = true;
7269 1 : return MATCH_ERROR;
7270 : }
7271 98 : if (p->expr->expr_type == EXPR_CONSTANT && !have_range)
7272 98 : need_range = true; /* Constant expr but not literal. */
7273 98 : p->where = p->expr->where;
7274 : }
7275 : else
7276 16 : p->where = p->expr->where;
7277 120 : gfc_gobble_whitespace ();
7278 120 : match m = gfc_match (": ");
7279 120 : if (need_range && m != MATCH_YES)
7280 : {
7281 1 : gfc_error ("expected %<:%> at %C");
7282 1 : return MATCH_ERROR;
7283 : }
7284 119 : if (m == MATCH_YES)
7285 : {
7286 6 : p->u.adj_args.range_start = have_range = true;
7287 6 : need_range = false;
7288 6 : continue;
7289 : }
7290 113 : need_range = have_range = false;
7291 113 : if (gfc_match (", ") == MATCH_YES)
7292 38 : continue;
7293 75 : if (gfc_match (") ") == MATCH_YES)
7294 : break;
7295 : }
7296 : }
7297 32 : else if (ccode == clause_append_args)
7298 : {
7299 32 : if (has_append_args)
7300 : {
7301 1 : gfc_error ("%qs clause at %L specified more than once",
7302 : "append_args", &gfc_current_locus);
7303 1 : return MATCH_ERROR;
7304 : }
7305 56 : has_append_args = true;
7306 : gfc_omp_namelist *append_args_last = NULL;
7307 81 : do
7308 : {
7309 56 : gfc_gobble_whitespace ();
7310 56 : if (gfc_match ("interop ") != MATCH_YES)
7311 : {
7312 0 : gfc_error ("expected %<interop%> at %C");
7313 3 : return MATCH_ERROR;
7314 : }
7315 56 : if (gfc_match ("( ") != MATCH_YES)
7316 : {
7317 0 : gfc_error ("expected %<(%> at %C");
7318 0 : return MATCH_ERROR;
7319 : }
7320 :
7321 56 : bool target, targetsync;
7322 56 : char *type_str = NULL;
7323 56 : int type_str_len;
7324 56 : locus loc = gfc_current_locus;
7325 56 : if (gfc_parser_omp_clause_init_modifiers (target, targetsync,
7326 : &type_str, type_str_len,
7327 : false) == MATCH_ERROR)
7328 : return MATCH_ERROR;
7329 :
7330 54 : gfc_omp_namelist *n = gfc_get_omp_namelist();
7331 54 : n->where = loc;
7332 54 : n->u.init.target = target;
7333 54 : n->u.init.targetsync = targetsync;
7334 54 : n->u.init.len = type_str_len;
7335 54 : n->u2.init_interop = type_str;
7336 54 : if (odv->append_args_list)
7337 : {
7338 25 : append_args_last->next = n;
7339 25 : append_args_last = n;
7340 : }
7341 : else
7342 29 : append_args_last = odv->append_args_list = n;
7343 :
7344 54 : gfc_gobble_whitespace ();
7345 54 : if (gfc_match_char (',') == MATCH_YES)
7346 25 : continue;
7347 29 : if (gfc_match_char (')') == MATCH_YES)
7348 : break;
7349 1 : gfc_error ("Expected %<,%> or %<)%> at %C");
7350 1 : return MATCH_ERROR;
7351 : }
7352 : while (true);
7353 : }
7354 466 : gfc_gobble_whitespace ();
7355 466 : if (gfc_match_omp_eos () == MATCH_YES)
7356 : break;
7357 109 : gfc_match_char (',');
7358 109 : }
7359 :
7360 363 : if (error_p || (!has_match && !has_adjust_args && !has_append_args))
7361 : {
7362 6 : gfc_error ("expected %<match%>, %<adjust_args%> or %<append_args%> at %C");
7363 6 : return MATCH_ERROR;
7364 : }
7365 :
7366 357 : if (!has_match)
7367 : {
7368 3 : gfc_error ("expected %<match%> clause at %C");
7369 3 : return MATCH_ERROR;
7370 : }
7371 :
7372 : return MATCH_YES;
7373 : }
7374 :
7375 :
7376 : static match
7377 160 : match_omp_metadirective (bool begin_p)
7378 : {
7379 160 : locus old_loc = gfc_current_locus;
7380 160 : gfc_omp_variant *variants_head;
7381 160 : gfc_omp_variant **next_variant = &variants_head;
7382 160 : bool default_seen = false;
7383 :
7384 : /* Parse the context selectors. */
7385 656 : for (;;)
7386 : {
7387 408 : bool default_p = false;
7388 408 : gfc_omp_set_selector *selectors = NULL;
7389 :
7390 408 : gfc_gobble_whitespace ();
7391 408 : if (gfc_match_eos () == MATCH_YES)
7392 : break;
7393 266 : gfc_match_char (',');
7394 266 : gfc_gobble_whitespace ();
7395 :
7396 266 : locus variant_locus = gfc_current_locus;
7397 :
7398 266 : if (gfc_match ("default ( ") == MATCH_YES)
7399 : {
7400 82 : default_p = true;
7401 82 : gfc_warning (OPT_Wdeprecated_openmp,
7402 : "%<default%> clause with metadirective at %L "
7403 : "deprecated since OpenMP 5.2", &variant_locus);
7404 : }
7405 184 : else if (gfc_match ("otherwise ( ") == MATCH_YES)
7406 : default_p = true;
7407 177 : else if (gfc_match ("when ( ") != MATCH_YES)
7408 : {
7409 1 : gfc_error ("expected %<when%>, %<otherwise%>, or %<default%> at %C");
7410 1 : gfc_current_locus = old_loc;
7411 18 : return MATCH_ERROR;
7412 : }
7413 89 : if (default_p && default_seen)
7414 : {
7415 3 : gfc_error ("too many %<otherwise%> or %<default%> clauses "
7416 : "in %<metadirective%> at %C");
7417 3 : gfc_current_locus = old_loc;
7418 3 : return MATCH_ERROR;
7419 : }
7420 262 : else if (default_seen)
7421 : {
7422 1 : gfc_error ("%<otherwise%> or %<default%> clause "
7423 : "must appear last in %<metadirective%> at %C");
7424 1 : gfc_current_locus = old_loc;
7425 1 : return MATCH_ERROR;
7426 : }
7427 :
7428 261 : if (!default_p)
7429 : {
7430 175 : if (gfc_match_omp_context_selector_specification (&selectors)
7431 : != MATCH_YES)
7432 : return MATCH_ERROR;
7433 :
7434 168 : if (gfc_match (" : ") != MATCH_YES)
7435 : {
7436 1 : gfc_error ("expected %<:%> at %C");
7437 1 : gfc_current_locus = old_loc;
7438 1 : return MATCH_ERROR;
7439 : }
7440 :
7441 167 : gfc_commit_symbols ();
7442 : }
7443 :
7444 253 : gfc_matching_omp_context_selector = true;
7445 253 : gfc_statement directive = match_omp_directive ();
7446 253 : gfc_matching_omp_context_selector = false;
7447 :
7448 253 : if (is_omp_declarative_stmt (directive))
7449 0 : sorry_at (gfc_get_location (&gfc_current_locus),
7450 : "declarative directive variants are not supported");
7451 :
7452 253 : if (gfc_error_flag_test ())
7453 : {
7454 2 : gfc_current_locus = old_loc;
7455 2 : return MATCH_ERROR;
7456 : }
7457 :
7458 251 : if (gfc_match (" )") != MATCH_YES)
7459 : {
7460 0 : gfc_error ("Expected %<)%> at %C");
7461 0 : gfc_current_locus = old_loc;
7462 0 : return MATCH_ERROR;
7463 : }
7464 :
7465 251 : gfc_commit_symbols ();
7466 :
7467 251 : if (begin_p
7468 251 : && directive != ST_NONE
7469 251 : && gfc_omp_end_stmt (directive) == ST_NONE)
7470 : {
7471 3 : gfc_error ("variant directive used in OMP BEGIN METADIRECTIVE "
7472 : "at %C must have a corresponding end directive");
7473 3 : gfc_current_locus = old_loc;
7474 3 : return MATCH_ERROR;
7475 : }
7476 :
7477 248 : if (default_p)
7478 : default_seen = true;
7479 :
7480 248 : gfc_omp_variant *omv = gfc_get_omp_variant ();
7481 248 : omv->selectors = selectors;
7482 248 : omv->stmt = directive;
7483 248 : omv->where = variant_locus;
7484 :
7485 248 : if (directive == ST_NONE)
7486 : {
7487 : /* The directive was a 'nothing' directive. */
7488 15 : omv->code = gfc_get_code (EXEC_CONTINUE);
7489 15 : omv->code->ext.omp_clauses = NULL;
7490 : }
7491 : else
7492 : {
7493 233 : omv->code = gfc_get_code (new_st.op);
7494 233 : omv->code->ext.omp_clauses = new_st.ext.omp_clauses;
7495 : /* Prevent the OpenMP clauses from being freed via NEW_ST. */
7496 233 : new_st.ext.omp_clauses = NULL;
7497 : }
7498 :
7499 248 : *next_variant = omv;
7500 248 : next_variant = &omv->next;
7501 248 : }
7502 :
7503 142 : if (gfc_match_omp_eos () != MATCH_YES)
7504 : {
7505 0 : gfc_error ("Unexpected junk after OMP METADIRECTIVE at %C");
7506 0 : gfc_current_locus = old_loc;
7507 0 : return MATCH_ERROR;
7508 : }
7509 :
7510 : /* Add a 'default (nothing)' clause if no default is explicitly given. */
7511 142 : if (!default_seen)
7512 : {
7513 65 : gfc_omp_variant *omv = gfc_get_omp_variant ();
7514 65 : omv->stmt = ST_NONE;
7515 65 : omv->code = gfc_get_code (EXEC_CONTINUE);
7516 65 : omv->code->ext.omp_clauses = NULL;
7517 65 : omv->where = old_loc;
7518 65 : omv->selectors = NULL;
7519 :
7520 65 : *next_variant = omv;
7521 65 : next_variant = &omv->next;
7522 : }
7523 :
7524 142 : new_st.op = EXEC_OMP_METADIRECTIVE;
7525 142 : new_st.ext.omp_variants = variants_head;
7526 :
7527 142 : return MATCH_YES;
7528 : }
7529 :
7530 : match
7531 43 : gfc_match_omp_begin_metadirective (void)
7532 : {
7533 43 : return match_omp_metadirective (true);
7534 : }
7535 :
7536 : match
7537 117 : gfc_match_omp_metadirective (void)
7538 : {
7539 117 : return match_omp_metadirective (false);
7540 : }
7541 :
7542 : /* Match 'omp threadprivate' or 'omp groupprivate'. */
7543 : static match
7544 259 : gfc_match_omp_thread_group_private (bool is_groupprivate)
7545 : {
7546 259 : locus old_loc;
7547 259 : char n[GFC_MAX_SYMBOL_LEN+1];
7548 259 : gfc_symbol *sym;
7549 259 : match m;
7550 259 : gfc_symtree *st;
7551 259 : struct sym_loc_t { gfc_symbol *sym; gfc_common_head *com; locus loc; };
7552 259 : auto_vec<sym_loc_t> syms;
7553 :
7554 259 : old_loc = gfc_current_locus;
7555 :
7556 259 : m = gfc_match (" ( ");
7557 259 : if (m != MATCH_YES)
7558 : return m;
7559 :
7560 369 : for (;;)
7561 : {
7562 314 : locus sym_loc = gfc_current_locus;
7563 314 : m = gfc_match_symbol (&sym, 0);
7564 314 : switch (m)
7565 : {
7566 209 : case MATCH_YES:
7567 209 : if (sym->attr.in_common)
7568 0 : gfc_error_now ("%qs variable at %L is an element of a COMMON block",
7569 : is_groupprivate ? "groupprivate" : "threadprivate",
7570 : &sym_loc);
7571 209 : else if (!is_groupprivate
7572 209 : && !gfc_add_threadprivate (&sym->attr, sym->name, &sym_loc))
7573 16 : goto cleanup;
7574 207 : else if (is_groupprivate)
7575 : {
7576 30 : if (!gfc_add_omp_groupprivate (&sym->attr, sym->name, &sym_loc))
7577 4 : goto cleanup;
7578 26 : syms.safe_push ({sym, nullptr, sym_loc});
7579 : }
7580 203 : goto next_item;
7581 : case MATCH_NO:
7582 : break;
7583 0 : case MATCH_ERROR:
7584 0 : goto cleanup;
7585 : }
7586 :
7587 105 : m = gfc_match (" / %n /", n);
7588 105 : if (m == MATCH_ERROR)
7589 0 : goto cleanup;
7590 105 : if (m == MATCH_NO || n[0] == '\0')
7591 0 : goto syntax;
7592 :
7593 105 : st = gfc_find_symtree (gfc_current_ns->common_root, n);
7594 105 : if (st == NULL)
7595 : {
7596 2 : gfc_error ("COMMON block /%s/ not found at %L", n, &sym_loc);
7597 2 : goto cleanup;
7598 : }
7599 103 : syms.safe_push ({nullptr, st->n.common, sym_loc});
7600 103 : if (is_groupprivate)
7601 30 : st->n.common->omp_groupprivate = 1;
7602 : else
7603 73 : st->n.common->threadprivate = 1;
7604 236 : for (sym = st->n.common->head; sym; sym = sym->common_next)
7605 141 : if (!is_groupprivate
7606 141 : && !gfc_add_threadprivate (&sym->attr, sym->name, &sym_loc))
7607 3 : goto cleanup;
7608 138 : else if (is_groupprivate
7609 138 : && !gfc_add_omp_groupprivate (&sym->attr, sym->name, &sym_loc))
7610 5 : goto cleanup;
7611 :
7612 95 : next_item:
7613 298 : if (gfc_match_char (')') == MATCH_YES)
7614 : break;
7615 55 : if (gfc_match_char (',') != MATCH_YES)
7616 0 : goto syntax;
7617 55 : }
7618 :
7619 243 : if (is_groupprivate)
7620 : {
7621 39 : gfc_omp_clauses *c;
7622 39 : m = gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_DEVICE_TYPE));
7623 39 : if (m == MATCH_ERROR)
7624 0 : return MATCH_ERROR;
7625 :
7626 39 : if (c->device_type == OMP_DEVICE_TYPE_UNSET)
7627 19 : c->device_type = OMP_DEVICE_TYPE_ANY;
7628 :
7629 86 : for (size_t i = 0; i < syms.length (); i++)
7630 47 : if (syms[i].sym)
7631 : {
7632 24 : sym_loc_t &n = syms[i];
7633 24 : if (n.sym->attr.in_common)
7634 0 : gfc_error_now ("Variable %qs at %L is an element of a COMMON "
7635 : "block", n.sym->name, &n.loc);
7636 24 : else if (n.sym->attr.omp_declare_target
7637 23 : || n.sym->attr.omp_declare_target_link)
7638 2 : gfc_error_now ("List item %qs at %L implies OMP DECLARE TARGET "
7639 : "with the LOCAL clause, but it has been specified"
7640 : " with a different clause before",
7641 : n.sym->name, &n.loc);
7642 24 : if (n.sym->attr.omp_device_type != OMP_DEVICE_TYPE_UNSET
7643 5 : && n.sym->attr.omp_device_type != c->device_type)
7644 : {
7645 2 : const char *dt = "any";
7646 2 : if (n.sym->attr.omp_device_type == OMP_DEVICE_TYPE_HOST)
7647 : dt = "host";
7648 0 : else if (n.sym->attr.omp_device_type == OMP_DEVICE_TYPE_NOHOST)
7649 0 : dt = "nohost";
7650 2 : gfc_error_now ("List item %qs at %L set in previous OMP DECLARE "
7651 : "TARGET directive to the different DEVICE_TYPE %qs",
7652 : n.sym->name, &n.loc, dt);
7653 : }
7654 24 : gfc_add_omp_declare_target_local (&n.sym->attr, n.sym->name,
7655 : &n.loc);
7656 24 : n.sym->attr.omp_device_type = c->device_type;
7657 : }
7658 : else /* Common block. */
7659 : {
7660 23 : sym_loc_t &n = syms[i];
7661 23 : if (n.com->omp_declare_target
7662 22 : || n.com->omp_declare_target_link)
7663 2 : gfc_error_now ("List item %</%s/%> at %L implies OMP DECLARE "
7664 : "TARGET with the LOCAL clause, but it has been "
7665 : "specified with a different clause before",
7666 2 : n.com->name, &n.loc);
7667 23 : if (n.com->omp_device_type != OMP_DEVICE_TYPE_UNSET
7668 5 : && n.com->omp_device_type != c->device_type)
7669 : {
7670 2 : const char *dt = "any";
7671 2 : if (n.com->omp_device_type == OMP_DEVICE_TYPE_HOST)
7672 : dt = "host";
7673 0 : else if (n.com->omp_device_type == OMP_DEVICE_TYPE_NOHOST)
7674 0 : dt = "nohost";
7675 2 : gfc_error_now ("List item %qs at %L set in previous OMP DECLARE"
7676 : " TARGET directive to the different DEVICE_TYPE "
7677 2 : "%qs", n.com->name, &n.loc, dt);
7678 : }
7679 23 : n.com->omp_declare_target_local = 1;
7680 23 : n.com->omp_device_type = c->device_type;
7681 46 : for (gfc_symbol *s = n.com->head; s; s = s->common_next)
7682 : {
7683 23 : gfc_add_omp_declare_target_local (&s->attr, s->name, &n.loc);
7684 23 : s->attr.omp_device_type = c->device_type;
7685 : }
7686 : }
7687 39 : free (c);
7688 : }
7689 :
7690 243 : if (gfc_match_omp_eos () != MATCH_YES)
7691 : {
7692 0 : gfc_error ("Unexpected junk after OMP %s at %C",
7693 : is_groupprivate ? "GROUPPRIVATE" : "THREADPRIVATE");
7694 0 : goto cleanup;
7695 : }
7696 :
7697 : return MATCH_YES;
7698 :
7699 0 : syntax:
7700 0 : gfc_error ("Syntax error in !$OMP %s list at %C",
7701 : is_groupprivate ? "GROUPPRIVATE" : "THREADPRIVATE");
7702 :
7703 16 : cleanup:
7704 16 : gfc_current_locus = old_loc;
7705 16 : return MATCH_ERROR;
7706 259 : }
7707 :
7708 :
7709 : match
7710 48 : gfc_match_omp_groupprivate (void)
7711 : {
7712 48 : return gfc_match_omp_thread_group_private (true);
7713 : }
7714 :
7715 :
7716 : match
7717 211 : gfc_match_omp_threadprivate (void)
7718 : {
7719 211 : return gfc_match_omp_thread_group_private (false);
7720 : }
7721 :
7722 :
7723 : match
7724 2145 : gfc_match_omp_parallel (void)
7725 : {
7726 2145 : return match_omp (EXEC_OMP_PARALLEL, OMP_PARALLEL_CLAUSES);
7727 : }
7728 :
7729 :
7730 : match
7731 1199 : gfc_match_omp_parallel_do (void)
7732 : {
7733 1199 : return match_omp (EXEC_OMP_PARALLEL_DO,
7734 1199 : (OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES)
7735 1199 : & ~(omp_mask (OMP_CLAUSE_NOWAIT)));
7736 : }
7737 :
7738 :
7739 : match
7740 298 : gfc_match_omp_parallel_do_simd (void)
7741 : {
7742 298 : return match_omp (EXEC_OMP_PARALLEL_DO_SIMD,
7743 298 : (OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES | OMP_SIMD_CLAUSES)
7744 298 : & ~(omp_mask (OMP_CLAUSE_NOWAIT)));
7745 : }
7746 :
7747 :
7748 : match
7749 14 : gfc_match_omp_parallel_masked (void)
7750 : {
7751 14 : return match_omp (EXEC_OMP_PARALLEL_MASKED,
7752 14 : OMP_PARALLEL_CLAUSES | OMP_MASKED_CLAUSES);
7753 : }
7754 :
7755 : match
7756 10 : gfc_match_omp_parallel_masked_taskloop (void)
7757 : {
7758 10 : return match_omp (EXEC_OMP_PARALLEL_MASKED_TASKLOOP,
7759 10 : (OMP_PARALLEL_CLAUSES | OMP_MASKED_CLAUSES
7760 10 : | OMP_TASKLOOP_CLAUSES)
7761 10 : & ~(omp_mask (OMP_CLAUSE_IN_REDUCTION)));
7762 : }
7763 :
7764 : match
7765 13 : gfc_match_omp_parallel_masked_taskloop_simd (void)
7766 : {
7767 13 : return match_omp (EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD,
7768 13 : (OMP_PARALLEL_CLAUSES | OMP_MASKED_CLAUSES
7769 13 : | OMP_TASKLOOP_CLAUSES | OMP_SIMD_CLAUSES)
7770 13 : & ~(omp_mask (OMP_CLAUSE_IN_REDUCTION)));
7771 : }
7772 :
7773 : match
7774 14 : gfc_match_omp_parallel_master (void)
7775 : {
7776 14 : gfc_warning (OPT_Wdeprecated_openmp,
7777 : "%<master%> construct at %C deprecated since OpenMP 5.1, use "
7778 : "%<masked%>");
7779 14 : return match_omp (EXEC_OMP_PARALLEL_MASTER, OMP_PARALLEL_CLAUSES);
7780 : }
7781 :
7782 : match
7783 15 : gfc_match_omp_parallel_master_taskloop (void)
7784 : {
7785 15 : gfc_warning (OPT_Wdeprecated_openmp,
7786 : "%<master%> construct at %C deprecated since OpenMP 5.1, "
7787 : "use %<masked%>");
7788 15 : return match_omp (EXEC_OMP_PARALLEL_MASTER_TASKLOOP,
7789 15 : (OMP_PARALLEL_CLAUSES | OMP_TASKLOOP_CLAUSES)
7790 15 : & ~(omp_mask (OMP_CLAUSE_IN_REDUCTION)));
7791 : }
7792 :
7793 : match
7794 21 : gfc_match_omp_parallel_master_taskloop_simd (void)
7795 : {
7796 21 : gfc_warning (OPT_Wdeprecated_openmp,
7797 : "%<master%> construct at %C deprecated since OpenMP 5.1, "
7798 : "use %<masked%>");
7799 21 : return match_omp (EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD,
7800 21 : (OMP_PARALLEL_CLAUSES | OMP_TASKLOOP_CLAUSES
7801 21 : | OMP_SIMD_CLAUSES)
7802 21 : & ~(omp_mask (OMP_CLAUSE_IN_REDUCTION)));
7803 : }
7804 :
7805 : match
7806 59 : gfc_match_omp_parallel_sections (void)
7807 : {
7808 59 : return match_omp (EXEC_OMP_PARALLEL_SECTIONS,
7809 59 : (OMP_PARALLEL_CLAUSES | OMP_SECTIONS_CLAUSES)
7810 59 : & ~(omp_mask (OMP_CLAUSE_NOWAIT)));
7811 : }
7812 :
7813 :
7814 : match
7815 56 : gfc_match_omp_parallel_workshare (void)
7816 : {
7817 56 : return match_omp (EXEC_OMP_PARALLEL_WORKSHARE, OMP_PARALLEL_CLAUSES);
7818 : }
7819 :
7820 : void
7821 49121 : gfc_check_omp_requires (gfc_namespace *ns, int ref_omp_requires)
7822 : {
7823 49121 : const char *msg = G_("Program unit at %L has OpenMP device "
7824 : "constructs/routines but does not set !$OMP REQUIRES %s "
7825 : "but other program units do");
7826 49121 : if (ns->omp_target_seen
7827 1240 : && (ns->omp_requires & OMP_REQ_TARGET_MASK)
7828 1240 : != (ref_omp_requires & OMP_REQ_TARGET_MASK))
7829 : {
7830 6 : gcc_assert (ns->proc_name);
7831 6 : if ((ref_omp_requires & OMP_REQ_REVERSE_OFFLOAD)
7832 5 : && !(ns->omp_requires & OMP_REQ_REVERSE_OFFLOAD))
7833 4 : gfc_error (msg, &ns->proc_name->declared_at, "REVERSE_OFFLOAD");
7834 6 : if ((ref_omp_requires & OMP_REQ_UNIFIED_ADDRESS)
7835 1 : && !(ns->omp_requires & OMP_REQ_UNIFIED_ADDRESS))
7836 1 : gfc_error (msg, &ns->proc_name->declared_at, "UNIFIED_ADDRESS");
7837 6 : if ((ref_omp_requires & OMP_REQ_UNIFIED_SHARED_MEMORY)
7838 4 : && !(ns->omp_requires & OMP_REQ_UNIFIED_SHARED_MEMORY))
7839 2 : gfc_error (msg, &ns->proc_name->declared_at, "UNIFIED_SHARED_MEMORY");
7840 6 : if ((ref_omp_requires & OMP_REQ_SELF_MAPS)
7841 1 : && !(ns->omp_requires & OMP_REQ_UNIFIED_SHARED_MEMORY))
7842 1 : gfc_error (msg, &ns->proc_name->declared_at, "SELF_MAPS");
7843 : }
7844 49121 : }
7845 :
7846 : bool
7847 120 : gfc_omp_requires_add_clause (gfc_omp_requires_kind clause,
7848 : const char *clause_name, locus *loc,
7849 : const char *module_name)
7850 : {
7851 120 : gfc_namespace *prog_unit = gfc_current_ns;
7852 144 : while (prog_unit->parent)
7853 : {
7854 25 : if (gfc_state_stack->previous
7855 25 : && gfc_state_stack->previous->state == COMP_INTERFACE)
7856 : break;
7857 : prog_unit = prog_unit->parent;
7858 : }
7859 :
7860 : /* Requires added after use. */
7861 120 : if (prog_unit->omp_target_seen
7862 24 : && (clause & OMP_REQ_TARGET_MASK)
7863 24 : && !(prog_unit->omp_requires & clause))
7864 : {
7865 0 : if (module_name)
7866 0 : gfc_error ("!$OMP REQUIRES clause %qs specified via module %qs use "
7867 : "at %L comes after using a device construct/routine",
7868 : clause_name, module_name, loc);
7869 : else
7870 0 : gfc_error ("!$OMP REQUIRES clause %qs specified at %L comes after "
7871 : "using a device construct/routine", clause_name, loc);
7872 0 : return false;
7873 : }
7874 :
7875 : /* Overriding atomic_default_mem_order clause value. */
7876 120 : if ((clause & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
7877 34 : && (prog_unit->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
7878 6 : && (prog_unit->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
7879 6 : != (int) clause)
7880 : {
7881 3 : const char *other;
7882 3 : switch (prog_unit->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
7883 : {
7884 : case OMP_REQ_ATOMIC_MEM_ORDER_SEQ_CST: other = "seq_cst"; break;
7885 0 : case OMP_REQ_ATOMIC_MEM_ORDER_ACQ_REL: other = "acq_rel"; break;
7886 1 : case OMP_REQ_ATOMIC_MEM_ORDER_ACQUIRE: other = "acquire"; break;
7887 1 : case OMP_REQ_ATOMIC_MEM_ORDER_RELAXED: other = "relaxed"; break;
7888 0 : case OMP_REQ_ATOMIC_MEM_ORDER_RELEASE: other = "release"; break;
7889 0 : default: gcc_unreachable ();
7890 : }
7891 :
7892 3 : if (module_name)
7893 0 : gfc_error ("!$OMP REQUIRES clause %<atomic_default_mem_order(%s)%> "
7894 : "specified via module %qs use at %L overrides a previous "
7895 : "%<atomic_default_mem_order(%s)%> (which might be through "
7896 : "using a module)", clause_name, module_name, loc, other);
7897 : else
7898 3 : gfc_error ("!$OMP REQUIRES clause %<atomic_default_mem_order(%s)%> "
7899 : "specified at %L overrides a previous "
7900 : "%<atomic_default_mem_order(%s)%> (which might be through "
7901 : "using a module)", clause_name, loc, other);
7902 3 : return false;
7903 : }
7904 :
7905 : /* Requires via module not at program-unit level and not repeating clause. */
7906 117 : if (prog_unit != gfc_current_ns && !(prog_unit->omp_requires & clause))
7907 : {
7908 0 : if (clause & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
7909 0 : gfc_error ("!$OMP REQUIRES clause %<atomic_default_mem_order(%s)%> "
7910 : "specified via module %qs use at %L but same clause is "
7911 : "not specified for the program unit", clause_name,
7912 : module_name, loc);
7913 : else
7914 0 : gfc_error ("!$OMP REQUIRES clause %qs specified via module %qs use at "
7915 : "%L but same clause is not specified for the program unit",
7916 : clause_name, module_name, loc);
7917 0 : return false;
7918 : }
7919 :
7920 117 : if (!gfc_state_stack->previous
7921 109 : || gfc_state_stack->previous->state != COMP_INTERFACE)
7922 116 : prog_unit->omp_requires |= clause;
7923 : return true;
7924 : }
7925 :
7926 : match
7927 92 : gfc_match_omp_requires (void)
7928 : {
7929 92 : static const char *clauses[] = {"reverse_offload",
7930 : "unified_address",
7931 : "unified_shared_memory",
7932 : "self_maps",
7933 : "dynamic_allocators",
7934 : "atomic_default"};
7935 92 : const char *clause = NULL;
7936 92 : int requires_clauses = 0;
7937 92 : bool first = true;
7938 92 : locus old_loc;
7939 :
7940 92 : if (gfc_current_ns->parent
7941 7 : && (!gfc_state_stack->previous
7942 7 : || gfc_state_stack->previous->state != COMP_INTERFACE))
7943 : {
7944 6 : gfc_error ("!$OMP REQUIRES at %C must appear in the specification part "
7945 : "of a program unit");
7946 6 : return MATCH_ERROR;
7947 : }
7948 :
7949 258 : while (true)
7950 : {
7951 172 : old_loc = gfc_current_locus;
7952 172 : gfc_omp_requires_kind requires_clause;
7953 86 : if ((first || gfc_match_char (',') != MATCH_YES)
7954 172 : && (first && gfc_match_space () != MATCH_YES))
7955 0 : goto error;
7956 172 : first = false;
7957 172 : gfc_gobble_whitespace ();
7958 172 : old_loc = gfc_current_locus;
7959 :
7960 172 : if (gfc_match_omp_eos () != MATCH_NO)
7961 : break;
7962 97 : if (gfc_match (clauses[0]) == MATCH_YES)
7963 : {
7964 34 : clause = clauses[0];
7965 34 : requires_clause = OMP_REQ_REVERSE_OFFLOAD;
7966 34 : if (requires_clauses & OMP_REQ_REVERSE_OFFLOAD)
7967 1 : goto duplicate_clause;
7968 : }
7969 63 : else if (gfc_match (clauses[1]) == MATCH_YES)
7970 : {
7971 9 : clause = clauses[1];
7972 9 : requires_clause = OMP_REQ_UNIFIED_ADDRESS;
7973 9 : if (requires_clauses & OMP_REQ_UNIFIED_ADDRESS)
7974 1 : goto duplicate_clause;
7975 : }
7976 54 : else if (gfc_match (clauses[2]) == MATCH_YES)
7977 : {
7978 14 : clause = clauses[2];
7979 14 : requires_clause = OMP_REQ_UNIFIED_SHARED_MEMORY;
7980 14 : if (requires_clauses & OMP_REQ_UNIFIED_SHARED_MEMORY)
7981 1 : goto duplicate_clause;
7982 : }
7983 40 : else if (gfc_match (clauses[3]) == MATCH_YES)
7984 : {
7985 1 : clause = clauses[3];
7986 1 : requires_clause = OMP_REQ_SELF_MAPS;
7987 1 : if (requires_clauses & OMP_REQ_SELF_MAPS)
7988 0 : goto duplicate_clause;
7989 : }
7990 39 : else if (gfc_match (clauses[4]) == MATCH_YES)
7991 : {
7992 7 : clause = clauses[4];
7993 7 : requires_clause = OMP_REQ_DYNAMIC_ALLOCATORS;
7994 7 : if (requires_clauses & OMP_REQ_DYNAMIC_ALLOCATORS)
7995 1 : goto duplicate_clause;
7996 : }
7997 32 : else if (gfc_match ("atomic_default_mem_order (") == MATCH_YES)
7998 : {
7999 31 : clause = clauses[5];
8000 31 : if (requires_clauses & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
8001 1 : goto duplicate_clause;
8002 30 : if (gfc_match (" seq_cst )") == MATCH_YES)
8003 : {
8004 : clause = "seq_cst";
8005 : requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_SEQ_CST;
8006 : }
8007 18 : else if (gfc_match (" acq_rel )") == MATCH_YES)
8008 : {
8009 : clause = "acq_rel";
8010 : requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_ACQ_REL;
8011 : }
8012 12 : else if (gfc_match (" acquire )") == MATCH_YES)
8013 : {
8014 : clause = "acquire";
8015 : requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_ACQUIRE;
8016 : }
8017 9 : else if (gfc_match (" relaxed )") == MATCH_YES)
8018 : {
8019 : clause = "relaxed";
8020 : requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_RELAXED;
8021 : }
8022 5 : else if (gfc_match (" release )") == MATCH_YES)
8023 : {
8024 : clause = "release";
8025 : requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_RELEASE;
8026 : }
8027 : else
8028 : {
8029 2 : gfc_error ("Expected ACQ_REL, ACQUIRE, RELAXED, RELEASE or "
8030 : "SEQ_CST for ATOMIC_DEFAULT_MEM_ORDER clause at %C");
8031 2 : goto error;
8032 : }
8033 : }
8034 : else
8035 1 : goto error;
8036 :
8037 89 : if (!gfc_omp_requires_add_clause (requires_clause, clause, &old_loc, NULL))
8038 3 : goto error;
8039 86 : requires_clauses |= requires_clause;
8040 86 : }
8041 :
8042 75 : if (requires_clauses == 0)
8043 : {
8044 1 : if (!gfc_error_flag_test ())
8045 1 : gfc_error ("Clause expected at %C");
8046 1 : goto error;
8047 : }
8048 : return MATCH_YES;
8049 :
8050 5 : duplicate_clause:
8051 5 : gfc_error ("%qs clause at %L specified more than once", clause, &old_loc);
8052 12 : error:
8053 12 : if (!gfc_error_flag_test ())
8054 1 : gfc_error ("Expected UNIFIED_ADDRESS, UNIFIED_SHARED_MEMORY, SELF_MAPS, "
8055 : "DYNAMIC_ALLOCATORS, REVERSE_OFFLOAD, or "
8056 : "ATOMIC_DEFAULT_MEM_ORDER clause at %L", &old_loc);
8057 : return MATCH_ERROR;
8058 : }
8059 :
8060 :
8061 : match
8062 51 : gfc_match_omp_scan (void)
8063 : {
8064 51 : bool incl;
8065 51 : gfc_omp_clauses *c = gfc_get_omp_clauses ();
8066 51 : gfc_gobble_whitespace ();
8067 51 : if ((incl = (gfc_match ("inclusive") == MATCH_YES))
8068 51 : || gfc_match ("exclusive") == MATCH_YES)
8069 : {
8070 70 : if (gfc_match_omp_variable_list (" (", &c->lists[incl ? OMP_LIST_SCAN_IN
8071 : : OMP_LIST_SCAN_EX],
8072 : false) != MATCH_YES)
8073 : {
8074 0 : gfc_free_omp_clauses (c);
8075 0 : return MATCH_ERROR;
8076 : }
8077 : }
8078 : else
8079 : {
8080 1 : gfc_error ("Expected INCLUSIVE or EXCLUSIVE clause at %C");
8081 1 : gfc_free_omp_clauses (c);
8082 1 : return MATCH_ERROR;
8083 : }
8084 50 : if (gfc_match_omp_eos () != MATCH_YES)
8085 : {
8086 1 : gfc_error ("Unexpected junk after !$OMP SCAN at %C");
8087 1 : gfc_free_omp_clauses (c);
8088 1 : return MATCH_ERROR;
8089 : }
8090 :
8091 49 : new_st.op = EXEC_OMP_SCAN;
8092 49 : new_st.ext.omp_clauses = c;
8093 49 : return MATCH_YES;
8094 : }
8095 :
8096 :
8097 : match
8098 58 : gfc_match_omp_scope (void)
8099 : {
8100 58 : return match_omp (EXEC_OMP_SCOPE, OMP_SCOPE_CLAUSES);
8101 : }
8102 :
8103 :
8104 : match
8105 82 : gfc_match_omp_sections (void)
8106 : {
8107 82 : return match_omp (EXEC_OMP_SECTIONS, OMP_SECTIONS_CLAUSES);
8108 : }
8109 :
8110 :
8111 : match
8112 782 : gfc_match_omp_simd (void)
8113 : {
8114 782 : return match_omp (EXEC_OMP_SIMD, OMP_SIMD_CLAUSES);
8115 : }
8116 :
8117 :
8118 : match
8119 570 : gfc_match_omp_single (void)
8120 : {
8121 570 : return match_omp (EXEC_OMP_SINGLE, OMP_SINGLE_CLAUSES);
8122 : }
8123 :
8124 :
8125 : match
8126 2166 : gfc_match_omp_target (void)
8127 : {
8128 2166 : return match_omp (EXEC_OMP_TARGET, OMP_TARGET_CLAUSES);
8129 : }
8130 :
8131 :
8132 : match
8133 1398 : gfc_match_omp_target_data (void)
8134 : {
8135 1398 : return match_omp (EXEC_OMP_TARGET_DATA, OMP_TARGET_DATA_CLAUSES);
8136 : }
8137 :
8138 :
8139 : match
8140 452 : gfc_match_omp_target_enter_data (void)
8141 : {
8142 452 : return match_omp (EXEC_OMP_TARGET_ENTER_DATA, OMP_TARGET_ENTER_DATA_CLAUSES);
8143 : }
8144 :
8145 :
8146 : match
8147 364 : gfc_match_omp_target_exit_data (void)
8148 : {
8149 364 : return match_omp (EXEC_OMP_TARGET_EXIT_DATA, OMP_TARGET_EXIT_DATA_CLAUSES);
8150 : }
8151 :
8152 :
8153 : match
8154 25 : gfc_match_omp_target_parallel (void)
8155 : {
8156 25 : return match_omp (EXEC_OMP_TARGET_PARALLEL,
8157 25 : (OMP_TARGET_CLAUSES | OMP_PARALLEL_CLAUSES)
8158 25 : & ~(omp_mask (OMP_CLAUSE_COPYIN)));
8159 : }
8160 :
8161 :
8162 : match
8163 81 : gfc_match_omp_target_parallel_do (void)
8164 : {
8165 81 : return match_omp (EXEC_OMP_TARGET_PARALLEL_DO,
8166 81 : (OMP_TARGET_CLAUSES | OMP_PARALLEL_CLAUSES
8167 81 : | OMP_DO_CLAUSES) & ~(omp_mask (OMP_CLAUSE_COPYIN)));
8168 : }
8169 :
8170 :
8171 : match
8172 19 : gfc_match_omp_target_parallel_do_simd (void)
8173 : {
8174 19 : return match_omp (EXEC_OMP_TARGET_PARALLEL_DO_SIMD,
8175 19 : (OMP_TARGET_CLAUSES | OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES
8176 19 : | OMP_SIMD_CLAUSES) & ~(omp_mask (OMP_CLAUSE_COPYIN)));
8177 : }
8178 :
8179 :
8180 : match
8181 34 : gfc_match_omp_target_simd (void)
8182 : {
8183 34 : return match_omp (EXEC_OMP_TARGET_SIMD,
8184 34 : OMP_TARGET_CLAUSES | OMP_SIMD_CLAUSES);
8185 : }
8186 :
8187 :
8188 : match
8189 72 : gfc_match_omp_target_teams (void)
8190 : {
8191 72 : return match_omp (EXEC_OMP_TARGET_TEAMS,
8192 72 : OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES);
8193 : }
8194 :
8195 :
8196 : match
8197 19 : gfc_match_omp_target_teams_distribute (void)
8198 : {
8199 19 : return match_omp (EXEC_OMP_TARGET_TEAMS_DISTRIBUTE,
8200 19 : OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES
8201 19 : | OMP_DISTRIBUTE_CLAUSES);
8202 : }
8203 :
8204 :
8205 : match
8206 64 : gfc_match_omp_target_teams_distribute_parallel_do (void)
8207 : {
8208 64 : return match_omp (EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO,
8209 64 : (OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES
8210 64 : | OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
8211 64 : | OMP_DO_CLAUSES)
8212 64 : & ~(omp_mask (OMP_CLAUSE_ORDERED))
8213 64 : & ~(omp_mask (OMP_CLAUSE_LINEAR)));
8214 : }
8215 :
8216 :
8217 : match
8218 35 : gfc_match_omp_target_teams_distribute_parallel_do_simd (void)
8219 : {
8220 35 : return match_omp (EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD,
8221 35 : (OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES
8222 35 : | OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
8223 35 : | OMP_DO_CLAUSES | OMP_SIMD_CLAUSES)
8224 35 : & ~(omp_mask (OMP_CLAUSE_ORDERED)));
8225 : }
8226 :
8227 :
8228 : match
8229 21 : gfc_match_omp_target_teams_distribute_simd (void)
8230 : {
8231 21 : return match_omp (EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD,
8232 21 : OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES
8233 21 : | OMP_DISTRIBUTE_CLAUSES | OMP_SIMD_CLAUSES);
8234 : }
8235 :
8236 :
8237 : match
8238 1704 : gfc_match_omp_target_update (void)
8239 : {
8240 1704 : return match_omp (EXEC_OMP_TARGET_UPDATE, OMP_TARGET_UPDATE_CLAUSES);
8241 : }
8242 :
8243 :
8244 : match
8245 1182 : gfc_match_omp_task (void)
8246 : {
8247 1182 : return match_omp (EXEC_OMP_TASK, OMP_TASK_CLAUSES);
8248 : }
8249 :
8250 :
8251 : match
8252 72 : gfc_match_omp_taskloop (void)
8253 : {
8254 72 : return match_omp (EXEC_OMP_TASKLOOP, OMP_TASKLOOP_CLAUSES);
8255 : }
8256 :
8257 :
8258 : match
8259 40 : gfc_match_omp_taskloop_simd (void)
8260 : {
8261 40 : return match_omp (EXEC_OMP_TASKLOOP_SIMD,
8262 40 : OMP_TASKLOOP_CLAUSES | OMP_SIMD_CLAUSES);
8263 : }
8264 :
8265 :
8266 : match
8267 147 : gfc_match_omp_taskwait (void)
8268 : {
8269 147 : if (gfc_match_omp_eos () == MATCH_YES)
8270 : {
8271 133 : new_st.op = EXEC_OMP_TASKWAIT;
8272 133 : new_st.ext.omp_clauses = NULL;
8273 133 : return MATCH_YES;
8274 : }
8275 14 : return match_omp (EXEC_OMP_TASKWAIT,
8276 14 : omp_mask (OMP_CLAUSE_DEPEND) | OMP_CLAUSE_NOWAIT);
8277 : }
8278 :
8279 :
8280 : match
8281 10 : gfc_match_omp_taskyield (void)
8282 : {
8283 10 : if (gfc_match_omp_eos () != MATCH_YES)
8284 : {
8285 0 : gfc_error ("Unexpected junk after TASKYIELD clause at %C");
8286 0 : return MATCH_ERROR;
8287 : }
8288 10 : new_st.op = EXEC_OMP_TASKYIELD;
8289 10 : new_st.ext.omp_clauses = NULL;
8290 10 : return MATCH_YES;
8291 : }
8292 :
8293 :
8294 : match
8295 150 : gfc_match_omp_teams (void)
8296 : {
8297 150 : return match_omp (EXEC_OMP_TEAMS, OMP_TEAMS_CLAUSES);
8298 : }
8299 :
8300 :
8301 : match
8302 22 : gfc_match_omp_teams_distribute (void)
8303 : {
8304 22 : return match_omp (EXEC_OMP_TEAMS_DISTRIBUTE,
8305 22 : OMP_TEAMS_CLAUSES | OMP_DISTRIBUTE_CLAUSES);
8306 : }
8307 :
8308 :
8309 : match
8310 39 : gfc_match_omp_teams_distribute_parallel_do (void)
8311 : {
8312 39 : return match_omp (EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO,
8313 39 : (OMP_TEAMS_CLAUSES | OMP_DISTRIBUTE_CLAUSES
8314 39 : | OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES)
8315 39 : & ~(omp_mask (OMP_CLAUSE_ORDERED)
8316 39 : | OMP_CLAUSE_LINEAR | OMP_CLAUSE_NOWAIT));
8317 : }
8318 :
8319 :
8320 : match
8321 62 : gfc_match_omp_teams_distribute_parallel_do_simd (void)
8322 : {
8323 62 : return match_omp (EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD,
8324 62 : (OMP_TEAMS_CLAUSES | OMP_DISTRIBUTE_CLAUSES
8325 62 : | OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES
8326 62 : | OMP_SIMD_CLAUSES)
8327 62 : & ~(omp_mask (OMP_CLAUSE_ORDERED) | OMP_CLAUSE_NOWAIT));
8328 : }
8329 :
8330 :
8331 : match
8332 44 : gfc_match_omp_teams_distribute_simd (void)
8333 : {
8334 44 : return match_omp (EXEC_OMP_TEAMS_DISTRIBUTE_SIMD,
8335 44 : OMP_TEAMS_CLAUSES | OMP_DISTRIBUTE_CLAUSES
8336 44 : | OMP_SIMD_CLAUSES);
8337 : }
8338 :
8339 : match
8340 203 : gfc_match_omp_tile (void)
8341 : {
8342 203 : return match_omp (EXEC_OMP_TILE, OMP_TILE_CLAUSES);
8343 : }
8344 :
8345 : match
8346 415 : gfc_match_omp_unroll (void)
8347 : {
8348 415 : return match_omp (EXEC_OMP_UNROLL, OMP_UNROLL_CLAUSES);
8349 : }
8350 :
8351 : match
8352 39 : gfc_match_omp_workshare (void)
8353 : {
8354 39 : return match_omp (EXEC_OMP_WORKSHARE, OMP_WORKSHARE_CLAUSES);
8355 : }
8356 :
8357 :
8358 : match
8359 49 : gfc_match_omp_masked (void)
8360 : {
8361 49 : return match_omp (EXEC_OMP_MASKED, OMP_MASKED_CLAUSES);
8362 : }
8363 :
8364 : match
8365 10 : gfc_match_omp_masked_taskloop (void)
8366 : {
8367 10 : return match_omp (EXEC_OMP_MASKED_TASKLOOP,
8368 10 : OMP_MASKED_CLAUSES | OMP_TASKLOOP_CLAUSES);
8369 : }
8370 :
8371 : match
8372 16 : gfc_match_omp_masked_taskloop_simd (void)
8373 : {
8374 16 : return match_omp (EXEC_OMP_MASKED_TASKLOOP_SIMD,
8375 16 : (OMP_MASKED_CLAUSES | OMP_TASKLOOP_CLAUSES
8376 16 : | OMP_SIMD_CLAUSES));
8377 : }
8378 :
8379 : match
8380 111 : gfc_match_omp_master (void)
8381 : {
8382 111 : gfc_warning (OPT_Wdeprecated_openmp,
8383 : "%<master%> construct at %C deprecated since OpenMP 5.1, "
8384 : "use %<masked%>");
8385 111 : if (gfc_match_omp_eos () != MATCH_YES)
8386 : {
8387 1 : gfc_error ("Unexpected junk after $OMP MASTER statement at %C");
8388 1 : return MATCH_ERROR;
8389 : }
8390 110 : new_st.op = EXEC_OMP_MASTER;
8391 110 : new_st.ext.omp_clauses = NULL;
8392 110 : return MATCH_YES;
8393 : }
8394 :
8395 : match
8396 16 : gfc_match_omp_master_taskloop (void)
8397 : {
8398 16 : gfc_warning (OPT_Wdeprecated_openmp,
8399 : "%<master%> construct at %C deprecated since OpenMP 5.1, "
8400 : "use %<masked%>");
8401 16 : return match_omp (EXEC_OMP_MASTER_TASKLOOP, OMP_TASKLOOP_CLAUSES);
8402 : }
8403 :
8404 : match
8405 21 : gfc_match_omp_master_taskloop_simd (void)
8406 : {
8407 21 : gfc_warning (OPT_Wdeprecated_openmp,
8408 : "%<master%> construct at %C deprecated since OpenMP 5.1, use "
8409 : "%<masked%>");
8410 21 : return match_omp (EXEC_OMP_MASTER_TASKLOOP_SIMD,
8411 21 : OMP_TASKLOOP_CLAUSES | OMP_SIMD_CLAUSES);
8412 : }
8413 :
8414 : match
8415 235 : gfc_match_omp_ordered (void)
8416 : {
8417 235 : return match_omp (EXEC_OMP_ORDERED, OMP_ORDERED_CLAUSES);
8418 : }
8419 :
8420 : match
8421 24 : gfc_match_omp_nothing (void)
8422 : {
8423 24 : if (gfc_match_omp_eos () != MATCH_YES)
8424 : {
8425 1 : gfc_error ("Unexpected junk after $OMP NOTHING statement at %C");
8426 1 : return MATCH_ERROR;
8427 : }
8428 : /* Will use ST_NONE; therefore, no EXEC_OMP_ is needed. */
8429 : return MATCH_YES;
8430 : }
8431 :
8432 : match
8433 317 : gfc_match_omp_ordered_depend (void)
8434 : {
8435 317 : return match_omp (EXEC_OMP_ORDERED, omp_mask (OMP_CLAUSE_DOACROSS));
8436 : }
8437 :
8438 :
8439 : /* omp atomic [clause-list]
8440 : - atomic-clause: read | write | update
8441 : - capture
8442 : - memory-order-clause: seq_cst | acq_rel | release | acquire | relaxed
8443 : - hint(hint-expr)
8444 : - OpenMP 5.1: compare | fail (seq_cst | acquire | relaxed ) | weak
8445 : */
8446 :
8447 : match
8448 2171 : gfc_match_omp_atomic (void)
8449 : {
8450 2171 : gfc_omp_clauses *c;
8451 2171 : locus loc = gfc_current_locus;
8452 :
8453 2171 : if (gfc_match_omp_clauses (&c, OMP_ATOMIC_CLAUSES, true, true) != MATCH_YES)
8454 : return MATCH_ERROR;
8455 :
8456 2153 : if (c->atomic_op == GFC_OMP_ATOMIC_UNSET)
8457 1011 : c->atomic_op = GFC_OMP_ATOMIC_UPDATE;
8458 :
8459 2153 : if (c->capture && c->atomic_op != GFC_OMP_ATOMIC_UPDATE)
8460 3 : gfc_error ("!$OMP ATOMIC at %L with %s clause is incompatible with "
8461 : "READ or WRITE", &loc, "CAPTURE");
8462 2153 : if (c->compare && c->atomic_op != GFC_OMP_ATOMIC_UPDATE)
8463 3 : gfc_error ("!$OMP ATOMIC at %L with %s clause is incompatible with "
8464 : "READ or WRITE", &loc, "COMPARE");
8465 2153 : if (c->fail != OMP_MEMORDER_UNSET && c->atomic_op != GFC_OMP_ATOMIC_UPDATE)
8466 2 : gfc_error ("!$OMP ATOMIC at %L with %s clause is incompatible with "
8467 : "READ or WRITE", &loc, "FAIL");
8468 2153 : if (c->weak && !c->compare)
8469 : {
8470 5 : gfc_error ("!$OMP ATOMIC at %L with %s clause requires %s clause", &loc,
8471 : "WEAK", "COMPARE");
8472 5 : c->weak = false;
8473 : }
8474 :
8475 2153 : if (c->memorder == OMP_MEMORDER_UNSET)
8476 : {
8477 1969 : gfc_namespace *prog_unit = gfc_current_ns;
8478 2525 : while (prog_unit->parent)
8479 : prog_unit = prog_unit->parent;
8480 1969 : switch (prog_unit->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
8481 : {
8482 1936 : case 0:
8483 1936 : case OMP_REQ_ATOMIC_MEM_ORDER_RELAXED:
8484 1936 : c->memorder = OMP_MEMORDER_RELAXED;
8485 1936 : break;
8486 7 : case OMP_REQ_ATOMIC_MEM_ORDER_SEQ_CST:
8487 7 : c->memorder = OMP_MEMORDER_SEQ_CST;
8488 7 : break;
8489 16 : case OMP_REQ_ATOMIC_MEM_ORDER_ACQ_REL:
8490 16 : if (c->capture)
8491 5 : c->memorder = OMP_MEMORDER_ACQ_REL;
8492 11 : else if (c->atomic_op == GFC_OMP_ATOMIC_READ)
8493 3 : c->memorder = OMP_MEMORDER_ACQUIRE;
8494 : else
8495 8 : c->memorder = OMP_MEMORDER_RELEASE;
8496 : break;
8497 5 : case OMP_REQ_ATOMIC_MEM_ORDER_ACQUIRE:
8498 5 : if (c->atomic_op == GFC_OMP_ATOMIC_WRITE)
8499 : {
8500 1 : gfc_error ("!$OMP ATOMIC WRITE at %L incompatible with "
8501 : "ACQUIRES clause implicitly provided by a "
8502 : "REQUIRES directive", &loc);
8503 1 : c->memorder = OMP_MEMORDER_SEQ_CST;
8504 : }
8505 : else
8506 4 : c->memorder = OMP_MEMORDER_ACQUIRE;
8507 : break;
8508 5 : case OMP_REQ_ATOMIC_MEM_ORDER_RELEASE:
8509 5 : if (c->atomic_op == GFC_OMP_ATOMIC_READ)
8510 : {
8511 1 : gfc_error ("!$OMP ATOMIC READ at %L incompatible with "
8512 : "RELEASE clause implicitly provided by a "
8513 : "REQUIRES directive", &loc);
8514 1 : c->memorder = OMP_MEMORDER_SEQ_CST;
8515 : }
8516 : else
8517 4 : c->memorder = OMP_MEMORDER_RELEASE;
8518 : break;
8519 0 : default:
8520 0 : gcc_unreachable ();
8521 : }
8522 : }
8523 : else
8524 184 : switch (c->atomic_op)
8525 : {
8526 29 : case GFC_OMP_ATOMIC_READ:
8527 29 : if (c->memorder == OMP_MEMORDER_RELEASE)
8528 : {
8529 1 : gfc_error ("!$OMP ATOMIC READ at %L incompatible with "
8530 : "RELEASE clause", &loc);
8531 1 : c->memorder = OMP_MEMORDER_SEQ_CST;
8532 : }
8533 28 : else if (c->memorder == OMP_MEMORDER_ACQ_REL)
8534 1 : c->memorder = OMP_MEMORDER_ACQUIRE;
8535 : break;
8536 35 : case GFC_OMP_ATOMIC_WRITE:
8537 35 : if (c->memorder == OMP_MEMORDER_ACQUIRE)
8538 : {
8539 1 : gfc_error ("!$OMP ATOMIC WRITE at %L incompatible with "
8540 : "ACQUIRE clause", &loc);
8541 1 : c->memorder = OMP_MEMORDER_SEQ_CST;
8542 : }
8543 34 : else if (c->memorder == OMP_MEMORDER_ACQ_REL)
8544 1 : c->memorder = OMP_MEMORDER_RELEASE;
8545 : break;
8546 : default:
8547 : break;
8548 : }
8549 2153 : gfc_error_check ();
8550 2153 : new_st.ext.omp_clauses = c;
8551 2153 : new_st.op = EXEC_OMP_ATOMIC;
8552 2153 : return MATCH_YES;
8553 : }
8554 :
8555 :
8556 : /* acc atomic [ read | write | update | capture] */
8557 :
8558 : match
8559 552 : gfc_match_oacc_atomic (void)
8560 : {
8561 552 : gfc_omp_clauses *c = gfc_get_omp_clauses ();
8562 552 : c->atomic_op = GFC_OMP_ATOMIC_UPDATE;
8563 552 : c->memorder = OMP_MEMORDER_RELAXED;
8564 552 : gfc_gobble_whitespace ();
8565 552 : if (gfc_match ("update") == MATCH_YES)
8566 : ;
8567 373 : else if (gfc_match ("read") == MATCH_YES)
8568 17 : c->atomic_op = GFC_OMP_ATOMIC_READ;
8569 356 : else if (gfc_match ("write") == MATCH_YES)
8570 13 : c->atomic_op = GFC_OMP_ATOMIC_WRITE;
8571 343 : else if (gfc_match ("capture") == MATCH_YES)
8572 319 : c->capture = true;
8573 552 : gfc_gobble_whitespace ();
8574 552 : if (gfc_match_omp_eos () != MATCH_YES)
8575 : {
8576 9 : gfc_error ("Unexpected junk after !$ACC ATOMIC statement at %C");
8577 9 : gfc_free_omp_clauses (c);
8578 9 : return MATCH_ERROR;
8579 : }
8580 543 : new_st.ext.omp_clauses = c;
8581 543 : new_st.op = EXEC_OACC_ATOMIC;
8582 543 : return MATCH_YES;
8583 : }
8584 :
8585 :
8586 : match
8587 614 : gfc_match_omp_barrier (void)
8588 : {
8589 614 : if (gfc_match_omp_eos () != MATCH_YES)
8590 : {
8591 0 : gfc_error ("Unexpected junk after $OMP BARRIER statement at %C");
8592 0 : return MATCH_ERROR;
8593 : }
8594 614 : new_st.op = EXEC_OMP_BARRIER;
8595 614 : new_st.ext.omp_clauses = NULL;
8596 614 : return MATCH_YES;
8597 : }
8598 :
8599 :
8600 : match
8601 188 : gfc_match_omp_taskgroup (void)
8602 : {
8603 188 : return match_omp (EXEC_OMP_TASKGROUP, OMP_TASKGROUP_CLAUSES);
8604 : }
8605 :
8606 :
8607 : static enum gfc_omp_cancel_kind
8608 494 : gfc_match_omp_cancel_kind (void)
8609 : {
8610 494 : if (gfc_match_space () != MATCH_YES)
8611 : return OMP_CANCEL_UNKNOWN;
8612 492 : if (gfc_match ("parallel") == MATCH_YES)
8613 : return OMP_CANCEL_PARALLEL;
8614 352 : if (gfc_match ("sections") == MATCH_YES)
8615 : return OMP_CANCEL_SECTIONS;
8616 253 : if (gfc_match ("do") == MATCH_YES)
8617 : return OMP_CANCEL_DO;
8618 123 : if (gfc_match ("taskgroup") == MATCH_YES)
8619 : return OMP_CANCEL_TASKGROUP;
8620 : return OMP_CANCEL_UNKNOWN;
8621 : }
8622 :
8623 :
8624 : match
8625 321 : gfc_match_omp_cancel (void)
8626 : {
8627 321 : gfc_omp_clauses *c;
8628 321 : enum gfc_omp_cancel_kind kind = gfc_match_omp_cancel_kind ();
8629 321 : if (kind == OMP_CANCEL_UNKNOWN)
8630 : return MATCH_ERROR;
8631 319 : if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_IF), false) != MATCH_YES)
8632 : return MATCH_ERROR;
8633 316 : c->cancel = kind;
8634 316 : new_st.op = EXEC_OMP_CANCEL;
8635 316 : new_st.ext.omp_clauses = c;
8636 316 : return MATCH_YES;
8637 : }
8638 :
8639 :
8640 : match
8641 173 : gfc_match_omp_cancellation_point (void)
8642 : {
8643 173 : gfc_omp_clauses *c;
8644 173 : enum gfc_omp_cancel_kind kind = gfc_match_omp_cancel_kind ();
8645 173 : if (kind == OMP_CANCEL_UNKNOWN)
8646 : {
8647 2 : gfc_error ("Expected construct-type PARALLEL, SECTIONS, DO or TASKGROUP "
8648 : "in $OMP CANCELLATION POINT statement at %C");
8649 2 : return MATCH_ERROR;
8650 : }
8651 171 : if (gfc_match_omp_eos () != MATCH_YES)
8652 : {
8653 0 : gfc_error ("Unexpected junk after $OMP CANCELLATION POINT statement "
8654 : "at %C");
8655 0 : return MATCH_ERROR;
8656 : }
8657 171 : c = gfc_get_omp_clauses ();
8658 171 : c->cancel = kind;
8659 171 : new_st.op = EXEC_OMP_CANCELLATION_POINT;
8660 171 : new_st.ext.omp_clauses = c;
8661 171 : return MATCH_YES;
8662 : }
8663 :
8664 :
8665 : match
8666 2676 : gfc_match_omp_end_nowait (void)
8667 : {
8668 2676 : bool nowait = false;
8669 2676 : if (gfc_match ("% nowait") == MATCH_YES)
8670 258 : nowait = true;
8671 2676 : if (gfc_match_omp_eos () != MATCH_YES)
8672 : {
8673 4 : if (nowait)
8674 3 : gfc_error ("Unexpected junk after NOWAIT clause at %C");
8675 : else
8676 1 : gfc_error ("Unexpected junk at %C");
8677 4 : return MATCH_ERROR;
8678 : }
8679 2672 : new_st.op = EXEC_OMP_END_NOWAIT;
8680 2672 : new_st.ext.omp_bool = nowait;
8681 2672 : return MATCH_YES;
8682 : }
8683 :
8684 :
8685 : match
8686 566 : gfc_match_omp_end_single (void)
8687 : {
8688 566 : gfc_omp_clauses *c;
8689 566 : if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_COPYPRIVATE)
8690 : | OMP_CLAUSE_NOWAIT) != MATCH_YES)
8691 : return MATCH_ERROR;
8692 566 : new_st.op = EXEC_OMP_END_SINGLE;
8693 566 : new_st.ext.omp_clauses = c;
8694 566 : return MATCH_YES;
8695 : }
8696 :
8697 :
8698 : static bool
8699 37071 : oacc_is_loop (gfc_code *code)
8700 : {
8701 37071 : return code->op == EXEC_OACC_PARALLEL_LOOP
8702 : || code->op == EXEC_OACC_KERNELS_LOOP
8703 20016 : || code->op == EXEC_OACC_SERIAL_LOOP
8704 13457 : || code->op == EXEC_OACC_LOOP;
8705 : }
8706 :
8707 : static void
8708 5725 : resolve_scalar_int_expr (gfc_expr *expr, const char *clause)
8709 : {
8710 5725 : if (!gfc_resolve_expr (expr)
8711 5725 : || expr->ts.type != BT_INTEGER
8712 11379 : || expr->rank != 0)
8713 89 : gfc_error ("%s clause at %L requires a scalar INTEGER expression",
8714 : clause, &expr->where);
8715 5725 : }
8716 :
8717 : static void
8718 3940 : resolve_positive_int_expr (gfc_expr *expr, const char *clause)
8719 : {
8720 3940 : resolve_scalar_int_expr (expr, clause);
8721 3940 : if (expr->expr_type == EXPR_CONSTANT
8722 3519 : && expr->ts.type == BT_INTEGER
8723 3486 : && mpz_sgn (expr->value.integer) <= 0)
8724 54 : gfc_warning ((flag_openmp || flag_openmp_simd) ? OPT_Wopenmp : 0,
8725 : "INTEGER expression of %s clause at %L must be positive",
8726 : clause, &expr->where);
8727 3940 : }
8728 :
8729 : static void
8730 86 : resolve_nonnegative_int_expr (gfc_expr *expr, const char *clause)
8731 : {
8732 86 : resolve_scalar_int_expr (expr, clause);
8733 86 : if (expr->expr_type == EXPR_CONSTANT
8734 13 : && expr->ts.type == BT_INTEGER
8735 11 : && mpz_sgn (expr->value.integer) < 0)
8736 6 : gfc_warning ((flag_openmp || flag_openmp_simd) ? OPT_Wopenmp : 0,
8737 : "INTEGER expression of %s clause at %L must be non-negative",
8738 : clause, &expr->where);
8739 86 : }
8740 :
8741 : /* Emits error when symbol is pointer, cray pointer or cray pointee
8742 : of derived of polymorphic type. */
8743 :
8744 : static void
8745 98 : check_symbol_not_pointer (gfc_symbol *sym, locus loc, const char *name)
8746 : {
8747 98 : if (sym->ts.type == BT_DERIVED && sym->attr.cray_pointer)
8748 0 : gfc_error ("Cray pointer object %qs of derived type in %s clause at %L",
8749 : sym->name, name, &loc);
8750 98 : if (sym->ts.type == BT_DERIVED && sym->attr.cray_pointee)
8751 0 : gfc_error ("Cray pointee object %qs of derived type in %s clause at %L",
8752 : sym->name, name, &loc);
8753 :
8754 98 : if ((sym->ts.type == BT_ASSUMED && sym->attr.pointer)
8755 98 : || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
8756 0 : && CLASS_DATA (sym)->attr.pointer))
8757 0 : gfc_error ("POINTER object %qs of polymorphic type in %s clause at %L",
8758 : sym->name, name, &loc);
8759 98 : if ((sym->ts.type == BT_ASSUMED && sym->attr.cray_pointer)
8760 98 : || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
8761 0 : && CLASS_DATA (sym)->attr.cray_pointer))
8762 0 : gfc_error ("Cray pointer object %qs of polymorphic type in %s clause at %L",
8763 : sym->name, name, &loc);
8764 98 : if ((sym->ts.type == BT_ASSUMED && sym->attr.cray_pointee)
8765 98 : || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
8766 0 : && CLASS_DATA (sym)->attr.cray_pointee))
8767 0 : gfc_error ("Cray pointee object %qs of polymorphic type in %s clause at %L",
8768 : sym->name, name, &loc);
8769 98 : }
8770 :
8771 : /* Emits error when symbol represents assumed size/rank array. */
8772 :
8773 : static void
8774 14844 : check_array_not_assumed (gfc_symbol *sym, locus loc, const char *name)
8775 : {
8776 14844 : if (sym->as && sym->as->type == AS_ASSUMED_SIZE)
8777 13 : gfc_error ("Assumed size array %qs in %s clause at %L",
8778 : sym->name, name, &loc);
8779 14844 : if (sym->as && sym->as->type == AS_ASSUMED_RANK)
8780 11 : gfc_error ("Assumed rank array %qs in %s clause at %L",
8781 : sym->name, name, &loc);
8782 14844 : }
8783 :
8784 : static void
8785 5850 : resolve_oacc_data_clauses (gfc_symbol *sym, locus loc, const char *name)
8786 : {
8787 0 : check_array_not_assumed (sym, loc, name);
8788 0 : }
8789 :
8790 : static void
8791 65 : resolve_oacc_deviceptr_clause (gfc_symbol *sym, locus loc, const char *name)
8792 : {
8793 65 : if (sym->attr.pointer
8794 64 : || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
8795 0 : && CLASS_DATA (sym)->attr.class_pointer))
8796 1 : gfc_error ("POINTER object %qs in %s clause at %L",
8797 : sym->name, name, &loc);
8798 65 : if (sym->attr.cray_pointer
8799 63 : || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
8800 0 : && CLASS_DATA (sym)->attr.cray_pointer))
8801 2 : gfc_error ("Cray pointer object %qs in %s clause at %L",
8802 : sym->name, name, &loc);
8803 65 : if (sym->attr.cray_pointee
8804 63 : || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
8805 0 : && CLASS_DATA (sym)->attr.cray_pointee))
8806 2 : gfc_error ("Cray pointee object %qs in %s clause at %L",
8807 : sym->name, name, &loc);
8808 65 : if (sym->attr.allocatable
8809 64 : || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
8810 0 : && CLASS_DATA (sym)->attr.allocatable))
8811 1 : gfc_error ("ALLOCATABLE object %qs in %s clause at %L",
8812 : sym->name, name, &loc);
8813 65 : if (sym->attr.value)
8814 1 : gfc_error ("VALUE object %qs in %s clause at %L",
8815 : sym->name, name, &loc);
8816 65 : check_array_not_assumed (sym, loc, name);
8817 65 : }
8818 :
8819 :
8820 : struct resolve_omp_udr_callback_data
8821 : {
8822 : gfc_symbol *sym1, *sym2;
8823 : };
8824 :
8825 :
8826 : static int
8827 1413 : resolve_omp_udr_callback (gfc_expr **e, int *, void *data)
8828 : {
8829 1413 : struct resolve_omp_udr_callback_data *rcd
8830 : = (struct resolve_omp_udr_callback_data *) data;
8831 1413 : if ((*e)->expr_type == EXPR_VARIABLE
8832 801 : && ((*e)->symtree->n.sym == rcd->sym1
8833 255 : || (*e)->symtree->n.sym == rcd->sym2))
8834 : {
8835 801 : gfc_ref *ref = gfc_get_ref ();
8836 801 : ref->type = REF_ARRAY;
8837 801 : ref->u.ar.where = (*e)->where;
8838 801 : ref->u.ar.as = (*e)->symtree->n.sym->as;
8839 801 : ref->u.ar.type = AR_FULL;
8840 801 : ref->u.ar.dimen = 0;
8841 801 : ref->next = (*e)->ref;
8842 801 : (*e)->ref = ref;
8843 : }
8844 1413 : return 0;
8845 : }
8846 :
8847 :
8848 : static int
8849 2990 : resolve_omp_udr_callback2 (gfc_expr **e, int *, void *)
8850 : {
8851 2990 : if ((*e)->expr_type == EXPR_FUNCTION
8852 360 : && (*e)->value.function.isym == NULL)
8853 : {
8854 174 : gfc_symbol *sym = (*e)->symtree->n.sym;
8855 174 : if (!sym->attr.intrinsic
8856 174 : && sym->attr.if_source == IFSRC_UNKNOWN)
8857 4 : gfc_error ("Implicitly declared function %s used in "
8858 : "!$OMP DECLARE REDUCTION at %L", sym->name, &(*e)->where);
8859 : }
8860 2990 : return 0;
8861 : }
8862 :
8863 :
8864 : static gfc_code *
8865 797 : resolve_omp_udr_clause (gfc_omp_namelist *n, gfc_namespace *ns,
8866 : gfc_symbol *sym1, gfc_symbol *sym2)
8867 : {
8868 797 : gfc_code *copy;
8869 797 : gfc_symbol sym1_copy, sym2_copy;
8870 :
8871 797 : if (ns->code->op == EXEC_ASSIGN)
8872 : {
8873 625 : copy = gfc_get_code (EXEC_ASSIGN);
8874 625 : copy->expr1 = gfc_copy_expr (ns->code->expr1);
8875 625 : copy->expr2 = gfc_copy_expr (ns->code->expr2);
8876 : }
8877 : else
8878 : {
8879 172 : copy = gfc_get_code (EXEC_CALL);
8880 172 : copy->symtree = ns->code->symtree;
8881 172 : copy->ext.actual = gfc_copy_actual_arglist (ns->code->ext.actual);
8882 : }
8883 797 : copy->loc = ns->code->loc;
8884 797 : sym1_copy = *sym1;
8885 797 : sym2_copy = *sym2;
8886 797 : *sym1 = *n->sym;
8887 797 : *sym2 = *n->sym;
8888 797 : sym1->name = sym1_copy.name;
8889 797 : sym2->name = sym2_copy.name;
8890 797 : ns->proc_name = ns->parent->proc_name;
8891 797 : if (n->sym->attr.dimension)
8892 : {
8893 348 : struct resolve_omp_udr_callback_data rcd;
8894 348 : rcd.sym1 = sym1;
8895 348 : rcd.sym2 = sym2;
8896 348 : gfc_code_walker (©, gfc_dummy_code_callback,
8897 : resolve_omp_udr_callback, &rcd);
8898 : }
8899 797 : gfc_resolve_code (copy, gfc_current_ns);
8900 797 : if (copy->op == EXEC_CALL && copy->resolved_isym == NULL)
8901 : {
8902 172 : gfc_symbol *sym = copy->resolved_sym;
8903 172 : if (sym
8904 170 : && !sym->attr.intrinsic
8905 170 : && sym->attr.if_source == IFSRC_UNKNOWN)
8906 4 : gfc_error ("Implicitly declared subroutine %s used in "
8907 : "!$OMP DECLARE REDUCTION at %L", sym->name,
8908 : ©->loc);
8909 : }
8910 797 : gfc_code_walker (©, gfc_dummy_code_callback,
8911 : resolve_omp_udr_callback2, NULL);
8912 797 : *sym1 = sym1_copy;
8913 797 : *sym2 = sym2_copy;
8914 797 : return copy;
8915 : }
8916 :
8917 : /* Assume that a constant expression in the range 1 (omp_default_mem_alloc)
8918 : to GOMP_OMP_PREDEF_ALLOC_MAX, or GOMP_OMPX_PREDEF_ALLOC_MIN to
8919 : GOMP_OMPX_PREDEF_ALLOC_MAX is fine. The original symbol name is already
8920 : lost during matching via gfc_match_expr. */
8921 : static bool
8922 130 : is_predefined_allocator (gfc_expr *expr)
8923 : {
8924 130 : return (gfc_resolve_expr (expr)
8925 129 : && expr->rank == 0
8926 124 : && expr->ts.type == BT_INTEGER
8927 119 : && expr->ts.kind == gfc_c_intptr_kind
8928 114 : && expr->expr_type == EXPR_CONSTANT
8929 239 : && ((mpz_sgn (expr->value.integer) > 0
8930 107 : && mpz_cmp_si (expr->value.integer,
8931 : GOMP_OMP_PREDEF_ALLOC_MAX) <= 0)
8932 4 : || (mpz_cmp_si (expr->value.integer,
8933 : GOMP_OMPX_PREDEF_ALLOC_MIN) >= 0
8934 1 : && mpz_cmp_si (expr->value.integer,
8935 130 : GOMP_OMPX_PREDEF_ALLOC_MAX) <= 0)));
8936 : }
8937 :
8938 : /* Resolve declarative ALLOCATE statement. Note: Common block vars only appear
8939 : as /block/ not individual, which is ensured during parsing. */
8940 :
8941 : void
8942 62 : gfc_resolve_omp_allocate (gfc_namespace *ns, gfc_omp_namelist *list)
8943 : {
8944 278 : for (gfc_omp_namelist *n = list; n; n = n->next)
8945 : {
8946 216 : if (n->sym->attr.result || n->sym->result == n->sym)
8947 : {
8948 1 : gfc_error ("Unexpected function-result variable %qs at %L in "
8949 : "declarative !$OMP ALLOCATE", n->sym->name, &n->where);
8950 31 : continue;
8951 : }
8952 215 : if (ns->omp_allocate->sym->attr.proc_pointer)
8953 : {
8954 0 : gfc_error ("Procedure pointer %qs not supported with !$OMP "
8955 : "ALLOCATE at %L", n->sym->name, &n->where);
8956 0 : continue;
8957 : }
8958 215 : if (n->sym->attr.flavor != FL_VARIABLE)
8959 : {
8960 3 : gfc_error ("Argument %qs at %L to declarative !$OMP ALLOCATE "
8961 : "directive must be a variable", n->sym->name,
8962 : &n->where);
8963 3 : continue;
8964 : }
8965 212 : if (ns != n->sym->ns || n->sym->attr.use_assoc || n->sym->attr.imported)
8966 : {
8967 8 : gfc_error ("Argument %qs at %L to declarative !$OMP ALLOCATE shall be"
8968 : " in the same scope as the variable declaration",
8969 : n->sym->name, &n->where);
8970 8 : continue;
8971 : }
8972 204 : if (n->sym->attr.dummy)
8973 : {
8974 3 : gfc_error ("Unexpected dummy argument %qs as argument at %L to "
8975 : "declarative !$OMP ALLOCATE", n->sym->name, &n->where);
8976 3 : continue;
8977 : }
8978 201 : if (n->sym->attr.codimension)
8979 : {
8980 0 : gfc_error ("Unexpected coarray argument %qs as argument at %L to "
8981 : "declarative !$OMP ALLOCATE", n->sym->name, &n->where);
8982 0 : continue;
8983 : }
8984 201 : if (n->sym->attr.omp_allocate)
8985 : {
8986 5 : if (n->sym->attr.in_common)
8987 : {
8988 1 : gfc_error ("Duplicated common block %</%s/%> in !$OMP ALLOCATE "
8989 1 : "at %L", n->sym->common_head->name, &n->where);
8990 3 : while (n->next && n->next->sym
8991 3 : && n->sym->common_head == n->next->sym->common_head)
8992 : n = n->next;
8993 : }
8994 : else
8995 4 : gfc_error ("Duplicated variable %qs in !$OMP ALLOCATE at %L",
8996 : n->sym->name, &n->where);
8997 5 : continue;
8998 : }
8999 : /* For 'equivalence(a,b)', a 'union_type {<type> a,b} equiv.0' is created
9000 : with a value expression for 'a' as 'equiv.0.a' (likewise for b); while
9001 : this can be handled, EQUIVALENCE is marked as obsolescent since Fortran
9002 : 2018 and also not widely used. However, it could be supported,
9003 : if needed. */
9004 196 : if (n->sym->attr.in_equivalence)
9005 : {
9006 2 : gfc_error ("Sorry, EQUIVALENCE object %qs not supported with !$OMP "
9007 : "ALLOCATE at %L", n->sym->name, &n->where);
9008 2 : continue;
9009 : }
9010 : /* Similar for Cray pointer/pointee - they could be implemented but as
9011 : common vendor extension but nowadays rarely used and requiring
9012 : -fcray-pointer, there is no need to support them. */
9013 194 : if (n->sym->attr.cray_pointer || n->sym->attr.cray_pointee)
9014 : {
9015 2 : gfc_error ("Sorry, Cray pointers and pointees such as %qs are not "
9016 : "supported with !$OMP ALLOCATE at %L",
9017 : n->sym->name, &n->where);
9018 2 : continue;
9019 : }
9020 192 : n->sym->attr.omp_allocate = 1;
9021 192 : if ((n->sym->ts.type == BT_CLASS && n->sym->attr.class_ok
9022 0 : && CLASS_DATA (n->sym)->attr.allocatable)
9023 192 : || (n->sym->ts.type != BT_CLASS && n->sym->attr.allocatable))
9024 1 : gfc_error ("Unexpected allocatable variable %qs at %L in declarative "
9025 : "!$OMP ALLOCATE directive", n->sym->name, &n->where);
9026 191 : else if ((n->sym->ts.type == BT_CLASS && n->sym->attr.class_ok
9027 0 : && CLASS_DATA (n->sym)->attr.class_pointer)
9028 191 : || (n->sym->ts.type != BT_CLASS && n->sym->attr.pointer))
9029 1 : gfc_error ("Unexpected pointer variable %qs at %L in declarative "
9030 : "!$OMP ALLOCATE directive", n->sym->name, &n->where);
9031 192 : HOST_WIDE_INT alignment = 0;
9032 198 : if (n->u.align
9033 192 : && (!gfc_resolve_expr (n->u.align)
9034 27 : || n->u.align->ts.type != BT_INTEGER
9035 26 : || n->u.align->rank != 0
9036 24 : || n->u.align->expr_type != EXPR_CONSTANT
9037 23 : || gfc_extract_hwi (n->u.align, &alignment)
9038 23 : || !pow2p_hwi (alignment)))
9039 : {
9040 6 : gfc_error ("ALIGN requires a scalar positive constant integer "
9041 : "alignment expression at %L that is a power of two",
9042 6 : &n->u.align->where);
9043 6 : while (n->sym->attr.in_common && n->next && n->next->sym
9044 6 : && n->sym->common_head == n->next->sym->common_head)
9045 : n = n->next;
9046 6 : continue;
9047 : }
9048 186 : if (n->sym->attr.in_common || n->sym->attr.save || n->sym->ns->save_all
9049 63 : || (n->sym->ns->proc_name
9050 63 : && (n->sym->ns->proc_name->attr.flavor == FL_PROGRAM
9051 : || n->sym->ns->proc_name->attr.flavor == FL_MODULE
9052 : || n->sym->ns->proc_name->attr.flavor == FL_BLOCK_DATA)))
9053 : {
9054 131 : bool com = n->sym->attr.in_common;
9055 131 : if (!n->u2.allocator)
9056 1 : gfc_error ("An ALLOCATOR clause is required as the list item "
9057 : "%<%s%s%s%> at %L has the SAVE attribute", com ? "/" : "",
9058 0 : com ? n->sym->common_head->name : n->sym->name,
9059 : com ? "/" : "", &n->where);
9060 130 : else if (!is_predefined_allocator (n->u2.allocator))
9061 24 : gfc_error ("Predefined allocator required in ALLOCATOR clause at %L"
9062 : " as the list item %<%s%s%s%> at %L has the SAVE attribute",
9063 24 : &n->u2.allocator->where, com ? "/" : "",
9064 24 : com ? n->sym->common_head->name : n->sym->name,
9065 : com ? "/" : "", &n->where);
9066 : /* Static variables may not use omp_cgroup_mem_alloc (6),
9067 : omp_pteam_mem_alloc (7), or omp_thread_mem_alloc (8). */
9068 106 : else if (mpz_cmp_si (n->u2.allocator->value.integer,
9069 : 6 /* cgroup */) >= 0
9070 34 : && mpz_cmp_si (n->u2.allocator->value.integer,
9071 : 8 /* thread */) <= 0)
9072 : {
9073 33 : STATIC_ASSERT (GOMP_OMP_PREDEF_ALLOC_CGROUP == 6);
9074 33 : STATIC_ASSERT (GOMP_OMP_PREDEF_ALLOC_PTEAM == 7);
9075 33 : STATIC_ASSERT (GOMP_OMP_PREDEF_ALLOC_THREAD == 8);
9076 33 : const char *alloc_name[] = {"omp_cgroup_mem_alloc",
9077 : "omp_pteam_mem_alloc",
9078 : "omp_thread_mem_alloc" };
9079 33 : gfc_error ("Predefined allocator %qs in ALLOCATOR clause at %L, "
9080 : "used for list item %<%s%s%s%> at %L, may not be used"
9081 : " for static variables",
9082 33 : alloc_name[mpz_get_ui (n->u2.allocator->value.integer)
9083 33 : - 6 /* cgroup */], &n->u2.allocator->where,
9084 : com ? "/" : "",
9085 33 : com ? n->sym->common_head->name : n->sym->name,
9086 : com ? "/" : "", &n->where);
9087 : }
9088 67 : while (n->sym->attr.in_common && n->next && n->next->sym
9089 186 : && n->sym->common_head == n->next->sym->common_head)
9090 : n = n->next;
9091 : }
9092 55 : else if (n->u2.allocator
9093 55 : && (!gfc_resolve_expr (n->u2.allocator)
9094 20 : || n->u2.allocator->ts.type != BT_INTEGER
9095 19 : || n->u2.allocator->rank != 0
9096 18 : || n->u2.allocator->ts.kind != gfc_c_intptr_kind))
9097 3 : gfc_error ("Expected integer expression of the "
9098 : "%<omp_allocator_handle_kind%> kind at %L",
9099 3 : &n->u2.allocator->where);
9100 : }
9101 62 : }
9102 :
9103 : /* Resolve ASSUME's and ASSUMES' assumption clauses. Note that absent/contains
9104 : is handled during parse time in omp_verify_merge_absent_contains. */
9105 :
9106 : void
9107 29 : gfc_resolve_omp_assumptions (gfc_omp_assumptions *assume)
9108 : {
9109 46 : for (gfc_expr_list *el = assume->holds; el; el = el->next)
9110 17 : if (!gfc_resolve_expr (el->expr)
9111 17 : || el->expr->ts.type != BT_LOGICAL
9112 32 : || el->expr->rank != 0)
9113 4 : gfc_error ("HOLDS expression at %L must be a scalar logical expression",
9114 4 : &el->expr->where);
9115 29 : }
9116 :
9117 :
9118 : /* OpenMP directive resolving routines. */
9119 :
9120 : static void
9121 32471 : resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
9122 : gfc_namespace *ns, bool openacc = false)
9123 : {
9124 32471 : gfc_omp_namelist *n, *last;
9125 32471 : gfc_expr_list *el;
9126 32471 : enum gfc_omp_list_type list;
9127 32471 : int ifc;
9128 32471 : bool if_without_mod = false;
9129 32471 : gfc_omp_linear_op linear_op = OMP_LINEAR_DEFAULT;
9130 32471 : static const char *clause_names[]
9131 : = { "PRIVATE", "FIRSTPRIVATE", "LASTPRIVATE", "COPYPRIVATE", "SHARED",
9132 : "COPYIN", "UNIFORM", "AFFINITY", "ALIGNED", "LINEAR", "DEPEND", "MAP",
9133 : "TO", "FROM", "INCLUSIVE", "EXCLUSIVE",
9134 : "REDUCTION", "REDUCTION" /*inscan*/, "REDUCTION" /*task*/,
9135 : "IN_REDUCTION", "TASK_REDUCTION",
9136 : "DEVICE_RESIDENT", "LINK", "LOCAL", "USE_DEVICE",
9137 : "CACHE", "IS_DEVICE_PTR", "USE_DEVICE_PTR", "USE_DEVICE_ADDR",
9138 : "NONTEMPORAL", "ALLOCATE", "HAS_DEVICE_ADDR", "ENTER",
9139 : "USES_ALLOCATORS", "INIT", "USE", "DESTROY", "INTEROP", "ADJUST_ARGS" };
9140 32471 : STATIC_ASSERT (ARRAY_SIZE (clause_names) == OMP_LIST_NUM);
9141 :
9142 32471 : if (omp_clauses == NULL)
9143 : return;
9144 :
9145 32471 : if (ns == NULL)
9146 32044 : ns = gfc_current_ns;
9147 :
9148 32471 : if (omp_clauses->orderedc && omp_clauses->orderedc < omp_clauses->collapse)
9149 0 : gfc_error ("ORDERED clause parameter is less than COLLAPSE at %L",
9150 : &code->loc);
9151 32471 : if (omp_clauses->order_concurrent && omp_clauses->ordered)
9152 4 : gfc_error ("ORDER clause must not be used together with ORDERED at %L",
9153 : &code->loc);
9154 32471 : if (omp_clauses->if_expr)
9155 : {
9156 1184 : gfc_expr *expr = omp_clauses->if_expr;
9157 1184 : if (!gfc_resolve_expr (expr)
9158 1184 : || expr->ts.type != BT_LOGICAL || expr->rank != 0)
9159 16 : gfc_error ("IF clause at %L requires a scalar LOGICAL expression",
9160 : &expr->where);
9161 : if_without_mod = true;
9162 : }
9163 357181 : for (ifc = 0; ifc < OMP_IF_LAST; ifc++)
9164 324710 : if (omp_clauses->if_exprs[ifc])
9165 : {
9166 137 : gfc_expr *expr = omp_clauses->if_exprs[ifc];
9167 137 : bool ok = true;
9168 137 : if (!gfc_resolve_expr (expr)
9169 137 : || expr->ts.type != BT_LOGICAL || expr->rank != 0)
9170 0 : gfc_error ("IF clause at %L requires a scalar LOGICAL expression",
9171 : &expr->where);
9172 137 : else if (if_without_mod)
9173 : {
9174 1 : gfc_error ("IF clause without modifier at %L used together with "
9175 : "IF clauses with modifiers",
9176 1 : &omp_clauses->if_expr->where);
9177 1 : if_without_mod = false;
9178 : }
9179 : else
9180 136 : switch (code->op)
9181 : {
9182 13 : case EXEC_OMP_CANCEL:
9183 13 : ok = ifc == OMP_IF_CANCEL;
9184 13 : break;
9185 :
9186 16 : case EXEC_OMP_PARALLEL:
9187 16 : case EXEC_OMP_PARALLEL_DO:
9188 16 : case EXEC_OMP_PARALLEL_LOOP:
9189 16 : case EXEC_OMP_PARALLEL_MASKED:
9190 16 : case EXEC_OMP_PARALLEL_MASTER:
9191 16 : case EXEC_OMP_PARALLEL_SECTIONS:
9192 16 : case EXEC_OMP_PARALLEL_WORKSHARE:
9193 16 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
9194 16 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
9195 16 : ok = ifc == OMP_IF_PARALLEL;
9196 16 : break;
9197 :
9198 28 : case EXEC_OMP_PARALLEL_DO_SIMD:
9199 28 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
9200 28 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
9201 28 : ok = ifc == OMP_IF_PARALLEL || ifc == OMP_IF_SIMD;
9202 28 : break;
9203 :
9204 8 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
9205 8 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
9206 8 : ok = ifc == OMP_IF_PARALLEL || ifc == OMP_IF_TASKLOOP;
9207 8 : break;
9208 :
9209 12 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
9210 12 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
9211 12 : ok = (ifc == OMP_IF_PARALLEL
9212 12 : || ifc == OMP_IF_TASKLOOP
9213 : || ifc == OMP_IF_SIMD);
9214 : break;
9215 :
9216 0 : case EXEC_OMP_SIMD:
9217 0 : case EXEC_OMP_DO_SIMD:
9218 0 : case EXEC_OMP_DISTRIBUTE_SIMD:
9219 0 : case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
9220 0 : ok = ifc == OMP_IF_SIMD;
9221 0 : break;
9222 :
9223 1 : case EXEC_OMP_TASK:
9224 1 : ok = ifc == OMP_IF_TASK;
9225 1 : break;
9226 :
9227 5 : case EXEC_OMP_TASKLOOP:
9228 5 : case EXEC_OMP_MASKED_TASKLOOP:
9229 5 : case EXEC_OMP_MASTER_TASKLOOP:
9230 5 : ok = ifc == OMP_IF_TASKLOOP;
9231 5 : break;
9232 :
9233 20 : case EXEC_OMP_TASKLOOP_SIMD:
9234 20 : case EXEC_OMP_MASKED_TASKLOOP_SIMD:
9235 20 : case EXEC_OMP_MASTER_TASKLOOP_SIMD:
9236 20 : ok = ifc == OMP_IF_TASKLOOP || ifc == OMP_IF_SIMD;
9237 20 : break;
9238 :
9239 5 : case EXEC_OMP_TARGET:
9240 5 : case EXEC_OMP_TARGET_TEAMS:
9241 5 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
9242 5 : case EXEC_OMP_TARGET_TEAMS_LOOP:
9243 5 : ok = ifc == OMP_IF_TARGET;
9244 5 : break;
9245 :
9246 4 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
9247 4 : case EXEC_OMP_TARGET_SIMD:
9248 4 : ok = ifc == OMP_IF_TARGET || ifc == OMP_IF_SIMD;
9249 4 : break;
9250 :
9251 1 : case EXEC_OMP_TARGET_DATA:
9252 1 : ok = ifc == OMP_IF_TARGET_DATA;
9253 1 : break;
9254 :
9255 1 : case EXEC_OMP_TARGET_UPDATE:
9256 1 : ok = ifc == OMP_IF_TARGET_UPDATE;
9257 1 : break;
9258 :
9259 1 : case EXEC_OMP_TARGET_ENTER_DATA:
9260 1 : ok = ifc == OMP_IF_TARGET_ENTER_DATA;
9261 1 : break;
9262 :
9263 1 : case EXEC_OMP_TARGET_EXIT_DATA:
9264 1 : ok = ifc == OMP_IF_TARGET_EXIT_DATA;
9265 1 : break;
9266 :
9267 10 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
9268 10 : case EXEC_OMP_TARGET_PARALLEL:
9269 10 : case EXEC_OMP_TARGET_PARALLEL_DO:
9270 10 : case EXEC_OMP_TARGET_PARALLEL_LOOP:
9271 10 : ok = ifc == OMP_IF_TARGET || ifc == OMP_IF_PARALLEL;
9272 10 : break;
9273 :
9274 10 : case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
9275 10 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
9276 10 : ok = (ifc == OMP_IF_TARGET
9277 10 : || ifc == OMP_IF_PARALLEL
9278 : || ifc == OMP_IF_SIMD);
9279 : break;
9280 :
9281 : default:
9282 : ok = false;
9283 : break;
9284 : }
9285 115 : if (!ok)
9286 : {
9287 2 : static const char *ifs[] = {
9288 : "CANCEL",
9289 : "PARALLEL",
9290 : "SIMD",
9291 : "TASK",
9292 : "TASKLOOP",
9293 : "TARGET",
9294 : "TARGET DATA",
9295 : "TARGET UPDATE",
9296 : "TARGET ENTER DATA",
9297 : "TARGET EXIT DATA"
9298 : };
9299 2 : gfc_error ("IF clause modifier %s at %L not appropriate for "
9300 : "the current OpenMP construct", ifs[ifc], &expr->where);
9301 : }
9302 : }
9303 :
9304 32471 : if (omp_clauses->self_expr)
9305 : {
9306 177 : gfc_expr *expr = omp_clauses->self_expr;
9307 177 : if (!gfc_resolve_expr (expr)
9308 177 : || expr->ts.type != BT_LOGICAL || expr->rank != 0)
9309 6 : gfc_error ("SELF clause at %L requires a scalar LOGICAL expression",
9310 : &expr->where);
9311 : }
9312 :
9313 32471 : if (omp_clauses->final_expr)
9314 : {
9315 64 : gfc_expr *expr = omp_clauses->final_expr;
9316 64 : if (!gfc_resolve_expr (expr)
9317 64 : || expr->ts.type != BT_LOGICAL || expr->rank != 0)
9318 0 : gfc_error ("FINAL clause at %L requires a scalar LOGICAL expression",
9319 : &expr->where);
9320 : }
9321 32471 : if (omp_clauses->novariants)
9322 : {
9323 9 : gfc_expr *expr = omp_clauses->novariants;
9324 18 : if (!gfc_resolve_expr (expr) || expr->ts.type != BT_LOGICAL
9325 17 : || expr->rank != 0)
9326 1 : gfc_error (
9327 : "NOVARIANTS clause at %L requires a scalar LOGICAL expression",
9328 : &expr->where);
9329 32471 : if_without_mod = true;
9330 : }
9331 32471 : if (omp_clauses->nocontext)
9332 : {
9333 12 : gfc_expr *expr = omp_clauses->nocontext;
9334 24 : if (!gfc_resolve_expr (expr) || expr->ts.type != BT_LOGICAL
9335 23 : || expr->rank != 0)
9336 1 : gfc_error (
9337 : "NOCONTEXT clause at %L requires a scalar LOGICAL expression",
9338 : &expr->where);
9339 32471 : if_without_mod = true;
9340 : }
9341 32471 : if (omp_clauses->num_threads)
9342 962 : resolve_positive_int_expr (omp_clauses->num_threads, "NUM_THREADS");
9343 32471 : if (omp_clauses->dyn_groupprivate)
9344 10 : resolve_nonnegative_int_expr (omp_clauses->dyn_groupprivate,
9345 : "DYN_GROUPPRIVATE");
9346 32471 : if (omp_clauses->chunk_size)
9347 : {
9348 510 : gfc_expr *expr = omp_clauses->chunk_size;
9349 510 : if (!gfc_resolve_expr (expr)
9350 510 : || expr->ts.type != BT_INTEGER || expr->rank != 0)
9351 0 : gfc_error ("SCHEDULE clause's chunk_size at %L requires "
9352 : "a scalar INTEGER expression", &expr->where);
9353 510 : else if (expr->expr_type == EXPR_CONSTANT
9354 : && expr->ts.type == BT_INTEGER
9355 485 : && mpz_sgn (expr->value.integer) <= 0)
9356 2 : gfc_warning (OPT_Wopenmp, "INTEGER expression of SCHEDULE clause's "
9357 : "chunk_size at %L must be positive", &expr->where);
9358 : }
9359 32471 : if (omp_clauses->sched_kind != OMP_SCHED_NONE
9360 891 : && omp_clauses->sched_nonmonotonic)
9361 : {
9362 34 : if (omp_clauses->sched_monotonic)
9363 2 : gfc_error ("Both MONOTONIC and NONMONOTONIC schedule modifiers "
9364 : "specified at %L", &code->loc);
9365 32 : else if (omp_clauses->ordered)
9366 4 : gfc_error ("NONMONOTONIC schedule modifier specified with ORDERED "
9367 : "clause at %L", &code->loc);
9368 : }
9369 :
9370 32471 : if (omp_clauses->depobj
9371 32471 : && (!gfc_resolve_expr (omp_clauses->depobj)
9372 115 : || omp_clauses->depobj->ts.type != BT_INTEGER
9373 114 : || omp_clauses->depobj->ts.kind != 2 * gfc_index_integer_kind
9374 113 : || omp_clauses->depobj->rank != 0))
9375 4 : gfc_error ("DEPOBJ in DEPOBJ construct at %L shall be a scalar integer "
9376 4 : "of OMP_DEPEND_KIND kind", &omp_clauses->depobj->where);
9377 :
9378 : /* Check that no symbol appears on multiple clauses, except that
9379 : a symbol can appear on both firstprivate and lastprivate. */
9380 1298840 : for (list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
9381 1266369 : list = gfc_omp_list_type (list + 1))
9382 1311975 : for (n = omp_clauses->lists[list]; n; n = n->next)
9383 : {
9384 45606 : if (!n->sym) /* omp_all_memory. */
9385 47 : continue;
9386 45559 : n->sym->mark = 0;
9387 45559 : n->sym->comp_mark = 0;
9388 45559 : n->sym->data_mark = 0;
9389 45559 : n->sym->dev_mark = 0;
9390 45559 : n->sym->gen_mark = 0;
9391 45559 : n->sym->reduc_mark = 0;
9392 45559 : if (n->sym->attr.flavor == FL_VARIABLE
9393 274 : || n->sym->attr.proc_pointer
9394 233 : || (!code
9395 0 : && !ns->omp_udm_ns
9396 0 : && (!n->sym->attr.dummy || n->sym->ns != ns)))
9397 : {
9398 45326 : if (!code
9399 271 : && !ns->omp_udm_ns
9400 264 : && (!n->sym->attr.dummy || n->sym->ns != ns))
9401 0 : gfc_error ("Variable %qs is not a dummy argument at %L",
9402 : n->sym->name, &n->where);
9403 45326 : continue;
9404 : }
9405 233 : if (n->sym->attr.flavor == FL_PROCEDURE
9406 153 : && n->sym->result == n->sym
9407 138 : && n->sym->attr.function)
9408 : {
9409 138 : if (ns->proc_name == n->sym
9410 44 : || (ns->parent && ns->parent->proc_name == n->sym))
9411 101 : continue;
9412 37 : if (ns->proc_name->attr.entry_master)
9413 : {
9414 32 : gfc_entry_list *el = ns->entries;
9415 51 : for (; el; el = el->next)
9416 51 : if (el->sym == n->sym)
9417 : break;
9418 32 : if (el)
9419 32 : continue;
9420 : }
9421 5 : if (ns->parent
9422 3 : && ns->parent->proc_name->attr.entry_master)
9423 : {
9424 2 : gfc_entry_list *el = ns->parent->entries;
9425 3 : for (; el; el = el->next)
9426 3 : if (el->sym == n->sym)
9427 : break;
9428 2 : if (el)
9429 2 : continue;
9430 : }
9431 : }
9432 98 : if (list == OMP_LIST_MAP
9433 18 : && n->sym->attr.flavor == FL_PARAMETER)
9434 : {
9435 : /* OpenACC since 3.4 permits for Fortran named constants, but
9436 : permits removing then as optimization is not needed and such
9437 : ignore them. Likewise below for FIRSTPRIVATE. */
9438 12 : if (openacc)
9439 10 : gfc_warning (OPT_Wsurprising, "Clause for object %qs at %L is "
9440 : "ignored as parameters need not be copied",
9441 : n->sym->name, &n->where);
9442 : else
9443 2 : gfc_error ("Object %qs is not a variable at %L; parameters"
9444 : " cannot be and need not be mapped", n->sym->name,
9445 : &n->where);
9446 : }
9447 86 : else if (openacc && n->sym->attr.flavor == FL_PARAMETER)
9448 9 : gfc_warning (OPT_Wsurprising, "Clause for object %qs at %L is ignored"
9449 : " as it is a parameter", n->sym->name, &n->where);
9450 77 : else if (list != OMP_LIST_USES_ALLOCATORS)
9451 30 : gfc_error ("Object %qs is not a variable at %L", n->sym->name,
9452 : &n->where);
9453 : }
9454 32471 : if (omp_clauses->lists[OMP_LIST_REDUCTION_INSCAN])
9455 : {
9456 69 : locus *loc = &omp_clauses->lists[OMP_LIST_REDUCTION_INSCAN]->where;
9457 69 : if (code->op != EXEC_OMP_DO
9458 : && code->op != EXEC_OMP_SIMD
9459 : && code->op != EXEC_OMP_DO_SIMD
9460 : && code->op != EXEC_OMP_PARALLEL_DO
9461 : && code->op != EXEC_OMP_PARALLEL_DO_SIMD)
9462 23 : gfc_error ("%<inscan%> REDUCTION clause on construct other than DO, "
9463 : "SIMD, DO SIMD, PARALLEL DO, PARALLEL DO SIMD at %L",
9464 : loc);
9465 69 : if (omp_clauses->ordered)
9466 2 : gfc_error ("ORDERED clause specified together with %<inscan%> "
9467 : "REDUCTION clause at %L", loc);
9468 69 : if (omp_clauses->sched_kind != OMP_SCHED_NONE)
9469 3 : gfc_error ("SCHEDULE clause specified together with %<inscan%> "
9470 : "REDUCTION clause at %L", loc);
9471 : }
9472 :
9473 1298840 : for (list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
9474 1266369 : list = gfc_omp_list_type (list + 1))
9475 1266369 : if (list != OMP_LIST_FIRSTPRIVATE
9476 1266369 : && list != OMP_LIST_LASTPRIVATE
9477 1266369 : && list != OMP_LIST_ALIGNED
9478 1168956 : && list != OMP_LIST_DEPEND
9479 1168956 : && list != OMP_LIST_FROM
9480 1104014 : && list != OMP_LIST_TO
9481 1104014 : && list != OMP_LIST_INTEROP
9482 1039072 : && (list != OMP_LIST_REDUCTION || !openacc)
9483 1026447 : && list != OMP_LIST_ALLOCATE)
9484 1028756 : for (n = omp_clauses->lists[list]; n; n = n->next)
9485 : {
9486 34780 : bool component_ref_p = false;
9487 :
9488 : /* Allow multiple components of the same (e.g. derived-type)
9489 : variable here. Duplicate components are detected elsewhere. */
9490 34780 : if (n->expr && n->expr->expr_type == EXPR_VARIABLE)
9491 15801 : for (gfc_ref *ref = n->expr->ref; ref; ref = ref->next)
9492 9591 : if (ref->type == REF_COMPONENT)
9493 3135 : component_ref_p = true;
9494 34780 : if ((list == OMP_LIST_IS_DEVICE_PTR
9495 34780 : || list == OMP_LIST_HAS_DEVICE_ADDR)
9496 313 : && !component_ref_p)
9497 : {
9498 313 : if (n->sym->gen_mark
9499 311 : || n->sym->dev_mark
9500 310 : || n->sym->reduc_mark
9501 310 : || n->sym->mark)
9502 5 : gfc_error ("Symbol %qs present on multiple clauses at %L",
9503 : n->sym->name, &n->where);
9504 : else
9505 308 : n->sym->dev_mark = 1;
9506 : }
9507 34467 : else if ((list == OMP_LIST_USE_DEVICE_PTR
9508 34467 : || list == OMP_LIST_USE_DEVICE_ADDR
9509 34467 : || list == OMP_LIST_PRIVATE
9510 : || list == OMP_LIST_SHARED)
9511 12851 : && !component_ref_p)
9512 : {
9513 12851 : if (n->sym->gen_mark || n->sym->dev_mark || n->sym->reduc_mark)
9514 13 : gfc_error ("Symbol %qs present on multiple clauses at %L",
9515 : n->sym->name, &n->where);
9516 : else
9517 : {
9518 12838 : n->sym->gen_mark = 1;
9519 : /* Set both generic and device bits if we have
9520 : use_device_*(x) or shared(x). This allows us to diagnose
9521 : "map(x) private(x)" below. */
9522 12838 : if (list != OMP_LIST_PRIVATE)
9523 3456 : n->sym->dev_mark = 1;
9524 : }
9525 : }
9526 21616 : else if ((list == OMP_LIST_REDUCTION
9527 21616 : || list == OMP_LIST_REDUCTION_TASK
9528 19159 : || list == OMP_LIST_REDUCTION_INSCAN
9529 19159 : || list == OMP_LIST_IN_REDUCTION
9530 18946 : || list == OMP_LIST_TASK_REDUCTION)
9531 2670 : && !component_ref_p)
9532 : {
9533 : /* Attempts to mix reduction types are diagnosed below. */
9534 2670 : if (n->sym->gen_mark || n->sym->dev_mark)
9535 2 : gfc_error ("Symbol %qs present on multiple clauses at %L",
9536 : n->sym->name, &n->where);
9537 2670 : n->sym->reduc_mark = 1;
9538 : }
9539 18946 : else if ((!component_ref_p && n->sym->comp_mark)
9540 2452 : || (component_ref_p && n->sym->mark))
9541 : {
9542 28 : if (openacc)
9543 3 : gfc_error ("Symbol %qs has mixed component and non-component "
9544 3 : "accesses at %L", n->sym->name, &n->where);
9545 : }
9546 18918 : else if ((openacc || list != OMP_LIST_MAP) && n->sym->mark)
9547 88 : gfc_error ("Symbol %qs present on multiple clauses at %L",
9548 : n->sym->name, &n->where);
9549 : else
9550 : {
9551 18830 : if (component_ref_p)
9552 2425 : n->sym->comp_mark = 1;
9553 : else
9554 16405 : n->sym->mark = 1;
9555 : }
9556 : }
9557 :
9558 32471 : if (code
9559 32247 : && code->op == EXEC_OMP_INTEROP
9560 63 : && omp_clauses->lists[OMP_LIST_DEPEND])
9561 : {
9562 12 : if (!omp_clauses->lists[OMP_LIST_INIT]
9563 5 : && !omp_clauses->lists[OMP_LIST_USE]
9564 1 : && !omp_clauses->lists[OMP_LIST_DESTROY])
9565 : {
9566 1 : gfc_error ("DEPEND clause at %L requires action clause with "
9567 : "%<targetsync%> interop-type",
9568 : &omp_clauses->lists[OMP_LIST_DEPEND]->where);
9569 : }
9570 22 : for (n = omp_clauses->lists[OMP_LIST_INIT]; n; n = n->next)
9571 12 : if (!n->u.init.targetsync)
9572 : {
9573 2 : gfc_error ("DEPEND clause at %L requires %<targetsync%> "
9574 : "interop-type, lacking it for %qs at %L",
9575 2 : &omp_clauses->lists[OMP_LIST_DEPEND]->where,
9576 2 : n->sym->name, &n->where);
9577 2 : break;
9578 : }
9579 : }
9580 32247 : if (code && (code->op == EXEC_OMP_INTEROP || code->op == EXEC_OMP_DISPATCH))
9581 1085 : for (list = OMP_LIST_INIT; list <= OMP_LIST_INTEROP;
9582 868 : list = gfc_omp_list_type (list + 1))
9583 1123 : for (n = omp_clauses->lists[list]; n; n = n->next)
9584 : {
9585 255 : if (n->sym->ts.type != BT_INTEGER
9586 252 : || n->sym->ts.kind != gfc_index_integer_kind
9587 248 : || n->sym->attr.dimension
9588 243 : || n->sym->attr.flavor != FL_VARIABLE)
9589 16 : gfc_error ("%qs at %L in %qs clause must be a scalar integer "
9590 : "variable of %<omp_interop_kind%> kind", n->sym->name,
9591 : &n->where, clause_names[list]);
9592 255 : if (list != OMP_LIST_USE && list != OMP_LIST_INTEROP
9593 109 : && n->sym->attr.intent == INTENT_IN)
9594 2 : gfc_error ("%qs at %L in %qs clause must be definable",
9595 : n->sym->name, &n->where, clause_names[list]);
9596 : }
9597 :
9598 : /* Detect specifically the case where we have "map(x) private(x)" and raise
9599 : an error. If we have "...simd" combined directives though, the "private"
9600 : applies to the simd part, so this is permitted though. */
9601 41861 : for (n = omp_clauses->lists[OMP_LIST_PRIVATE]; n; n = n->next)
9602 9390 : if (n->sym->mark
9603 6 : && n->sym->gen_mark
9604 6 : && !n->sym->dev_mark
9605 6 : && !n->sym->reduc_mark
9606 5 : && code->op != EXEC_OMP_TARGET_SIMD
9607 : && code->op != EXEC_OMP_TARGET_PARALLEL_DO_SIMD
9608 : && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD
9609 : && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD)
9610 1 : gfc_error ("Symbol %qs present on multiple clauses at %L",
9611 : n->sym->name, &n->where);
9612 :
9613 : gcc_assert (OMP_LIST_LASTPRIVATE == OMP_LIST_FIRSTPRIVATE + 1);
9614 97413 : for (list = OMP_LIST_FIRSTPRIVATE; list <= OMP_LIST_LASTPRIVATE;
9615 64942 : list = gfc_omp_list_type (list + 1))
9616 69103 : for (n = omp_clauses->lists[list]; n; n = n->next)
9617 4161 : if (n->sym->data_mark || n->sym->gen_mark || n->sym->dev_mark)
9618 : {
9619 9 : gfc_error ("Symbol %qs present on multiple clauses at %L",
9620 : n->sym->name, &n->where);
9621 9 : n->sym->data_mark = n->sym->gen_mark = n->sym->dev_mark = 0;
9622 : }
9623 4152 : else if (n->sym->mark
9624 18 : && code->op != EXEC_OMP_TARGET_TEAMS
9625 : && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE
9626 : && code->op != EXEC_OMP_TARGET_TEAMS_LOOP
9627 : && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD
9628 : && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO
9629 : && code->op != EXEC_OMP_TARGET_PARALLEL
9630 : && code->op != EXEC_OMP_TARGET_PARALLEL_DO
9631 : && code->op != EXEC_OMP_TARGET_PARALLEL_LOOP
9632 : && code->op != EXEC_OMP_TARGET_PARALLEL_DO_SIMD
9633 : && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD)
9634 7 : gfc_error ("Symbol %qs present on both data and map clauses "
9635 : "at %L", n->sym->name, &n->where);
9636 :
9637 34326 : for (n = omp_clauses->lists[OMP_LIST_FIRSTPRIVATE]; n; n = n->next)
9638 : {
9639 1855 : if (n->sym->data_mark || n->sym->gen_mark || n->sym->dev_mark)
9640 7 : gfc_error ("Symbol %qs present on multiple clauses at %L",
9641 : n->sym->name, &n->where);
9642 : else
9643 1848 : n->sym->data_mark = 1;
9644 : }
9645 34777 : for (n = omp_clauses->lists[OMP_LIST_LASTPRIVATE]; n; n = n->next)
9646 2306 : n->sym->data_mark = 0;
9647 :
9648 34777 : for (n = omp_clauses->lists[OMP_LIST_LASTPRIVATE]; n; n = n->next)
9649 : {
9650 2306 : if (n->sym->data_mark || n->sym->gen_mark || n->sym->dev_mark)
9651 0 : gfc_error ("Symbol %qs present on multiple clauses at %L",
9652 : n->sym->name, &n->where);
9653 : else
9654 2306 : n->sym->data_mark = 1;
9655 : }
9656 :
9657 32621 : for (n = omp_clauses->lists[OMP_LIST_ALIGNED]; n; n = n->next)
9658 150 : n->sym->mark = 0;
9659 :
9660 32621 : for (n = omp_clauses->lists[OMP_LIST_ALIGNED]; n; n = n->next)
9661 : {
9662 150 : if (n->sym->mark)
9663 0 : gfc_error ("Symbol %qs present on multiple clauses at %L",
9664 : n->sym->name, &n->where);
9665 : else
9666 150 : n->sym->mark = 1;
9667 : }
9668 :
9669 32471 : if (omp_clauses->lists[OMP_LIST_ALLOCATE])
9670 : {
9671 791 : for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; n = n->next)
9672 : {
9673 513 : if (n->u2.allocator
9674 513 : && (!gfc_resolve_expr (n->u2.allocator)
9675 288 : || n->u2.allocator->ts.type != BT_INTEGER
9676 286 : || n->u2.allocator->rank != 0
9677 285 : || n->u2.allocator->ts.kind != gfc_c_intptr_kind))
9678 : {
9679 8 : gfc_error ("Expected integer expression of the "
9680 : "%<omp_allocator_handle_kind%> kind at %L",
9681 8 : &n->u2.allocator->where);
9682 28 : break;
9683 : }
9684 505 : if (!n->u.align)
9685 397 : continue;
9686 108 : HOST_WIDE_INT alignment = 0;
9687 108 : if (!gfc_resolve_expr (n->u.align)
9688 108 : || n->u.align->ts.type != BT_INTEGER
9689 105 : || n->u.align->rank != 0
9690 102 : || n->u.align->expr_type != EXPR_CONSTANT
9691 99 : || gfc_extract_hwi (n->u.align, &alignment)
9692 99 : || alignment <= 0
9693 207 : || !pow2p_hwi (alignment))
9694 : {
9695 12 : gfc_error ("ALIGN requires a scalar positive constant integer "
9696 : "alignment expression at %L that is a power of two",
9697 12 : &n->u.align->where);
9698 12 : break;
9699 : }
9700 : }
9701 :
9702 : /* Check for 2 things here.
9703 : 1. There is no duplication of variable in allocate clause.
9704 : 2. Variable in allocate clause are also present in some
9705 : privatization clase (non-composite case). */
9706 811 : for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; n = n->next)
9707 513 : if (n->sym)
9708 487 : n->sym->mark = 0;
9709 :
9710 : gfc_omp_namelist *prev = NULL;
9711 811 : for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; )
9712 : {
9713 513 : if (n->sym == NULL)
9714 : {
9715 26 : n = n->next;
9716 26 : continue;
9717 : }
9718 487 : if (n->sym->mark == 1)
9719 : {
9720 3 : gfc_warning (OPT_Wopenmp, "%qs appears more than once in "
9721 : "%<allocate%> at %L" , n->sym->name, &n->where);
9722 : /* We have already seen this variable so it is a duplicate.
9723 : Remove it. */
9724 3 : if (prev != NULL && prev->next == n)
9725 : {
9726 3 : prev->next = n->next;
9727 3 : n->next = NULL;
9728 3 : gfc_free_omp_namelist (n, OMP_LIST_ALLOCATE);
9729 3 : n = prev->next;
9730 : }
9731 3 : continue;
9732 : }
9733 484 : n->sym->mark = 1;
9734 484 : prev = n;
9735 484 : n = n->next;
9736 : }
9737 :
9738 : /* Non-composite constructs. */
9739 298 : if (code && code->op < EXEC_OMP_DO_SIMD)
9740 : {
9741 4760 : for (list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
9742 4641 : list = gfc_omp_list_type (list + 1))
9743 4641 : switch (list)
9744 : {
9745 1071 : case OMP_LIST_PRIVATE:
9746 1071 : case OMP_LIST_FIRSTPRIVATE:
9747 1071 : case OMP_LIST_LASTPRIVATE:
9748 1071 : case OMP_LIST_REDUCTION:
9749 1071 : case OMP_LIST_REDUCTION_INSCAN:
9750 1071 : case OMP_LIST_REDUCTION_TASK:
9751 1071 : case OMP_LIST_IN_REDUCTION:
9752 1071 : case OMP_LIST_TASK_REDUCTION:
9753 1071 : case OMP_LIST_LINEAR:
9754 1370 : for (n = omp_clauses->lists[list]; n; n = n->next)
9755 299 : n->sym->mark = 0;
9756 : break;
9757 : default:
9758 : break;
9759 : }
9760 :
9761 410 : for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; n = n->next)
9762 291 : if (n->sym->mark == 1)
9763 4 : gfc_error ("%qs specified in %<allocate%> clause at %L but not "
9764 : "in an explicit privatization clause",
9765 : n->sym->name, &n->where);
9766 : }
9767 : if (code
9768 298 : && (code->op == EXEC_OMP_ALLOCATORS || code->op == EXEC_OMP_ALLOCATE)
9769 73 : && code->block
9770 72 : && code->block->next
9771 71 : && code->block->next->op == EXEC_ALLOCATE)
9772 : {
9773 68 : if (code->op == EXEC_OMP_ALLOCATE)
9774 49 : gfc_warning (OPT_Wdeprecated_openmp,
9775 : "The use of one or more %<allocate%> directives with "
9776 : "an associated %<allocate%> statement at %L is "
9777 : "deprecated since OpenMP 5.2, use an %<allocators%> "
9778 : "directive", &code->loc);
9779 68 : gfc_alloc *a;
9780 68 : gfc_omp_namelist *n_null = NULL;
9781 68 : bool missing_allocator = false;
9782 68 : gfc_symbol *missing_allocator_sym = NULL;
9783 161 : for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; n = n->next)
9784 : {
9785 93 : if (n->u2.allocator == NULL)
9786 : {
9787 77 : if (!missing_allocator_sym)
9788 59 : missing_allocator_sym = n->sym;
9789 : missing_allocator = true;
9790 : }
9791 93 : if (n->sym == NULL)
9792 : {
9793 26 : n_null = n;
9794 26 : continue;
9795 : }
9796 67 : if (n->sym->attr.codimension)
9797 2 : gfc_error ("Unexpected coarray %qs in %<allocate%> at %L",
9798 : n->sym->name, &n->where);
9799 103 : for (a = code->block->next->ext.alloc.list; a; a = a->next)
9800 101 : if (a->expr->expr_type == EXPR_VARIABLE
9801 101 : && a->expr->symtree->n.sym == n->sym)
9802 : {
9803 65 : gfc_ref *ref;
9804 82 : for (ref = a->expr->ref; ref; ref = ref->next)
9805 17 : if (ref->type == REF_COMPONENT)
9806 : break;
9807 : if (ref == NULL)
9808 : break;
9809 : }
9810 67 : if (a == NULL)
9811 2 : gfc_error ("%qs specified in %<allocate%> at %L but not "
9812 : "in the associated ALLOCATE statement",
9813 2 : n->sym->name, &n->where);
9814 : }
9815 : /* If there is an ALLOCATE directive without list argument, a
9816 : namelist with its allocator/align clauses and n->sym = NULL is
9817 : created during parsing; here, we add all not otherwise specified
9818 : items from the Fortran allocate to that list.
9819 : For an ALLOCATORS directive, not listed items use the normal
9820 : Fortran way.
9821 : The behavior of an ALLOCATE directive that does not list all
9822 : arguments but there is no directive without list argument is not
9823 : well specified. Thus, we reject such code below. In OpenMP 5.2
9824 : the executable ALLOCATE directive is deprecated and in 6.0
9825 : deleted such that no spec clarification is to be expected. */
9826 125 : for (a = code->block->next->ext.alloc.list; a; a = a->next)
9827 89 : if (a->expr->expr_type == EXPR_VARIABLE)
9828 : {
9829 154 : for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; n = n->next)
9830 122 : if (a->expr->symtree->n.sym == n->sym)
9831 : {
9832 57 : gfc_ref *ref;
9833 72 : for (ref = a->expr->ref; ref; ref = ref->next)
9834 15 : if (ref->type == REF_COMPONENT)
9835 : break;
9836 : if (ref == NULL)
9837 : break;
9838 : }
9839 89 : if (n == NULL && n_null == NULL)
9840 : {
9841 : /* OK for ALLOCATORS but for ALLOCATE: Unspecified whether
9842 : that should use the default allocator of OpenMP or the
9843 : Fortran allocator. Thus, just reject it. */
9844 7 : if (code->op == EXEC_OMP_ALLOCATE)
9845 1 : gfc_error ("%qs listed in %<allocate%> statement at %L "
9846 : "but it is neither explicitly in listed in "
9847 : "the %<!$OMP ALLOCATE%> directive nor exists"
9848 : " a directive without argument list",
9849 1 : a->expr->symtree->n.sym->name,
9850 : &a->expr->where);
9851 : break;
9852 : }
9853 82 : if (n == NULL)
9854 : {
9855 25 : if (a->expr->symtree->n.sym->attr.codimension)
9856 1 : gfc_error ("Unexpected coarray %qs in %<allocate%> at "
9857 : "%L, implicitly listed in %<!$OMP ALLOCATE%>"
9858 : " at %L", a->expr->symtree->n.sym->name,
9859 : &a->expr->where, &n_null->where);
9860 : break;
9861 : }
9862 : }
9863 68 : gfc_namespace *prog_unit = ns;
9864 87 : while (prog_unit->parent)
9865 : prog_unit = prog_unit->parent;
9866 : gfc_namespace *fn_ns = ns;
9867 72 : while (fn_ns)
9868 : {
9869 70 : if (ns->proc_name
9870 70 : && (ns->proc_name->attr.subroutine
9871 6 : || ns->proc_name->attr.function))
9872 : break;
9873 4 : fn_ns = fn_ns->parent;
9874 : }
9875 68 : if (missing_allocator
9876 58 : && !(prog_unit->omp_requires & OMP_REQ_DYNAMIC_ALLOCATORS)
9877 58 : && ((fn_ns && fn_ns->proc_name->attr.omp_declare_target)
9878 55 : || omp_clauses->contained_in_target_construct))
9879 : {
9880 6 : if (code->op == EXEC_OMP_ALLOCATORS)
9881 2 : gfc_error ("ALLOCATORS directive at %L inside a target region "
9882 : "must specify an ALLOCATOR modifier for %qs",
9883 : &code->loc, missing_allocator_sym->name);
9884 4 : else if (missing_allocator_sym)
9885 2 : gfc_error ("ALLOCATE directive at %L inside a target region "
9886 : "must specify an ALLOCATOR clause for %qs",
9887 : &code->loc, missing_allocator_sym->name);
9888 : else
9889 2 : gfc_error ("ALLOCATE directive at %L inside a target region "
9890 : "must specify an ALLOCATOR clause", &code->loc);
9891 : }
9892 :
9893 : }
9894 : }
9895 :
9896 : /* OpenACC reductions. */
9897 32471 : if (openacc)
9898 : {
9899 14761 : for (n = omp_clauses->lists[OMP_LIST_REDUCTION]; n; n = n->next)
9900 2136 : n->sym->mark = 0;
9901 :
9902 14761 : for (n = omp_clauses->lists[OMP_LIST_REDUCTION]; n; n = n->next)
9903 : {
9904 2136 : if (n->sym->mark)
9905 0 : gfc_error ("Symbol %qs present on multiple clauses at %L",
9906 : n->sym->name, &n->where);
9907 : else
9908 2136 : n->sym->mark = 1;
9909 :
9910 : /* OpenACC does not support reductions on arrays. */
9911 2136 : if (n->sym->as)
9912 71 : gfc_error ("Array %qs is not permitted in reduction at %L",
9913 : n->sym->name, &n->where);
9914 : }
9915 : }
9916 :
9917 33225 : for (n = omp_clauses->lists[OMP_LIST_TO]; n; n = n->next)
9918 754 : n->sym->mark = 0;
9919 33502 : for (n = omp_clauses->lists[OMP_LIST_FROM]; n; n = n->next)
9920 1031 : if (n->expr == NULL)
9921 1015 : n->sym->mark = 1;
9922 33225 : for (n = omp_clauses->lists[OMP_LIST_TO]; n; n = n->next)
9923 : {
9924 754 : if (n->expr == NULL && n->sym->mark)
9925 0 : gfc_error ("Symbol %qs present on both FROM and TO clauses at %L",
9926 : n->sym->name, &n->where);
9927 : else
9928 754 : n->sym->mark = 1;
9929 : }
9930 :
9931 : bool has_inscan = false, has_notinscan = false;
9932 1298840 : for (enum gfc_omp_list_type list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
9933 1266369 : list = gfc_omp_list_type (list + 1))
9934 1266369 : if ((n = omp_clauses->lists[list]) != NULL)
9935 : {
9936 29155 : const char *name = clause_names[list];
9937 :
9938 29155 : switch (list)
9939 : {
9940 : case OMP_LIST_COPYIN:
9941 267 : for (; n != NULL; n = n->next)
9942 : {
9943 170 : if (!n->sym->attr.threadprivate)
9944 0 : gfc_error ("Non-THREADPRIVATE object %qs in COPYIN clause"
9945 : " at %L", n->sym->name, &n->where);
9946 : }
9947 : break;
9948 83 : case OMP_LIST_COPYPRIVATE:
9949 83 : if (omp_clauses->nowait)
9950 6 : gfc_error ("NOWAIT clause must not be used with COPYPRIVATE "
9951 : "clause at %L", &n->where);
9952 376 : for (; n != NULL; n = n->next)
9953 : {
9954 293 : if (n->sym->as && n->sym->as->type == AS_ASSUMED_SIZE)
9955 0 : gfc_error ("Assumed size array %qs in COPYPRIVATE clause "
9956 : "at %L", n->sym->name, &n->where);
9957 293 : if (n->sym->attr.pointer && n->sym->attr.intent == INTENT_IN)
9958 1 : gfc_error ("INTENT(IN) POINTER %qs in COPYPRIVATE clause "
9959 : "at %L", n->sym->name, &n->where);
9960 : }
9961 : break;
9962 : case OMP_LIST_SHARED:
9963 2604 : for (; n != NULL; n = n->next)
9964 : {
9965 1642 : if (n->sym->attr.threadprivate)
9966 0 : gfc_error ("THREADPRIVATE object %qs in SHARED clause at "
9967 : "%L", n->sym->name, &n->where);
9968 1642 : if (n->sym->attr.cray_pointee)
9969 1 : gfc_error ("Cray pointee %qs in SHARED clause at %L",
9970 : n->sym->name, &n->where);
9971 1642 : if (n->sym->attr.associate_var)
9972 8 : gfc_error ("Associate name %qs in SHARED clause at %L",
9973 8 : n->sym->attr.select_type_temporary
9974 4 : ? n->sym->assoc->target->symtree->n.sym->name
9975 : : n->sym->name, &n->where);
9976 1642 : if (omp_clauses->detach
9977 1 : && n->sym == omp_clauses->detach->symtree->n.sym)
9978 1 : gfc_error ("DETACH event handle %qs in SHARED clause at %L",
9979 : n->sym->name, &n->where);
9980 : }
9981 : break;
9982 : case OMP_LIST_ALIGNED:
9983 256 : for (; n != NULL; n = n->next)
9984 : {
9985 150 : if (!n->sym->attr.pointer
9986 45 : && !n->sym->attr.allocatable
9987 30 : && !n->sym->attr.cray_pointer
9988 18 : && (n->sym->ts.type != BT_DERIVED
9989 18 : || (n->sym->ts.u.derived->from_intmod
9990 : != INTMOD_ISO_C_BINDING)
9991 18 : || (n->sym->ts.u.derived->intmod_sym_id
9992 : != ISOCBINDING_PTR)))
9993 0 : gfc_error ("%qs in ALIGNED clause must be POINTER, "
9994 : "ALLOCATABLE, Cray pointer or C_PTR at %L",
9995 : n->sym->name, &n->where);
9996 150 : else if (n->expr)
9997 : {
9998 147 : if (!gfc_resolve_expr (n->expr)
9999 147 : || n->expr->ts.type != BT_INTEGER
10000 146 : || n->expr->rank != 0
10001 146 : || n->expr->expr_type != EXPR_CONSTANT
10002 292 : || mpz_sgn (n->expr->value.integer) <= 0)
10003 4 : gfc_error ("%qs in ALIGNED clause at %L requires a scalar"
10004 : " positive constant integer alignment "
10005 4 : "expression", n->sym->name, &n->where);
10006 : }
10007 : }
10008 : break;
10009 : case OMP_LIST_AFFINITY:
10010 : case OMP_LIST_DEPEND:
10011 : case OMP_LIST_MAP:
10012 : case OMP_LIST_TO:
10013 : case OMP_LIST_FROM:
10014 : case OMP_LIST_CACHE:
10015 32966 : for (; n != NULL; n = n->next)
10016 : {
10017 20805 : if ((list == OMP_LIST_DEPEND || list == OMP_LIST_AFFINITY)
10018 1998 : && n->u2.ns && !n->u2.ns->resolved)
10019 : {
10020 56 : n->u2.ns->resolved = 1;
10021 56 : for (gfc_symbol *sym = n->u2.ns->omp_affinity_iterators;
10022 116 : sym; sym = sym->tlink)
10023 : {
10024 60 : gfc_constructor *c;
10025 60 : c = gfc_constructor_first (sym->value->value.constructor);
10026 60 : if (!gfc_resolve_expr (c->expr)
10027 60 : || c->expr->ts.type != BT_INTEGER
10028 118 : || c->expr->rank != 0)
10029 2 : gfc_error ("Scalar integer expression for range begin"
10030 2 : " expected at %L", &c->expr->where);
10031 60 : c = gfc_constructor_next (c);
10032 60 : if (!gfc_resolve_expr (c->expr)
10033 60 : || c->expr->ts.type != BT_INTEGER
10034 118 : || c->expr->rank != 0)
10035 2 : gfc_error ("Scalar integer expression for range end "
10036 2 : "expected at %L", &c->expr->where);
10037 60 : c = gfc_constructor_next (c);
10038 60 : if (c && (!gfc_resolve_expr (c->expr)
10039 16 : || c->expr->ts.type != BT_INTEGER
10040 14 : || c->expr->rank != 0))
10041 2 : gfc_error ("Scalar integer expression for range step "
10042 2 : "expected at %L", &c->expr->where);
10043 58 : else if (c
10044 14 : && c->expr->expr_type == EXPR_CONSTANT
10045 12 : && mpz_cmp_si (c->expr->value.integer, 0) == 0)
10046 2 : gfc_error ("Nonzero range step expected at %L",
10047 : &c->expr->where);
10048 : }
10049 : }
10050 :
10051 1998 : if (list == OMP_LIST_DEPEND)
10052 : {
10053 3196 : if (n->u.depend_doacross_op == OMP_DEPEND_SINK_FIRST
10054 : || n->u.depend_doacross_op == OMP_DOACROSS_SINK_FIRST
10055 1963 : || n->u.depend_doacross_op == OMP_DOACROSS_SINK)
10056 : {
10057 1233 : if (omp_clauses->doacross_source)
10058 : {
10059 0 : gfc_error ("Dependence-type SINK used together with"
10060 : " SOURCE on the same construct at %L",
10061 : &n->where);
10062 0 : omp_clauses->doacross_source = false;
10063 : }
10064 1233 : else if (n->expr)
10065 : {
10066 571 : if (!gfc_resolve_expr (n->expr)
10067 571 : || n->expr->ts.type != BT_INTEGER
10068 1142 : || n->expr->rank != 0)
10069 0 : gfc_error ("SINK addend not a constant integer "
10070 : "at %L", &n->where);
10071 : }
10072 1233 : if (n->sym == NULL
10073 4 : && (n->expr == NULL
10074 3 : || mpz_cmp_si (n->expr->value.integer, -1) != 0))
10075 2 : gfc_error ("omp_cur_iteration at %L requires %<-1%> "
10076 : "as logical offset", &n->where);
10077 1233 : continue;
10078 : }
10079 730 : else if (n->u.depend_doacross_op == OMP_DEPEND_DEPOBJ
10080 38 : && !n->expr
10081 22 : && (n->sym->ts.type != BT_INTEGER
10082 22 : || n->sym->ts.kind
10083 22 : != 2 * gfc_index_integer_kind
10084 22 : || n->sym->attr.dimension))
10085 0 : gfc_error ("Locator %qs at %L in DEPEND clause of depobj "
10086 : "type shall be a scalar integer of "
10087 : "OMP_DEPEND_KIND kind", n->sym->name,
10088 : &n->where);
10089 730 : else if (n->u.depend_doacross_op == OMP_DEPEND_DEPOBJ
10090 38 : && n->expr
10091 746 : && (!gfc_resolve_expr (n->expr)
10092 16 : || n->expr->ts.type != BT_INTEGER
10093 16 : || n->expr->ts.kind
10094 16 : != 2 * gfc_index_integer_kind
10095 16 : || n->expr->rank != 0))
10096 0 : gfc_error ("Locator at %L in DEPEND clause of depobj "
10097 : "type shall be a scalar integer of "
10098 0 : "OMP_DEPEND_KIND kind", &n->expr->where);
10099 : }
10100 19572 : gfc_ref *lastref = NULL, *lastslice = NULL;
10101 19572 : bool resolved = false;
10102 19572 : if (n->expr)
10103 : {
10104 6462 : lastref = n->expr->ref;
10105 6462 : resolved = gfc_resolve_expr (n->expr);
10106 :
10107 : /* Look through component refs to find last array
10108 : reference. */
10109 6462 : if (resolved)
10110 : {
10111 16305 : for (gfc_ref *ref = n->expr->ref; ref; ref = ref->next)
10112 9861 : if (ref->type == REF_COMPONENT
10113 : || ref->type == REF_SUBSTRING
10114 9861 : || ref->type == REF_INQUIRY)
10115 : lastref = ref;
10116 6678 : else if (ref->type == REF_ARRAY)
10117 : {
10118 14046 : for (int i = 0; i < ref->u.ar.dimen; i++)
10119 7368 : if (ref->u.ar.dimen_type[i] == DIMEN_RANGE)
10120 6214 : lastslice = ref;
10121 :
10122 : lastref = ref;
10123 : }
10124 :
10125 : /* The "!$acc cache" directive allows rectangular
10126 : subarrays to be specified, with some restrictions
10127 : on the form of bounds (not implemented).
10128 : Only raise an error here if we're really sure the
10129 : array isn't contiguous. An expression such as
10130 : arr(-n:n,-n:n) could be contiguous even if it looks
10131 : like it may not be. */
10132 6444 : if (code
10133 6443 : && code->op != EXEC_OACC_UPDATE
10134 5661 : && list != OMP_LIST_CACHE
10135 5661 : && list != OMP_LIST_DEPEND
10136 5339 : && !gfc_is_simply_contiguous (n->expr, false, true)
10137 1467 : && gfc_is_not_contiguous (n->expr)
10138 6457 : && !(lastslice
10139 13 : && (lastslice->next
10140 3 : || lastslice->type != REF_ARRAY)))
10141 3 : gfc_error ("Array is not contiguous at %L",
10142 : &n->where);
10143 : }
10144 : }
10145 19572 : if (list == OMP_LIST_MAP
10146 16921 : && (n->sym->attr.omp_groupprivate
10147 16920 : || n->sym->attr.omp_declare_target_local))
10148 2 : gfc_error ("%qs argument to MAP clause at %L must not be a "
10149 : "device-local variable, including GROUPPRIVATE",
10150 : n->sym->name, &n->where);
10151 19572 : if (openacc
10152 19572 : && list == OMP_LIST_MAP
10153 9571 : && (n->u.map.op == OMP_MAP_ATTACH
10154 9501 : || n->u.map.op == OMP_MAP_DETACH))
10155 : {
10156 117 : symbol_attribute attr;
10157 117 : if (n->expr)
10158 99 : attr = gfc_expr_attr (n->expr);
10159 : else
10160 18 : attr = n->sym->attr;
10161 117 : if (!attr.pointer && !attr.allocatable)
10162 7 : gfc_error ("%qs clause argument must be ALLOCATABLE or "
10163 : "a POINTER at %L",
10164 7 : (n->u.map.op == OMP_MAP_ATTACH) ? "attach"
10165 : : "detach", &n->where);
10166 : }
10167 19572 : if (lastref
10168 13122 : || (n->expr
10169 12 : && (!resolved || n->expr->expr_type != EXPR_VARIABLE)))
10170 : {
10171 6462 : if (!lastslice
10172 6462 : && lastref
10173 898 : && lastref->type == REF_SUBSTRING)
10174 11 : gfc_error ("Unexpected substring reference in %s clause "
10175 : "at %L", name, &n->where);
10176 6451 : else if (!lastslice
10177 : && lastref
10178 887 : && lastref->type == REF_INQUIRY)
10179 : {
10180 12 : gcc_assert (lastref->u.i == INQUIRY_RE
10181 : || lastref->u.i == INQUIRY_IM);
10182 12 : gfc_error ("Unexpected complex-parts designator "
10183 : "reference in %s clause at %L",
10184 : name, &n->where);
10185 : }
10186 6439 : else if (!resolved
10187 6421 : || n->expr->expr_type != EXPR_VARIABLE
10188 6409 : || (lastslice
10189 5552 : && (lastslice->next
10190 5536 : || lastslice->type != REF_ARRAY)))
10191 46 : gfc_error ("%qs in %s clause at %L is not a proper "
10192 46 : "array section", n->sym->name, name,
10193 : &n->where);
10194 : else if (lastslice)
10195 : {
10196 : int i;
10197 : gfc_array_ref *ar = &lastslice->u.ar;
10198 11747 : for (i = 0; i < ar->dimen; i++)
10199 6212 : if (ar->stride[i] && code->op != EXEC_OACC_UPDATE)
10200 : {
10201 1 : gfc_error ("Stride should not be specified for "
10202 : "array section in %s clause at %L",
10203 : name, &n->where);
10204 1 : break;
10205 : }
10206 6211 : else if (ar->dimen_type[i] != DIMEN_ELEMENT
10207 6211 : && ar->dimen_type[i] != DIMEN_RANGE)
10208 : {
10209 0 : gfc_error ("%qs in %s clause at %L is not a "
10210 : "proper array section",
10211 0 : n->sym->name, name, &n->where);
10212 0 : break;
10213 : }
10214 6211 : else if ((list == OMP_LIST_DEPEND
10215 : || list == OMP_LIST_AFFINITY)
10216 161 : && ar->start[i]
10217 133 : && ar->start[i]->expr_type == EXPR_CONSTANT
10218 97 : && ar->end[i]
10219 72 : && ar->end[i]->expr_type == EXPR_CONSTANT
10220 72 : && mpz_cmp (ar->start[i]->value.integer,
10221 72 : ar->end[i]->value.integer) > 0)
10222 : {
10223 0 : gfc_error ("%qs in %s clause at %L is a "
10224 : "zero size array section",
10225 0 : n->sym->name,
10226 : list == OMP_LIST_DEPEND
10227 : ? "DEPEND" : "AFFINITY", &n->where);
10228 0 : break;
10229 : }
10230 : }
10231 : }
10232 13110 : else if (openacc)
10233 : {
10234 5915 : if (list == OMP_LIST_MAP
10235 5900 : && n->u.map.op == OMP_MAP_FORCE_DEVICEPTR)
10236 65 : resolve_oacc_deviceptr_clause (n->sym, n->where, name);
10237 : else
10238 5850 : resolve_oacc_data_clauses (n->sym, n->where, name);
10239 : }
10240 7195 : else if (list != OMP_LIST_DEPEND
10241 6702 : && n->sym->as
10242 3331 : && n->sym->as->type == AS_ASSUMED_SIZE)
10243 5 : gfc_error ("Assumed size array %qs in %s clause at %L",
10244 : n->sym->name, name, &n->where);
10245 19572 : if (code && list == OMP_LIST_MAP && !openacc)
10246 7343 : switch (code->op)
10247 : {
10248 6085 : case EXEC_OMP_TARGET:
10249 6085 : case EXEC_OMP_TARGET_PARALLEL:
10250 6085 : case EXEC_OMP_TARGET_PARALLEL_DO:
10251 6085 : case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
10252 6085 : case EXEC_OMP_TARGET_PARALLEL_LOOP:
10253 6085 : case EXEC_OMP_TARGET_SIMD:
10254 6085 : case EXEC_OMP_TARGET_TEAMS:
10255 6085 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
10256 6085 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
10257 6085 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
10258 6085 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
10259 6085 : case EXEC_OMP_TARGET_TEAMS_LOOP:
10260 6085 : case EXEC_OMP_TARGET_DATA:
10261 6085 : switch (n->u.map.op)
10262 : {
10263 : case OMP_MAP_TO:
10264 : case OMP_MAP_ALWAYS_TO:
10265 : case OMP_MAP_PRESENT_TO:
10266 : case OMP_MAP_ALWAYS_PRESENT_TO:
10267 : case OMP_MAP_FROM:
10268 : case OMP_MAP_ALWAYS_FROM:
10269 : case OMP_MAP_PRESENT_FROM:
10270 : case OMP_MAP_ALWAYS_PRESENT_FROM:
10271 : case OMP_MAP_TOFROM:
10272 : case OMP_MAP_ALWAYS_TOFROM:
10273 : case OMP_MAP_PRESENT_TOFROM:
10274 : case OMP_MAP_ALWAYS_PRESENT_TOFROM:
10275 : case OMP_MAP_ALLOC:
10276 : case OMP_MAP_PRESENT_ALLOC:
10277 : break;
10278 2 : default:
10279 2 : gfc_error ("TARGET%s with map-type other than TO, "
10280 : "FROM, TOFROM, or ALLOC on MAP clause "
10281 : "at %L",
10282 : code->op == EXEC_OMP_TARGET_DATA
10283 : ? " DATA" : "", &n->where);
10284 2 : break;
10285 : }
10286 : break;
10287 681 : case EXEC_OMP_TARGET_ENTER_DATA:
10288 681 : switch (n->u.map.op)
10289 : {
10290 : case OMP_MAP_TO:
10291 : case OMP_MAP_ALWAYS_TO:
10292 : case OMP_MAP_PRESENT_TO:
10293 : case OMP_MAP_ALWAYS_PRESENT_TO:
10294 : case OMP_MAP_ALLOC:
10295 : case OMP_MAP_PRESENT_ALLOC:
10296 : break;
10297 177 : case OMP_MAP_TOFROM:
10298 177 : n->u.map.op = OMP_MAP_TO;
10299 177 : break;
10300 3 : case OMP_MAP_ALWAYS_TOFROM:
10301 3 : n->u.map.op = OMP_MAP_ALWAYS_TO;
10302 3 : break;
10303 2 : case OMP_MAP_PRESENT_TOFROM:
10304 2 : n->u.map.op = OMP_MAP_PRESENT_TO;
10305 2 : break;
10306 2 : case OMP_MAP_ALWAYS_PRESENT_TOFROM:
10307 2 : n->u.map.op = OMP_MAP_ALWAYS_PRESENT_TO;
10308 2 : break;
10309 2 : default:
10310 2 : gfc_error ("TARGET ENTER DATA with map-type other "
10311 : "than TO, TOFROM or ALLOC on MAP clause "
10312 : "at %L", &n->where);
10313 2 : break;
10314 : }
10315 : break;
10316 577 : case EXEC_OMP_TARGET_EXIT_DATA:
10317 577 : switch (n->u.map.op)
10318 : {
10319 : case OMP_MAP_FROM:
10320 : case OMP_MAP_ALWAYS_FROM:
10321 : case OMP_MAP_PRESENT_FROM:
10322 : case OMP_MAP_ALWAYS_PRESENT_FROM:
10323 : case OMP_MAP_RELEASE:
10324 : case OMP_MAP_DELETE:
10325 : break;
10326 132 : case OMP_MAP_TOFROM:
10327 132 : n->u.map.op = OMP_MAP_FROM;
10328 132 : break;
10329 1 : case OMP_MAP_ALWAYS_TOFROM:
10330 1 : n->u.map.op = OMP_MAP_ALWAYS_FROM;
10331 1 : break;
10332 0 : case OMP_MAP_PRESENT_TOFROM:
10333 0 : n->u.map.op = OMP_MAP_PRESENT_FROM;
10334 0 : break;
10335 0 : case OMP_MAP_ALWAYS_PRESENT_TOFROM:
10336 0 : n->u.map.op = OMP_MAP_ALWAYS_PRESENT_FROM;
10337 0 : break;
10338 2 : default:
10339 2 : gfc_error ("TARGET EXIT DATA with map-type other "
10340 : "than FROM, TOFROM, RELEASE, or DELETE on "
10341 : "MAP clause at %L", &n->where);
10342 2 : break;
10343 : }
10344 : break;
10345 : default:
10346 : break;
10347 : }
10348 : }
10349 :
10350 12161 : if (list != OMP_LIST_DEPEND)
10351 30156 : for (n = omp_clauses->lists[list]; n != NULL; n = n->next)
10352 : {
10353 18842 : n->sym->attr.referenced = 1;
10354 18842 : if (n->sym->attr.threadprivate)
10355 1 : gfc_error ("THREADPRIVATE object %qs in %s clause at %L",
10356 : n->sym->name, name, &n->where);
10357 18842 : if (n->sym->attr.cray_pointee)
10358 14 : gfc_error ("Cray pointee %qs in %s clause at %L",
10359 : n->sym->name, name, &n->where);
10360 : }
10361 : break;
10362 : case OMP_LIST_IS_DEVICE_PTR:
10363 : last = NULL;
10364 377 : for (n = omp_clauses->lists[list]; n != NULL; )
10365 : {
10366 257 : if ((n->sym->ts.type != BT_DERIVED
10367 71 : || !n->sym->ts.u.derived->ts.is_iso_c
10368 71 : || (n->sym->ts.u.derived->intmod_sym_id
10369 : != ISOCBINDING_PTR))
10370 187 : && code->op == EXEC_OMP_DISPATCH)
10371 : /* Non-TARGET (i.e. DISPATCH) requires a C_PTR. */
10372 3 : gfc_error ("List item %qs in %s clause at %L must be of "
10373 : "TYPE(C_PTR)", n->sym->name, name, &n->where);
10374 254 : else if (n->sym->ts.type != BT_DERIVED
10375 70 : || !n->sym->ts.u.derived->ts.is_iso_c
10376 70 : || (n->sym->ts.u.derived->intmod_sym_id
10377 : != ISOCBINDING_PTR))
10378 : {
10379 : /* For TARGET, non-C_PTR are deprecated and handled as
10380 : has_device_addr. */
10381 184 : gfc_warning (OPT_Wdeprecated_openmp,
10382 : "Non-C_PTR type argument at %L is deprecated, "
10383 : "use HAS_DEVICE_ADDR", &n->where);
10384 184 : gfc_omp_namelist *n2 = n;
10385 184 : n = n->next;
10386 184 : if (last)
10387 0 : last->next = n;
10388 : else
10389 184 : omp_clauses->lists[list] = n;
10390 184 : n2->next = omp_clauses->lists[OMP_LIST_HAS_DEVICE_ADDR];
10391 184 : omp_clauses->lists[OMP_LIST_HAS_DEVICE_ADDR] = n2;
10392 184 : continue;
10393 184 : }
10394 73 : last = n;
10395 73 : n = n->next;
10396 : }
10397 : break;
10398 : case OMP_LIST_HAS_DEVICE_ADDR:
10399 : case OMP_LIST_USE_DEVICE_ADDR:
10400 : break;
10401 : case OMP_LIST_USE_DEVICE_PTR:
10402 : /* Non-C_PTR are deprecated and handled as use_device_ADDR. */
10403 : last = NULL;
10404 475 : for (n = omp_clauses->lists[list]; n != NULL; )
10405 : {
10406 312 : gfc_omp_namelist *n2 = n;
10407 312 : if (n->sym->ts.type != BT_DERIVED
10408 18 : || !n->sym->ts.u.derived->ts.is_iso_c)
10409 : {
10410 294 : gfc_warning (OPT_Wdeprecated_openmp,
10411 : "Non-C_PTR type argument at %L is "
10412 : "deprecated, use USE_DEVICE_ADDR", &n->where);
10413 294 : n = n->next;
10414 294 : if (last)
10415 0 : last->next = n;
10416 : else
10417 294 : omp_clauses->lists[list] = n;
10418 294 : n2->next = omp_clauses->lists[OMP_LIST_USE_DEVICE_ADDR];
10419 294 : omp_clauses->lists[OMP_LIST_USE_DEVICE_ADDR] = n2;
10420 294 : continue;
10421 : }
10422 18 : last = n;
10423 18 : n = n->next;
10424 : }
10425 : break;
10426 48 : case OMP_LIST_USES_ALLOCATORS:
10427 48 : {
10428 48 : if (n != NULL
10429 48 : && n->u.memspace_sym
10430 14 : && (n->u.memspace_sym->attr.flavor != FL_PARAMETER
10431 13 : || n->u.memspace_sym->ts.type != BT_INTEGER
10432 13 : || n->u.memspace_sym->ts.kind != gfc_c_intptr_kind
10433 13 : || n->u.memspace_sym->attr.dimension
10434 13 : || (!startswith (n->u.memspace_sym->name, "omp_")
10435 0 : && !startswith (n->u.memspace_sym->name, "ompx_"))
10436 13 : || !endswith (n->u.memspace_sym->name, "_mem_space")))
10437 2 : gfc_error ("Memspace %qs at %L in USES_ALLOCATORS must be "
10438 : "a predefined memory space",
10439 : n->u.memspace_sym->name, &n->where);
10440 144 : for (; n != NULL; n = n->next)
10441 : {
10442 102 : if (n->sym->ts.type != BT_INTEGER
10443 102 : || n->sym->ts.kind != gfc_c_intptr_kind
10444 101 : || n->sym->attr.dimension)
10445 2 : gfc_error ("Allocator %qs at %L in USES_ALLOCATORS must "
10446 : "be a scalar integer of kind "
10447 : "%<omp_allocator_handle_kind%>", n->sym->name,
10448 : &n->where);
10449 100 : else if (n->sym->attr.flavor != FL_VARIABLE
10450 47 : && strcmp (n->sym->name, "omp_null_allocator") != 0
10451 144 : && ((!startswith (n->sym->name, "omp_")
10452 1 : && !startswith (n->sym->name, "ompx_"))
10453 43 : || !endswith (n->sym->name, "_mem_alloc")))
10454 2 : gfc_error ("Allocator %qs at %L in USES_ALLOCATORS must "
10455 : "either a variable or a predefined allocator",
10456 : n->sym->name, &n->where);
10457 98 : else if ((n->u.memspace_sym || n->u2.traits_sym)
10458 47 : && n->sym->attr.flavor != FL_VARIABLE)
10459 3 : gfc_error ("A memory space or traits array may not be "
10460 : "specified for predefined allocator %qs at %L",
10461 : n->sym->name, &n->where);
10462 102 : if (n->u2.traits_sym
10463 41 : && (n->u2.traits_sym->attr.flavor != FL_PARAMETER
10464 39 : || !n->u2.traits_sym->attr.dimension
10465 37 : || n->u2.traits_sym->as->rank != 1
10466 37 : || n->u2.traits_sym->ts.type != BT_DERIVED
10467 35 : || strcmp (n->u2.traits_sym->ts.u.derived->name,
10468 : "omp_alloctrait") != 0))
10469 : {
10470 6 : gfc_error ("Traits array %qs in USES_ALLOCATORS %L must "
10471 : "be a one-dimensional named constant array of "
10472 : "type %<omp_alloctrait%>",
10473 : n->u2.traits_sym->name, &n->where);
10474 6 : break;
10475 : }
10476 : }
10477 : break;
10478 : }
10479 : default:
10480 34670 : for (; n != NULL; n = n->next)
10481 : {
10482 20309 : if (n->sym == NULL)
10483 : {
10484 26 : gcc_assert (code->op == EXEC_OMP_ALLOCATORS
10485 : || code->op == EXEC_OMP_ALLOCATE);
10486 26 : continue;
10487 : }
10488 20283 : bool bad = false;
10489 20283 : bool is_reduction = (list == OMP_LIST_REDUCTION
10490 : || list == OMP_LIST_REDUCTION_INSCAN
10491 : || list == OMP_LIST_REDUCTION_TASK
10492 : || list == OMP_LIST_IN_REDUCTION
10493 20283 : || list == OMP_LIST_TASK_REDUCTION);
10494 20283 : if (list == OMP_LIST_REDUCTION_INSCAN)
10495 : has_inscan = true;
10496 20211 : else if (is_reduction)
10497 4734 : has_notinscan = true;
10498 20283 : if (has_inscan && has_notinscan && is_reduction)
10499 : {
10500 3 : gfc_error ("%<inscan%> and non-%<inscan%> %<reduction%> "
10501 : "clauses on the same construct at %L",
10502 : &n->where);
10503 3 : break;
10504 : }
10505 20280 : if (n->sym->attr.threadprivate)
10506 1 : gfc_error ("THREADPRIVATE object %qs in %s clause at %L",
10507 : n->sym->name, name, &n->where);
10508 20280 : if (n->sym->attr.cray_pointee)
10509 14 : gfc_error ("Cray pointee %qs in %s clause at %L",
10510 : n->sym->name, name, &n->where);
10511 20280 : if (n->sym->attr.associate_var)
10512 22 : gfc_error ("Associate name %qs in %s clause at %L",
10513 22 : n->sym->attr.select_type_temporary
10514 4 : ? n->sym->assoc->target->symtree->n.sym->name
10515 : : n->sym->name, name, &n->where);
10516 20280 : if (list != OMP_LIST_PRIVATE && is_reduction)
10517 : {
10518 4803 : if (n->sym->attr.proc_pointer)
10519 1 : gfc_error ("Procedure pointer %qs in %s clause at %L",
10520 : n->sym->name, name, &n->where);
10521 4803 : if (n->sym->attr.pointer)
10522 3 : gfc_error ("POINTER object %qs in %s clause at %L",
10523 : n->sym->name, name, &n->where);
10524 4803 : if (n->sym->attr.cray_pointer)
10525 5 : gfc_error ("Cray pointer %qs in %s clause at %L",
10526 : n->sym->name, name, &n->where);
10527 : }
10528 20280 : if (code
10529 20280 : && (oacc_is_loop (code)
10530 : || code->op == EXEC_OACC_PARALLEL
10531 : || code->op == EXEC_OACC_SERIAL))
10532 8741 : check_array_not_assumed (n->sym, n->where, name);
10533 11539 : else if (list != OMP_LIST_UNIFORM
10534 11422 : && n->sym->as && n->sym->as->type == AS_ASSUMED_SIZE)
10535 2 : gfc_error ("Assumed size array %qs in %s clause at %L",
10536 : n->sym->name, name, &n->where);
10537 20280 : if (n->sym->attr.in_namelist && !is_reduction)
10538 0 : gfc_error ("Variable %qs in %s clause is used in "
10539 : "NAMELIST statement at %L",
10540 : n->sym->name, name, &n->where);
10541 20280 : if (n->sym->attr.pointer && n->sym->attr.intent == INTENT_IN)
10542 3 : switch (list)
10543 : {
10544 3 : case OMP_LIST_PRIVATE:
10545 3 : case OMP_LIST_LASTPRIVATE:
10546 3 : case OMP_LIST_LINEAR:
10547 : /* case OMP_LIST_REDUCTION: */
10548 3 : gfc_error ("INTENT(IN) POINTER %qs in %s clause at %L",
10549 : n->sym->name, name, &n->where);
10550 3 : break;
10551 : default:
10552 : break;
10553 : }
10554 20280 : if (omp_clauses->detach
10555 3 : && (list == OMP_LIST_PRIVATE
10556 : || list == OMP_LIST_FIRSTPRIVATE
10557 : || list == OMP_LIST_LASTPRIVATE)
10558 3 : && n->sym == omp_clauses->detach->symtree->n.sym)
10559 1 : gfc_error ("DETACH event handle %qs in %s clause at %L",
10560 : n->sym->name, name, &n->where);
10561 :
10562 20280 : if (!openacc
10563 20280 : && (list == OMP_LIST_PRIVATE
10564 20280 : || list == OMP_LIST_FIRSTPRIVATE)
10565 4640 : && ((n->sym->ts.type == BT_DERIVED
10566 158 : && n->sym->ts.u.derived->attr.alloc_comp)
10567 4530 : || n->sym->ts.type == BT_CLASS))
10568 170 : switch (code->op)
10569 : {
10570 8 : case EXEC_OMP_TARGET:
10571 8 : case EXEC_OMP_TARGET_PARALLEL:
10572 8 : case EXEC_OMP_TARGET_PARALLEL_DO:
10573 8 : case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
10574 8 : case EXEC_OMP_TARGET_PARALLEL_LOOP:
10575 8 : case EXEC_OMP_TARGET_SIMD:
10576 8 : case EXEC_OMP_TARGET_TEAMS:
10577 8 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
10578 8 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
10579 8 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
10580 8 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
10581 8 : case EXEC_OMP_TARGET_TEAMS_LOOP:
10582 8 : if (n->sym->ts.type == BT_DERIVED
10583 2 : && n->sym->ts.u.derived->attr.alloc_comp)
10584 3 : gfc_error ("Sorry, list item %qs at %L with allocatable"
10585 : " components is not yet supported in %s "
10586 : "clause", n->sym->name, &n->where,
10587 : list == OMP_LIST_PRIVATE ? "PRIVATE"
10588 : : "FIRSTPRIVATE");
10589 : else
10590 9 : gfc_error ("Polymorphic list item %qs at %L in %s "
10591 : "clause has unspecified behavior and "
10592 : "unsupported", n->sym->name, &n->where,
10593 : list == OMP_LIST_PRIVATE ? "PRIVATE"
10594 : : "FIRSTPRIVATE");
10595 : break;
10596 : default:
10597 : break;
10598 : }
10599 :
10600 20280 : switch (list)
10601 : {
10602 104 : case OMP_LIST_REDUCTION_TASK:
10603 104 : if (code
10604 104 : && (code->op == EXEC_OMP_LOOP
10605 : || code->op == EXEC_OMP_TASKLOOP
10606 : || code->op == EXEC_OMP_TASKLOOP_SIMD
10607 : || code->op == EXEC_OMP_MASKED_TASKLOOP
10608 : || code->op == EXEC_OMP_MASKED_TASKLOOP_SIMD
10609 : || code->op == EXEC_OMP_MASTER_TASKLOOP
10610 : || code->op == EXEC_OMP_MASTER_TASKLOOP_SIMD
10611 : || code->op == EXEC_OMP_PARALLEL_LOOP
10612 : || code->op == EXEC_OMP_PARALLEL_MASKED_TASKLOOP
10613 : || code->op == EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD
10614 : || code->op == EXEC_OMP_PARALLEL_MASTER_TASKLOOP
10615 : || code->op == EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD
10616 : || code->op == EXEC_OMP_TARGET_PARALLEL_LOOP
10617 : || code->op == EXEC_OMP_TARGET_TEAMS_LOOP
10618 : || code->op == EXEC_OMP_TEAMS
10619 : || code->op == EXEC_OMP_TEAMS_DISTRIBUTE
10620 : || code->op == EXEC_OMP_TEAMS_LOOP))
10621 : {
10622 17 : gfc_error ("Only DEFAULT permitted as reduction-"
10623 : "modifier in REDUCTION clause at %L",
10624 : &n->where);
10625 17 : break;
10626 : }
10627 4786 : gcc_fallthrough ();
10628 4786 : case OMP_LIST_REDUCTION:
10629 4786 : case OMP_LIST_IN_REDUCTION:
10630 4786 : case OMP_LIST_TASK_REDUCTION:
10631 4786 : case OMP_LIST_REDUCTION_INSCAN:
10632 4786 : switch (n->u.reduction_op)
10633 : {
10634 2652 : case OMP_REDUCTION_PLUS:
10635 2652 : case OMP_REDUCTION_TIMES:
10636 2652 : case OMP_REDUCTION_MINUS:
10637 2652 : if (!gfc_numeric_ts (&n->sym->ts))
10638 : bad = true;
10639 : break;
10640 1112 : case OMP_REDUCTION_AND:
10641 1112 : case OMP_REDUCTION_OR:
10642 1112 : case OMP_REDUCTION_EQV:
10643 1112 : case OMP_REDUCTION_NEQV:
10644 1112 : if (n->sym->ts.type != BT_LOGICAL)
10645 : bad = true;
10646 : break;
10647 480 : case OMP_REDUCTION_MAX:
10648 480 : case OMP_REDUCTION_MIN:
10649 480 : if (n->sym->ts.type != BT_INTEGER
10650 212 : && n->sym->ts.type != BT_REAL)
10651 : bad = true;
10652 : break;
10653 192 : case OMP_REDUCTION_IAND:
10654 192 : case OMP_REDUCTION_IOR:
10655 192 : case OMP_REDUCTION_IEOR:
10656 192 : if (n->sym->ts.type != BT_INTEGER)
10657 : bad = true;
10658 : break;
10659 : case OMP_REDUCTION_USER:
10660 : bad = true;
10661 : break;
10662 : default:
10663 : break;
10664 : }
10665 : if (!bad)
10666 4215 : n->u2.udr = NULL;
10667 : else
10668 : {
10669 571 : const char *udr_name = NULL;
10670 571 : if (n->u2.udr)
10671 : {
10672 467 : udr_name = n->u2.udr->udr->name;
10673 467 : n->u2.udr->udr
10674 934 : = gfc_find_omp_udr (NULL, udr_name,
10675 467 : &n->sym->ts);
10676 467 : if (n->u2.udr->udr == NULL)
10677 : {
10678 0 : free (n->u2.udr);
10679 0 : n->u2.udr = NULL;
10680 : }
10681 : }
10682 571 : if (n->u2.udr == NULL)
10683 : {
10684 104 : if (udr_name == NULL)
10685 104 : switch (n->u.reduction_op)
10686 : {
10687 50 : case OMP_REDUCTION_PLUS:
10688 50 : case OMP_REDUCTION_TIMES:
10689 50 : case OMP_REDUCTION_MINUS:
10690 50 : case OMP_REDUCTION_AND:
10691 50 : case OMP_REDUCTION_OR:
10692 50 : case OMP_REDUCTION_EQV:
10693 50 : case OMP_REDUCTION_NEQV:
10694 50 : udr_name = gfc_op2string ((gfc_intrinsic_op)
10695 : n->u.reduction_op);
10696 50 : break;
10697 : case OMP_REDUCTION_MAX:
10698 : udr_name = "max";
10699 : break;
10700 9 : case OMP_REDUCTION_MIN:
10701 9 : udr_name = "min";
10702 9 : break;
10703 12 : case OMP_REDUCTION_IAND:
10704 12 : udr_name = "iand";
10705 12 : break;
10706 12 : case OMP_REDUCTION_IOR:
10707 12 : udr_name = "ior";
10708 12 : break;
10709 9 : case OMP_REDUCTION_IEOR:
10710 9 : udr_name = "ieor";
10711 9 : break;
10712 0 : default:
10713 0 : gcc_unreachable ();
10714 : }
10715 104 : gfc_error ("!$OMP DECLARE REDUCTION %s not found "
10716 : "for type %s at %L", udr_name,
10717 104 : gfc_typename (&n->sym->ts), &n->where);
10718 : }
10719 : else
10720 : {
10721 467 : gfc_omp_udr *udr = n->u2.udr->udr;
10722 467 : n->u.reduction_op = OMP_REDUCTION_USER;
10723 467 : n->u2.udr->combiner
10724 934 : = resolve_omp_udr_clause (n, udr->combiner_ns,
10725 467 : udr->omp_out,
10726 467 : udr->omp_in);
10727 467 : if (udr->initializer_ns)
10728 330 : n->u2.udr->initializer
10729 330 : = resolve_omp_udr_clause (n,
10730 : udr->initializer_ns,
10731 330 : udr->omp_priv,
10732 330 : udr->omp_orig);
10733 : }
10734 : }
10735 : break;
10736 874 : case OMP_LIST_LINEAR:
10737 874 : if (code)
10738 : {
10739 727 : bool is_worksharing_for = false;
10740 727 : switch (code->op)
10741 : {
10742 54 : case EXEC_OMP_DO:
10743 54 : case EXEC_OMP_PARALLEL_DO:
10744 54 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
10745 54 : case EXEC_OMP_TARGET_PARALLEL_DO:
10746 54 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
10747 54 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
10748 54 : is_worksharing_for = true;
10749 54 : break;
10750 : default:
10751 : break;
10752 : }
10753 :
10754 54 : if (is_worksharing_for
10755 54 : && (n->sym->attr.dimension
10756 53 : || n->sym->attr.allocatable))
10757 : {
10758 1 : if (n->sym->attr.allocatable)
10759 0 : gfc_error ("Sorry, ALLOCATABLE object %qs in "
10760 : "LINEAR clause on worksharing-loop "
10761 : "construct at %L is not yet supported",
10762 : n->sym->name, &n->where);
10763 : else
10764 1 : gfc_error ("Sorry, array %qs in LINEAR clause "
10765 : "on worksharing-loop construct at %L "
10766 : "is not yet supported",
10767 : n->sym->name, &n->where);
10768 : break;
10769 : }
10770 : }
10771 :
10772 726 : if (code
10773 726 : && n->u.linear.op != OMP_LINEAR_DEFAULT
10774 23 : && n->u.linear.op != linear_op)
10775 : {
10776 23 : if (n->u.linear.old_modifier)
10777 : {
10778 9 : gfc_error ("LINEAR clause modifier used on DO or "
10779 : "SIMD construct at %L", &n->where);
10780 9 : linear_op = n->u.linear.op;
10781 : }
10782 14 : else if (n->u.linear.op != OMP_LINEAR_VAL)
10783 : {
10784 6 : gfc_error ("LINEAR clause modifier other than VAL "
10785 : "used on DO or SIMD construct at %L",
10786 : &n->where);
10787 6 : linear_op = n->u.linear.op;
10788 : }
10789 : }
10790 850 : else if (n->u.linear.op != OMP_LINEAR_REF
10791 800 : && n->sym->ts.type != BT_INTEGER)
10792 1 : gfc_error ("LINEAR variable %qs must be INTEGER "
10793 : "at %L", n->sym->name, &n->where);
10794 849 : else if ((n->u.linear.op == OMP_LINEAR_REF
10795 799 : || n->u.linear.op == OMP_LINEAR_UVAL)
10796 61 : && n->sym->attr.value)
10797 0 : gfc_error ("LINEAR dummy argument %qs with VALUE "
10798 : "attribute with %s modifier at %L",
10799 : n->sym->name,
10800 : n->u.linear.op == OMP_LINEAR_REF
10801 : ? "REF" : "UVAL", &n->where);
10802 849 : else if (n->expr)
10803 : {
10804 830 : gfc_expr *expr = n->expr;
10805 830 : if (!gfc_resolve_expr (expr)
10806 830 : || expr->ts.type != BT_INTEGER
10807 1660 : || expr->rank != 0)
10808 0 : gfc_error ("%qs in LINEAR clause at %L requires "
10809 : "a scalar integer linear-step expression",
10810 0 : n->sym->name, &n->where);
10811 830 : else if (!code && expr->expr_type != EXPR_CONSTANT)
10812 : {
10813 11 : if (expr->expr_type == EXPR_VARIABLE
10814 7 : && expr->symtree->n.sym->attr.dummy
10815 6 : && expr->symtree->n.sym->ns == ns)
10816 : {
10817 6 : gfc_omp_namelist *n2;
10818 6 : for (n2 = omp_clauses->lists[OMP_LIST_UNIFORM];
10819 6 : n2; n2 = n2->next)
10820 6 : if (n2->sym == expr->symtree->n.sym)
10821 : break;
10822 6 : if (n2)
10823 : break;
10824 : }
10825 5 : gfc_error ("%qs in LINEAR clause at %L requires "
10826 : "a constant integer linear-step "
10827 : "expression or dummy argument "
10828 : "specified in UNIFORM clause",
10829 5 : n->sym->name, &n->where);
10830 : }
10831 : }
10832 : break;
10833 : /* Workaround for PR middle-end/26316, nothing really needs
10834 : to be done here for OMP_LIST_PRIVATE. */
10835 9390 : case OMP_LIST_PRIVATE:
10836 9390 : gcc_assert (code && code->op != EXEC_NOP);
10837 : break;
10838 98 : case OMP_LIST_USE_DEVICE:
10839 98 : if (n->sym->attr.allocatable
10840 98 : || (n->sym->ts.type == BT_CLASS && CLASS_DATA (n->sym)
10841 0 : && CLASS_DATA (n->sym)->attr.allocatable))
10842 0 : gfc_error ("ALLOCATABLE object %qs in %s clause at %L",
10843 : n->sym->name, name, &n->where);
10844 98 : if (n->sym->ts.type == BT_CLASS
10845 0 : && CLASS_DATA (n->sym)
10846 0 : && CLASS_DATA (n->sym)->attr.class_pointer)
10847 0 : gfc_error ("POINTER object %qs of polymorphic type in "
10848 : "%s clause at %L", n->sym->name, name,
10849 : &n->where);
10850 98 : if (n->sym->attr.cray_pointer)
10851 2 : gfc_error ("Cray pointer object %qs in %s clause at %L",
10852 : n->sym->name, name, &n->where);
10853 96 : else if (n->sym->attr.cray_pointee)
10854 2 : gfc_error ("Cray pointee object %qs in %s clause at %L",
10855 : n->sym->name, name, &n->where);
10856 94 : else if (n->sym->attr.flavor == FL_VARIABLE
10857 93 : && !n->sym->as
10858 54 : && !n->sym->attr.pointer)
10859 13 : gfc_error ("%s clause variable %qs at %L is neither "
10860 : "a POINTER nor an array", name,
10861 : n->sym->name, &n->where);
10862 : /* FALLTHRU */
10863 98 : case OMP_LIST_DEVICE_RESIDENT:
10864 98 : check_symbol_not_pointer (n->sym, n->where, name);
10865 98 : check_array_not_assumed (n->sym, n->where, name);
10866 98 : break;
10867 : default:
10868 : break;
10869 : }
10870 : }
10871 : break;
10872 : }
10873 : }
10874 : /* OpenMP 5.1: use_device_ptr acts like use_device_addr, except for
10875 : type(c_ptr). */
10876 32471 : if (omp_clauses->lists[OMP_LIST_USE_DEVICE_PTR])
10877 : {
10878 9 : gfc_omp_namelist *n_prev, *n_next, *n_addr;
10879 9 : n_addr = omp_clauses->lists[OMP_LIST_USE_DEVICE_ADDR];
10880 28 : for (; n_addr && n_addr->next; n_addr = n_addr->next)
10881 : ;
10882 : n_prev = NULL;
10883 : n = omp_clauses->lists[OMP_LIST_USE_DEVICE_PTR];
10884 27 : while (n)
10885 : {
10886 18 : n_next = n->next;
10887 18 : if (n->sym->ts.type != BT_DERIVED
10888 18 : || n->sym->ts.u.derived->ts.f90_type != BT_VOID)
10889 : {
10890 0 : n->next = NULL;
10891 0 : if (n_addr)
10892 0 : n_addr->next = n;
10893 : else
10894 0 : omp_clauses->lists[OMP_LIST_USE_DEVICE_ADDR] = n;
10895 0 : n_addr = n;
10896 0 : if (n_prev)
10897 0 : n_prev->next = n_next;
10898 : else
10899 0 : omp_clauses->lists[OMP_LIST_USE_DEVICE_PTR] = n_next;
10900 : }
10901 : else
10902 : n_prev = n;
10903 : n = n_next;
10904 : }
10905 : }
10906 32471 : if (omp_clauses->safelen_expr)
10907 93 : resolve_positive_int_expr (omp_clauses->safelen_expr, "SAFELEN");
10908 32471 : if (omp_clauses->simdlen_expr)
10909 123 : resolve_positive_int_expr (omp_clauses->simdlen_expr, "SIMDLEN");
10910 32471 : if (omp_clauses->num_teams_lower)
10911 21 : resolve_positive_int_expr (omp_clauses->num_teams_lower, "NUM_TEAMS");
10912 32471 : if (omp_clauses->num_teams_upper)
10913 127 : resolve_positive_int_expr (omp_clauses->num_teams_upper, "NUM_TEAMS");
10914 32471 : if (omp_clauses->num_teams_lower
10915 21 : && omp_clauses->num_teams_lower->expr_type == EXPR_CONSTANT
10916 7 : && omp_clauses->num_teams_upper->expr_type == EXPR_CONSTANT
10917 7 : && mpz_cmp (omp_clauses->num_teams_lower->value.integer,
10918 7 : omp_clauses->num_teams_upper->value.integer) > 0)
10919 2 : gfc_warning (OPT_Wopenmp, "NUM_TEAMS lower bound at %L larger than upper "
10920 : "bound at %L", &omp_clauses->num_teams_lower->where,
10921 : &omp_clauses->num_teams_upper->where);
10922 32471 : if (omp_clauses->device)
10923 331 : resolve_scalar_int_expr (omp_clauses->device, "DEVICE");
10924 32471 : if (omp_clauses->filter)
10925 42 : resolve_nonnegative_int_expr (omp_clauses->filter, "FILTER");
10926 32471 : if (omp_clauses->hint)
10927 : {
10928 42 : resolve_scalar_int_expr (omp_clauses->hint, "HINT");
10929 42 : if (omp_clauses->hint->ts.type != BT_INTEGER
10930 40 : || omp_clauses->hint->expr_type != EXPR_CONSTANT
10931 38 : || mpz_sgn (omp_clauses->hint->value.integer) < 0)
10932 5 : gfc_error ("Value of HINT clause at %L shall be a valid "
10933 : "constant hint expression", &omp_clauses->hint->where);
10934 : }
10935 32471 : if (omp_clauses->priority)
10936 34 : resolve_nonnegative_int_expr (omp_clauses->priority, "PRIORITY");
10937 32471 : if (omp_clauses->dist_chunk_size)
10938 : {
10939 83 : gfc_expr *expr = omp_clauses->dist_chunk_size;
10940 83 : if (!gfc_resolve_expr (expr)
10941 83 : || expr->ts.type != BT_INTEGER || expr->rank != 0)
10942 0 : gfc_error ("DIST_SCHEDULE clause's chunk_size at %L requires "
10943 : "a scalar INTEGER expression", &expr->where);
10944 : }
10945 32471 : if (omp_clauses->thread_limit)
10946 72 : resolve_positive_int_expr (omp_clauses->thread_limit, "THREAD_LIMIT");
10947 32471 : if (omp_clauses->grainsize)
10948 34 : resolve_positive_int_expr (omp_clauses->grainsize, "GRAINSIZE");
10949 32471 : if (omp_clauses->num_tasks)
10950 26 : resolve_positive_int_expr (omp_clauses->num_tasks, "NUM_TASKS");
10951 32471 : if (omp_clauses->grainsize && omp_clauses->num_tasks)
10952 1 : gfc_error ("%<GRAINSIZE%> clause at %L must not be used together with "
10953 : "%<NUM_TASKS%> clause", &omp_clauses->grainsize->where);
10954 32471 : if (omp_clauses->lists[OMP_LIST_REDUCTION] && omp_clauses->nogroup)
10955 1 : gfc_error ("%<REDUCTION%> clause at %L must not be used together with "
10956 : "%<NOGROUP%> clause",
10957 : &omp_clauses->lists[OMP_LIST_REDUCTION]->where);
10958 32471 : if (omp_clauses->full && omp_clauses->partial)
10959 0 : gfc_error ("%<FULL%> clause at %C must not be used together with "
10960 : "%<PARTIAL%> clause");
10961 32471 : if (omp_clauses->async)
10962 610 : if (omp_clauses->async_expr)
10963 610 : resolve_scalar_int_expr (omp_clauses->async_expr, "ASYNC");
10964 32471 : if (omp_clauses->num_gangs_expr)
10965 682 : resolve_positive_int_expr (omp_clauses->num_gangs_expr, "NUM_GANGS");
10966 32471 : if (omp_clauses->num_workers_expr)
10967 599 : resolve_positive_int_expr (omp_clauses->num_workers_expr, "NUM_WORKERS");
10968 32471 : if (omp_clauses->vector_length_expr)
10969 569 : resolve_positive_int_expr (omp_clauses->vector_length_expr,
10970 : "VECTOR_LENGTH");
10971 32471 : if (omp_clauses->gang_num_expr)
10972 114 : resolve_positive_int_expr (omp_clauses->gang_num_expr, "GANG");
10973 32471 : if (omp_clauses->gang_static_expr)
10974 94 : resolve_positive_int_expr (omp_clauses->gang_static_expr, "GANG");
10975 32471 : if (omp_clauses->worker_expr)
10976 101 : resolve_positive_int_expr (omp_clauses->worker_expr, "WORKER");
10977 32471 : if (omp_clauses->vector_expr)
10978 132 : resolve_positive_int_expr (omp_clauses->vector_expr, "VECTOR");
10979 32810 : for (el = omp_clauses->wait_list; el; el = el->next)
10980 339 : resolve_scalar_int_expr (el->expr, "WAIT");
10981 32471 : if (omp_clauses->collapse && omp_clauses->tile_list)
10982 4 : gfc_error ("Incompatible use of TILE and COLLAPSE at %L", &code->loc);
10983 32471 : if (omp_clauses->message)
10984 : {
10985 45 : gfc_expr *expr = omp_clauses->message;
10986 45 : if (!gfc_resolve_expr (expr)
10987 45 : || expr->ts.kind != gfc_default_character_kind
10988 87 : || expr->ts.type != BT_CHARACTER || expr->rank != 0)
10989 4 : gfc_error ("MESSAGE clause at %L requires a scalar default-kind "
10990 : "CHARACTER expression", &expr->where);
10991 : }
10992 32471 : if (!openacc
10993 32471 : && code
10994 19622 : && omp_clauses->lists[OMP_LIST_MAP] == NULL
10995 15896 : && omp_clauses->lists[OMP_LIST_USE_DEVICE_PTR] == NULL
10996 15893 : && omp_clauses->lists[OMP_LIST_USE_DEVICE_ADDR] == NULL)
10997 : {
10998 15870 : const char *p = NULL;
10999 15870 : switch (code->op)
11000 : {
11001 1 : case EXEC_OMP_TARGET_ENTER_DATA: p = "TARGET ENTER DATA"; break;
11002 1 : case EXEC_OMP_TARGET_EXIT_DATA: p = "TARGET EXIT DATA"; break;
11003 : default: break;
11004 : }
11005 15870 : if (code->op == EXEC_OMP_TARGET_DATA)
11006 1 : gfc_error ("TARGET DATA must contain at least one MAP, USE_DEVICE_PTR, "
11007 : "or USE_DEVICE_ADDR clause at %L", &code->loc);
11008 15869 : else if (p)
11009 2 : gfc_error ("%s must contain at least one MAP clause at %L",
11010 : p, &code->loc);
11011 : }
11012 32471 : if (omp_clauses->sizes_list)
11013 : {
11014 : gfc_expr_list *el;
11015 572 : for (el = omp_clauses->sizes_list; el; el = el->next)
11016 : {
11017 377 : resolve_scalar_int_expr (el->expr, "SIZES");
11018 377 : if (el->expr->expr_type != EXPR_CONSTANT)
11019 1 : gfc_error ("SIZES requires constant expression at %L",
11020 : &el->expr->where);
11021 376 : else if (el->expr->expr_type == EXPR_CONSTANT
11022 376 : && el->expr->ts.type == BT_INTEGER
11023 376 : && mpz_sgn (el->expr->value.integer) <= 0)
11024 2 : gfc_error ("INTEGER expression of %s clause at %L must be "
11025 : "positive", "SIZES", &el->expr->where);
11026 : }
11027 : }
11028 :
11029 32471 : if (!openacc && omp_clauses->detach)
11030 : {
11031 125 : if (!gfc_resolve_expr (omp_clauses->detach)
11032 125 : || omp_clauses->detach->ts.type != BT_INTEGER
11033 124 : || omp_clauses->detach->ts.kind != gfc_c_intptr_kind
11034 248 : || omp_clauses->detach->rank != 0)
11035 3 : gfc_error ("%qs at %L should be a scalar of type "
11036 : "integer(kind=omp_event_handle_kind)",
11037 3 : omp_clauses->detach->symtree->n.sym->name,
11038 3 : &omp_clauses->detach->where);
11039 122 : else if (omp_clauses->detach->symtree->n.sym->attr.dimension > 0)
11040 1 : gfc_error ("The event handle at %L must not be an array element",
11041 : &omp_clauses->detach->where);
11042 121 : else if (omp_clauses->detach->symtree->n.sym->ts.type == BT_DERIVED
11043 120 : || omp_clauses->detach->symtree->n.sym->ts.type == BT_CLASS)
11044 1 : gfc_error ("The event handle at %L must not be part of "
11045 : "a derived type or class", &omp_clauses->detach->where);
11046 :
11047 125 : if (omp_clauses->mergeable)
11048 2 : gfc_error ("%<DETACH%> clause at %L must not be used together with "
11049 2 : "%<MERGEABLE%> clause", &omp_clauses->detach->where);
11050 : }
11051 :
11052 12625 : if (openacc
11053 12625 : && code->op == EXEC_OACC_HOST_DATA
11054 60 : && omp_clauses->lists[OMP_LIST_USE_DEVICE] == NULL)
11055 1 : gfc_error ("%<host_data%> construct at %L requires %<use_device%> clause",
11056 : &code->loc);
11057 :
11058 32471 : if (omp_clauses->assume)
11059 16 : gfc_resolve_omp_assumptions (omp_clauses->assume);
11060 : }
11061 :
11062 :
11063 : /* Return true if SYM is ever referenced in EXPR except in the SE node. */
11064 :
11065 : static bool
11066 4991 : expr_references_sym (gfc_expr *e, gfc_symbol *s, gfc_expr *se)
11067 : {
11068 6617 : gfc_actual_arglist *arg;
11069 6617 : if (e == NULL || e == se)
11070 : return false;
11071 5366 : switch (e->expr_type)
11072 : {
11073 3120 : case EXPR_CONSTANT:
11074 3120 : case EXPR_NULL:
11075 3120 : case EXPR_VARIABLE:
11076 3120 : case EXPR_STRUCTURE:
11077 3120 : case EXPR_ARRAY:
11078 3120 : if (e->symtree != NULL
11079 1152 : && e->symtree->n.sym == s)
11080 : return true;
11081 : return false;
11082 0 : case EXPR_SUBSTRING:
11083 0 : if (e->ref != NULL
11084 0 : && (expr_references_sym (e->ref->u.ss.start, s, se)
11085 0 : || expr_references_sym (e->ref->u.ss.end, s, se)))
11086 0 : return true;
11087 : return false;
11088 1735 : case EXPR_OP:
11089 1735 : if (expr_references_sym (e->value.op.op2, s, se))
11090 : return true;
11091 1626 : return expr_references_sym (e->value.op.op1, s, se);
11092 511 : case EXPR_FUNCTION:
11093 896 : for (arg = e->value.function.actual; arg; arg = arg->next)
11094 586 : if (expr_references_sym (arg->expr, s, se))
11095 : return true;
11096 : return false;
11097 0 : default:
11098 0 : gcc_unreachable ();
11099 : }
11100 : }
11101 :
11102 :
11103 : /* If EXPR is a conversion function that widens the type
11104 : if WIDENING is true or narrows the type if NARROW is true,
11105 : return the inner expression, otherwise return NULL. */
11106 :
11107 : static gfc_expr *
11108 5911 : is_conversion (gfc_expr *expr, bool narrowing, bool widening)
11109 : {
11110 5911 : gfc_typespec *ts1, *ts2;
11111 :
11112 5911 : if (expr->expr_type != EXPR_FUNCTION
11113 917 : || expr->value.function.isym == NULL
11114 894 : || expr->value.function.esym != NULL
11115 894 : || expr->value.function.isym->id != GFC_ISYM_CONVERSION
11116 388 : || (!narrowing && !widening))
11117 : return NULL;
11118 :
11119 388 : if (narrowing && widening)
11120 267 : return expr->value.function.actual->expr;
11121 :
11122 121 : if (widening)
11123 : {
11124 121 : ts1 = &expr->ts;
11125 121 : ts2 = &expr->value.function.actual->expr->ts;
11126 : }
11127 : else
11128 : {
11129 0 : ts1 = &expr->value.function.actual->expr->ts;
11130 0 : ts2 = &expr->ts;
11131 : }
11132 :
11133 121 : if (ts1->type > ts2->type
11134 49 : || (ts1->type == ts2->type && ts1->kind > ts2->kind))
11135 121 : return expr->value.function.actual->expr;
11136 :
11137 : return NULL;
11138 : }
11139 :
11140 : static bool
11141 6855 : is_scalar_intrinsic_expr (gfc_expr *expr, bool must_be_var, bool conv_ok)
11142 : {
11143 6855 : if (must_be_var
11144 4020 : && (expr->expr_type != EXPR_VARIABLE || !expr->symtree))
11145 : {
11146 37 : if (!conv_ok)
11147 : return false;
11148 37 : gfc_expr *conv = is_conversion (expr, true, true);
11149 37 : if (!conv)
11150 : return false;
11151 36 : if (conv->expr_type != EXPR_VARIABLE || !conv->symtree)
11152 : return false;
11153 : }
11154 6852 : return (expr->rank == 0
11155 6848 : && !gfc_is_coindexed (expr)
11156 13700 : && (expr->ts.type == BT_INTEGER
11157 : || expr->ts.type == BT_REAL
11158 : || expr->ts.type == BT_COMPLEX
11159 : || expr->ts.type == BT_LOGICAL));
11160 : }
11161 :
11162 : static void
11163 2697 : resolve_omp_atomic (gfc_code *code)
11164 : {
11165 2697 : gfc_code *atomic_code = code->block;
11166 2697 : gfc_symbol *var;
11167 2697 : gfc_expr *stmt_expr2, *capt_expr2;
11168 2697 : gfc_omp_atomic_op aop
11169 2697 : = (gfc_omp_atomic_op) (atomic_code->ext.omp_clauses->atomic_op
11170 : & GFC_OMP_ATOMIC_MASK);
11171 2697 : gfc_code *stmt = NULL, *capture_stmt = NULL, *tailing_stmt = NULL;
11172 2697 : gfc_expr *comp_cond = NULL;
11173 2697 : locus *loc = NULL;
11174 :
11175 2697 : code = code->block->next;
11176 : /* resolve_blocks asserts this is initially EXEC_ASSIGN or EXEC_IF
11177 : If it changed to EXEC_NOP, assume an error has been emitted already. */
11178 2697 : if (code->op == EXEC_NOP)
11179 : return;
11180 :
11181 2696 : if (atomic_code->ext.omp_clauses->compare
11182 156 : && atomic_code->ext.omp_clauses->capture)
11183 : {
11184 : /* Must be either "if (x == e) then; x = d; else; v = x; end if"
11185 : or "v = expr" followed/preceded by
11186 : "if (x == e) then; x = d; end if" or "if (x == e) x = d". */
11187 103 : gfc_code *next = code;
11188 103 : if (code->op == EXEC_ASSIGN)
11189 : {
11190 19 : capture_stmt = code;
11191 19 : next = code->next;
11192 : }
11193 103 : if (next->op == EXEC_IF
11194 103 : && next->block
11195 103 : && next->block->op == EXEC_IF
11196 103 : && next->block->next
11197 102 : && next->block->next->op == EXEC_ASSIGN)
11198 : {
11199 102 : comp_cond = next->block->expr1;
11200 102 : stmt = next->block->next;
11201 102 : if (stmt->next)
11202 : {
11203 0 : loc = &stmt->loc;
11204 0 : goto unexpected;
11205 : }
11206 : }
11207 1 : else if (capture_stmt)
11208 : {
11209 0 : gfc_error ("Expected IF at %L in atomic compare capture",
11210 : &next->loc);
11211 0 : return;
11212 : }
11213 103 : if (stmt && !capture_stmt && next->block->block)
11214 : {
11215 64 : if (next->block->block->expr1)
11216 : {
11217 0 : gfc_error ("Expected ELSE at %L in atomic compare capture",
11218 : &next->block->block->expr1->where);
11219 0 : return;
11220 : }
11221 64 : if (!code->block->block->next
11222 64 : || code->block->block->next->op != EXEC_ASSIGN)
11223 : {
11224 0 : loc = (code->block->block->next ? &code->block->block->next->loc
11225 : : &code->block->block->loc);
11226 0 : goto unexpected;
11227 : }
11228 64 : capture_stmt = code->block->block->next;
11229 64 : if (capture_stmt->next)
11230 : {
11231 0 : loc = &capture_stmt->next->loc;
11232 0 : goto unexpected;
11233 : }
11234 : }
11235 103 : if (stmt && !capture_stmt && next->next->op == EXEC_ASSIGN)
11236 : capture_stmt = next->next;
11237 84 : else if (!capture_stmt)
11238 : {
11239 1 : loc = &code->loc;
11240 1 : goto unexpected;
11241 : }
11242 : }
11243 2593 : else if (atomic_code->ext.omp_clauses->compare)
11244 : {
11245 : /* Must be: "if (x == e) then; x = d; end if" or "if (x == e) x = d". */
11246 53 : if (code->op == EXEC_IF
11247 53 : && code->block
11248 53 : && code->block->op == EXEC_IF
11249 53 : && code->block->next
11250 51 : && code->block->next->op == EXEC_ASSIGN)
11251 : {
11252 51 : comp_cond = code->block->expr1;
11253 51 : stmt = code->block->next;
11254 51 : if (stmt->next || code->block->block)
11255 : {
11256 0 : loc = stmt->next ? &stmt->next->loc : &code->block->block->loc;
11257 0 : goto unexpected;
11258 : }
11259 : }
11260 : else
11261 : {
11262 2 : loc = &code->loc;
11263 2 : goto unexpected;
11264 : }
11265 : }
11266 2540 : else if (atomic_code->ext.omp_clauses->capture)
11267 : {
11268 : /* Must be: "v = x" followed/preceded by "x = ...". */
11269 489 : if (code->op != EXEC_ASSIGN)
11270 0 : goto unexpected;
11271 489 : if (code->next->op != EXEC_ASSIGN)
11272 : {
11273 0 : loc = &code->next->loc;
11274 0 : goto unexpected;
11275 : }
11276 489 : gfc_expr *expr2, *expr2_next;
11277 489 : expr2 = is_conversion (code->expr2, true, true);
11278 489 : if (expr2 == NULL)
11279 447 : expr2 = code->expr2;
11280 489 : expr2_next = is_conversion (code->next->expr2, true, true);
11281 489 : if (expr2_next == NULL)
11282 478 : expr2_next = code->next->expr2;
11283 489 : if (code->expr1->expr_type == EXPR_VARIABLE
11284 489 : && code->next->expr1->expr_type == EXPR_VARIABLE
11285 489 : && expr2->expr_type == EXPR_VARIABLE
11286 243 : && expr2_next->expr_type == EXPR_VARIABLE)
11287 : {
11288 1 : if (code->expr1->symtree->n.sym == expr2_next->symtree->n.sym)
11289 : {
11290 : stmt = code;
11291 : capture_stmt = code->next;
11292 : }
11293 : else
11294 : {
11295 489 : capture_stmt = code;
11296 489 : stmt = code->next;
11297 : }
11298 : }
11299 488 : else if (expr2->expr_type == EXPR_VARIABLE)
11300 : {
11301 : capture_stmt = code;
11302 : stmt = code->next;
11303 : }
11304 : else
11305 : {
11306 247 : stmt = code;
11307 247 : capture_stmt = code->next;
11308 : }
11309 : /* Shall be NULL but can happen for invalid code. */
11310 489 : tailing_stmt = code->next->next;
11311 : }
11312 : else
11313 : {
11314 : /* x = ... */
11315 2051 : stmt = code;
11316 2051 : if (!atomic_code->ext.omp_clauses->compare && stmt->op != EXEC_ASSIGN)
11317 1 : goto unexpected;
11318 : /* Shall be NULL but can happen for invalid code. */
11319 2050 : tailing_stmt = code->next;
11320 : }
11321 :
11322 2692 : if (comp_cond)
11323 : {
11324 153 : if (comp_cond->expr_type != EXPR_OP
11325 153 : || (comp_cond->value.op.op != INTRINSIC_EQ
11326 : && comp_cond->value.op.op != INTRINSIC_EQ_OS
11327 : && comp_cond->value.op.op != INTRINSIC_EQV))
11328 : {
11329 0 : gfc_error ("Expected %<==%>, %<.EQ.%> or %<.EQV.%> atomic comparison "
11330 : "expression at %L", &comp_cond->where);
11331 0 : return;
11332 : }
11333 153 : if (!is_scalar_intrinsic_expr (comp_cond->value.op.op1, true, true))
11334 : {
11335 1 : gfc_error ("Expected scalar intrinsic variable at %L in atomic "
11336 1 : "comparison", &comp_cond->value.op.op1->where);
11337 1 : return;
11338 : }
11339 152 : if (!gfc_resolve_expr (comp_cond->value.op.op2))
11340 : return;
11341 152 : if (!is_scalar_intrinsic_expr (comp_cond->value.op.op2, false, false))
11342 : {
11343 0 : gfc_error ("Expected scalar intrinsic expression at %L in atomic "
11344 0 : "comparison", &comp_cond->value.op.op1->where);
11345 0 : return;
11346 : }
11347 : }
11348 :
11349 2691 : if (!is_scalar_intrinsic_expr (stmt->expr1, true, false))
11350 : {
11351 4 : gfc_error ("!$OMP ATOMIC statement must set a scalar variable of "
11352 4 : "intrinsic type at %L", &stmt->expr1->where);
11353 4 : return;
11354 : }
11355 :
11356 2687 : if (!gfc_resolve_expr (stmt->expr2))
11357 : return;
11358 2683 : if (!is_scalar_intrinsic_expr (stmt->expr2, false, false))
11359 : {
11360 0 : gfc_error ("!$OMP ATOMIC statement must assign an expression of "
11361 0 : "intrinsic type at %L", &stmt->expr2->where);
11362 0 : return;
11363 : }
11364 :
11365 2683 : if (gfc_expr_attr (stmt->expr1).allocatable)
11366 : {
11367 0 : gfc_error ("!$OMP ATOMIC with ALLOCATABLE variable at %L",
11368 0 : &stmt->expr1->where);
11369 0 : return;
11370 : }
11371 :
11372 : /* Should be diagnosed above already. */
11373 2683 : gcc_assert (tailing_stmt == NULL);
11374 :
11375 2683 : var = stmt->expr1->symtree->n.sym;
11376 2683 : stmt_expr2 = is_conversion (stmt->expr2, true, true);
11377 2683 : if (stmt_expr2 == NULL)
11378 2527 : stmt_expr2 = stmt->expr2;
11379 :
11380 2683 : switch (aop)
11381 : {
11382 503 : case GFC_OMP_ATOMIC_READ:
11383 503 : if (stmt_expr2->expr_type != EXPR_VARIABLE)
11384 0 : gfc_error ("!$OMP ATOMIC READ statement must read from a scalar "
11385 : "variable of intrinsic type at %L", &stmt_expr2->where);
11386 : return;
11387 421 : case GFC_OMP_ATOMIC_WRITE:
11388 421 : if (expr_references_sym (stmt_expr2, var, NULL))
11389 0 : gfc_error ("expr in !$OMP ATOMIC WRITE assignment var = expr "
11390 : "must be scalar and cannot reference var at %L",
11391 : &stmt_expr2->where);
11392 : return;
11393 1759 : default:
11394 1759 : break;
11395 : }
11396 :
11397 1759 : if (atomic_code->ext.omp_clauses->capture)
11398 : {
11399 588 : if (!is_scalar_intrinsic_expr (capture_stmt->expr1, true, false))
11400 : {
11401 0 : gfc_error ("!$OMP ATOMIC capture-statement must set a scalar "
11402 : "variable of intrinsic type at %L",
11403 0 : &capture_stmt->expr1->where);
11404 0 : return;
11405 : }
11406 :
11407 588 : if (!is_scalar_intrinsic_expr (capture_stmt->expr2, true, true))
11408 : {
11409 2 : gfc_error ("!$OMP ATOMIC capture-statement requires a scalar variable"
11410 2 : " of intrinsic type at %L", &capture_stmt->expr2->where);
11411 2 : return;
11412 : }
11413 586 : capt_expr2 = is_conversion (capture_stmt->expr2, true, true);
11414 586 : if (capt_expr2 == NULL)
11415 564 : capt_expr2 = capture_stmt->expr2;
11416 :
11417 586 : if (capt_expr2->symtree->n.sym != var)
11418 : {
11419 1 : gfc_error ("!$OMP ATOMIC CAPTURE capture statement reads from "
11420 : "different variable than update statement writes "
11421 : "into at %L", &capture_stmt->expr2->where);
11422 1 : return;
11423 : }
11424 : }
11425 :
11426 1756 : if (atomic_code->ext.omp_clauses->compare)
11427 : {
11428 149 : gfc_expr *var_expr;
11429 149 : if (comp_cond->value.op.op1->expr_type == EXPR_VARIABLE)
11430 : var_expr = comp_cond->value.op.op1;
11431 : else
11432 12 : var_expr = comp_cond->value.op.op1->value.function.actual->expr;
11433 149 : if (var_expr->symtree->n.sym != var)
11434 : {
11435 2 : gfc_error ("For !$OMP ATOMIC COMPARE, the first operand in comparison"
11436 : " at %L must be the variable %qs that the update statement"
11437 : " writes into at %L", &var_expr->where, var->name,
11438 2 : &stmt->expr1->where);
11439 2 : return;
11440 : }
11441 147 : if (stmt_expr2->rank != 0 || expr_references_sym (stmt_expr2, var, NULL))
11442 : {
11443 1 : gfc_error ("expr in !$OMP ATOMIC COMPARE assignment var = expr "
11444 : "must be scalar and cannot reference var at %L",
11445 : &stmt_expr2->where);
11446 1 : return;
11447 : }
11448 : }
11449 1607 : else if (atomic_code->ext.omp_clauses->capture
11450 1607 : && !expr_references_sym (stmt_expr2, var, NULL))
11451 22 : atomic_code->ext.omp_clauses->atomic_op
11452 22 : = (gfc_omp_atomic_op) (atomic_code->ext.omp_clauses->atomic_op
11453 : | GFC_OMP_ATOMIC_SWAP);
11454 1585 : else if (stmt_expr2->expr_type == EXPR_OP)
11455 : {
11456 1229 : gfc_expr *v = NULL, *e, *c;
11457 1229 : gfc_intrinsic_op op = stmt_expr2->value.op.op;
11458 1229 : gfc_intrinsic_op alt_op = INTRINSIC_NONE;
11459 :
11460 1229 : if (atomic_code->ext.omp_clauses->fail != OMP_MEMORDER_UNSET)
11461 3 : gfc_error ("!$OMP ATOMIC UPDATE at %L with FAIL clause requires either"
11462 : " the COMPARE clause or using the intrinsic MIN/MAX "
11463 : "procedure", &atomic_code->loc);
11464 1229 : switch (op)
11465 : {
11466 742 : case INTRINSIC_PLUS:
11467 742 : alt_op = INTRINSIC_MINUS;
11468 742 : break;
11469 94 : case INTRINSIC_TIMES:
11470 94 : alt_op = INTRINSIC_DIVIDE;
11471 94 : break;
11472 120 : case INTRINSIC_MINUS:
11473 120 : alt_op = INTRINSIC_PLUS;
11474 120 : break;
11475 94 : case INTRINSIC_DIVIDE:
11476 94 : alt_op = INTRINSIC_TIMES;
11477 94 : break;
11478 : case INTRINSIC_AND:
11479 : case INTRINSIC_OR:
11480 : break;
11481 43 : case INTRINSIC_EQV:
11482 43 : alt_op = INTRINSIC_NEQV;
11483 43 : break;
11484 43 : case INTRINSIC_NEQV:
11485 43 : alt_op = INTRINSIC_EQV;
11486 43 : break;
11487 1 : default:
11488 1 : gfc_error ("!$OMP ATOMIC assignment operator must be binary "
11489 : "+, *, -, /, .AND., .OR., .EQV. or .NEQV. at %L",
11490 : &stmt_expr2->where);
11491 1 : return;
11492 : }
11493 :
11494 : /* Check for var = var op expr resp. var = expr op var where
11495 : expr doesn't reference var and var op expr is mathematically
11496 : equivalent to var op (expr) resp. expr op var equivalent to
11497 : (expr) op var. We rely here on the fact that the matcher
11498 : for x op1 y op2 z where op1 and op2 have equal precedence
11499 : returns (x op1 y) op2 z. */
11500 1228 : e = stmt_expr2->value.op.op2;
11501 1228 : if (e->expr_type == EXPR_VARIABLE
11502 288 : && e->symtree != NULL
11503 288 : && e->symtree->n.sym == var)
11504 : v = e;
11505 999 : else if ((c = is_conversion (e, false, true)) != NULL
11506 48 : && c->expr_type == EXPR_VARIABLE
11507 48 : && c->symtree != NULL
11508 1047 : && c->symtree->n.sym == var)
11509 : v = c;
11510 : else
11511 : {
11512 951 : gfc_expr **p = NULL, **q;
11513 1049 : for (q = &stmt_expr2->value.op.op1; (e = *q) != NULL; )
11514 1049 : if (e->expr_type == EXPR_VARIABLE
11515 948 : && e->symtree != NULL
11516 948 : && e->symtree->n.sym == var)
11517 : {
11518 : v = e;
11519 : break;
11520 : }
11521 101 : else if ((c = is_conversion (e, false, true)) != NULL)
11522 60 : q = &e->value.function.actual->expr;
11523 41 : else if (e->expr_type != EXPR_OP
11524 41 : || (e->value.op.op != op
11525 15 : && e->value.op.op != alt_op)
11526 38 : || e->rank != 0)
11527 : break;
11528 : else
11529 : {
11530 38 : p = q;
11531 38 : q = &e->value.op.op1;
11532 : }
11533 :
11534 951 : if (v == NULL)
11535 : {
11536 3 : gfc_error ("!$OMP ATOMIC assignment must be var = var op expr "
11537 : "or var = expr op var at %L", &stmt_expr2->where);
11538 3 : return;
11539 : }
11540 :
11541 948 : if (p != NULL)
11542 : {
11543 38 : e = *p;
11544 38 : switch (e->value.op.op)
11545 : {
11546 8 : case INTRINSIC_MINUS:
11547 8 : case INTRINSIC_DIVIDE:
11548 8 : case INTRINSIC_EQV:
11549 8 : case INTRINSIC_NEQV:
11550 8 : gfc_error ("!$OMP ATOMIC var = var op expr not "
11551 : "mathematically equivalent to var = var op "
11552 : "(expr) at %L", &stmt_expr2->where);
11553 8 : break;
11554 : default:
11555 : break;
11556 : }
11557 :
11558 : /* Canonicalize into var = var op (expr). */
11559 38 : *p = e->value.op.op2;
11560 38 : e->value.op.op2 = stmt_expr2;
11561 38 : e->ts = stmt_expr2->ts;
11562 38 : if (stmt->expr2 == stmt_expr2)
11563 26 : stmt->expr2 = stmt_expr2 = e;
11564 : else
11565 12 : stmt->expr2->value.function.actual->expr = stmt_expr2 = e;
11566 :
11567 38 : if (!gfc_compare_types (&stmt_expr2->value.op.op1->ts,
11568 : &stmt_expr2->ts))
11569 : {
11570 24 : for (p = &stmt_expr2->value.op.op1; *p != v;
11571 12 : p = &(*p)->value.function.actual->expr)
11572 : ;
11573 12 : *p = NULL;
11574 12 : gfc_free_expr (stmt_expr2->value.op.op1);
11575 12 : stmt_expr2->value.op.op1 = v;
11576 12 : gfc_convert_type (v, &stmt_expr2->ts, 2);
11577 : }
11578 : }
11579 : }
11580 :
11581 1225 : if (e->rank != 0 || expr_references_sym (stmt->expr2, var, v))
11582 : {
11583 1 : gfc_error ("expr in !$OMP ATOMIC assignment var = var op expr "
11584 : "must be scalar and cannot reference var at %L",
11585 : &stmt_expr2->where);
11586 1 : return;
11587 : }
11588 : }
11589 356 : else if (stmt_expr2->expr_type == EXPR_FUNCTION
11590 355 : && stmt_expr2->value.function.isym != NULL
11591 355 : && stmt_expr2->value.function.esym == NULL
11592 355 : && stmt_expr2->value.function.actual != NULL
11593 355 : && stmt_expr2->value.function.actual->next != NULL)
11594 : {
11595 355 : gfc_actual_arglist *arg, *var_arg;
11596 :
11597 355 : switch (stmt_expr2->value.function.isym->id)
11598 : {
11599 : case GFC_ISYM_MIN:
11600 : case GFC_ISYM_MAX:
11601 : break;
11602 147 : case GFC_ISYM_IAND:
11603 147 : case GFC_ISYM_IOR:
11604 147 : case GFC_ISYM_IEOR:
11605 147 : if (stmt_expr2->value.function.actual->next->next != NULL)
11606 : {
11607 0 : gfc_error ("!$OMP ATOMIC assignment intrinsic IAND, IOR "
11608 : "or IEOR must have two arguments at %L",
11609 : &stmt_expr2->where);
11610 0 : return;
11611 : }
11612 : break;
11613 1 : default:
11614 1 : gfc_error ("!$OMP ATOMIC assignment intrinsic must be "
11615 : "MIN, MAX, IAND, IOR or IEOR at %L",
11616 : &stmt_expr2->where);
11617 1 : return;
11618 : }
11619 :
11620 : var_arg = NULL;
11621 1088 : for (arg = stmt_expr2->value.function.actual; arg; arg = arg->next)
11622 : {
11623 741 : gfc_expr *e = NULL;
11624 741 : if (arg == stmt_expr2->value.function.actual
11625 387 : || (var_arg == NULL && arg->next == NULL))
11626 : {
11627 527 : e = is_conversion (arg->expr, false, true);
11628 527 : if (!e)
11629 514 : e = arg->expr;
11630 527 : if (e->expr_type == EXPR_VARIABLE
11631 453 : && e->symtree != NULL
11632 453 : && e->symtree->n.sym == var)
11633 741 : var_arg = arg;
11634 : }
11635 741 : if ((!var_arg || !e) && expr_references_sym (arg->expr, var, NULL))
11636 : {
11637 7 : gfc_error ("!$OMP ATOMIC intrinsic arguments except one must "
11638 : "not reference %qs at %L",
11639 : var->name, &arg->expr->where);
11640 7 : return;
11641 : }
11642 734 : if (arg->expr->rank != 0)
11643 : {
11644 0 : gfc_error ("!$OMP ATOMIC intrinsic arguments must be scalar "
11645 : "at %L", &arg->expr->where);
11646 0 : return;
11647 : }
11648 : }
11649 :
11650 347 : if (var_arg == NULL)
11651 : {
11652 1 : gfc_error ("First or last !$OMP ATOMIC intrinsic argument must "
11653 : "be %qs at %L", var->name, &stmt_expr2->where);
11654 1 : return;
11655 : }
11656 :
11657 346 : if (var_arg != stmt_expr2->value.function.actual)
11658 : {
11659 : /* Canonicalize, so that var comes first. */
11660 172 : gcc_assert (var_arg->next == NULL);
11661 : for (arg = stmt_expr2->value.function.actual;
11662 185 : arg->next != var_arg; arg = arg->next)
11663 : ;
11664 172 : var_arg->next = stmt_expr2->value.function.actual;
11665 172 : stmt_expr2->value.function.actual = var_arg;
11666 172 : arg->next = NULL;
11667 : }
11668 : }
11669 : else
11670 1 : gfc_error ("!$OMP ATOMIC assignment must have an operator or "
11671 : "intrinsic on right hand side at %L", &stmt_expr2->where);
11672 : return;
11673 :
11674 4 : unexpected:
11675 4 : gfc_error ("unexpected !$OMP ATOMIC expression at %L",
11676 : loc ? loc : &code->loc);
11677 4 : return;
11678 : }
11679 :
11680 :
11681 : static struct fortran_omp_context
11682 : {
11683 : gfc_code *code;
11684 : hash_set<gfc_symbol *> *sharing_clauses;
11685 : hash_set<gfc_symbol *> *private_iterators;
11686 : struct fortran_omp_context *previous;
11687 : bool is_openmp;
11688 : } *omp_current_ctx;
11689 : static gfc_code *omp_current_do_code;
11690 : static int omp_current_do_collapse;
11691 :
11692 : /* Forward declaration for mutually recursive functions. */
11693 : static gfc_code *
11694 : find_nested_loop_in_block (gfc_code *block);
11695 :
11696 : /* Return the first nested DO loop in CHAIN, or NULL if there
11697 : isn't one. Does no error checking on intervening code. */
11698 :
11699 : static gfc_code *
11700 27482 : find_nested_loop_in_chain (gfc_code *chain)
11701 : {
11702 27482 : gfc_code *code;
11703 :
11704 27482 : if (!chain)
11705 : return NULL;
11706 :
11707 31643 : for (code = chain; code; code = code->next)
11708 31222 : switch (code->op)
11709 : {
11710 : case EXEC_DO:
11711 : case EXEC_OMP_TILE:
11712 : case EXEC_OMP_UNROLL:
11713 : return code;
11714 621 : case EXEC_BLOCK:
11715 621 : if (gfc_code *c = find_nested_loop_in_block (code))
11716 : return c;
11717 : break;
11718 : default:
11719 : break;
11720 : }
11721 : return NULL;
11722 : }
11723 :
11724 : /* Return the first nested DO loop in BLOCK, or NULL if there
11725 : isn't one. Does no error checking on intervening code. */
11726 : static gfc_code *
11727 939 : find_nested_loop_in_block (gfc_code *block)
11728 : {
11729 939 : gfc_namespace *ns;
11730 939 : gcc_assert (block->op == EXEC_BLOCK);
11731 939 : ns = block->ext.block.ns;
11732 939 : gcc_assert (ns);
11733 939 : return find_nested_loop_in_chain (ns->code);
11734 : }
11735 :
11736 : void
11737 5420 : gfc_resolve_omp_do_blocks (gfc_code *code, gfc_namespace *ns)
11738 : {
11739 5420 : if (code->block->next && code->block->next->op == EXEC_DO)
11740 : {
11741 5067 : int i;
11742 :
11743 5067 : omp_current_do_code = code->block->next;
11744 5067 : if (code->ext.omp_clauses->orderedc)
11745 142 : omp_current_do_collapse = code->ext.omp_clauses->orderedc;
11746 4925 : else if (code->ext.omp_clauses->collapse)
11747 1121 : omp_current_do_collapse = code->ext.omp_clauses->collapse;
11748 3804 : else if (code->ext.omp_clauses->sizes_list)
11749 175 : omp_current_do_collapse
11750 175 : = gfc_expr_list_len (code->ext.omp_clauses->sizes_list);
11751 : else
11752 3629 : omp_current_do_collapse = 1;
11753 5067 : if (code->ext.omp_clauses->lists[OMP_LIST_REDUCTION_INSCAN])
11754 : {
11755 : /* Checking that there is a matching EXEC_OMP_SCAN in the
11756 : innermost body cannot be deferred to resolve_omp_do because
11757 : we process directives nested in the loop before we get
11758 : there. */
11759 60 : locus *loc
11760 : = &code->ext.omp_clauses->lists[OMP_LIST_REDUCTION_INSCAN]->where;
11761 60 : gfc_code *c;
11762 :
11763 80 : for (i = 1, c = omp_current_do_code;
11764 80 : i < omp_current_do_collapse; i++)
11765 : {
11766 22 : c = find_nested_loop_in_chain (c->block->next);
11767 22 : if (!c || c->op != EXEC_DO || c->block == NULL)
11768 : break;
11769 : }
11770 :
11771 : /* Skip this if we don't have enough nested loops. That
11772 : problem will be diagnosed elsewhere. */
11773 60 : if (c && c->op == EXEC_DO)
11774 : {
11775 58 : gfc_code *block = c->block ? c->block->next : NULL;
11776 58 : if (block && block->op != EXEC_OMP_SCAN)
11777 54 : while (block && block->next
11778 54 : && block->next->op != EXEC_OMP_SCAN)
11779 : block = block->next;
11780 43 : if (!block
11781 46 : || (block->op != EXEC_OMP_SCAN
11782 43 : && (!block->next || block->next->op != EXEC_OMP_SCAN)))
11783 19 : gfc_error ("With INSCAN at %L, expected loop body with "
11784 : "!$OMP SCAN between two "
11785 : "structured block sequences", loc);
11786 : else
11787 : {
11788 39 : if (block->op == EXEC_OMP_SCAN)
11789 3 : gfc_warning (OPT_Wopenmp,
11790 : "!$OMP SCAN at %L with zero executable "
11791 : "statements in preceding structured block "
11792 : "sequence", &block->loc);
11793 39 : if ((block->op == EXEC_OMP_SCAN && !block->next)
11794 38 : || (block->next && block->next->op == EXEC_OMP_SCAN
11795 36 : && !block->next->next))
11796 3 : gfc_warning (OPT_Wopenmp,
11797 : "!$OMP SCAN at %L with zero executable "
11798 : "statements in succeeding structured block "
11799 : "sequence", block->op == EXEC_OMP_SCAN
11800 1 : ? &block->loc : &block->next->loc);
11801 : }
11802 58 : if (block && block->op != EXEC_OMP_SCAN)
11803 43 : block = block->next;
11804 46 : if (block && block->op == EXEC_OMP_SCAN)
11805 : /* Mark 'omp scan' as checked; flag will be unset later. */
11806 39 : block->ext.omp_clauses->if_present = true;
11807 : }
11808 : }
11809 : }
11810 5420 : gfc_resolve_blocks (code->block, ns);
11811 5420 : omp_current_do_collapse = 0;
11812 5420 : omp_current_do_code = NULL;
11813 5420 : }
11814 :
11815 :
11816 : void
11817 6031 : gfc_resolve_omp_parallel_blocks (gfc_code *code, gfc_namespace *ns)
11818 : {
11819 6031 : struct fortran_omp_context ctx;
11820 6031 : gfc_omp_clauses *omp_clauses = code->ext.omp_clauses;
11821 6031 : gfc_omp_namelist *n;
11822 :
11823 6031 : ctx.code = code;
11824 6031 : ctx.sharing_clauses = new hash_set<gfc_symbol *>;
11825 6031 : ctx.private_iterators = new hash_set<gfc_symbol *>;
11826 6031 : ctx.previous = omp_current_ctx;
11827 6031 : ctx.is_openmp = true;
11828 6031 : omp_current_ctx = &ctx;
11829 :
11830 241240 : for (enum gfc_omp_list_type list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
11831 235209 : list = gfc_omp_list_type (list + 1))
11832 235209 : switch (list)
11833 : {
11834 60310 : case OMP_LIST_SHARED:
11835 60310 : case OMP_LIST_PRIVATE:
11836 60310 : case OMP_LIST_FIRSTPRIVATE:
11837 60310 : case OMP_LIST_LASTPRIVATE:
11838 60310 : case OMP_LIST_REDUCTION:
11839 60310 : case OMP_LIST_REDUCTION_INSCAN:
11840 60310 : case OMP_LIST_REDUCTION_TASK:
11841 60310 : case OMP_LIST_IN_REDUCTION:
11842 60310 : case OMP_LIST_TASK_REDUCTION:
11843 60310 : case OMP_LIST_LINEAR:
11844 69267 : for (n = omp_clauses->lists[list]; n; n = n->next)
11845 8957 : ctx.sharing_clauses->add (n->sym);
11846 : break;
11847 : default:
11848 : break;
11849 : }
11850 :
11851 6031 : switch (code->op)
11852 : {
11853 2357 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
11854 2357 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
11855 2357 : case EXEC_OMP_MASKED_TASKLOOP:
11856 2357 : case EXEC_OMP_MASKED_TASKLOOP_SIMD:
11857 2357 : case EXEC_OMP_MASTER_TASKLOOP:
11858 2357 : case EXEC_OMP_MASTER_TASKLOOP_SIMD:
11859 2357 : case EXEC_OMP_PARALLEL_DO:
11860 2357 : case EXEC_OMP_PARALLEL_DO_SIMD:
11861 2357 : case EXEC_OMP_PARALLEL_LOOP:
11862 2357 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
11863 2357 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
11864 2357 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
11865 2357 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
11866 2357 : case EXEC_OMP_TARGET_PARALLEL_DO:
11867 2357 : case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
11868 2357 : case EXEC_OMP_TARGET_PARALLEL_LOOP:
11869 2357 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
11870 2357 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
11871 2357 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
11872 2357 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
11873 2357 : case EXEC_OMP_TARGET_TEAMS_LOOP:
11874 2357 : case EXEC_OMP_TASKLOOP:
11875 2357 : case EXEC_OMP_TASKLOOP_SIMD:
11876 2357 : case EXEC_OMP_TEAMS_DISTRIBUTE:
11877 2357 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
11878 2357 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
11879 2357 : case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
11880 2357 : case EXEC_OMP_TEAMS_LOOP:
11881 2357 : gfc_resolve_omp_do_blocks (code, ns);
11882 2357 : break;
11883 3674 : default:
11884 3674 : gfc_resolve_blocks (code->block, ns);
11885 : }
11886 :
11887 6031 : omp_current_ctx = ctx.previous;
11888 12062 : delete ctx.sharing_clauses;
11889 12062 : delete ctx.private_iterators;
11890 6031 : }
11891 :
11892 :
11893 : /* Save and clear openmp.cc private state. */
11894 :
11895 : void
11896 288079 : gfc_omp_save_and_clear_state (struct gfc_omp_saved_state *state)
11897 : {
11898 288079 : state->ptrs[0] = omp_current_ctx;
11899 288079 : state->ptrs[1] = omp_current_do_code;
11900 288079 : state->ints[0] = omp_current_do_collapse;
11901 288079 : omp_current_ctx = NULL;
11902 288079 : omp_current_do_code = NULL;
11903 288079 : omp_current_do_collapse = 0;
11904 288079 : }
11905 :
11906 :
11907 : /* Restore openmp.cc private state from the saved state. */
11908 :
11909 : void
11910 288078 : gfc_omp_restore_state (struct gfc_omp_saved_state *state)
11911 : {
11912 288078 : omp_current_ctx = (struct fortran_omp_context *) state->ptrs[0];
11913 288078 : omp_current_do_code = (gfc_code *) state->ptrs[1];
11914 288078 : omp_current_do_collapse = state->ints[0];
11915 288078 : }
11916 :
11917 :
11918 : /* Note a DO iterator variable. This is special in !$omp parallel
11919 : construct, where they are predetermined private. */
11920 :
11921 : void
11922 32897 : gfc_resolve_do_iterator (gfc_code *code, gfc_symbol *sym, bool add_clause)
11923 : {
11924 32897 : if (omp_current_ctx == NULL)
11925 : return;
11926 :
11927 13094 : int i = omp_current_do_collapse;
11928 13094 : gfc_code *c = omp_current_do_code;
11929 :
11930 13094 : if (sym->attr.threadprivate)
11931 : return;
11932 :
11933 : /* !$omp do and !$omp parallel do iteration variable is predetermined
11934 : private just in the !$omp do resp. !$omp parallel do construct,
11935 : with no implications for the outer parallel constructs. */
11936 :
11937 17929 : while (i-- >= 1 && c)
11938 : {
11939 9490 : if (code == c)
11940 : return;
11941 4835 : c = find_nested_loop_in_chain (c->block->next);
11942 4835 : if (c && (c->op == EXEC_OMP_TILE || c->op == EXEC_OMP_UNROLL))
11943 : return;
11944 : }
11945 :
11946 : /* An openacc context may represent a data clause. Abort if so. */
11947 8439 : if (!omp_current_ctx->is_openmp && !oacc_is_loop (omp_current_ctx->code))
11948 : return;
11949 :
11950 7461 : if (omp_current_ctx->sharing_clauses->contains (sym))
11951 : return;
11952 :
11953 6459 : if (! omp_current_ctx->private_iterators->add (sym) && add_clause)
11954 : {
11955 6272 : gfc_omp_clauses *omp_clauses = omp_current_ctx->code->ext.omp_clauses;
11956 6272 : gfc_omp_namelist *p;
11957 :
11958 6272 : p = gfc_get_omp_namelist ();
11959 6272 : p->sym = sym;
11960 6272 : p->where = omp_current_ctx->code->loc;
11961 6272 : p->next = omp_clauses->lists[OMP_LIST_PRIVATE];
11962 6272 : omp_clauses->lists[OMP_LIST_PRIVATE] = p;
11963 : }
11964 : }
11965 :
11966 : static void
11967 698 : handle_local_var (gfc_symbol *sym)
11968 : {
11969 698 : if (sym->attr.flavor != FL_VARIABLE
11970 178 : || sym->as != NULL
11971 137 : || (sym->ts.type != BT_INTEGER && sym->ts.type != BT_REAL))
11972 : return;
11973 71 : gfc_resolve_do_iterator (sym->ns->code, sym, false);
11974 : }
11975 :
11976 : void
11977 334285 : gfc_resolve_omp_local_vars (gfc_namespace *ns)
11978 : {
11979 334285 : if (omp_current_ctx)
11980 452 : gfc_traverse_ns (ns, handle_local_var);
11981 334285 : }
11982 :
11983 :
11984 : /* Error checking on intervening code uses a code walker. */
11985 :
11986 : struct icode_error_state
11987 : {
11988 : const char *name;
11989 : bool errorp;
11990 : gfc_code *nested;
11991 : gfc_code *next;
11992 : };
11993 :
11994 : static int
11995 944 : icode_code_error_callback (gfc_code **codep,
11996 : int *walk_subtrees ATTRIBUTE_UNUSED, void *opaque)
11997 : {
11998 944 : gfc_code *code = *codep;
11999 944 : icode_error_state *state = (icode_error_state *)opaque;
12000 :
12001 : /* gfc_code_walker walks down CODE's next chain as well as
12002 : walking things that are actually nested in CODE. We need to
12003 : special-case traversal of outer blocks, so stop immediately if we
12004 : are heading down such a next chain. */
12005 944 : if (code == state->next)
12006 : return 1;
12007 :
12008 647 : switch (code->op)
12009 : {
12010 1 : case EXEC_DO:
12011 1 : case EXEC_DO_WHILE:
12012 1 : case EXEC_DO_CONCURRENT:
12013 1 : gfc_error ("%s cannot contain loop in intervening code at %L",
12014 : state->name, &code->loc);
12015 1 : state->errorp = true;
12016 1 : break;
12017 0 : case EXEC_CYCLE:
12018 0 : case EXEC_EXIT:
12019 : /* Errors have already been diagnosed in match_exit_cycle. */
12020 0 : state->errorp = true;
12021 0 : break;
12022 : case EXEC_OMP_ASSUME:
12023 : case EXEC_OMP_METADIRECTIVE:
12024 : /* Per OpenMP 6.0, some non-executable directives are allowed in
12025 : intervening code. */
12026 : break;
12027 477 : case EXEC_CALL:
12028 : /* Per OpenMP 5.2, the "omp_" prefix is reserved, so we don't have to
12029 : consider the possibility that some locally-bound definition
12030 : overrides the runtime routine. */
12031 477 : if (code->resolved_sym
12032 477 : && omp_runtime_api_procname (code->resolved_sym->name))
12033 : {
12034 1 : gfc_error ("%s cannot contain OpenMP API call in intervening code "
12035 : "at %L",
12036 : state->name, &code->loc);
12037 1 : state->errorp = true;
12038 : }
12039 : break;
12040 168 : default:
12041 168 : if (code->op >= EXEC_OMP_FIRST_OPENMP_EXEC
12042 168 : && code->op <= EXEC_OMP_LAST_OPENMP_EXEC)
12043 : {
12044 2 : gfc_error ("%s cannot contain OpenMP directive in intervening code "
12045 : "at %L",
12046 : state->name, &code->loc);
12047 2 : state->errorp = true;
12048 : }
12049 : }
12050 : return 0;
12051 : }
12052 :
12053 : static int
12054 1081 : icode_expr_error_callback (gfc_expr **expr,
12055 : int *walk_subtrees ATTRIBUTE_UNUSED, void *opaque)
12056 : {
12057 1081 : icode_error_state *state = (icode_error_state *)opaque;
12058 :
12059 1081 : switch ((*expr)->expr_type)
12060 : {
12061 : /* As for EXPR_CALL with "omp_"-prefixed symbols. */
12062 2 : case EXPR_FUNCTION:
12063 2 : {
12064 2 : gfc_symbol *sym = (*expr)->value.function.esym;
12065 2 : if (sym && omp_runtime_api_procname (sym->name))
12066 : {
12067 1 : gfc_error ("%s cannot contain OpenMP API call in intervening code "
12068 : "at %L",
12069 1 : state->name, &((*expr)->where));
12070 1 : state->errorp = true;
12071 : }
12072 : }
12073 :
12074 : break;
12075 : default:
12076 : break;
12077 : }
12078 :
12079 : /* FIXME: The description of canonical loop form in the OpenMP standard
12080 : also says "array expressions" are not permitted in intervening code.
12081 : That term is not defined in either the OpenMP spec or the Fortran
12082 : standard, although the latter uses it informally to refer to any
12083 : expression that is not scalar-valued. It is also apparently not the
12084 : thing GCC internally calls EXPR_ARRAY. It seems the intent of the
12085 : OpenMP restriction is to disallow elemental operations/intrinsics
12086 : (including things that are not expressions, like assignment
12087 : statements) that generate implicit loops over array operands
12088 : (even if the result is a scalar), but even if the spec said
12089 : that there is no list of all the cases that would be forbidden.
12090 : This is OpenMP issue 3326. */
12091 :
12092 1081 : return 0;
12093 : }
12094 :
12095 : static void
12096 267 : diagnose_intervening_code_errors_1 (gfc_code *chain,
12097 : struct icode_error_state *state)
12098 : {
12099 267 : gfc_code *code;
12100 1080 : for (code = chain; code; code = code->next)
12101 : {
12102 813 : if (code == state->nested)
12103 : /* Do not walk the nested loop or its body, we are only
12104 : interested in intervening code. */
12105 : ;
12106 636 : else if (code->op == EXEC_BLOCK
12107 636 : && find_nested_loop_in_block (code) == state->nested)
12108 : /* This block contains the nested loop, recurse on its
12109 : statements. */
12110 : {
12111 90 : gfc_namespace* ns = code->ext.block.ns;
12112 90 : diagnose_intervening_code_errors_1 (ns->code, state);
12113 : }
12114 : else
12115 : /* Treat the whole statement as a unit. */
12116 : {
12117 546 : gfc_code *temp = state->next;
12118 546 : state->next = code->next;
12119 546 : gfc_code_walker (&code, icode_code_error_callback,
12120 : icode_expr_error_callback, state);
12121 546 : state->next = temp;
12122 : }
12123 : }
12124 267 : }
12125 :
12126 : /* Diagnose intervening code errors in BLOCK with nested loop NESTED.
12127 : NAME is the user-friendly name of the OMP directive, used for error
12128 : messages. Returns true if any error was found. */
12129 : static bool
12130 177 : diagnose_intervening_code_errors (gfc_code *chain, const char *name,
12131 : gfc_code *nested)
12132 : {
12133 177 : struct icode_error_state state;
12134 177 : state.name = name;
12135 177 : state.errorp = false;
12136 177 : state.nested = nested;
12137 177 : state.next = NULL;
12138 0 : diagnose_intervening_code_errors_1 (chain, &state);
12139 177 : return state.errorp;
12140 : }
12141 :
12142 : /* Helper function for restructure_intervening_code: wrap CHAIN in
12143 : a marker to indicate that it is a structured block sequence. That
12144 : information will be used later on (in omp-low.cc) for error checking. */
12145 : static gfc_code *
12146 461 : make_structured_block (gfc_code *chain)
12147 : {
12148 461 : gcc_assert (chain);
12149 461 : gfc_namespace *ns = gfc_build_block_ns (gfc_current_ns);
12150 461 : gfc_code *result = gfc_get_code (EXEC_BLOCK);
12151 461 : result->op = EXEC_BLOCK;
12152 461 : result->ext.block.ns = ns;
12153 461 : result->ext.block.assoc = NULL;
12154 461 : result->loc = chain->loc;
12155 461 : ns->omp_structured_block = 1;
12156 461 : ns->code = chain;
12157 461 : return result;
12158 : }
12159 :
12160 : /* Push intervening code surrounding a loop, including nested scopes,
12161 : into the body of the loop. CHAINP is the pointer to the head of
12162 : the next-chain to scan, OUTER_LOOP is the EXEC_DO for the next outer
12163 : loop level, and COLLAPSE is the number of nested loops we need to
12164 : process.
12165 : Note that CHAINP may point at outer_loop->block->next when we
12166 : are scanning the body of a loop, but if there is an intervening block
12167 : CHAINP points into the block's chain rather than its enclosing outer
12168 : loop. This is why OUTER_LOOP is passed separately. */
12169 : static gfc_code *
12170 7170 : restructure_intervening_code (gfc_code **chainp, gfc_code *outer_loop,
12171 : int count)
12172 : {
12173 7170 : gfc_code *code;
12174 7170 : gfc_code *head = *chainp;
12175 7170 : gfc_code *tail = NULL;
12176 7170 : gfc_code *innermost_loop = NULL;
12177 :
12178 7434 : for (code = *chainp; code; code = code->next, chainp = &(*chainp)->next)
12179 : {
12180 7434 : if (code->op == EXEC_DO)
12181 : {
12182 : /* Cut CODE free from its chain, leaving the ends dangling. */
12183 7086 : *chainp = NULL;
12184 7086 : tail = code->next;
12185 7086 : code->next = NULL;
12186 :
12187 7086 : if (count == 1)
12188 : innermost_loop = code;
12189 : else
12190 2090 : innermost_loop
12191 2090 : = restructure_intervening_code (&code->block->next,
12192 : code, count - 1);
12193 : break;
12194 : }
12195 348 : else if (code->op == EXEC_BLOCK
12196 348 : && find_nested_loop_in_block (code))
12197 : {
12198 84 : gfc_namespace *ns = code->ext.block.ns;
12199 :
12200 : /* Cut CODE free from its chain, leaving the ends dangling. */
12201 84 : *chainp = NULL;
12202 84 : tail = code->next;
12203 84 : code->next = NULL;
12204 :
12205 84 : innermost_loop
12206 84 : = restructure_intervening_code (&ns->code, outer_loop,
12207 : count);
12208 :
12209 : /* At this point we have already pulled out the nested loop and
12210 : pointed outer_loop at it, and moved the intervening code that
12211 : was previously in the block into the body of innermost_loop.
12212 : Now we want to move the BLOCK itself so it wraps the entire
12213 : current body of innermost_loop. */
12214 84 : ns->code = innermost_loop->block->next;
12215 84 : innermost_loop->block->next = code;
12216 84 : break;
12217 : }
12218 : }
12219 :
12220 2174 : gcc_assert (innermost_loop);
12221 :
12222 : /* Now we have split the intervening code into two parts:
12223 : head is the start of the part before the loop/block, terminating
12224 : at *chainp, and tail is the part after it. Mark each part as
12225 : a structured block sequence, and splice the two parts around the
12226 : existing body of the innermost loop. */
12227 7170 : if (head != code)
12228 : {
12229 222 : gfc_code *block = make_structured_block (head);
12230 222 : if (innermost_loop->block->next)
12231 221 : gfc_append_code (block, innermost_loop->block->next);
12232 222 : innermost_loop->block->next = block;
12233 : }
12234 7170 : if (tail)
12235 : {
12236 239 : gfc_code *block = make_structured_block (tail);
12237 239 : if (innermost_loop->block->next)
12238 237 : gfc_append_code (innermost_loop->block->next, block);
12239 : else
12240 2 : innermost_loop->block->next = block;
12241 : }
12242 :
12243 : /* For loops, finally splice CODE into OUTER_LOOP. We already handled
12244 : relinking EXEC_BLOCK above. */
12245 7170 : if (code->op == EXEC_DO && outer_loop)
12246 7086 : outer_loop->block->next = code;
12247 :
12248 7170 : return innermost_loop;
12249 : }
12250 :
12251 : /* CODE is an OMP loop construct. Return true if VAR matches an iteration
12252 : variable outer to level DEPTH. */
12253 : static bool
12254 8083 : is_outer_iteration_variable (gfc_code *code, int depth, gfc_symbol *var)
12255 : {
12256 8083 : int i;
12257 8083 : gfc_code *do_code = code;
12258 :
12259 12610 : for (i = 1; i < depth; i++)
12260 : {
12261 5028 : do_code = find_nested_loop_in_chain (do_code->block->next);
12262 5028 : gcc_assert (do_code);
12263 5028 : if (do_code->op == EXEC_OMP_TILE || do_code->op == EXEC_OMP_UNROLL)
12264 : {
12265 51 : --i;
12266 51 : continue;
12267 : }
12268 4977 : gfc_symbol *ivar = do_code->ext.iterator->var->symtree->n.sym;
12269 4977 : if (var == ivar)
12270 : return true;
12271 : }
12272 : return false;
12273 : }
12274 :
12275 : /* Forward declaration for recursive functions. */
12276 : static gfc_code *
12277 : check_nested_loop_in_block (gfc_code *block, gfc_expr *expr, gfc_symbol *sym,
12278 : bool *bad);
12279 :
12280 : /* Like find_nested_loop_in_chain, but additionally check that EXPR
12281 : does not reference any variables bound in intervening EXEC_BLOCKs
12282 : and that SYM is not bound in such intervening blocks. Either EXPR or SYM
12283 : may be null. Sets *BAD to true if either test fails. */
12284 : static gfc_code *
12285 48165 : check_nested_loop_in_chain (gfc_code *chain, gfc_expr *expr, gfc_symbol *sym,
12286 : bool *bad)
12287 : {
12288 51769 : for (gfc_code *code = chain; code; code = code->next)
12289 : {
12290 51481 : if (code->op == EXEC_DO)
12291 : return code;
12292 4123 : else if (code->op == EXEC_OMP_TILE || code->op == EXEC_OMP_UNROLL)
12293 1682 : return check_nested_loop_in_chain (code->block->next, expr, sym, bad);
12294 2441 : else if (code->op == EXEC_BLOCK)
12295 : {
12296 807 : gfc_code *c = check_nested_loop_in_block (code, expr, sym, bad);
12297 807 : if (c)
12298 : return c;
12299 : }
12300 : }
12301 : return NULL;
12302 : }
12303 :
12304 : /* Code walker for block symtrees. It doesn't take any kind of state
12305 : argument, so use a static variable. */
12306 : static struct check_nested_loop_in_block_state_t {
12307 : gfc_expr *expr;
12308 : gfc_symbol *sym;
12309 : bool *bad;
12310 : } check_nested_loop_in_block_state;
12311 :
12312 : static void
12313 766 : check_nested_loop_in_block_symbol (gfc_symbol *sym)
12314 : {
12315 766 : if (sym == check_nested_loop_in_block_state.sym
12316 766 : || (check_nested_loop_in_block_state.expr
12317 567 : && gfc_find_sym_in_expr (sym,
12318 : check_nested_loop_in_block_state.expr)))
12319 5 : *check_nested_loop_in_block_state.bad = true;
12320 766 : }
12321 :
12322 : /* Return the first nested DO loop in BLOCK, or NULL if there
12323 : isn't one. Set *BAD to true if EXPR references any variables in BLOCK, or
12324 : SYM is bound in BLOCK. Either EXPR or SYM may be null. */
12325 : static gfc_code *
12326 807 : check_nested_loop_in_block (gfc_code *block, gfc_expr *expr,
12327 : gfc_symbol *sym, bool *bad)
12328 : {
12329 807 : gfc_namespace *ns;
12330 807 : gcc_assert (block->op == EXEC_BLOCK);
12331 807 : ns = block->ext.block.ns;
12332 807 : gcc_assert (ns);
12333 :
12334 : /* Skip the check if this block doesn't contain the nested loop, or
12335 : if we already know it's bad. */
12336 807 : gfc_code *result = check_nested_loop_in_chain (ns->code, expr, sym, bad);
12337 807 : if (result && !*bad)
12338 : {
12339 519 : check_nested_loop_in_block_state.expr = expr;
12340 519 : check_nested_loop_in_block_state.sym = sym;
12341 519 : check_nested_loop_in_block_state.bad = bad;
12342 519 : gfc_traverse_ns (ns, check_nested_loop_in_block_symbol);
12343 519 : check_nested_loop_in_block_state.expr = NULL;
12344 519 : check_nested_loop_in_block_state.sym = NULL;
12345 519 : check_nested_loop_in_block_state.bad = NULL;
12346 : }
12347 807 : return result;
12348 : }
12349 :
12350 : /* CODE is an OMP loop construct. Return true if EXPR references
12351 : any variables bound in intervening code, to level DEPTH. */
12352 : static bool
12353 22717 : expr_uses_intervening_var (gfc_code *code, int depth, gfc_expr *expr)
12354 : {
12355 22717 : int i;
12356 22717 : gfc_code *do_code = code;
12357 :
12358 58213 : for (i = 0; i < depth; i++)
12359 : {
12360 35499 : bool bad = false;
12361 35499 : do_code = check_nested_loop_in_chain (do_code->block->next,
12362 : expr, NULL, &bad);
12363 35499 : if (bad)
12364 3 : return true;
12365 : }
12366 : return false;
12367 : }
12368 :
12369 : /* CODE is an OMP loop construct. Return true if SYM is bound in
12370 : intervening code, to level DEPTH. */
12371 : static bool
12372 7582 : is_intervening_var (gfc_code *code, int depth, gfc_symbol *sym)
12373 : {
12374 7582 : int i;
12375 7582 : gfc_code *do_code = code;
12376 :
12377 19439 : for (i = 0; i < depth; i++)
12378 : {
12379 11859 : bool bad = false;
12380 11859 : do_code = check_nested_loop_in_chain (do_code->block->next,
12381 : NULL, sym, &bad);
12382 11859 : if (bad)
12383 2 : return true;
12384 : }
12385 : return false;
12386 : }
12387 :
12388 : /* CODE is an OMP loop construct. Return true if EXPR does not reference
12389 : any iteration variables outer to level DEPTH. */
12390 : static bool
12391 23796 : expr_is_invariant (gfc_code *code, int depth, gfc_expr *expr)
12392 : {
12393 23796 : int i;
12394 23796 : gfc_code *do_code = code;
12395 :
12396 37118 : for (i = 1; i < depth; i++)
12397 : {
12398 14388 : do_code = find_nested_loop_in_chain (do_code->block->next);
12399 14388 : gcc_assert (do_code);
12400 14388 : if (do_code->op == EXEC_OMP_TILE || do_code->op == EXEC_OMP_UNROLL)
12401 : {
12402 136 : --i;
12403 136 : continue;
12404 : }
12405 14252 : gfc_symbol *ivar = do_code->ext.iterator->var->symtree->n.sym;
12406 14252 : if (gfc_find_sym_in_expr (ivar, expr))
12407 : return false;
12408 : }
12409 : return true;
12410 : }
12411 :
12412 : /* CODE is an OMP loop construct. Return true if EXPR matches one of the
12413 : canonical forms for a bound expression. It may include references to
12414 : an iteration variable outer to level DEPTH; set OUTER_VARP if so. */
12415 : static bool
12416 15155 : bound_expr_is_canonical (gfc_code *code, int depth, gfc_expr *expr,
12417 : gfc_symbol **outer_varp)
12418 : {
12419 15155 : gfc_expr *expr2 = NULL;
12420 :
12421 : /* Rectangular case. */
12422 15155 : if (depth == 0 || expr_is_invariant (code, depth, expr))
12423 14587 : return true;
12424 :
12425 : /* Any simple variable that didn't pass expr_is_invariant must be
12426 : an outer_var. */
12427 568 : if (expr->expr_type == EXPR_VARIABLE && expr->rank == 0)
12428 : {
12429 63 : *outer_varp = expr->symtree->n.sym;
12430 63 : return true;
12431 : }
12432 :
12433 : /* All other permitted forms are binary operators. */
12434 505 : if (expr->expr_type != EXPR_OP)
12435 : return false;
12436 :
12437 : /* Check for plus/minus a loop invariant expr. */
12438 503 : if (expr->value.op.op == INTRINSIC_PLUS
12439 503 : || expr->value.op.op == INTRINSIC_MINUS)
12440 : {
12441 483 : if (expr_is_invariant (code, depth, expr->value.op.op1))
12442 48 : expr2 = expr->value.op.op2;
12443 435 : else if (expr_is_invariant (code, depth, expr->value.op.op2))
12444 434 : expr2 = expr->value.op.op1;
12445 : else
12446 : return false;
12447 : }
12448 : else
12449 : expr2 = expr;
12450 :
12451 : /* Check for a product with a loop-invariant expr. */
12452 502 : if (expr2->expr_type == EXPR_OP
12453 96 : && expr2->value.op.op == INTRINSIC_TIMES)
12454 : {
12455 96 : if (expr_is_invariant (code, depth, expr2->value.op.op1))
12456 40 : expr2 = expr2->value.op.op2;
12457 56 : else if (expr_is_invariant (code, depth, expr2->value.op.op2))
12458 53 : expr2 = expr2->value.op.op1;
12459 : else
12460 : return false;
12461 : }
12462 :
12463 : /* What's left must be a reference to an outer loop variable. */
12464 499 : if (expr2->expr_type == EXPR_VARIABLE
12465 499 : && expr2->rank == 0
12466 998 : && is_outer_iteration_variable (code, depth, expr2->symtree->n.sym))
12467 : {
12468 499 : *outer_varp = expr2->symtree->n.sym;
12469 499 : return true;
12470 : }
12471 :
12472 : return false;
12473 : }
12474 :
12475 : static void
12476 5420 : resolve_omp_do (gfc_code *code)
12477 : {
12478 5420 : gfc_code *do_code, *next;
12479 5420 : int i, count, non_generated_count;
12480 5420 : gfc_omp_namelist *n;
12481 5420 : gfc_symbol *dovar;
12482 5420 : const char *name;
12483 5420 : bool is_simd = false;
12484 5420 : bool errorp = false;
12485 5420 : bool perfect_nesting_errorp = false;
12486 5420 : bool imperfect = false;
12487 :
12488 5420 : switch (code->op)
12489 : {
12490 : case EXEC_OMP_DISTRIBUTE: name = "!$OMP DISTRIBUTE"; break;
12491 49 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
12492 49 : name = "!$OMP DISTRIBUTE PARALLEL DO";
12493 49 : break;
12494 32 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
12495 32 : name = "!$OMP DISTRIBUTE PARALLEL DO SIMD";
12496 32 : is_simd = true;
12497 32 : break;
12498 50 : case EXEC_OMP_DISTRIBUTE_SIMD:
12499 50 : name = "!$OMP DISTRIBUTE SIMD";
12500 50 : is_simd = true;
12501 50 : break;
12502 1335 : case EXEC_OMP_DO: name = "!$OMP DO"; break;
12503 134 : case EXEC_OMP_DO_SIMD: name = "!$OMP DO SIMD"; is_simd = true; break;
12504 64 : case EXEC_OMP_LOOP: name = "!$OMP LOOP"; break;
12505 1216 : case EXEC_OMP_PARALLEL_DO: name = "!$OMP PARALLEL DO"; break;
12506 304 : case EXEC_OMP_PARALLEL_DO_SIMD:
12507 304 : name = "!$OMP PARALLEL DO SIMD";
12508 304 : is_simd = true;
12509 304 : break;
12510 46 : case EXEC_OMP_PARALLEL_LOOP: name = "!$OMP PARALLEL LOOP"; break;
12511 7 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
12512 7 : name = "!$OMP PARALLEL MASKED TASKLOOP";
12513 7 : break;
12514 10 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
12515 10 : name = "!$OMP PARALLEL MASKED TASKLOOP SIMD";
12516 10 : is_simd = true;
12517 10 : break;
12518 12 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
12519 12 : name = "!$OMP PARALLEL MASTER TASKLOOP";
12520 12 : break;
12521 18 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
12522 18 : name = "!$OMP PARALLEL MASTER TASKLOOP SIMD";
12523 18 : is_simd = true;
12524 18 : break;
12525 8 : case EXEC_OMP_MASKED_TASKLOOP: name = "!$OMP MASKED TASKLOOP"; break;
12526 14 : case EXEC_OMP_MASKED_TASKLOOP_SIMD:
12527 14 : name = "!$OMP MASKED TASKLOOP SIMD";
12528 14 : is_simd = true;
12529 14 : break;
12530 14 : case EXEC_OMP_MASTER_TASKLOOP: name = "!$OMP MASTER TASKLOOP"; break;
12531 19 : case EXEC_OMP_MASTER_TASKLOOP_SIMD:
12532 19 : name = "!$OMP MASTER TASKLOOP SIMD";
12533 19 : is_simd = true;
12534 19 : break;
12535 783 : case EXEC_OMP_SIMD: name = "!$OMP SIMD"; is_simd = true; break;
12536 88 : case EXEC_OMP_TARGET_PARALLEL_DO: name = "!$OMP TARGET PARALLEL DO"; break;
12537 19 : case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
12538 19 : name = "!$OMP TARGET PARALLEL DO SIMD";
12539 19 : is_simd = true;
12540 19 : break;
12541 16 : case EXEC_OMP_TARGET_PARALLEL_LOOP:
12542 16 : name = "!$OMP TARGET PARALLEL LOOP";
12543 16 : break;
12544 33 : case EXEC_OMP_TARGET_SIMD:
12545 33 : name = "!$OMP TARGET SIMD";
12546 33 : is_simd = true;
12547 33 : break;
12548 20 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
12549 20 : name = "!$OMP TARGET TEAMS DISTRIBUTE";
12550 20 : break;
12551 75 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
12552 75 : name = "!$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO";
12553 75 : break;
12554 37 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
12555 37 : name = "!$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD";
12556 37 : is_simd = true;
12557 37 : break;
12558 20 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
12559 20 : name = "!$OMP TARGET TEAMS DISTRIBUTE SIMD";
12560 20 : is_simd = true;
12561 20 : break;
12562 19 : case EXEC_OMP_TARGET_TEAMS_LOOP: name = "!$OMP TARGET TEAMS LOOP"; break;
12563 69 : case EXEC_OMP_TASKLOOP: name = "!$OMP TASKLOOP"; break;
12564 38 : case EXEC_OMP_TASKLOOP_SIMD:
12565 38 : name = "!$OMP TASKLOOP SIMD";
12566 38 : is_simd = true;
12567 38 : break;
12568 20 : case EXEC_OMP_TEAMS_DISTRIBUTE: name = "!$OMP TEAMS DISTRIBUTE"; break;
12569 37 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
12570 37 : name = "!$OMP TEAMS DISTRIBUTE PARALLEL DO";
12571 37 : break;
12572 60 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
12573 60 : name = "!$OMP TEAMS DISTRIBUTE PARALLEL DO SIMD";
12574 60 : is_simd = true;
12575 60 : break;
12576 42 : case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
12577 42 : name = "!$OMP TEAMS DISTRIBUTE SIMD";
12578 42 : is_simd = true;
12579 42 : break;
12580 48 : case EXEC_OMP_TEAMS_LOOP: name = "!$OMP TEAMS LOOP"; break;
12581 195 : case EXEC_OMP_TILE: name = "!$OMP TILE"; break;
12582 415 : case EXEC_OMP_UNROLL: name = "!$OMP UNROLL"; break;
12583 0 : default: gcc_unreachable ();
12584 : }
12585 :
12586 5420 : if (code->ext.omp_clauses)
12587 5420 : resolve_omp_clauses (code, code->ext.omp_clauses, NULL);
12588 :
12589 5420 : if (code->op == EXEC_OMP_TILE && code->ext.omp_clauses->sizes_list == NULL)
12590 0 : gfc_error ("SIZES clause is required on !$OMP TILE construct at %L",
12591 : &code->loc);
12592 :
12593 5420 : do_code = code->block->next;
12594 5420 : if (code->ext.omp_clauses->orderedc)
12595 : count = code->ext.omp_clauses->orderedc;
12596 5276 : else if (code->ext.omp_clauses->sizes_list)
12597 195 : count = gfc_expr_list_len (code->ext.omp_clauses->sizes_list);
12598 : else
12599 : {
12600 5081 : count = code->ext.omp_clauses->collapse;
12601 5081 : if (count <= 0)
12602 : count = 1;
12603 : }
12604 :
12605 5420 : non_generated_count = count;
12606 : /* While the spec defines the loop nest depth independently of the COLLAPSE
12607 : clause, in practice the middle end only pays attention to the COLLAPSE
12608 : depth and treats any further inner loops as the final-loop-body. So
12609 : here we also check canonical loop nest form only for the number of
12610 : outer loops specified by the COLLAPSE clause too. */
12611 8060 : for (i = 1; i <= count; i++)
12612 : {
12613 8060 : gfc_symbol *start_var = NULL, *end_var = NULL;
12614 : /* Parse errors are not recoverable. */
12615 8060 : if (do_code->op == EXEC_DO_WHILE)
12616 : {
12617 6 : gfc_error ("%s cannot be a DO WHILE or DO without loop control "
12618 : "at %L", name, &do_code->loc);
12619 106 : goto fail;
12620 : }
12621 8054 : if (do_code->op == EXEC_DO_CONCURRENT)
12622 : {
12623 4 : gfc_error ("%s cannot be a DO CONCURRENT loop at %L", name,
12624 : &do_code->loc);
12625 4 : goto fail;
12626 : }
12627 8050 : if (do_code->op == EXEC_OMP_TILE || do_code->op == EXEC_OMP_UNROLL)
12628 : {
12629 466 : if (do_code->op == EXEC_OMP_UNROLL)
12630 : {
12631 308 : if (!do_code->ext.omp_clauses->partial)
12632 : {
12633 53 : gfc_error ("Generated loop of UNROLL construct at %L "
12634 : "without PARTIAL clause does not have "
12635 : "canonical form", &do_code->loc);
12636 53 : goto fail;
12637 : }
12638 255 : else if (i != count)
12639 : {
12640 5 : gfc_error ("UNROLL construct at %L with PARTIAL clause "
12641 : "generates just one loop with canonical form "
12642 : "but %d loops are needed",
12643 5 : &do_code->loc, count - i + 1);
12644 5 : goto fail;
12645 : }
12646 : }
12647 158 : else if (do_code->op == EXEC_OMP_TILE)
12648 : {
12649 158 : if (do_code->ext.omp_clauses->sizes_list == NULL)
12650 : /* This should have been diagnosed earlier already. */
12651 0 : return;
12652 158 : int l = gfc_expr_list_len (do_code->ext.omp_clauses->sizes_list);
12653 158 : if (count - i + 1 > l)
12654 : {
12655 14 : gfc_error ("TILE construct at %L generates %d loops "
12656 : "with canonical form but %d loops are needed",
12657 : &do_code->loc, l, count - i + 1);
12658 14 : goto fail;
12659 : }
12660 : }
12661 394 : if (do_code->ext.omp_clauses && do_code->ext.omp_clauses->erroneous)
12662 17 : goto fail;
12663 377 : if (imperfect && !perfect_nesting_errorp)
12664 : {
12665 4 : sorry_at (gfc_get_location (&do_code->loc),
12666 : "Imperfectly nested loop using generated loops");
12667 4 : errorp = true;
12668 : }
12669 377 : if (non_generated_count == count)
12670 329 : non_generated_count = i - 1;
12671 377 : --i;
12672 377 : do_code = do_code->block->next;
12673 377 : continue;
12674 377 : }
12675 7584 : gcc_assert (do_code->op == EXEC_DO);
12676 7584 : if (do_code->ext.iterator->var->ts.type != BT_INTEGER)
12677 : {
12678 3 : gfc_error ("%s iteration variable must be of type integer at %L",
12679 : name, &do_code->loc);
12680 3 : errorp = true;
12681 : }
12682 7584 : dovar = do_code->ext.iterator->var->symtree->n.sym;
12683 7584 : if (dovar->attr.threadprivate)
12684 : {
12685 0 : gfc_error ("%s iteration variable must not be THREADPRIVATE "
12686 : "at %L", name, &do_code->loc);
12687 0 : errorp = true;
12688 : }
12689 7584 : if (code->ext.omp_clauses)
12690 303360 : for (enum gfc_omp_list_type list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
12691 295776 : list = gfc_omp_list_type (list + 1))
12692 97461 : if (!is_simd || code->ext.omp_clauses->collapse > 1
12693 295776 : ? (list != OMP_LIST_PRIVATE && list != OMP_LIST_LASTPRIVATE
12694 254670 : && list != OMP_LIST_ALLOCATE)
12695 41106 : : (list != OMP_LIST_PRIVATE && list != OMP_LIST_LASTPRIVATE
12696 41106 : && list != OMP_LIST_ALLOCATE && list != OMP_LIST_LINEAR))
12697 276351 : for (n = code->ext.omp_clauses->lists[list]; n; n = n->next)
12698 4381 : if (dovar == n->sym)
12699 : {
12700 5 : if (!is_simd || code->ext.omp_clauses->collapse > 1)
12701 4 : gfc_error ("%s iteration variable present on clause "
12702 : "other than PRIVATE, LASTPRIVATE or "
12703 : "ALLOCATE at %L", name, &do_code->loc);
12704 : else
12705 1 : gfc_error ("%s iteration variable present on clause "
12706 : "other than PRIVATE, LASTPRIVATE, ALLOCATE or "
12707 : "LINEAR at %L", name, &do_code->loc);
12708 : errorp = true;
12709 : }
12710 7584 : if (is_outer_iteration_variable (code, i, dovar))
12711 : {
12712 2 : gfc_error ("%s iteration variable used in more than one loop at %L",
12713 : name, &do_code->loc);
12714 2 : errorp = true;
12715 : }
12716 7582 : else if (is_intervening_var (code, i, dovar))
12717 : {
12718 2 : gfc_error ("%s iteration variable at %L is bound in "
12719 : "intervening code",
12720 : name, &do_code->loc);
12721 2 : errorp = true;
12722 : }
12723 7580 : else if (!bound_expr_is_canonical (code, i,
12724 7580 : do_code->ext.iterator->start,
12725 : &start_var))
12726 : {
12727 4 : gfc_error ("%s loop start expression not in canonical form at %L",
12728 : name, &do_code->loc);
12729 4 : errorp = true;
12730 : }
12731 7576 : else if (expr_uses_intervening_var (code, i,
12732 7576 : do_code->ext.iterator->start))
12733 : {
12734 1 : gfc_error ("%s loop start expression at %L uses variable bound in "
12735 : "intervening code",
12736 : name, &do_code->loc);
12737 1 : errorp = true;
12738 : }
12739 7575 : else if (!bound_expr_is_canonical (code, i,
12740 7575 : do_code->ext.iterator->end,
12741 : &end_var))
12742 : {
12743 2 : gfc_error ("%s loop end expression not in canonical form at %L",
12744 : name, &do_code->loc);
12745 2 : errorp = true;
12746 : }
12747 7573 : else if (expr_uses_intervening_var (code, i,
12748 7573 : do_code->ext.iterator->end))
12749 : {
12750 1 : gfc_error ("%s loop end expression at %L uses variable bound in "
12751 : "intervening code",
12752 : name, &do_code->loc);
12753 1 : errorp = true;
12754 : }
12755 7572 : else if (start_var && end_var && start_var != end_var)
12756 : {
12757 1 : gfc_error ("%s loop bounds reference different "
12758 : "iteration variables at %L", name, &do_code->loc);
12759 1 : errorp = true;
12760 : }
12761 7571 : else if (!expr_is_invariant (code, i, do_code->ext.iterator->step))
12762 : {
12763 3 : gfc_error ("%s loop increment not in canonical form at %L",
12764 : name, &do_code->loc);
12765 3 : errorp = true;
12766 : }
12767 7568 : else if (expr_uses_intervening_var (code, i,
12768 7568 : do_code->ext.iterator->step))
12769 : {
12770 1 : gfc_error ("%s loop increment expression at %L uses variable "
12771 : "bound in intervening code",
12772 : name, &do_code->loc);
12773 1 : errorp = true;
12774 : }
12775 7584 : if (start_var || end_var)
12776 : {
12777 528 : code->ext.omp_clauses->non_rectangular = 1;
12778 528 : if (i > non_generated_count)
12779 : {
12780 3 : sorry_at (gfc_get_location (&do_code->loc),
12781 : "Non-rectangular loops from generated loops "
12782 : "unsupported");
12783 3 : errorp = true;
12784 : }
12785 : }
12786 :
12787 : /* Only parse loop body into nested loop and intervening code if
12788 : there are supposed to be more loops in the nest to collapse. */
12789 7584 : if (i == count)
12790 : break;
12791 :
12792 2270 : next = find_nested_loop_in_chain (do_code->block->next);
12793 :
12794 2270 : if (!next)
12795 : {
12796 : /* Parse error, can't recover from this. */
12797 7 : gfc_error ("not enough DO loops for collapsed %s (level %d) at %L",
12798 : name, i, &code->loc);
12799 7 : goto fail;
12800 : }
12801 2263 : else if (next != do_code->block->next
12802 2103 : || (next->next && next->next->op != EXEC_CONTINUE))
12803 : /* Imperfectly nested loop found. */
12804 : {
12805 : /* Only diagnose violation of imperfect nesting constraints once. */
12806 177 : if (!perfect_nesting_errorp)
12807 : {
12808 176 : if (code->ext.omp_clauses->orderedc)
12809 : {
12810 3 : gfc_error ("%s inner loops must be perfectly nested with "
12811 : "ORDERED clause at %L",
12812 : name, &code->loc);
12813 3 : perfect_nesting_errorp = true;
12814 : }
12815 173 : else if (code->ext.omp_clauses->lists[OMP_LIST_REDUCTION_INSCAN])
12816 : {
12817 2 : gfc_error ("%s inner loops must be perfectly nested with "
12818 : "REDUCTION INSCAN clause at %L",
12819 : name, &code->loc);
12820 2 : perfect_nesting_errorp = true;
12821 : }
12822 171 : else if (code->op == EXEC_OMP_TILE)
12823 : {
12824 8 : gfc_error ("%s inner loops must be perfectly nested at %L",
12825 : name, &code->loc);
12826 8 : perfect_nesting_errorp = true;
12827 : }
12828 13 : if (perfect_nesting_errorp)
12829 : errorp = true;
12830 : }
12831 177 : if (diagnose_intervening_code_errors (do_code->block->next,
12832 : name, next))
12833 5 : errorp = true;
12834 : imperfect = true;
12835 : }
12836 2263 : do_code = next;
12837 : }
12838 :
12839 : /* Give up now if we found any constraint violations. */
12840 5314 : if (errorp)
12841 : {
12842 48 : fail:
12843 154 : if (code->ext.omp_clauses)
12844 154 : code->ext.omp_clauses->erroneous = 1;
12845 154 : return;
12846 : }
12847 :
12848 5266 : if (non_generated_count)
12849 4996 : restructure_intervening_code (&code->block->next, code,
12850 : non_generated_count);
12851 : }
12852 :
12853 : /* Resolve the context selector. In particular, SKIP_P is set to true,
12854 : the context can never be matched. */
12855 :
12856 : static void
12857 764 : gfc_resolve_omp_context_selector (gfc_omp_set_selector *oss,
12858 : bool is_metadirective, bool *skip_p)
12859 : {
12860 764 : if (skip_p)
12861 310 : *skip_p = false;
12862 1453 : for (gfc_omp_set_selector *set_selector = oss; set_selector;
12863 689 : set_selector = set_selector->next)
12864 1485 : for (gfc_omp_selector *os = set_selector->trait_selectors; os; os = os->next)
12865 : {
12866 814 : if (os->score)
12867 : {
12868 52 : if (!gfc_resolve_expr (os->score)
12869 52 : || os->score->ts.type != BT_INTEGER
12870 104 : || os->score->rank != 0)
12871 : {
12872 0 : gfc_error ("%<score%> argument must be constant integer "
12873 0 : "expression at %L", &os->score->where);
12874 0 : gfc_free_expr (os->score);
12875 0 : os->score = nullptr;
12876 : }
12877 52 : else if (os->score->expr_type == EXPR_CONSTANT
12878 52 : && mpz_sgn (os->score->value.integer) < 0)
12879 : {
12880 1 : gfc_error ("%<score%> argument must be non-negative at %L",
12881 : &os->score->where);
12882 1 : gfc_free_expr (os->score);
12883 1 : os->score = nullptr;
12884 : }
12885 : }
12886 :
12887 814 : if (os->code == OMP_TRAIT_INVALID)
12888 : break;
12889 796 : enum omp_tp_type property_kind = omp_ts_map[os->code].tp_type;
12890 796 : gfc_omp_trait_property *otp = os->properties;
12891 :
12892 796 : if (!otp)
12893 409 : continue;
12894 387 : switch (property_kind)
12895 : {
12896 139 : case OMP_TRAIT_PROPERTY_DEV_NUM_EXPR:
12897 139 : case OMP_TRAIT_PROPERTY_BOOL_EXPR:
12898 139 : if (!gfc_resolve_expr (otp->expr)
12899 138 : || (property_kind == OMP_TRAIT_PROPERTY_BOOL_EXPR
12900 124 : && otp->expr->ts.type != BT_LOGICAL)
12901 137 : || (property_kind == OMP_TRAIT_PROPERTY_DEV_NUM_EXPR
12902 14 : && otp->expr->ts.type != BT_INTEGER)
12903 137 : || otp->expr->rank != 0
12904 276 : || (!is_metadirective && otp->expr->expr_type != EXPR_CONSTANT))
12905 : {
12906 3 : if (is_metadirective)
12907 : {
12908 0 : if (property_kind == OMP_TRAIT_PROPERTY_BOOL_EXPR)
12909 0 : gfc_error ("property must be a "
12910 : "logical expression at %L",
12911 0 : &otp->expr->where);
12912 : else
12913 0 : gfc_error ("property must be an "
12914 : "integer expression at %L",
12915 0 : &otp->expr->where);
12916 : }
12917 : else
12918 : {
12919 3 : if (property_kind == OMP_TRAIT_PROPERTY_BOOL_EXPR)
12920 2 : gfc_error ("property must be a constant "
12921 : "logical expression at %L",
12922 2 : &otp->expr->where);
12923 : else
12924 1 : gfc_error ("property must be a constant "
12925 : "integer expression at %L",
12926 1 : &otp->expr->where);
12927 : }
12928 : /* Prevent later ICEs. */
12929 3 : gfc_expr *e;
12930 3 : if (property_kind == OMP_TRAIT_PROPERTY_BOOL_EXPR)
12931 2 : e = gfc_get_logical_expr (gfc_default_logical_kind,
12932 2 : &otp->expr->where, true);
12933 : else
12934 1 : e = gfc_get_int_expr (gfc_default_integer_kind,
12935 1 : &otp->expr->where, 0);
12936 3 : gfc_free_expr (otp->expr);
12937 3 : otp->expr = e;
12938 3 : continue;
12939 3 : }
12940 : /* Device number must be conforming, which includes
12941 : omp_initial_device (-1), omp_invalid_device (-4),
12942 : and omp_default_device (-5). */
12943 136 : if (property_kind == OMP_TRAIT_PROPERTY_DEV_NUM_EXPR
12944 14 : && otp->expr->expr_type == EXPR_CONSTANT
12945 5 : && mpz_sgn (otp->expr->value.integer) < 0
12946 3 : && mpz_cmp_si (otp->expr->value.integer, -1) != 0
12947 2 : && mpz_cmp_si (otp->expr->value.integer, -4) != 0
12948 1 : && mpz_cmp_si (otp->expr->value.integer, -5) != 0)
12949 1 : gfc_error ("property must be a conforming device number at %L",
12950 : &otp->expr->where);
12951 : break;
12952 : default:
12953 : break;
12954 : }
12955 : /* This only handles one specific case: User condition.
12956 : FIXME: Handle more cases by calling omp_context_selector_matches;
12957 : unfortunately, we cannot generate the tree here as, e.g., PARM_DECL
12958 : backend decl are not available at this stage - but might be used in,
12959 : e.g. user conditions. See PR122361. */
12960 384 : if (skip_p && otp
12961 138 : && os->code == OMP_TRAIT_USER_CONDITION
12962 81 : && otp->expr->expr_type == EXPR_CONSTANT
12963 14 : && otp->expr->value.logical == false)
12964 12 : *skip_p = true;
12965 : }
12966 764 : }
12967 :
12968 :
12969 : static void
12970 138 : resolve_omp_metadirective (gfc_code *code, gfc_namespace *ns)
12971 : {
12972 138 : gfc_omp_variant *variant = code->ext.omp_variants;
12973 138 : gfc_omp_variant *prev_variant = variant;
12974 :
12975 448 : while (variant)
12976 : {
12977 310 : bool skip;
12978 310 : gfc_resolve_omp_context_selector (variant->selectors, true, &skip);
12979 310 : gfc_code *variant_code = variant->code;
12980 310 : gfc_resolve_code (variant_code, ns);
12981 310 : if (skip)
12982 : {
12983 : /* The following should only be true if an error occurred
12984 : as the 'otherwise' clause should always match. */
12985 12 : if (variant == code->ext.omp_variants && !variant->next)
12986 : break;
12987 12 : gfc_omp_variant *tmp = variant;
12988 12 : if (variant == code->ext.omp_variants)
12989 11 : variant = prev_variant = code->ext.omp_variants = variant->next;
12990 : else
12991 1 : variant = prev_variant->next = variant->next;
12992 12 : gfc_free_omp_set_selector_list (tmp->selectors);
12993 12 : free (tmp);
12994 : }
12995 : else
12996 : {
12997 298 : prev_variant = variant;
12998 298 : variant = variant->next;
12999 : }
13000 : }
13001 : /* Replace metadirective by its body if only 'nothing' remains. */
13002 138 : if (!code->ext.omp_variants->next && code->ext.omp_variants->stmt == ST_NONE)
13003 : {
13004 11 : gfc_code *next = code->next;
13005 11 : gfc_code *inner = code->ext.omp_variants->code;
13006 11 : gfc_free_omp_set_selector_list (code->ext.omp_variants->selectors);
13007 11 : free (code->ext.omp_variants);
13008 11 : *code = *inner;
13009 11 : free (inner);
13010 11 : while (code->next)
13011 : code = code->next;
13012 11 : code->next = next;
13013 : }
13014 138 : }
13015 :
13016 :
13017 : static gfc_statement
13018 63 : omp_code_to_statement (gfc_code *code)
13019 : {
13020 63 : switch (code->op)
13021 : {
13022 : case EXEC_OMP_PARALLEL:
13023 : return ST_OMP_PARALLEL;
13024 0 : case EXEC_OMP_PARALLEL_MASKED:
13025 0 : return ST_OMP_PARALLEL_MASKED;
13026 0 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
13027 0 : return ST_OMP_PARALLEL_MASKED_TASKLOOP;
13028 0 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
13029 0 : return ST_OMP_PARALLEL_MASKED_TASKLOOP_SIMD;
13030 0 : case EXEC_OMP_PARALLEL_MASTER:
13031 0 : return ST_OMP_PARALLEL_MASTER;
13032 0 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
13033 0 : return ST_OMP_PARALLEL_MASTER_TASKLOOP;
13034 0 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
13035 0 : return ST_OMP_PARALLEL_MASTER_TASKLOOP_SIMD;
13036 1 : case EXEC_OMP_PARALLEL_SECTIONS:
13037 1 : return ST_OMP_PARALLEL_SECTIONS;
13038 1 : case EXEC_OMP_SECTIONS:
13039 1 : return ST_OMP_SECTIONS;
13040 1 : case EXEC_OMP_ORDERED:
13041 1 : return ST_OMP_ORDERED;
13042 1 : case EXEC_OMP_CRITICAL:
13043 1 : return ST_OMP_CRITICAL;
13044 0 : case EXEC_OMP_MASKED:
13045 0 : return ST_OMP_MASKED;
13046 0 : case EXEC_OMP_MASKED_TASKLOOP:
13047 0 : return ST_OMP_MASKED_TASKLOOP;
13048 0 : case EXEC_OMP_MASKED_TASKLOOP_SIMD:
13049 0 : return ST_OMP_MASKED_TASKLOOP_SIMD;
13050 1 : case EXEC_OMP_MASTER:
13051 1 : return ST_OMP_MASTER;
13052 0 : case EXEC_OMP_MASTER_TASKLOOP:
13053 0 : return ST_OMP_MASTER_TASKLOOP;
13054 0 : case EXEC_OMP_MASTER_TASKLOOP_SIMD:
13055 0 : return ST_OMP_MASTER_TASKLOOP_SIMD;
13056 1 : case EXEC_OMP_SINGLE:
13057 1 : return ST_OMP_SINGLE;
13058 1 : case EXEC_OMP_TASK:
13059 1 : return ST_OMP_TASK;
13060 1 : case EXEC_OMP_WORKSHARE:
13061 1 : return ST_OMP_WORKSHARE;
13062 1 : case EXEC_OMP_PARALLEL_WORKSHARE:
13063 1 : return ST_OMP_PARALLEL_WORKSHARE;
13064 3 : case EXEC_OMP_DO:
13065 3 : return ST_OMP_DO;
13066 0 : case EXEC_OMP_LOOP:
13067 0 : return ST_OMP_LOOP;
13068 0 : case EXEC_OMP_ALLOCATE:
13069 0 : return ST_OMP_ALLOCATE_EXEC;
13070 0 : case EXEC_OMP_ALLOCATORS:
13071 0 : return ST_OMP_ALLOCATORS;
13072 0 : case EXEC_OMP_ASSUME:
13073 0 : return ST_OMP_ASSUME;
13074 1 : case EXEC_OMP_ATOMIC:
13075 1 : return ST_OMP_ATOMIC;
13076 1 : case EXEC_OMP_BARRIER:
13077 1 : return ST_OMP_BARRIER;
13078 1 : case EXEC_OMP_CANCEL:
13079 1 : return ST_OMP_CANCEL;
13080 1 : case EXEC_OMP_CANCELLATION_POINT:
13081 1 : return ST_OMP_CANCELLATION_POINT;
13082 0 : case EXEC_OMP_ERROR:
13083 0 : return ST_OMP_ERROR;
13084 1 : case EXEC_OMP_FLUSH:
13085 1 : return ST_OMP_FLUSH;
13086 0 : case EXEC_OMP_INTEROP:
13087 0 : return ST_OMP_INTEROP;
13088 1 : case EXEC_OMP_DISTRIBUTE:
13089 1 : return ST_OMP_DISTRIBUTE;
13090 1 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
13091 1 : return ST_OMP_DISTRIBUTE_PARALLEL_DO;
13092 1 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
13093 1 : return ST_OMP_DISTRIBUTE_PARALLEL_DO_SIMD;
13094 1 : case EXEC_OMP_DISTRIBUTE_SIMD:
13095 1 : return ST_OMP_DISTRIBUTE_SIMD;
13096 1 : case EXEC_OMP_DO_SIMD:
13097 1 : return ST_OMP_DO_SIMD;
13098 0 : case EXEC_OMP_SCAN:
13099 0 : return ST_OMP_SCAN;
13100 0 : case EXEC_OMP_SCOPE:
13101 0 : return ST_OMP_SCOPE;
13102 1 : case EXEC_OMP_SIMD:
13103 1 : return ST_OMP_SIMD;
13104 1 : case EXEC_OMP_TARGET:
13105 1 : return ST_OMP_TARGET;
13106 1 : case EXEC_OMP_TARGET_DATA:
13107 1 : return ST_OMP_TARGET_DATA;
13108 1 : case EXEC_OMP_TARGET_ENTER_DATA:
13109 1 : return ST_OMP_TARGET_ENTER_DATA;
13110 1 : case EXEC_OMP_TARGET_EXIT_DATA:
13111 1 : return ST_OMP_TARGET_EXIT_DATA;
13112 1 : case EXEC_OMP_TARGET_PARALLEL:
13113 1 : return ST_OMP_TARGET_PARALLEL;
13114 1 : case EXEC_OMP_TARGET_PARALLEL_DO:
13115 1 : return ST_OMP_TARGET_PARALLEL_DO;
13116 1 : case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
13117 1 : return ST_OMP_TARGET_PARALLEL_DO_SIMD;
13118 0 : case EXEC_OMP_TARGET_PARALLEL_LOOP:
13119 0 : return ST_OMP_TARGET_PARALLEL_LOOP;
13120 1 : case EXEC_OMP_TARGET_SIMD:
13121 1 : return ST_OMP_TARGET_SIMD;
13122 1 : case EXEC_OMP_TARGET_TEAMS:
13123 1 : return ST_OMP_TARGET_TEAMS;
13124 1 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
13125 1 : return ST_OMP_TARGET_TEAMS_DISTRIBUTE;
13126 1 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
13127 1 : return ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO;
13128 1 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
13129 1 : return ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD;
13130 1 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
13131 1 : return ST_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD;
13132 0 : case EXEC_OMP_TARGET_TEAMS_LOOP:
13133 0 : return ST_OMP_TARGET_TEAMS_LOOP;
13134 1 : case EXEC_OMP_TARGET_UPDATE:
13135 1 : return ST_OMP_TARGET_UPDATE;
13136 1 : case EXEC_OMP_TASKGROUP:
13137 1 : return ST_OMP_TASKGROUP;
13138 1 : case EXEC_OMP_TASKLOOP:
13139 1 : return ST_OMP_TASKLOOP;
13140 1 : case EXEC_OMP_TASKLOOP_SIMD:
13141 1 : return ST_OMP_TASKLOOP_SIMD;
13142 1 : case EXEC_OMP_TASKWAIT:
13143 1 : return ST_OMP_TASKWAIT;
13144 1 : case EXEC_OMP_TASKYIELD:
13145 1 : return ST_OMP_TASKYIELD;
13146 1 : case EXEC_OMP_TEAMS:
13147 1 : return ST_OMP_TEAMS;
13148 1 : case EXEC_OMP_TEAMS_DISTRIBUTE:
13149 1 : return ST_OMP_TEAMS_DISTRIBUTE;
13150 1 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
13151 1 : return ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO;
13152 1 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
13153 1 : return ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD;
13154 1 : case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
13155 1 : return ST_OMP_TEAMS_DISTRIBUTE_SIMD;
13156 0 : case EXEC_OMP_TEAMS_LOOP:
13157 0 : return ST_OMP_TEAMS_LOOP;
13158 6 : case EXEC_OMP_PARALLEL_DO:
13159 6 : return ST_OMP_PARALLEL_DO;
13160 1 : case EXEC_OMP_PARALLEL_DO_SIMD:
13161 1 : return ST_OMP_PARALLEL_DO_SIMD;
13162 0 : case EXEC_OMP_PARALLEL_LOOP:
13163 0 : return ST_OMP_PARALLEL_LOOP;
13164 1 : case EXEC_OMP_DEPOBJ:
13165 1 : return ST_OMP_DEPOBJ;
13166 0 : case EXEC_OMP_TILE:
13167 0 : return ST_OMP_TILE;
13168 0 : case EXEC_OMP_UNROLL:
13169 0 : return ST_OMP_UNROLL;
13170 0 : case EXEC_OMP_DISPATCH:
13171 0 : return ST_OMP_DISPATCH;
13172 0 : default:
13173 0 : gcc_unreachable ();
13174 : }
13175 : }
13176 :
13177 : static gfc_statement
13178 63 : oacc_code_to_statement (gfc_code *code)
13179 : {
13180 63 : switch (code->op)
13181 : {
13182 : case EXEC_OACC_PARALLEL:
13183 : return ST_OACC_PARALLEL;
13184 : case EXEC_OACC_KERNELS:
13185 : return ST_OACC_KERNELS;
13186 : case EXEC_OACC_SERIAL:
13187 : return ST_OACC_SERIAL;
13188 : case EXEC_OACC_DATA:
13189 : return ST_OACC_DATA;
13190 : case EXEC_OACC_HOST_DATA:
13191 : return ST_OACC_HOST_DATA;
13192 : case EXEC_OACC_PARALLEL_LOOP:
13193 : return ST_OACC_PARALLEL_LOOP;
13194 : case EXEC_OACC_KERNELS_LOOP:
13195 : return ST_OACC_KERNELS_LOOP;
13196 : case EXEC_OACC_SERIAL_LOOP:
13197 : return ST_OACC_SERIAL_LOOP;
13198 : case EXEC_OACC_LOOP:
13199 : return ST_OACC_LOOP;
13200 : case EXEC_OACC_ATOMIC:
13201 : return ST_OACC_ATOMIC;
13202 : case EXEC_OACC_ROUTINE:
13203 : return ST_OACC_ROUTINE;
13204 : case EXEC_OACC_UPDATE:
13205 : return ST_OACC_UPDATE;
13206 : case EXEC_OACC_WAIT:
13207 : return ST_OACC_WAIT;
13208 : case EXEC_OACC_CACHE:
13209 : return ST_OACC_CACHE;
13210 : case EXEC_OACC_ENTER_DATA:
13211 : return ST_OACC_ENTER_DATA;
13212 : case EXEC_OACC_EXIT_DATA:
13213 : return ST_OACC_EXIT_DATA;
13214 : case EXEC_OACC_DECLARE:
13215 : return ST_OACC_DECLARE;
13216 0 : default:
13217 0 : gcc_unreachable ();
13218 : }
13219 : }
13220 :
13221 : static void
13222 13168 : resolve_oacc_directive_inside_omp_region (gfc_code *code)
13223 : {
13224 13168 : if (omp_current_ctx != NULL && omp_current_ctx->is_openmp)
13225 : {
13226 11 : gfc_statement st = omp_code_to_statement (omp_current_ctx->code);
13227 11 : gfc_statement oacc_st = oacc_code_to_statement (code);
13228 11 : gfc_error ("The %s directive cannot be specified within "
13229 : "a %s region at %L", gfc_ascii_statement (oacc_st),
13230 : gfc_ascii_statement (st), &code->loc);
13231 : }
13232 13168 : }
13233 :
13234 : static void
13235 21062 : resolve_omp_directive_inside_oacc_region (gfc_code *code)
13236 : {
13237 21062 : if (omp_current_ctx != NULL && !omp_current_ctx->is_openmp)
13238 : {
13239 52 : gfc_statement st = oacc_code_to_statement (omp_current_ctx->code);
13240 52 : gfc_statement omp_st = omp_code_to_statement (code);
13241 52 : gfc_error ("The %s directive cannot be specified within "
13242 : "a %s region at %L", gfc_ascii_statement (omp_st),
13243 : gfc_ascii_statement (st), &code->loc);
13244 : }
13245 21062 : }
13246 :
13247 :
13248 : static void
13249 5272 : resolve_oacc_nested_loops (gfc_code *code, gfc_code* do_code, int collapse,
13250 : const char *clause)
13251 : {
13252 5272 : gfc_symbol *dovar;
13253 5272 : gfc_code *c;
13254 5272 : int i;
13255 :
13256 5792 : for (i = 1; i <= collapse; i++)
13257 : {
13258 5792 : if (do_code->op == EXEC_DO_WHILE)
13259 : {
13260 10 : gfc_error ("!$ACC LOOP cannot be a DO WHILE or DO without loop control "
13261 : "at %L", &do_code->loc);
13262 10 : break;
13263 : }
13264 5782 : if (do_code->op == EXEC_DO_CONCURRENT)
13265 : {
13266 3 : gfc_error ("!$ACC LOOP cannot be a DO CONCURRENT loop at %L",
13267 : &do_code->loc);
13268 3 : break;
13269 : }
13270 5779 : gcc_assert (do_code->op == EXEC_DO);
13271 5779 : if (do_code->ext.iterator->var->ts.type != BT_INTEGER)
13272 6 : gfc_error ("!$ACC LOOP iteration variable must be of type integer at %L",
13273 : &do_code->loc);
13274 5779 : dovar = do_code->ext.iterator->var->symtree->n.sym;
13275 5779 : if (i > 1)
13276 : {
13277 518 : gfc_code *do_code2 = code->block->next;
13278 518 : int j;
13279 :
13280 1218 : for (j = 1; j < i; j++)
13281 : {
13282 710 : gfc_symbol *ivar = do_code2->ext.iterator->var->symtree->n.sym;
13283 710 : if (dovar == ivar
13284 710 : || gfc_find_sym_in_expr (ivar, do_code->ext.iterator->start)
13285 701 : || gfc_find_sym_in_expr (ivar, do_code->ext.iterator->end)
13286 1410 : || gfc_find_sym_in_expr (ivar, do_code->ext.iterator->step))
13287 : {
13288 10 : gfc_error ("!$ACC LOOP %s loops don't form rectangular "
13289 : "iteration space at %L", clause, &do_code->loc);
13290 10 : break;
13291 : }
13292 700 : do_code2 = do_code2->block->next;
13293 : }
13294 : }
13295 5779 : if (i == collapse)
13296 : break;
13297 577 : for (c = do_code->next; c; c = c->next)
13298 48 : if (c->op != EXEC_NOP && c->op != EXEC_CONTINUE)
13299 : {
13300 0 : gfc_error ("%s !$ACC LOOP loops not perfectly nested at %L",
13301 : clause, &c->loc);
13302 0 : break;
13303 : }
13304 529 : if (c)
13305 : break;
13306 529 : do_code = do_code->block;
13307 529 : if (do_code->op != EXEC_DO && do_code->op != EXEC_DO_WHILE
13308 0 : && do_code->op != EXEC_DO_CONCURRENT)
13309 : {
13310 0 : gfc_error ("not enough DO loops for %s !$ACC LOOP at %L",
13311 : clause, &code->loc);
13312 0 : break;
13313 : }
13314 529 : do_code = do_code->next;
13315 529 : if (do_code == NULL
13316 522 : || (do_code->op != EXEC_DO && do_code->op != EXEC_DO_WHILE
13317 2 : && do_code->op != EXEC_DO_CONCURRENT))
13318 : {
13319 9 : gfc_error ("not enough DO loops for %s !$ACC LOOP at %L",
13320 : clause, &code->loc);
13321 9 : break;
13322 : }
13323 : }
13324 5272 : }
13325 :
13326 :
13327 : static void
13328 10119 : resolve_oacc_loop_blocks (gfc_code *code)
13329 : {
13330 10119 : if (!oacc_is_loop (code))
13331 : return;
13332 :
13333 5272 : if (code->ext.omp_clauses->tile_list && code->ext.omp_clauses->gang
13334 24 : && code->ext.omp_clauses->worker && code->ext.omp_clauses->vector)
13335 0 : gfc_error ("Tiled loop cannot be parallelized across gangs, workers and "
13336 : "vectors at the same time at %L", &code->loc);
13337 :
13338 5272 : if (code->ext.omp_clauses->tile_list)
13339 : {
13340 : gfc_expr_list *el;
13341 501 : for (el = code->ext.omp_clauses->tile_list; el; el = el->next)
13342 : {
13343 304 : if (el->expr == NULL)
13344 : {
13345 : /* NULL expressions are used to represent '*' arguments.
13346 : Convert those to a 0 expressions. */
13347 113 : el->expr = gfc_get_constant_expr (BT_INTEGER,
13348 : gfc_default_integer_kind,
13349 : &code->loc);
13350 113 : mpz_set_si (el->expr->value.integer, 0);
13351 : }
13352 : else
13353 : {
13354 191 : resolve_positive_int_expr (el->expr, "TILE");
13355 191 : if (el->expr->expr_type != EXPR_CONSTANT)
13356 14 : gfc_error ("TILE requires constant expression at %L",
13357 : &code->loc);
13358 : }
13359 : }
13360 : }
13361 : }
13362 :
13363 :
13364 : void
13365 10119 : gfc_resolve_oacc_blocks (gfc_code *code, gfc_namespace *ns)
13366 : {
13367 10119 : fortran_omp_context ctx;
13368 10119 : gfc_omp_clauses *omp_clauses = code->ext.omp_clauses;
13369 10119 : gfc_omp_namelist *n;
13370 :
13371 10119 : resolve_oacc_loop_blocks (code);
13372 :
13373 10119 : ctx.code = code;
13374 10119 : ctx.sharing_clauses = new hash_set<gfc_symbol *>;
13375 10119 : ctx.private_iterators = new hash_set<gfc_symbol *>;
13376 10119 : ctx.previous = omp_current_ctx;
13377 10119 : ctx.is_openmp = false;
13378 10119 : omp_current_ctx = &ctx;
13379 :
13380 404760 : for (enum gfc_omp_list_type list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
13381 394641 : list = gfc_omp_list_type (list + 1))
13382 394641 : switch (list)
13383 : {
13384 10119 : case OMP_LIST_PRIVATE:
13385 10710 : for (n = omp_clauses->lists[list]; n; n = n->next)
13386 591 : ctx.sharing_clauses->add (n->sym);
13387 : break;
13388 : default:
13389 : break;
13390 : }
13391 :
13392 10119 : gfc_resolve_blocks (code->block, ns);
13393 :
13394 10119 : omp_current_ctx = ctx.previous;
13395 20238 : delete ctx.sharing_clauses;
13396 20238 : delete ctx.private_iterators;
13397 10119 : }
13398 :
13399 :
13400 : static void
13401 5272 : resolve_oacc_loop (gfc_code *code)
13402 : {
13403 5272 : gfc_code *do_code;
13404 5272 : int collapse;
13405 :
13406 5272 : if (code->ext.omp_clauses)
13407 5272 : resolve_omp_clauses (code, code->ext.omp_clauses, NULL, true);
13408 :
13409 5272 : do_code = code->block->next;
13410 5272 : collapse = code->ext.omp_clauses->collapse;
13411 :
13412 : /* Both collapsed and tiled loops are lowered the same way, but are not
13413 : compatible. In gfc_trans_omp_do, the tile is prioritized. */
13414 5272 : if (code->ext.omp_clauses->tile_list)
13415 : {
13416 : int num = 0;
13417 : gfc_expr_list *el;
13418 501 : for (el = code->ext.omp_clauses->tile_list; el; el = el->next)
13419 304 : ++num;
13420 197 : resolve_oacc_nested_loops (code, code->block->next, num, "tiled");
13421 197 : return;
13422 : }
13423 :
13424 5075 : if (collapse <= 0)
13425 : collapse = 1;
13426 5075 : resolve_oacc_nested_loops (code, do_code, collapse, "collapsed");
13427 : }
13428 :
13429 : void
13430 334285 : gfc_resolve_oacc_declare (gfc_namespace *ns)
13431 : {
13432 334285 : enum gfc_omp_list_type list;
13433 334285 : gfc_omp_namelist *n;
13434 334285 : gfc_oacc_declare *oc;
13435 :
13436 334285 : if (ns->oacc_declare == NULL)
13437 : return;
13438 :
13439 290 : for (oc = ns->oacc_declare; oc; oc = oc->next)
13440 : {
13441 6480 : for (list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
13442 6318 : list = gfc_omp_list_type (list + 1))
13443 6574 : for (n = oc->clauses->lists[list]; n; n = n->next)
13444 : {
13445 256 : n->sym->mark = 0;
13446 256 : if (n->sym->attr.flavor != FL_VARIABLE
13447 16 : && (n->sym->attr.flavor != FL_PROCEDURE
13448 8 : || n->sym->result != n->sym))
13449 : {
13450 14 : if (n->sym->attr.flavor != FL_PARAMETER)
13451 : {
13452 8 : gfc_error ("Object %qs is not a variable at %L",
13453 : n->sym->name, &oc->loc);
13454 8 : continue;
13455 : }
13456 : /* Note that OpenACC 3.4 permits name constants, but the
13457 : implementation is permitted to ignore the clause;
13458 : as semantically, device_resident kind of makes sense
13459 : (and the wording with it is a bit odd), the warning
13460 : is suppressed. */
13461 6 : if (list != OMP_LIST_DEVICE_RESIDENT)
13462 5 : gfc_warning (OPT_Wsurprising, "Object %qs at %L is ignored as"
13463 : " parameters need not be copied", n->sym->name,
13464 : &oc->loc);
13465 : }
13466 :
13467 248 : if (n->expr && n->expr->ref->type == REF_ARRAY)
13468 : {
13469 1 : gfc_error ("Array sections: %qs not allowed in"
13470 1 : " !$ACC DECLARE at %L", n->sym->name, &oc->loc);
13471 1 : continue;
13472 : }
13473 : }
13474 :
13475 252 : for (n = oc->clauses->lists[OMP_LIST_DEVICE_RESIDENT]; n; n = n->next)
13476 90 : check_array_not_assumed (n->sym, oc->loc, "DEVICE_RESIDENT");
13477 : }
13478 :
13479 290 : for (oc = ns->oacc_declare; oc; oc = oc->next)
13480 : {
13481 6480 : for (list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
13482 6318 : list = gfc_omp_list_type (list + 1))
13483 6574 : for (n = oc->clauses->lists[list]; n; n = n->next)
13484 : {
13485 256 : if (n->sym->mark)
13486 : {
13487 9 : gfc_error ("Symbol %qs present on multiple clauses at %L",
13488 : n->sym->name, &oc->loc);
13489 9 : continue;
13490 : }
13491 : else
13492 247 : n->sym->mark = 1;
13493 : }
13494 : }
13495 :
13496 290 : for (oc = ns->oacc_declare; oc; oc = oc->next)
13497 : {
13498 6480 : for (list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
13499 6318 : list = gfc_omp_list_type (list + 1))
13500 6574 : for (n = oc->clauses->lists[list]; n; n = n->next)
13501 256 : n->sym->mark = 0;
13502 : }
13503 : }
13504 :
13505 :
13506 : void
13507 334285 : gfc_resolve_oacc_routines (gfc_namespace *ns)
13508 : {
13509 334285 : for (gfc_oacc_routine_name *orn = ns->oacc_routine_names;
13510 334385 : orn;
13511 100 : orn = orn->next)
13512 : {
13513 100 : gfc_symbol *sym = orn->sym;
13514 100 : if (!sym->attr.external
13515 29 : && !sym->attr.function
13516 27 : && !sym->attr.subroutine)
13517 : {
13518 7 : gfc_error ("NAME %qs does not refer to a subroutine or function"
13519 : " in !$ACC ROUTINE ( NAME ) at %L", sym->name, &orn->loc);
13520 7 : continue;
13521 : }
13522 93 : if (!gfc_add_omp_declare_target (&sym->attr, sym->name, &orn->loc))
13523 : {
13524 20 : gfc_error ("NAME %qs invalid"
13525 : " in !$ACC ROUTINE ( NAME ) at %L", sym->name, &orn->loc);
13526 20 : continue;
13527 : }
13528 : }
13529 334285 : }
13530 :
13531 :
13532 : void
13533 13168 : gfc_resolve_oacc_directive (gfc_code *code, gfc_namespace *ns ATTRIBUTE_UNUSED)
13534 : {
13535 13168 : resolve_oacc_directive_inside_omp_region (code);
13536 :
13537 13168 : switch (code->op)
13538 : {
13539 7353 : case EXEC_OACC_PARALLEL:
13540 7353 : case EXEC_OACC_KERNELS:
13541 7353 : case EXEC_OACC_SERIAL:
13542 7353 : case EXEC_OACC_DATA:
13543 7353 : case EXEC_OACC_HOST_DATA:
13544 7353 : case EXEC_OACC_UPDATE:
13545 7353 : case EXEC_OACC_ENTER_DATA:
13546 7353 : case EXEC_OACC_EXIT_DATA:
13547 7353 : case EXEC_OACC_WAIT:
13548 7353 : case EXEC_OACC_CACHE:
13549 7353 : resolve_omp_clauses (code, code->ext.omp_clauses, NULL, true);
13550 7353 : break;
13551 5272 : case EXEC_OACC_PARALLEL_LOOP:
13552 5272 : case EXEC_OACC_KERNELS_LOOP:
13553 5272 : case EXEC_OACC_SERIAL_LOOP:
13554 5272 : case EXEC_OACC_LOOP:
13555 5272 : resolve_oacc_loop (code);
13556 5272 : break;
13557 543 : case EXEC_OACC_ATOMIC:
13558 543 : resolve_omp_atomic (code);
13559 543 : break;
13560 : default:
13561 : break;
13562 : }
13563 13168 : }
13564 :
13565 :
13566 : static void
13567 2109 : resolve_omp_target (gfc_code *code)
13568 : {
13569 : #define GFC_IS_TEAMS_CONSTRUCT(op) \
13570 : (op == EXEC_OMP_TEAMS \
13571 : || op == EXEC_OMP_TEAMS_DISTRIBUTE \
13572 : || op == EXEC_OMP_TEAMS_DISTRIBUTE_SIMD \
13573 : || op == EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO \
13574 : || op == EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD \
13575 : || op == EXEC_OMP_TEAMS_LOOP)
13576 :
13577 2109 : if (!code->ext.omp_clauses->contains_teams_construct)
13578 : return;
13579 203 : gfc_code *c = code->block->next;
13580 203 : if (c->op == EXEC_BLOCK)
13581 30 : c = c->ext.block.ns->code;
13582 203 : if (code->ext.omp_clauses->target_first_st_is_teams_or_meta)
13583 : {
13584 192 : if (c->op == EXEC_OMP_METADIRECTIVE)
13585 : {
13586 15 : struct gfc_omp_variant *mc
13587 : = c->ext.omp_variants;
13588 : /* All mc->(next...->)code should be identical with regards
13589 : to the diagnostic below. */
13590 16 : do
13591 : {
13592 16 : if (mc->stmt != ST_NONE
13593 15 : && GFC_IS_TEAMS_CONSTRUCT (mc->code->op))
13594 : {
13595 14 : if (c->next == NULL && mc->code->next == NULL)
13596 : return;
13597 : c = mc->code;
13598 : break;
13599 : }
13600 2 : mc = mc->next;
13601 : }
13602 2 : while (mc);
13603 : }
13604 177 : else if (GFC_IS_TEAMS_CONSTRUCT (c->op) && c->next == NULL)
13605 : return;
13606 : }
13607 :
13608 31 : while (c && !GFC_IS_TEAMS_CONSTRUCT (c->op))
13609 8 : c = c->next;
13610 23 : if (c)
13611 19 : gfc_error ("!$OMP TARGET region at %L with a nested TEAMS at %L may not "
13612 : "contain any other statement, declaration or directive outside "
13613 : "of the single TEAMS construct", &c->loc, &code->loc);
13614 : else
13615 4 : gfc_error ("!$OMP TARGET region at %L with a nested TEAMS may not "
13616 : "contain any other statement, declaration or directive outside "
13617 : "of the single TEAMS construct", &code->loc);
13618 : #undef GFC_IS_TEAMS_CONSTRUCT
13619 : }
13620 :
13621 : static void
13622 154 : resolve_omp_dispatch (gfc_code *code)
13623 : {
13624 154 : gfc_code *next = code->block->next;
13625 154 : if (next == NULL)
13626 : return;
13627 :
13628 151 : gfc_exec_op op = next->op;
13629 151 : gcc_assert (op == EXEC_CALL || op == EXEC_ASSIGN);
13630 151 : if (op != EXEC_CALL
13631 74 : && (op != EXEC_ASSIGN || next->expr2->expr_type != EXPR_FUNCTION))
13632 3 : gfc_error (
13633 : "%<OMP DISPATCH%> directive at %L must be followed by a procedure "
13634 : "call with optional assignment",
13635 : &code->loc);
13636 :
13637 77 : if ((op == EXEC_CALL && next->resolved_sym != NULL
13638 76 : && next->resolved_sym->attr.proc_pointer)
13639 150 : || (op == EXEC_ASSIGN && gfc_expr_attr (next->expr2).proc_pointer))
13640 1 : gfc_error ("%<OMP DISPATCH%> directive at %L cannot be followed by a "
13641 : "procedure pointer",
13642 : &code->loc);
13643 : }
13644 :
13645 : /* Resolve OpenMP directive clauses and check various requirements
13646 : of each directive. */
13647 :
13648 : void
13649 21062 : gfc_resolve_omp_directive (gfc_code *code, gfc_namespace *ns)
13650 : {
13651 21062 : resolve_omp_directive_inside_oacc_region (code);
13652 :
13653 21062 : if (code->op != EXEC_OMP_ATOMIC)
13654 18908 : gfc_maybe_initialize_eh ();
13655 :
13656 21062 : switch (code->op)
13657 : {
13658 5420 : case EXEC_OMP_DISTRIBUTE:
13659 5420 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
13660 5420 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
13661 5420 : case EXEC_OMP_DISTRIBUTE_SIMD:
13662 5420 : case EXEC_OMP_DO:
13663 5420 : case EXEC_OMP_DO_SIMD:
13664 5420 : case EXEC_OMP_LOOP:
13665 5420 : case EXEC_OMP_PARALLEL_DO:
13666 5420 : case EXEC_OMP_PARALLEL_DO_SIMD:
13667 5420 : case EXEC_OMP_PARALLEL_LOOP:
13668 5420 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
13669 5420 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
13670 5420 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
13671 5420 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
13672 5420 : case EXEC_OMP_MASKED_TASKLOOP:
13673 5420 : case EXEC_OMP_MASKED_TASKLOOP_SIMD:
13674 5420 : case EXEC_OMP_MASTER_TASKLOOP:
13675 5420 : case EXEC_OMP_MASTER_TASKLOOP_SIMD:
13676 5420 : case EXEC_OMP_SIMD:
13677 5420 : case EXEC_OMP_TARGET_PARALLEL_DO:
13678 5420 : case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
13679 5420 : case EXEC_OMP_TARGET_PARALLEL_LOOP:
13680 5420 : case EXEC_OMP_TARGET_SIMD:
13681 5420 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
13682 5420 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
13683 5420 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
13684 5420 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
13685 5420 : case EXEC_OMP_TARGET_TEAMS_LOOP:
13686 5420 : case EXEC_OMP_TASKLOOP:
13687 5420 : case EXEC_OMP_TASKLOOP_SIMD:
13688 5420 : case EXEC_OMP_TEAMS_DISTRIBUTE:
13689 5420 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
13690 5420 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
13691 5420 : case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
13692 5420 : case EXEC_OMP_TEAMS_LOOP:
13693 5420 : case EXEC_OMP_TILE:
13694 5420 : case EXEC_OMP_UNROLL:
13695 5420 : resolve_omp_do (code);
13696 5420 : break;
13697 2109 : case EXEC_OMP_TARGET:
13698 2109 : resolve_omp_target (code);
13699 10115 : gcc_fallthrough ();
13700 10115 : case EXEC_OMP_ALLOCATE:
13701 10115 : case EXEC_OMP_ALLOCATORS:
13702 10115 : case EXEC_OMP_ASSUME:
13703 10115 : case EXEC_OMP_CANCEL:
13704 10115 : case EXEC_OMP_ERROR:
13705 10115 : case EXEC_OMP_INTEROP:
13706 10115 : case EXEC_OMP_MASKED:
13707 10115 : case EXEC_OMP_ORDERED:
13708 10115 : case EXEC_OMP_PARALLEL_WORKSHARE:
13709 10115 : case EXEC_OMP_PARALLEL:
13710 10115 : case EXEC_OMP_PARALLEL_MASKED:
13711 10115 : case EXEC_OMP_PARALLEL_MASTER:
13712 10115 : case EXEC_OMP_PARALLEL_SECTIONS:
13713 10115 : case EXEC_OMP_SCOPE:
13714 10115 : case EXEC_OMP_SECTIONS:
13715 10115 : case EXEC_OMP_SINGLE:
13716 10115 : case EXEC_OMP_TARGET_DATA:
13717 10115 : case EXEC_OMP_TARGET_ENTER_DATA:
13718 10115 : case EXEC_OMP_TARGET_EXIT_DATA:
13719 10115 : case EXEC_OMP_TARGET_PARALLEL:
13720 10115 : case EXEC_OMP_TARGET_TEAMS:
13721 10115 : case EXEC_OMP_TASK:
13722 10115 : case EXEC_OMP_TASKWAIT:
13723 10115 : case EXEC_OMP_TEAMS:
13724 10115 : case EXEC_OMP_WORKSHARE:
13725 10115 : case EXEC_OMP_DEPOBJ:
13726 10115 : if (code->ext.omp_clauses)
13727 9982 : resolve_omp_clauses (code, code->ext.omp_clauses, NULL);
13728 : break;
13729 1704 : case EXEC_OMP_TARGET_UPDATE:
13730 1704 : if (code->ext.omp_clauses)
13731 1704 : resolve_omp_clauses (code, code->ext.omp_clauses, NULL);
13732 1704 : if (code->ext.omp_clauses == NULL
13733 1704 : || (code->ext.omp_clauses->lists[OMP_LIST_TO] == NULL
13734 992 : && code->ext.omp_clauses->lists[OMP_LIST_FROM] == NULL))
13735 0 : gfc_error ("OMP TARGET UPDATE at %L requires at least one TO or "
13736 : "FROM clause", &code->loc);
13737 : break;
13738 2154 : case EXEC_OMP_ATOMIC:
13739 2154 : resolve_omp_clauses (code, code->block->ext.omp_clauses, NULL);
13740 2154 : resolve_omp_atomic (code);
13741 2154 : break;
13742 159 : case EXEC_OMP_CRITICAL:
13743 159 : resolve_omp_clauses (code, code->ext.omp_clauses, NULL);
13744 159 : if (!code->ext.omp_clauses->critical_name
13745 112 : && code->ext.omp_clauses->hint
13746 3 : && code->ext.omp_clauses->hint->ts.type == BT_INTEGER
13747 3 : && code->ext.omp_clauses->hint->expr_type == EXPR_CONSTANT
13748 3 : && mpz_sgn (code->ext.omp_clauses->hint->value.integer) != 0)
13749 1 : gfc_error ("OMP CRITICAL at %L with HINT clause requires a NAME, "
13750 : "except when omp_sync_hint_none is used", &code->loc);
13751 : break;
13752 49 : case EXEC_OMP_SCAN:
13753 : /* Flag is only used to checking, hence, it is unset afterwards. */
13754 49 : if (!code->ext.omp_clauses->if_present)
13755 10 : gfc_error ("Unexpected !$OMP SCAN at %L outside loop construct with "
13756 : "%<inscan%> REDUCTION clause", &code->loc);
13757 49 : code->ext.omp_clauses->if_present = false;
13758 49 : resolve_omp_clauses (code, code->ext.omp_clauses, ns);
13759 49 : break;
13760 154 : case EXEC_OMP_DISPATCH:
13761 154 : if (code->ext.omp_clauses)
13762 154 : resolve_omp_clauses (code, code->ext.omp_clauses, ns);
13763 154 : resolve_omp_dispatch (code);
13764 154 : break;
13765 138 : case EXEC_OMP_METADIRECTIVE:
13766 138 : resolve_omp_metadirective (code, ns);
13767 138 : break;
13768 : default:
13769 : break;
13770 : }
13771 21062 : }
13772 :
13773 : /* Resolve !$omp declare {variant|simd} constructs in NS.
13774 : Note that !$omp declare target is resolved in resolve_symbol. */
13775 :
13776 : void
13777 345787 : gfc_resolve_omp_declare (gfc_namespace *ns)
13778 : {
13779 345787 : gfc_omp_declare_simd *ods;
13780 346023 : for (ods = ns->omp_declare_simd; ods; ods = ods->next)
13781 : {
13782 236 : if (ods->proc_name != NULL
13783 196 : && ods->proc_name != ns->proc_name)
13784 6 : gfc_error ("!$OMP DECLARE SIMD should refer to containing procedure "
13785 : "%qs at %L", ns->proc_name->name, &ods->where);
13786 236 : if (ods->clauses)
13787 218 : resolve_omp_clauses (NULL, ods->clauses, ns);
13788 : }
13789 :
13790 345787 : gfc_omp_declare_variant *odv;
13791 345787 : gfc_omp_namelist *range_begin = NULL;
13792 :
13793 346241 : for (odv = ns->omp_declare_variant; odv; odv = odv->next)
13794 454 : gfc_resolve_omp_context_selector (odv->set_selectors, false, nullptr);
13795 346241 : for (odv = ns->omp_declare_variant; odv; odv = odv->next)
13796 657 : for (gfc_omp_namelist *n = odv->adjust_args_list; n != NULL; n = n->next)
13797 : {
13798 203 : if ((n->expr == NULL
13799 6 : && (range_begin
13800 4 : || n->u.adj_args.range_start
13801 1 : || n->u.adj_args.omp_num_args_plus
13802 1 : || n->u.adj_args.omp_num_args_minus))
13803 198 : || n->u.adj_args.error_p)
13804 : {
13805 : }
13806 197 : else if (range_begin
13807 191 : || n->u.adj_args.range_start
13808 186 : || n->u.adj_args.omp_num_args_plus
13809 186 : || n->u.adj_args.omp_num_args_minus)
13810 : {
13811 11 : if (!n->expr
13812 11 : || !gfc_resolve_expr (n->expr)
13813 11 : || n->expr->expr_type != EXPR_CONSTANT
13814 10 : || n->expr->ts.type != BT_INTEGER
13815 10 : || n->expr->rank != 0
13816 10 : || mpz_sgn (n->expr->value.integer) < 0
13817 20 : || ((n->u.adj_args.omp_num_args_plus
13818 8 : || n->u.adj_args.omp_num_args_minus)
13819 5 : && mpz_sgn (n->expr->value.integer) == 0))
13820 : {
13821 2 : if (n->u.adj_args.omp_num_args_plus
13822 2 : || n->u.adj_args.omp_num_args_minus)
13823 0 : gfc_error ("Expected constant non-negative scalar integer "
13824 : "offset expression at %L", &n->where);
13825 : else
13826 2 : gfc_error ("For range-based %<adjust_args%>, a constant "
13827 : "positive scalar integer expression is required "
13828 : "at %L", &n->where);
13829 : }
13830 : }
13831 186 : else if (n->expr
13832 186 : && n->expr->expr_type == EXPR_CONSTANT
13833 21 : && n->expr->ts.type == BT_INTEGER
13834 20 : && mpz_sgn (n->expr->value.integer) > 0)
13835 : {
13836 : }
13837 166 : else if (!n->expr
13838 166 : || !gfc_resolve_expr (n->expr)
13839 331 : || n->expr->expr_type != EXPR_VARIABLE)
13840 2 : gfc_error ("Expected dummy parameter name or a positive integer "
13841 : "at %L", &n->where);
13842 164 : else if (n->expr->expr_type == EXPR_VARIABLE)
13843 164 : n->sym = n->expr->symtree->n.sym;
13844 :
13845 203 : range_begin = n->u.adj_args.range_start ? n : NULL;
13846 : }
13847 345787 : }
13848 :
13849 : struct omp_udr_callback_data
13850 : {
13851 : gfc_omp_udr *omp_udr;
13852 : bool is_initializer;
13853 : };
13854 :
13855 : static int
13856 3598 : omp_udr_callback (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
13857 : void *data)
13858 : {
13859 3598 : struct omp_udr_callback_data *cd = (struct omp_udr_callback_data *) data;
13860 3598 : if ((*e)->expr_type == EXPR_VARIABLE)
13861 : {
13862 2203 : if (cd->is_initializer)
13863 : {
13864 535 : if ((*e)->symtree->n.sym != cd->omp_udr->omp_priv
13865 140 : && (*e)->symtree->n.sym != cd->omp_udr->omp_orig)
13866 4 : gfc_error ("Variable other than OMP_PRIV or OMP_ORIG used in "
13867 : "INITIALIZER clause of !$OMP DECLARE REDUCTION at %L",
13868 : &(*e)->where);
13869 : }
13870 : else
13871 : {
13872 1668 : if ((*e)->symtree->n.sym != cd->omp_udr->omp_out
13873 597 : && (*e)->symtree->n.sym != cd->omp_udr->omp_in)
13874 6 : gfc_error ("Variable other than OMP_OUT or OMP_IN used in "
13875 : "combiner of !$OMP DECLARE REDUCTION at %L",
13876 : &(*e)->where);
13877 : }
13878 : }
13879 3598 : return 0;
13880 : }
13881 :
13882 : /* Resolve !$omp declare reduction constructs. */
13883 :
13884 : static void
13885 600 : gfc_resolve_omp_udr (gfc_omp_udr *omp_udr)
13886 : {
13887 600 : gfc_actual_arglist *a;
13888 600 : const char *predef_name = NULL;
13889 :
13890 600 : switch (omp_udr->rop)
13891 : {
13892 599 : case OMP_REDUCTION_PLUS:
13893 599 : case OMP_REDUCTION_TIMES:
13894 599 : case OMP_REDUCTION_MINUS:
13895 599 : case OMP_REDUCTION_AND:
13896 599 : case OMP_REDUCTION_OR:
13897 599 : case OMP_REDUCTION_EQV:
13898 599 : case OMP_REDUCTION_NEQV:
13899 599 : case OMP_REDUCTION_MAX:
13900 599 : case OMP_REDUCTION_USER:
13901 599 : break;
13902 1 : default:
13903 1 : gfc_error ("Invalid operator for !$OMP DECLARE REDUCTION %s at %L",
13904 : omp_udr->name, &omp_udr->where);
13905 22 : return;
13906 : }
13907 :
13908 599 : if (gfc_omp_udr_predef (omp_udr->rop, omp_udr->name,
13909 : &omp_udr->ts, &predef_name))
13910 : {
13911 18 : if (predef_name)
13912 18 : gfc_error_now ("Redefinition of predefined %s "
13913 : "!$OMP DECLARE REDUCTION at %L",
13914 : predef_name, &omp_udr->where);
13915 : else
13916 0 : gfc_error_now ("Redefinition of predefined "
13917 : "!$OMP DECLARE REDUCTION at %L", &omp_udr->where);
13918 18 : return;
13919 : }
13920 :
13921 581 : if (omp_udr->ts.type == BT_CHARACTER
13922 62 : && omp_udr->ts.u.cl->length
13923 32 : && omp_udr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
13924 : {
13925 1 : gfc_error ("CHARACTER length in !$OMP DECLARE REDUCTION %s not "
13926 : "constant at %L", omp_udr->name, &omp_udr->where);
13927 1 : return;
13928 : }
13929 :
13930 580 : struct omp_udr_callback_data cd;
13931 580 : cd.omp_udr = omp_udr;
13932 580 : cd.is_initializer = false;
13933 580 : gfc_code_walker (&omp_udr->combiner_ns->code, gfc_dummy_code_callback,
13934 : omp_udr_callback, &cd);
13935 580 : if (omp_udr->combiner_ns->code->op == EXEC_CALL)
13936 : {
13937 346 : for (a = omp_udr->combiner_ns->code->ext.actual; a; a = a->next)
13938 237 : if (a->expr == NULL)
13939 : break;
13940 110 : if (a)
13941 1 : gfc_error ("Subroutine call with alternate returns in combiner "
13942 : "of !$OMP DECLARE REDUCTION at %L",
13943 : &omp_udr->combiner_ns->code->loc);
13944 : }
13945 580 : if (omp_udr->initializer_ns)
13946 : {
13947 373 : cd.is_initializer = true;
13948 373 : gfc_code_walker (&omp_udr->initializer_ns->code, gfc_dummy_code_callback,
13949 : omp_udr_callback, &cd);
13950 373 : if (omp_udr->initializer_ns->code->op == EXEC_CALL)
13951 : {
13952 377 : for (a = omp_udr->initializer_ns->code->ext.actual; a; a = a->next)
13953 243 : if (a->expr == NULL)
13954 : break;
13955 135 : if (a)
13956 1 : gfc_error ("Subroutine call with alternate returns in "
13957 : "INITIALIZER clause of !$OMP DECLARE REDUCTION "
13958 : "at %L", &omp_udr->initializer_ns->code->loc);
13959 136 : for (a = omp_udr->initializer_ns->code->ext.actual; a; a = a->next)
13960 135 : if (a->expr
13961 135 : && a->expr->expr_type == EXPR_VARIABLE
13962 135 : && a->expr->symtree->n.sym == omp_udr->omp_priv
13963 134 : && a->expr->ref == NULL)
13964 : break;
13965 135 : if (a == NULL)
13966 1 : gfc_error ("One of actual subroutine arguments in INITIALIZER "
13967 : "clause of !$OMP DECLARE REDUCTION must be OMP_PRIV "
13968 : "at %L", &omp_udr->initializer_ns->code->loc);
13969 : }
13970 : }
13971 207 : else if (omp_udr->ts.type == BT_DERIVED
13972 207 : && !gfc_has_default_initializer (omp_udr->ts.u.derived))
13973 : {
13974 1 : gfc_error ("Missing INITIALIZER clause for !$OMP DECLARE REDUCTION "
13975 : "of derived type without default initializer at %L",
13976 : &omp_udr->where);
13977 1 : return;
13978 : }
13979 : }
13980 :
13981 : void
13982 346795 : gfc_resolve_omp_udrs (gfc_symtree *st)
13983 : {
13984 346795 : gfc_omp_udr *omp_udr;
13985 :
13986 346795 : if (st == NULL)
13987 : return;
13988 504 : gfc_resolve_omp_udrs (st->left);
13989 504 : gfc_resolve_omp_udrs (st->right);
13990 1104 : for (omp_udr = st->n.omp_udr; omp_udr; omp_udr = omp_udr->next)
13991 600 : gfc_resolve_omp_udr (omp_udr);
13992 : }
13993 :
13994 : /* Resolve !$omp declare mapper constructs. */
13995 :
13996 : static void
13997 6 : gfc_resolve_omp_udm (gfc_omp_udm *omp_udm)
13998 : {
13999 6 : resolve_omp_clauses (NULL, omp_udm->clauses, omp_udm->mapper_ns);
14000 :
14001 6 : gfc_omp_namelist *n;
14002 8 : for (n = omp_udm->clauses->lists[OMP_LIST_MAP]; n; n = n->next)
14003 6 : if (n->sym == omp_udm->var_sym)
14004 : break;
14005 6 : if (!n)
14006 2 : gfc_error ("At least one %<map%> clause in !$OMP DECLARE MAPPER at %L must "
14007 : "map %qs or an element of it",
14008 2 : &omp_udm->where, omp_udm->var_sym->name);
14009 6 : }
14010 :
14011 : void
14012 345799 : gfc_resolve_omp_udms (gfc_symtree *st)
14013 : {
14014 345799 : gfc_omp_udm *omp_udm;
14015 :
14016 345799 : if (st == NULL)
14017 : return;
14018 6 : gfc_resolve_omp_udms (st->left);
14019 6 : gfc_resolve_omp_udms (st->right);
14020 12 : for (omp_udm = st->n.omp_udm; omp_udm; omp_udm = omp_udm->next)
14021 6 : gfc_resolve_omp_udm (omp_udm);
14022 : }
|