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 55977 : gfc_match_omp_eos (void)
135 : {
136 55977 : locus old_loc;
137 55977 : char c;
138 :
139 55977 : old_loc = gfc_current_locus;
140 55977 : gfc_gobble_whitespace ();
141 :
142 55977 : if (gfc_matching_omp_context_selector)
143 : {
144 269 : if (gfc_peek_ascii_char () == ')')
145 : return MATCH_YES;
146 : }
147 : else
148 : {
149 55708 : c = gfc_next_ascii_char ();
150 55708 : 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 53960 : case '\n':
159 53960 : return MATCH_YES;
160 : }
161 : }
162 :
163 1749 : gfc_current_locus = old_loc;
164 1749 : return MATCH_NO;
165 : }
166 :
167 : match
168 13206 : gfc_match_omp_eos_error (void)
169 : {
170 13206 : 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 62205 : gfc_free_omp_clauses (gfc_omp_clauses *c)
182 : {
183 62205 : if (c == NULL)
184 : return;
185 :
186 35223 : gfc_free_expr (c->if_expr);
187 387453 : for (int i = 0; i < OMP_IF_LAST; i++)
188 352230 : gfc_free_expr (c->if_exprs[i]);
189 35223 : gfc_free_expr (c->self_expr);
190 35223 : gfc_free_expr (c->final_expr);
191 35223 : gfc_free_expr (c->chunk_size);
192 35223 : gfc_free_expr (c->safelen_expr);
193 35223 : gfc_free_expr (c->simdlen_expr);
194 35223 : gfc_free_expr (c->device);
195 35223 : gfc_free_expr (c->dyn_groupprivate);
196 35223 : gfc_free_expr (c->dist_chunk_size);
197 35223 : gfc_free_expr (c->grainsize);
198 35223 : gfc_free_expr (c->hint);
199 35223 : gfc_free_expr (c->num_tasks);
200 35223 : gfc_free_expr (c->priority);
201 35223 : gfc_free_expr (c->detach);
202 35223 : gfc_free_expr (c->novariants);
203 35223 : gfc_free_expr (c->nocontext);
204 35223 : gfc_free_expr (c->async_expr);
205 35223 : gfc_free_expr (c->gang_num_expr);
206 35223 : gfc_free_expr (c->gang_static_expr);
207 35223 : gfc_free_expr (c->worker_expr);
208 35223 : gfc_free_expr (c->vector_expr);
209 35223 : gfc_free_expr (c->num_gangs_expr);
210 35223 : gfc_free_expr (c->num_workers_expr);
211 35223 : gfc_free_expr (c->vector_length_expr);
212 35223 : gfc_free_expr (c->device_num_expr);
213 1408920 : for (enum gfc_omp_list_type t = OMP_LIST_FIRST; t < OMP_LIST_NUM;
214 1373697 : t = gfc_omp_list_type (t + 1))
215 1373697 : gfc_free_omp_namelist (c->lists[t], t);
216 35223 : gfc_free_expr_list (c->num_teams_list);
217 35223 : gfc_free_expr_list (c->thread_limit_list);
218 35223 : gfc_free_expr_list (c->num_threads_list);
219 35223 : gfc_free_expr_list (c->wait_list);
220 35223 : gfc_free_expr_list (c->tile_list);
221 35223 : gfc_free_expr_list (c->sizes_list);
222 35223 : free (const_cast<char *> (c->critical_name));
223 35223 : 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 35223 : 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 212357 : gfc_free_expr_list (gfc_expr_list *list)
255 : {
256 212357 : gfc_expr_list *n;
257 :
258 215145 : for (; list; list = n)
259 : {
260 2788 : n = list->next;
261 2788 : free (list);
262 : }
263 212357 : }
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 543391 : gfc_free_omp_declare_simd_list (gfc_omp_declare_simd *list)
279 : {
280 543627 : 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 543391 : }
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 543391 : gfc_free_omp_declare_variant_list (gfc_omp_declare_variant *list)
342 : {
343 543845 : 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 543391 : }
352 :
353 : /* Free an !$omp declare reduction. */
354 :
355 : void
356 1271 : gfc_free_omp_udr (gfc_omp_udr *omp_udr)
357 : {
358 1271 : if (omp_udr)
359 : {
360 685 : gfc_free_omp_udr (omp_udr->next);
361 685 : gfc_free_namespace (omp_udr->combiner_ns);
362 685 : if (omp_udr->initializer_ns)
363 386 : gfc_free_namespace (omp_udr->initializer_ns);
364 685 : free (omp_udr);
365 : }
366 1271 : }
367 :
368 : /* Free variants of an !$omp metadirective construct. */
369 :
370 : void
371 93 : gfc_free_omp_variants (gfc_omp_variant *variant)
372 : {
373 284 : while (variant)
374 : {
375 191 : gfc_omp_variant *next_variant = variant->next;
376 191 : gfc_free_omp_set_selector_list (variant->selectors);
377 191 : free (variant);
378 191 : variant = next_variant;
379 : }
380 93 : }
381 :
382 : /* Free an !$omp declare mapper. */
383 :
384 : void
385 46 : gfc_free_omp_udm (gfc_omp_udm *omp_udm)
386 : {
387 46 : if (omp_udm)
388 : {
389 23 : gfc_free_omp_udm (omp_udm->next);
390 23 : gfc_free_namespace (omp_udm->mapper_ns);
391 23 : free (omp_udm);
392 : }
393 46 : }
394 :
395 : static gfc_omp_udr *
396 4716 : gfc_find_omp_udr (gfc_namespace *ns, const char *name, gfc_typespec *ts)
397 : {
398 4716 : gfc_symtree *st;
399 :
400 4716 : if (ns == NULL)
401 470 : ns = gfc_current_ns;
402 5664 : do
403 : {
404 5664 : gfc_omp_udr *omp_udr;
405 :
406 5664 : st = gfc_find_symtree (ns->omp_udr_root, name);
407 5664 : if (st != NULL)
408 : {
409 941 : for (omp_udr = st->n.omp_udr; omp_udr; omp_udr = omp_udr->next)
410 941 : if (ts == NULL)
411 : return omp_udr;
412 571 : else if (gfc_compare_types (&omp_udr->ts, ts))
413 : {
414 482 : if (ts->type == BT_CHARACTER)
415 : {
416 60 : if (omp_udr->ts.u.cl->length == NULL)
417 : return omp_udr;
418 36 : if (ts->u.cl->length == NULL)
419 0 : continue;
420 36 : if (gfc_compare_expr (omp_udr->ts.u.cl->length,
421 : ts->u.cl->length,
422 : INTRINSIC_EQ) != 0)
423 12 : continue;
424 : }
425 446 : return omp_udr;
426 : }
427 : }
428 :
429 : /* Don't escape an interface block. */
430 4824 : if (ns && !ns->has_import_set
431 4824 : && ns->proc_name && ns->proc_name->attr.if_source == IFSRC_IFBODY)
432 : break;
433 :
434 4824 : ns = ns->parent;
435 : }
436 4824 : while (ns != NULL);
437 :
438 : return NULL;
439 : }
440 :
441 :
442 : /* Match a variable/common block list and construct a namelist from it;
443 : if has_all_memory != NULL, *has_all_memory is set and omp_all_memory
444 : yields a list->sym NULL entry. */
445 :
446 : static match
447 31751 : 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 31751 : gfc_omp_namelist *head, *tail, *p;
457 31751 : locus old_loc, cur_loc;
458 31751 : char n[GFC_MAX_SYMBOL_LEN+1];
459 31751 : gfc_symbol *sym;
460 31751 : match m;
461 31751 : gfc_symtree *st;
462 :
463 31751 : head = tail = NULL;
464 :
465 31751 : old_loc = gfc_current_locus;
466 31751 : if (has_all_memory)
467 708 : *has_all_memory = false;
468 31751 : m = gfc_match (str);
469 31751 : if (m != MATCH_YES)
470 : return m;
471 :
472 38493 : for (;;)
473 : {
474 38493 : gfc_gobble_whitespace ();
475 38493 : cur_loc = gfc_current_locus;
476 :
477 38493 : m = gfc_match_name (n);
478 38493 : if (m == MATCH_YES && strcmp (n, "omp_all_memory") == 0)
479 : {
480 23 : locus loc = gfc_get_location_range (NULL, 0, &cur_loc, 1,
481 : &gfc_current_locus);
482 23 : if (!has_all_memory)
483 : {
484 2 : gfc_error ("%<omp_all_memory%> at %L not permitted in this "
485 : "clause", &loc);
486 2 : goto cleanup;
487 : }
488 21 : *has_all_memory = true;
489 21 : p = gfc_get_omp_namelist ();
490 21 : if (head == NULL)
491 : head = tail = p;
492 : else
493 : {
494 3 : tail->next = p;
495 3 : tail = tail->next;
496 : }
497 21 : tail->where = loc;
498 21 : goto next_item;
499 : }
500 38214 : if (m == MATCH_YES)
501 : {
502 38214 : gfc_symtree *st;
503 38214 : if ((m = gfc_get_ha_sym_tree (n, &st) ? MATCH_ERROR : MATCH_YES)
504 : == MATCH_YES)
505 38214 : sym = st->n.sym;
506 : }
507 38470 : switch (m)
508 : {
509 38214 : case MATCH_YES:
510 38214 : gfc_expr *expr;
511 38214 : expr = NULL;
512 38214 : gfc_gobble_whitespace ();
513 23527 : if ((allow_sections && gfc_peek_ascii_char () == '(')
514 57379 : || (allow_derived && gfc_peek_ascii_char () == '%'))
515 : {
516 6602 : gfc_current_locus = cur_loc;
517 6602 : m = gfc_match_variable (&expr, 0);
518 6602 : switch (m)
519 : {
520 4 : case MATCH_ERROR:
521 12 : goto cleanup;
522 0 : case MATCH_NO:
523 0 : goto syntax;
524 6598 : default:
525 6598 : break;
526 : }
527 6598 : if (gfc_is_coindexed (expr))
528 : {
529 5 : gfc_error ("List item shall not be coindexed at %L",
530 5 : &expr->where);
531 5 : goto cleanup;
532 : }
533 : }
534 38205 : gfc_set_sym_referenced (sym);
535 38205 : p = gfc_get_omp_namelist ();
536 38205 : if (head == NULL)
537 : head = tail = p;
538 10165 : else if (reverse_order)
539 : {
540 57 : p->next = head;
541 57 : head = p;
542 : }
543 : else
544 : {
545 10108 : tail->next = p;
546 10108 : tail = tail->next;
547 : }
548 38205 : p->sym = sym;
549 38205 : p->expr = expr;
550 38205 : p->where = gfc_get_location_range (NULL, 0, &cur_loc, 1,
551 : &gfc_current_locus);
552 38205 : if (reject_common_vars && sym->attr.in_common)
553 : {
554 3 : gcc_assert (allow_common);
555 3 : gfc_error ("%qs at %L is part of the common block %</%s/%> and "
556 : "may only be specified implicitly via the named "
557 : "common block", sym->name, &cur_loc,
558 3 : sym->common_head->name);
559 3 : goto cleanup;
560 : }
561 38202 : goto next_item;
562 256 : case MATCH_NO:
563 256 : break;
564 0 : case MATCH_ERROR:
565 0 : goto cleanup;
566 : }
567 :
568 256 : if (!allow_common)
569 12 : goto syntax;
570 :
571 244 : m = gfc_match ("/ %n /", n);
572 244 : if (m == MATCH_ERROR)
573 0 : goto cleanup;
574 244 : if (m == MATCH_NO)
575 19 : goto syntax;
576 :
577 225 : cur_loc = gfc_get_location_range (NULL, 0, &cur_loc, 1,
578 : &gfc_current_locus);
579 225 : st = gfc_find_symtree (gfc_current_ns->common_root, n);
580 225 : if (st == NULL)
581 : {
582 2 : gfc_error ("COMMON block %</%s/%> not found at %L", n, &cur_loc);
583 2 : goto cleanup;
584 : }
585 724 : for (sym = st->n.common->head; sym; sym = sym->common_next)
586 : {
587 501 : gfc_set_sym_referenced (sym);
588 501 : p = gfc_get_omp_namelist ();
589 501 : if (head == NULL)
590 : head = tail = p;
591 325 : else if (reverse_order)
592 : {
593 0 : p->next = head;
594 0 : head = p;
595 : }
596 : else
597 : {
598 325 : tail->next = p;
599 325 : tail = tail->next;
600 : }
601 501 : p->sym = sym;
602 501 : p->where = cur_loc;
603 : }
604 :
605 223 : next_item:
606 38446 : if (end_colon && gfc_match_char (':') == MATCH_YES)
607 : {
608 793 : *end_colon = true;
609 793 : break;
610 : }
611 37653 : if (gfc_match_char (')') == MATCH_YES)
612 : break;
613 10236 : if (gfc_match_char (',') != MATCH_YES)
614 21 : goto syntax;
615 : }
616 :
617 38248 : while (*list)
618 10038 : list = &(*list)->next;
619 :
620 28210 : *list = head;
621 28210 : if (headp)
622 22317 : *headp = list;
623 : return MATCH_YES;
624 :
625 52 : syntax:
626 52 : gfc_error ("Syntax error in OpenMP variable list at %C");
627 :
628 68 : cleanup:
629 68 : gfc_free_omp_namelist (head, OMP_LIST_NONE);
630 68 : gfc_current_locus = old_loc;
631 68 : return MATCH_ERROR;
632 : }
633 :
634 : /* Match a variable/procedure/common block list and construct a namelist
635 : from it. */
636 :
637 : static match
638 363 : gfc_match_omp_to_link (const char *str, gfc_omp_namelist **list)
639 : {
640 363 : gfc_omp_namelist *head, *tail, *p;
641 363 : locus old_loc, cur_loc;
642 363 : char n[GFC_MAX_SYMBOL_LEN+1];
643 363 : gfc_symbol *sym;
644 363 : match m;
645 363 : gfc_symtree *st;
646 :
647 363 : head = tail = NULL;
648 :
649 363 : old_loc = gfc_current_locus;
650 :
651 363 : m = gfc_match (str);
652 363 : if (m != MATCH_YES)
653 : return m;
654 :
655 549 : for (;;)
656 : {
657 549 : cur_loc = gfc_current_locus;
658 549 : m = gfc_match_symbol (&sym, 1);
659 549 : switch (m)
660 : {
661 508 : case MATCH_YES:
662 508 : p = gfc_get_omp_namelist ();
663 508 : if (head == NULL)
664 : head = tail = p;
665 : else
666 : {
667 194 : tail->next = p;
668 194 : tail = tail->next;
669 : }
670 508 : tail->sym = sym;
671 508 : tail->where = cur_loc;
672 508 : goto next_item;
673 : case MATCH_NO:
674 : break;
675 0 : case MATCH_ERROR:
676 0 : goto cleanup;
677 : }
678 :
679 41 : m = gfc_match (" / %n /", n);
680 41 : if (m == MATCH_ERROR)
681 0 : goto cleanup;
682 41 : if (m == MATCH_NO)
683 0 : goto syntax;
684 :
685 41 : st = gfc_find_symtree (gfc_current_ns->common_root, n);
686 41 : if (st == NULL)
687 : {
688 0 : gfc_error ("COMMON block /%s/ not found at %C", n);
689 0 : goto cleanup;
690 : }
691 41 : p = gfc_get_omp_namelist ();
692 41 : if (head == NULL)
693 : head = tail = p;
694 : else
695 : {
696 4 : tail->next = p;
697 4 : tail = tail->next;
698 : }
699 41 : tail->u.common = st->n.common;
700 41 : tail->where = cur_loc;
701 :
702 549 : next_item:
703 549 : if (gfc_match_char (')') == MATCH_YES)
704 : break;
705 198 : if (gfc_match_char (',') != MATCH_YES)
706 0 : goto syntax;
707 : }
708 :
709 362 : while (*list)
710 11 : list = &(*list)->next;
711 :
712 351 : *list = head;
713 351 : return MATCH_YES;
714 :
715 0 : syntax:
716 0 : gfc_error ("Syntax error in OpenMP variable list at %C");
717 :
718 0 : cleanup:
719 0 : gfc_free_omp_namelist (head, OMP_LIST_NONE);
720 0 : gfc_current_locus = old_loc;
721 0 : return MATCH_ERROR;
722 : }
723 :
724 : /* Match detach(event-handle). */
725 :
726 : static match
727 126 : gfc_match_omp_detach (gfc_expr **expr)
728 : {
729 126 : locus old_loc = gfc_current_locus;
730 :
731 126 : if (gfc_match ("detach ( ") != MATCH_YES)
732 0 : goto syntax_error;
733 :
734 126 : if (gfc_match_variable (expr, 0) != MATCH_YES)
735 0 : goto syntax_error;
736 :
737 126 : if (gfc_match_char (')') != MATCH_YES)
738 0 : goto syntax_error;
739 :
740 : return MATCH_YES;
741 :
742 0 : syntax_error:
743 0 : gfc_error ("Syntax error in OpenMP detach clause at %C");
744 0 : gfc_current_locus = old_loc;
745 0 : return MATCH_ERROR;
746 :
747 : }
748 :
749 : /* Match doacross(sink : ...) construct a namelist from it;
750 : if depend is true, match legacy 'depend(sink : ...)'. */
751 :
752 : static match
753 241 : gfc_match_omp_doacross_sink (gfc_omp_namelist **list, bool depend)
754 : {
755 241 : char n[GFC_MAX_SYMBOL_LEN+1];
756 241 : gfc_omp_namelist *head, *tail, *p;
757 241 : locus old_loc, cur_loc;
758 241 : gfc_symbol *sym;
759 :
760 241 : head = tail = NULL;
761 :
762 241 : old_loc = gfc_current_locus;
763 :
764 2231 : for (;;)
765 : {
766 1236 : gfc_gobble_whitespace ();
767 1236 : cur_loc = gfc_current_locus;
768 :
769 1236 : if (gfc_match_name (n) != MATCH_YES)
770 1 : goto syntax;
771 1235 : locus loc = gfc_get_location_range (NULL, 0, &cur_loc, 1,
772 : &gfc_current_locus);
773 1235 : if (UNLIKELY (strcmp (n, "omp_all_memory") == 0))
774 : {
775 1 : gfc_error ("%<omp_all_memory%> used with dependence-type "
776 : "other than OUT or INOUT at %L", &loc);
777 1 : goto cleanup;
778 : }
779 1234 : sym = NULL;
780 1234 : if (!(strcmp (n, "omp_cur_iteration") == 0))
781 : {
782 1229 : gfc_symtree *st;
783 1229 : if (gfc_get_ha_sym_tree (n, &st))
784 0 : goto syntax;
785 1229 : sym = st->n.sym;
786 1229 : gfc_set_sym_referenced (sym);
787 : }
788 1234 : p = gfc_get_omp_namelist ();
789 1234 : if (head == NULL)
790 : {
791 239 : head = tail = p;
792 253 : head->u.depend_doacross_op = (depend ? OMP_DEPEND_SINK_FIRST
793 : : OMP_DOACROSS_SINK_FIRST);
794 : }
795 : else
796 : {
797 995 : tail->next = p;
798 995 : tail = tail->next;
799 995 : tail->u.depend_doacross_op = OMP_DOACROSS_SINK;
800 : }
801 1234 : tail->sym = sym;
802 1234 : tail->expr = NULL;
803 1234 : tail->where = loc;
804 1234 : if (gfc_match_char ('+') == MATCH_YES)
805 : {
806 154 : if (gfc_match_literal_constant (&tail->expr, 0) != MATCH_YES)
807 0 : goto syntax;
808 : }
809 1080 : else if (gfc_match_char ('-') == MATCH_YES)
810 : {
811 418 : if (gfc_match_literal_constant (&tail->expr, 0) != MATCH_YES)
812 1 : goto syntax;
813 417 : tail->expr = gfc_uminus (tail->expr);
814 : }
815 1233 : if (gfc_match_char (')') == MATCH_YES)
816 : break;
817 995 : if (gfc_match_char (',') != MATCH_YES)
818 0 : goto syntax;
819 995 : }
820 :
821 1030 : while (*list)
822 792 : list = &(*list)->next;
823 :
824 238 : *list = head;
825 238 : return MATCH_YES;
826 :
827 2 : syntax:
828 2 : gfc_error ("Syntax error in OpenMP SINK dependence-type list at %C");
829 :
830 3 : cleanup:
831 3 : gfc_free_omp_namelist (head, OMP_LIST_DEPEND);
832 3 : gfc_current_locus = old_loc;
833 3 : return MATCH_ERROR;
834 : }
835 :
836 : static int
837 332 : match_oacc_device_type_kind (void)
838 : {
839 332 : char name[GFC_MAX_SYMBOL_LEN + 1];
840 :
841 : /* Since device_type arg accept * as all,
842 : we need to check first the case when
843 : the user inputs * as the parameter. */
844 332 : gfc_gobble_whitespace ();
845 332 : name[0] = (char) gfc_next_char ();
846 :
847 332 : if (name[0] == '*')
848 : return GOMP_DEVICE_NONE;
849 :
850 : /* If is not *, we try to match the
851 : pre-defined names. */
852 :
853 332 : match m = gfc_match (" %n ", name + 1);
854 :
855 332 : if (m != MATCH_YES)
856 : return -1;
857 :
858 332 : if (strcmp (name ,"host") == 0)
859 : return GOMP_DEVICE_HOST;
860 144 : if (strcmp (name, "nvidia") == 0)
861 : return GOMP_DEVICE_NVIDIA_PTX;
862 72 : if (strcmp (name, "radeon") == 0)
863 69 : return GOMP_DEVICE_GCN;
864 :
865 : return -1;
866 : }
867 :
868 : static match
869 332 : match_oacc_device_type (gfc_omp_clauses *c)
870 : {
871 332 : locus old_loc = gfc_current_locus;
872 :
873 332 : int result = match_oacc_device_type_kind ();
874 332 : match m;
875 :
876 332 : if (result == -1)
877 3 : goto syntax;
878 :
879 329 : m = gfc_match_char (')', true);
880 :
881 329 : if (m != MATCH_YES)
882 3 : goto single_argument;
883 :
884 326 : c->oacc_device_type = (unsigned) result;
885 326 : c->oacc_device_type_present = 1;
886 :
887 326 : return MATCH_YES;
888 :
889 3 : single_argument:
890 3 : gfc_error ("OpenACC %<DEVICE_TYPE%> clause only accepts one argument, "
891 : "unexpected char at %C");
892 3 : goto cleanup;
893 :
894 3 : syntax:
895 3 : gfc_error ("Syntax error in OpenACC %<DEVICE_TYPE%> argument at %C. Expected "
896 : "host, radeon, nvidia or * as argument.");
897 :
898 6 : cleanup:
899 6 : gfc_current_locus = old_loc;
900 6 : return MATCH_ERROR;
901 : }
902 :
903 : static match
904 1960 : match_omp_oacc_expr_list (const char *str, gfc_expr_list **list,
905 : bool allow_asterisk, bool is_omp)
906 : {
907 1960 : gfc_expr_list *head, *tail, *p;
908 1960 : locus old_loc;
909 1960 : gfc_expr *expr;
910 1960 : match m;
911 :
912 1960 : head = tail = NULL;
913 :
914 1960 : old_loc = gfc_current_locus;
915 :
916 1960 : if (str && (m = gfc_match (str)) != MATCH_YES)
917 : return m;
918 :
919 2237 : for (;;)
920 : {
921 2237 : m = gfc_match_expr (&expr);
922 2237 : if (m == MATCH_YES || allow_asterisk)
923 : {
924 2220 : p = gfc_get_expr_list ();
925 2220 : if (head == NULL)
926 : head = tail = p;
927 : else
928 : {
929 400 : tail->next = p;
930 400 : tail = tail->next;
931 : }
932 2220 : if (m == MATCH_YES)
933 2087 : tail->expr = expr;
934 133 : else if (gfc_match (" *") != MATCH_YES)
935 18 : goto syntax;
936 2202 : goto next_item;
937 : }
938 17 : if (m == MATCH_ERROR)
939 0 : goto cleanup;
940 17 : goto syntax;
941 :
942 2202 : next_item:
943 2202 : if (gfc_match_char (')') == MATCH_YES)
944 : break;
945 422 : if (gfc_match_char (',') != MATCH_YES)
946 17 : goto syntax;
947 : }
948 :
949 1786 : while (*list)
950 6 : list = &(*list)->next;
951 :
952 1780 : *list = head;
953 1780 : return MATCH_YES;
954 :
955 52 : syntax:
956 52 : if (is_omp)
957 23 : gfc_error ("Syntax error in OpenMP expression list at %C");
958 : else
959 29 : gfc_error ("Syntax error in OpenACC expression list at %C");
960 :
961 52 : cleanup:
962 52 : gfc_free_expr_list (head);
963 52 : gfc_current_locus = old_loc;
964 52 : return MATCH_ERROR;
965 : }
966 :
967 : static match
968 3056 : match_oacc_clause_gwv (gfc_omp_clauses *cp, unsigned gwv)
969 : {
970 3056 : match ret = MATCH_YES;
971 :
972 3056 : if (gfc_match (" ( ") != MATCH_YES)
973 : return MATCH_NO;
974 :
975 470 : if (gwv == GOMP_DIM_GANG)
976 : {
977 : /* The gang clause accepts two optional arguments, num and static.
978 : The num argument may either be explicit (num: <val>) or
979 : implicit without (<val> without num:). */
980 :
981 457 : while (ret == MATCH_YES)
982 : {
983 236 : if (gfc_match (" static :") == MATCH_YES)
984 : {
985 114 : if (cp->gang_static)
986 : return MATCH_ERROR;
987 : else
988 113 : cp->gang_static = true;
989 113 : if (gfc_match_char ('*') == MATCH_YES)
990 18 : cp->gang_static_expr = NULL;
991 95 : else if (gfc_match (" %e ", &cp->gang_static_expr) != MATCH_YES)
992 : return MATCH_ERROR;
993 : }
994 : else
995 : {
996 122 : if (cp->gang_num_expr)
997 : return MATCH_ERROR;
998 :
999 : /* The 'num' argument is optional. */
1000 121 : gfc_match (" num :");
1001 :
1002 121 : if (gfc_match (" %e ", &cp->gang_num_expr) != MATCH_YES)
1003 : return MATCH_ERROR;
1004 : }
1005 :
1006 231 : ret = gfc_match (" , ");
1007 : }
1008 : }
1009 244 : else if (gwv == GOMP_DIM_WORKER)
1010 : {
1011 : /* The 'num' argument is optional. */
1012 107 : gfc_match (" num :");
1013 :
1014 107 : if (gfc_match (" %e ", &cp->worker_expr) != MATCH_YES)
1015 : return MATCH_ERROR;
1016 : }
1017 137 : else if (gwv == GOMP_DIM_VECTOR)
1018 : {
1019 : /* The 'length' argument is optional. */
1020 137 : gfc_match (" length :");
1021 :
1022 137 : if (gfc_match (" %e ", &cp->vector_expr) != MATCH_YES)
1023 : return MATCH_ERROR;
1024 : }
1025 : else
1026 0 : gfc_fatal_error ("Unexpected OpenACC parallelism.");
1027 :
1028 459 : return gfc_match (" )");
1029 : }
1030 :
1031 : static match
1032 8 : gfc_match_oacc_clause_link (const char *str, gfc_omp_namelist **list)
1033 : {
1034 8 : gfc_omp_namelist *head = NULL;
1035 8 : gfc_omp_namelist *tail, *p;
1036 8 : locus old_loc;
1037 8 : char n[GFC_MAX_SYMBOL_LEN+1];
1038 8 : gfc_symbol *sym;
1039 8 : match m;
1040 8 : gfc_symtree *st;
1041 :
1042 8 : old_loc = gfc_current_locus;
1043 :
1044 8 : m = gfc_match (str);
1045 8 : if (m != MATCH_YES)
1046 : return m;
1047 :
1048 8 : m = gfc_match (" (");
1049 :
1050 14 : for (;;)
1051 : {
1052 14 : m = gfc_match_symbol (&sym, 0);
1053 14 : switch (m)
1054 : {
1055 8 : case MATCH_YES:
1056 8 : if (sym->attr.in_common)
1057 : {
1058 2 : gfc_error_now ("Variable at %C is an element of a COMMON block");
1059 2 : goto cleanup;
1060 : }
1061 6 : gfc_set_sym_referenced (sym);
1062 6 : p = gfc_get_omp_namelist ();
1063 6 : if (head == NULL)
1064 : head = tail = p;
1065 : else
1066 : {
1067 4 : tail->next = p;
1068 4 : tail = tail->next;
1069 : }
1070 6 : tail->sym = sym;
1071 6 : tail->expr = NULL;
1072 6 : tail->where = gfc_current_locus;
1073 6 : goto next_item;
1074 : case MATCH_NO:
1075 : break;
1076 :
1077 0 : case MATCH_ERROR:
1078 0 : goto cleanup;
1079 : }
1080 :
1081 6 : m = gfc_match (" / %n /", n);
1082 6 : if (m == MATCH_ERROR)
1083 0 : goto cleanup;
1084 6 : if (m == MATCH_NO || n[0] == '\0')
1085 0 : goto syntax;
1086 :
1087 6 : st = gfc_find_symtree (gfc_current_ns->common_root, n);
1088 6 : if (st == NULL)
1089 : {
1090 1 : gfc_error ("COMMON block /%s/ not found at %C", n);
1091 1 : goto cleanup;
1092 : }
1093 :
1094 20 : for (sym = st->n.common->head; sym; sym = sym->common_next)
1095 : {
1096 15 : gfc_set_sym_referenced (sym);
1097 15 : p = gfc_get_omp_namelist ();
1098 15 : if (head == NULL)
1099 : head = tail = p;
1100 : else
1101 : {
1102 12 : tail->next = p;
1103 12 : tail = tail->next;
1104 : }
1105 15 : tail->sym = sym;
1106 15 : tail->where = gfc_current_locus;
1107 : }
1108 :
1109 5 : next_item:
1110 11 : if (gfc_match_char (')') == MATCH_YES)
1111 : break;
1112 6 : if (gfc_match_char (',') != MATCH_YES)
1113 0 : goto syntax;
1114 : }
1115 :
1116 5 : if (gfc_match_omp_eos () != MATCH_YES)
1117 : {
1118 1 : gfc_error ("Unexpected junk after !$ACC DECLARE at %C");
1119 1 : goto cleanup;
1120 : }
1121 :
1122 4 : while (*list)
1123 0 : list = &(*list)->next;
1124 4 : *list = head;
1125 4 : return MATCH_YES;
1126 :
1127 0 : syntax:
1128 0 : gfc_error ("Syntax error in !$ACC DECLARE list at %C");
1129 :
1130 4 : cleanup:
1131 4 : gfc_current_locus = old_loc;
1132 4 : return MATCH_ERROR;
1133 : }
1134 :
1135 : /* OpenMP clauses. */
1136 : enum omp_mask1
1137 : {
1138 : OMP_CLAUSE_PRIVATE,
1139 : OMP_CLAUSE_FIRSTPRIVATE,
1140 : OMP_CLAUSE_LASTPRIVATE,
1141 : OMP_CLAUSE_COPYPRIVATE,
1142 : OMP_CLAUSE_SHARED,
1143 : OMP_CLAUSE_COPYIN,
1144 : OMP_CLAUSE_REDUCTION,
1145 : OMP_CLAUSE_IN_REDUCTION,
1146 : OMP_CLAUSE_TASK_REDUCTION,
1147 : OMP_CLAUSE_IF,
1148 : OMP_CLAUSE_NUM_THREADS,
1149 : OMP_CLAUSE_SCHEDULE,
1150 : OMP_CLAUSE_DEFAULT,
1151 : OMP_CLAUSE_ORDER,
1152 : OMP_CLAUSE_ORDERED,
1153 : OMP_CLAUSE_COLLAPSE,
1154 : OMP_CLAUSE_UNTIED,
1155 : OMP_CLAUSE_FINAL,
1156 : OMP_CLAUSE_MERGEABLE,
1157 : OMP_CLAUSE_ALIGNED,
1158 : OMP_CLAUSE_DEPEND,
1159 : OMP_CLAUSE_INBRANCH,
1160 : OMP_CLAUSE_LINEAR,
1161 : OMP_CLAUSE_NOTINBRANCH,
1162 : OMP_CLAUSE_PROC_BIND,
1163 : OMP_CLAUSE_SAFELEN,
1164 : OMP_CLAUSE_SIMDLEN,
1165 : OMP_CLAUSE_UNIFORM,
1166 : OMP_CLAUSE_DEVICE,
1167 : OMP_CLAUSE_MAP,
1168 : OMP_CLAUSE_TO,
1169 : OMP_CLAUSE_FROM,
1170 : OMP_CLAUSE_NUM_TEAMS,
1171 : OMP_CLAUSE_THREAD_LIMIT,
1172 : OMP_CLAUSE_DIST_SCHEDULE,
1173 : OMP_CLAUSE_DEFAULTMAP,
1174 : OMP_CLAUSE_GRAINSIZE,
1175 : OMP_CLAUSE_HINT,
1176 : OMP_CLAUSE_IS_DEVICE_PTR,
1177 : OMP_CLAUSE_LINK,
1178 : OMP_CLAUSE_NOGROUP,
1179 : OMP_CLAUSE_NOTEMPORAL,
1180 : OMP_CLAUSE_NUM_TASKS,
1181 : OMP_CLAUSE_PRIORITY,
1182 : OMP_CLAUSE_SIMD,
1183 : OMP_CLAUSE_THREADS,
1184 : OMP_CLAUSE_USE_DEVICE_PTR,
1185 : OMP_CLAUSE_USE_DEVICE_ADDR, /* OpenMP 5.0. */
1186 : OMP_CLAUSE_DEVICE_TYPE, /* OpenMP 5.0. */
1187 : OMP_CLAUSE_ATOMIC, /* OpenMP 5.0. */
1188 : OMP_CLAUSE_CAPTURE, /* OpenMP 5.0. */
1189 : OMP_CLAUSE_MEMORDER, /* OpenMP 5.0. */
1190 : OMP_CLAUSE_DETACH, /* OpenMP 5.0. */
1191 : OMP_CLAUSE_AFFINITY, /* OpenMP 5.0. */
1192 : OMP_CLAUSE_ALLOCATE, /* OpenMP 5.0. */
1193 : OMP_CLAUSE_BIND, /* OpenMP 5.0. */
1194 : OMP_CLAUSE_FILTER, /* OpenMP 5.1. */
1195 : OMP_CLAUSE_AT, /* OpenMP 5.1. */
1196 : OMP_CLAUSE_MESSAGE, /* OpenMP 5.1. */
1197 : OMP_CLAUSE_SEVERITY, /* OpenMP 5.1. */
1198 : OMP_CLAUSE_COMPARE, /* OpenMP 5.1. */
1199 : OMP_CLAUSE_FAIL, /* OpenMP 5.1. */
1200 : OMP_CLAUSE_WEAK, /* OpenMP 5.1. */
1201 : OMP_CLAUSE_NOWAIT,
1202 : /* This must come last. */
1203 : OMP_MASK1_LAST
1204 : };
1205 :
1206 : /* More OpenMP clauses and OpenACC 2.0+ specific clauses. */
1207 : enum omp_mask2
1208 : {
1209 : OMP_CLAUSE_ASYNC,
1210 : OMP_CLAUSE_NUM_GANGS,
1211 : OMP_CLAUSE_NUM_WORKERS,
1212 : OMP_CLAUSE_VECTOR_LENGTH,
1213 : OMP_CLAUSE_COPY,
1214 : OMP_CLAUSE_COPYOUT,
1215 : OMP_CLAUSE_CREATE,
1216 : OMP_CLAUSE_NO_CREATE,
1217 : OMP_CLAUSE_PRESENT,
1218 : OMP_CLAUSE_DEVICEPTR,
1219 : OMP_CLAUSE_GANG,
1220 : OMP_CLAUSE_WORKER,
1221 : OMP_CLAUSE_VECTOR,
1222 : OMP_CLAUSE_SEQ,
1223 : OMP_CLAUSE_INDEPENDENT,
1224 : OMP_CLAUSE_USE_DEVICE,
1225 : OMP_CLAUSE_DEVICE_RESIDENT,
1226 : OMP_CLAUSE_SELF,
1227 : OMP_CLAUSE_HOST,
1228 : OMP_CLAUSE_WAIT,
1229 : OMP_CLAUSE_DELETE,
1230 : OMP_CLAUSE_AUTO,
1231 : OMP_CLAUSE_TILE,
1232 : OMP_CLAUSE_IF_PRESENT,
1233 : OMP_CLAUSE_FINALIZE,
1234 : OMP_CLAUSE_ATTACH,
1235 : OMP_CLAUSE_NOHOST,
1236 : OMP_CLAUSE_HAS_DEVICE_ADDR, /* OpenMP 5.1 */
1237 : OMP_CLAUSE_ENTER, /* OpenMP 5.2 */
1238 : OMP_CLAUSE_DOACROSS, /* OpenMP 5.2 */
1239 : OMP_CLAUSE_ASSUMPTIONS, /* OpenMP 5.1. */
1240 : OMP_CLAUSE_USES_ALLOCATORS, /* OpenMP 5.0 */
1241 : OMP_CLAUSE_INDIRECT, /* OpenMP 5.1 */
1242 : OMP_CLAUSE_FULL, /* OpenMP 5.1. */
1243 : OMP_CLAUSE_PARTIAL, /* OpenMP 5.1. */
1244 : OMP_CLAUSE_SIZES, /* OpenMP 5.1. */
1245 : OMP_CLAUSE_INIT, /* OpenMP 5.1. */
1246 : OMP_CLAUSE_DESTROY, /* OpenMP 5.1. */
1247 : OMP_CLAUSE_USE, /* OpenMP 5.1. */
1248 : OMP_CLAUSE_NOVARIANTS, /* OpenMP 5.1 */
1249 : OMP_CLAUSE_NOCONTEXT, /* OpenMP 5.1 */
1250 : OMP_CLAUSE_INTEROP, /* OpenMP 5.1 */
1251 : OMP_CLAUSE_LOCAL, /* OpenMP 6.0 */
1252 : OMP_CLAUSE_DYN_GROUPPRIVATE, /* OpenMP 6.1 */
1253 : OMP_CLAUSE_DEVICE_NUM,
1254 : /* This must come last. */
1255 : OMP_MASK2_LAST
1256 : };
1257 :
1258 : struct omp_inv_mask;
1259 :
1260 : /* Customized bitset for up to 128-bits.
1261 : The two enums above provide bit numbers to use, and which of the
1262 : two enums it is determines which of the two mask fields is used.
1263 : Supported operations are defining a mask, like:
1264 : #define XXX_CLAUSES \
1265 : (omp_mask (OMP_CLAUSE_XXX) | OMP_CLAUSE_YYY | OMP_CLAUSE_ZZZ)
1266 : oring such bitsets together or removing selected bits:
1267 : (XXX_CLAUSES | YYY_CLAUSES) & ~(omp_mask (OMP_CLAUSE_VVV))
1268 : and testing individual bits:
1269 : if (mask & OMP_CLAUSE_UUU) */
1270 :
1271 : struct omp_mask {
1272 : const uint64_t mask1;
1273 : const uint64_t mask2;
1274 : inline omp_mask ();
1275 : inline omp_mask (omp_mask1);
1276 : inline omp_mask (omp_mask2);
1277 : inline omp_mask (uint64_t, uint64_t);
1278 : inline omp_mask operator| (omp_mask1) const;
1279 : inline omp_mask operator| (omp_mask2) const;
1280 : inline omp_mask operator| (omp_mask) const;
1281 : inline omp_mask operator& (const omp_inv_mask &) const;
1282 : inline bool operator& (omp_mask1) const;
1283 : inline bool operator& (omp_mask2) const;
1284 : inline omp_inv_mask operator~ () const;
1285 : };
1286 :
1287 : struct omp_inv_mask : public omp_mask {
1288 : inline omp_inv_mask (const omp_mask &);
1289 : };
1290 :
1291 : omp_mask::omp_mask () : mask1 (0), mask2 (0)
1292 : {
1293 : }
1294 :
1295 32873 : omp_mask::omp_mask (omp_mask1 m) : mask1 (((uint64_t) 1) << m), mask2 (0)
1296 : {
1297 : }
1298 :
1299 2205 : omp_mask::omp_mask (omp_mask2 m) : mask1 (0), mask2 (((uint64_t) 1) << m)
1300 : {
1301 : }
1302 :
1303 33755 : omp_mask::omp_mask (uint64_t m1, uint64_t m2) : mask1 (m1), mask2 (m2)
1304 : {
1305 : }
1306 :
1307 : omp_mask
1308 32804 : omp_mask::operator| (omp_mask1 m) const
1309 : {
1310 32804 : return omp_mask (mask1 | (((uint64_t) 1) << m), mask2);
1311 : }
1312 :
1313 : omp_mask
1314 17264 : omp_mask::operator| (omp_mask2 m) const
1315 : {
1316 17264 : return omp_mask (mask1, mask2 | (((uint64_t) 1) << m));
1317 : }
1318 :
1319 : omp_mask
1320 4374 : omp_mask::operator| (omp_mask m) const
1321 : {
1322 4374 : return omp_mask (mask1 | m.mask1, mask2 | m.mask2);
1323 : }
1324 :
1325 : omp_mask
1326 2031 : omp_mask::operator& (const omp_inv_mask &m) const
1327 : {
1328 2031 : return omp_mask (mask1 & ~m.mask1, mask2 & ~m.mask2);
1329 : }
1330 :
1331 : bool
1332 129578 : omp_mask::operator& (omp_mask1 m) const
1333 : {
1334 129578 : return (mask1 & (((uint64_t) 1) << m)) != 0;
1335 : }
1336 :
1337 : bool
1338 92329 : omp_mask::operator& (omp_mask2 m) const
1339 : {
1340 92329 : return (mask2 & (((uint64_t) 1) << m)) != 0;
1341 : }
1342 :
1343 : omp_inv_mask
1344 2031 : omp_mask::operator~ () const
1345 : {
1346 2031 : return omp_inv_mask (*this);
1347 : }
1348 :
1349 2031 : omp_inv_mask::omp_inv_mask (const omp_mask &m) : omp_mask (m)
1350 : {
1351 : }
1352 :
1353 : /* Helper function for OpenACC and OpenMP clauses involving memory
1354 : mapping. */
1355 :
1356 : static bool
1357 5544 : gfc_match_omp_map_clause (gfc_omp_namelist **list, gfc_omp_map_op map_op,
1358 : bool allow_common, bool allow_derived)
1359 : {
1360 5544 : gfc_omp_namelist **head = NULL;
1361 5544 : if (gfc_match_omp_variable_list ("", list, allow_common, NULL, &head, true,
1362 : allow_derived)
1363 : == MATCH_YES)
1364 : {
1365 5535 : gfc_omp_namelist *n;
1366 13409 : for (n = *head; n; n = n->next)
1367 7874 : n->u.map.op = map_op;
1368 : return true;
1369 : }
1370 :
1371 : return false;
1372 : }
1373 :
1374 : static match
1375 8729 : gfc_match_iterator (gfc_namespace **ns, bool permit_var)
1376 : {
1377 8729 : locus old_loc = gfc_current_locus;
1378 :
1379 8729 : if (gfc_match ("iterator ( ") != MATCH_YES)
1380 : return MATCH_NO;
1381 :
1382 142 : gfc_typespec ts;
1383 142 : gfc_symbol *last = NULL;
1384 142 : gfc_expr *begin, *end, *step;
1385 142 : *ns = gfc_build_block_ns (gfc_current_ns);
1386 161 : char name[GFC_MAX_SYMBOL_LEN + 1];
1387 180 : while (true)
1388 : {
1389 161 : locus prev_loc = gfc_current_locus;
1390 161 : if (gfc_match_type_spec (&ts) == MATCH_YES
1391 161 : && gfc_match (" :: ") == MATCH_YES)
1392 : {
1393 5 : if (ts.type != BT_INTEGER)
1394 : {
1395 2 : gfc_error ("Expected INTEGER type at %L", &prev_loc);
1396 5 : return MATCH_ERROR;
1397 : }
1398 : permit_var = false;
1399 : }
1400 : else
1401 : {
1402 156 : ts.type = BT_INTEGER;
1403 156 : ts.kind = gfc_default_integer_kind;
1404 156 : gfc_current_locus = prev_loc;
1405 : }
1406 159 : prev_loc = gfc_current_locus;
1407 159 : if (gfc_match_name (name) != MATCH_YES)
1408 : {
1409 4 : gfc_error ("Expected identifier at %C");
1410 4 : goto failed;
1411 : }
1412 155 : if (gfc_find_symtree ((*ns)->sym_root, name))
1413 : {
1414 2 : gfc_error ("Same identifier %qs specified again at %C", name);
1415 2 : goto failed;
1416 : }
1417 :
1418 153 : gfc_symbol *sym = gfc_new_symbol (name, *ns);
1419 153 : if (last)
1420 17 : last->tlink = sym;
1421 : else
1422 136 : (*ns)->omp_affinity_iterators = sym;
1423 153 : last = sym;
1424 153 : sym->declared_at = prev_loc;
1425 153 : sym->ts = ts;
1426 153 : sym->attr.flavor = FL_VARIABLE;
1427 153 : sym->attr.artificial = 1;
1428 153 : sym->attr.referenced = 1;
1429 153 : sym->refs++;
1430 153 : gfc_symtree *st = gfc_new_symtree (&(*ns)->sym_root, name);
1431 153 : st->n.sym = sym;
1432 :
1433 153 : prev_loc = gfc_current_locus;
1434 153 : if (gfc_match (" = ") != MATCH_YES)
1435 3 : goto failed;
1436 150 : permit_var = false;
1437 150 : begin = end = step = NULL;
1438 150 : if (gfc_match ("%e : ", &begin) != MATCH_YES
1439 150 : || gfc_match ("%e ", &end) != MATCH_YES)
1440 : {
1441 3 : gfc_error ("Expected range-specification at %C");
1442 3 : gfc_free_expr (begin);
1443 3 : gfc_free_expr (end);
1444 3 : return MATCH_ERROR;
1445 : }
1446 147 : if (':' == gfc_peek_ascii_char ())
1447 : {
1448 23 : if (gfc_match (": %e ", &step) != MATCH_YES)
1449 : {
1450 5 : gfc_free_expr (begin);
1451 5 : gfc_free_expr (end);
1452 5 : gfc_free_expr (step);
1453 5 : goto failed;
1454 : }
1455 : }
1456 :
1457 142 : gfc_expr *e = gfc_get_expr ();
1458 142 : e->where = prev_loc;
1459 142 : e->expr_type = EXPR_ARRAY;
1460 142 : e->ts = ts;
1461 142 : e->rank = 1;
1462 142 : e->shape = gfc_get_shape (1);
1463 266 : mpz_init_set_ui (e->shape[0], step ? 3 : 2);
1464 142 : gfc_constructor_append_expr (&e->value.constructor, begin, &begin->where);
1465 142 : gfc_constructor_append_expr (&e->value.constructor, end, &end->where);
1466 142 : if (step)
1467 18 : gfc_constructor_append_expr (&e->value.constructor, step, &step->where);
1468 142 : sym->value = e;
1469 :
1470 142 : if (gfc_match (") ") == MATCH_YES)
1471 : break;
1472 19 : if (gfc_match (", ") != MATCH_YES)
1473 0 : goto failed;
1474 19 : }
1475 123 : return MATCH_YES;
1476 :
1477 14 : failed:
1478 14 : gfc_namespace *prev_ns = NULL;
1479 14 : for (gfc_namespace *it = gfc_current_ns->contained; it; it = it->sibling)
1480 : {
1481 0 : if (it == *ns)
1482 : {
1483 0 : if (prev_ns)
1484 0 : prev_ns->sibling = it->sibling;
1485 : else
1486 0 : gfc_current_ns->contained = it->sibling;
1487 0 : gfc_free_namespace (it);
1488 0 : break;
1489 : }
1490 0 : prev_ns = it;
1491 : }
1492 14 : *ns = NULL;
1493 14 : if (!permit_var)
1494 : return MATCH_ERROR;
1495 4 : gfc_current_locus = old_loc;
1496 4 : return MATCH_NO;
1497 : }
1498 :
1499 : /* Match target update's to/from( [present:] var-list). */
1500 :
1501 : static match
1502 1736 : gfc_match_motion_var_list (const char *str, gfc_omp_namelist **list,
1503 : gfc_omp_namelist ***headp)
1504 : {
1505 1736 : match m = gfc_match (str);
1506 1736 : if (m != MATCH_YES)
1507 : return m;
1508 :
1509 1736 : gfc_namespace *ns_iter = NULL, *ns_curr = gfc_current_ns;
1510 1736 : locus old_loc = gfc_current_locus;
1511 1736 : int present_modifier = 0;
1512 1736 : int iterator_modifier = 0;
1513 1736 : locus second_present_locus = old_loc;
1514 1736 : locus second_iterator_locus = old_loc;
1515 1736 : bool saw_modifier = false;
1516 :
1517 1748 : for (;;)
1518 : {
1519 1742 : locus current_locus = gfc_current_locus;
1520 1742 : if (gfc_match ("present ") == MATCH_YES)
1521 : {
1522 8 : if (present_modifier++ == 1)
1523 0 : second_present_locus = current_locus;
1524 : }
1525 1734 : else if (gfc_match_iterator (&ns_iter, true) == MATCH_YES)
1526 : {
1527 20 : if (iterator_modifier++ == 1)
1528 1 : second_iterator_locus = current_locus;
1529 : }
1530 1714 : else if (!saw_modifier)
1531 : break;
1532 : else
1533 : {
1534 2 : gfc_error ("Expected clause modifier at %C");
1535 4 : return MATCH_ERROR;
1536 : }
1537 :
1538 : /* OpenMP 5.1 syntax mistakenly allowed commas to be optional
1539 : between and after modifiers in a clause. This was corrected
1540 : in 5.2 and later specifications: they're now required between
1541 : modifiers and a trailing comma is not permitted. We implement
1542 : the 5.2 syntax here. */
1543 28 : saw_modifier = true;
1544 28 : if (gfc_match (" : ") == MATCH_YES)
1545 : break;
1546 8 : else if (gfc_match (", ") == MATCH_YES)
1547 6 : continue;
1548 : else
1549 : {
1550 2 : gfc_error ("Expected %<,%> or %<:%> after clause modifier at %C");
1551 2 : return MATCH_ERROR;
1552 : }
1553 : }
1554 :
1555 1732 : if (!saw_modifier)
1556 : {
1557 1712 : gfc_current_locus = old_loc;
1558 1712 : present_modifier = 0;
1559 1712 : iterator_modifier = 0;
1560 : }
1561 :
1562 1732 : if (present_modifier > 1)
1563 : {
1564 0 : gfc_error ("Too many %<present%> modifiers at %L", &second_present_locus);
1565 0 : return MATCH_ERROR;
1566 : }
1567 1732 : if (iterator_modifier > 1)
1568 : {
1569 1 : gfc_error ("Too many %<iterator%> modifiers at %L",
1570 : &second_iterator_locus);
1571 1 : return MATCH_ERROR;
1572 : }
1573 :
1574 1731 : if (ns_iter)
1575 14 : gfc_current_ns = ns_iter;
1576 :
1577 1731 : m = gfc_match_omp_variable_list ("", list, false, NULL, headp, true, true);
1578 1731 : gfc_current_ns = ns_curr;
1579 1731 : if (m != MATCH_YES)
1580 : return m;
1581 1729 : gfc_omp_namelist *n;
1582 3532 : for (n = **headp; n; n = n->next)
1583 : {
1584 1803 : if (present_modifier)
1585 6 : n->u.present_modifier = true;
1586 1803 : if (iterator_modifier)
1587 : {
1588 18 : n->u2.ns = ns_iter;
1589 18 : ns_iter->refs++;
1590 : }
1591 : }
1592 : return MATCH_YES;
1593 : }
1594 :
1595 : /* reduction ( reduction-modifier, reduction-operator : variable-list )
1596 : in_reduction ( reduction-operator : variable-list )
1597 : task_reduction ( reduction-operator : variable-list ) */
1598 :
1599 : static match
1600 4360 : gfc_match_omp_clause_reduction (char pc, gfc_omp_clauses *c, bool openacc,
1601 : bool allow_derived, bool openmp_target = false)
1602 : {
1603 4360 : if (pc == 'r' && gfc_match ("reduction ( ") != MATCH_YES)
1604 : return MATCH_NO;
1605 4360 : else if (pc == 'i' && gfc_match ("in_reduction ( ") != MATCH_YES)
1606 : return MATCH_NO;
1607 4248 : else if (pc == 't' && gfc_match ("task_reduction ( ") != MATCH_YES)
1608 : return MATCH_NO;
1609 :
1610 4248 : locus old_loc = gfc_current_locus;
1611 4248 : enum gfc_omp_list_type list_idx = OMP_LIST_NONE;
1612 :
1613 4248 : if (pc == 'r' && !openacc)
1614 : {
1615 2121 : if (gfc_match ("inscan") == MATCH_YES)
1616 : list_idx = OMP_LIST_REDUCTION_INSCAN;
1617 2051 : else if (gfc_match ("task") == MATCH_YES)
1618 : list_idx = OMP_LIST_REDUCTION_TASK;
1619 1946 : else if (gfc_match ("default") == MATCH_YES)
1620 : list_idx = OMP_LIST_REDUCTION;
1621 231 : if (list_idx != OMP_LIST_NONE && gfc_match (", ") != MATCH_YES)
1622 : {
1623 1 : gfc_error ("Comma expected at %C");
1624 1 : gfc_current_locus = old_loc;
1625 1 : return MATCH_NO;
1626 : }
1627 2120 : if (list_idx == OMP_LIST_NONE)
1628 3834 : list_idx = OMP_LIST_REDUCTION;
1629 : }
1630 2127 : else if (pc == 'i')
1631 : list_idx = OMP_LIST_IN_REDUCTION;
1632 2009 : else if (pc == 't')
1633 : list_idx = OMP_LIST_TASK_REDUCTION;
1634 : else
1635 3834 : list_idx = OMP_LIST_REDUCTION;
1636 :
1637 4247 : gfc_omp_reduction_op rop = OMP_REDUCTION_NONE;
1638 4247 : char buffer[GFC_MAX_SYMBOL_LEN + 3];
1639 4247 : if (gfc_match_char ('+') == MATCH_YES)
1640 : rop = OMP_REDUCTION_PLUS;
1641 2223 : else if (gfc_match_char ('*') == MATCH_YES)
1642 : rop = OMP_REDUCTION_TIMES;
1643 1991 : else if (gfc_match_char ('-') == MATCH_YES)
1644 : {
1645 171 : if (!openacc)
1646 16 : gfc_warning (OPT_Wdeprecated_openmp,
1647 : "%<-%> operator at %C for reductions deprecated in "
1648 : "OpenMP 5.2");
1649 : rop = OMP_REDUCTION_MINUS;
1650 : }
1651 1820 : else if (gfc_match (".and.") == MATCH_YES)
1652 : rop = OMP_REDUCTION_AND;
1653 1714 : else if (gfc_match (".or.") == MATCH_YES)
1654 : rop = OMP_REDUCTION_OR;
1655 929 : else if (gfc_match (".eqv.") == MATCH_YES)
1656 : rop = OMP_REDUCTION_EQV;
1657 831 : else if (gfc_match (".neqv.") == MATCH_YES)
1658 : rop = OMP_REDUCTION_NEQV;
1659 736 : if (rop != OMP_REDUCTION_NONE)
1660 3511 : snprintf (buffer, sizeof buffer, "operator %s",
1661 : gfc_op2string ((gfc_intrinsic_op) rop));
1662 736 : else if (gfc_match_defined_op_name (buffer + 1, 1) == MATCH_YES)
1663 : {
1664 38 : buffer[0] = '.';
1665 38 : strcat (buffer, ".");
1666 : }
1667 698 : else if (gfc_match_name (buffer) == MATCH_YES)
1668 : {
1669 697 : gfc_symbol *sym;
1670 697 : const char *n = buffer;
1671 :
1672 697 : gfc_find_symbol (buffer, NULL, 1, &sym);
1673 697 : if (sym != NULL)
1674 : {
1675 216 : if (sym->attr.intrinsic)
1676 139 : n = sym->name;
1677 77 : else if ((sym->attr.flavor != FL_UNKNOWN
1678 75 : && sym->attr.flavor != FL_PROCEDURE)
1679 75 : || sym->attr.external
1680 64 : || sym->attr.generic
1681 64 : || sym->attr.entry
1682 64 : || sym->attr.result
1683 64 : || sym->attr.dummy
1684 64 : || sym->attr.subroutine
1685 63 : || sym->attr.pointer
1686 63 : || sym->attr.target
1687 63 : || sym->attr.cray_pointer
1688 63 : || sym->attr.cray_pointee
1689 63 : || (sym->attr.proc != PROC_UNKNOWN
1690 1 : && sym->attr.proc != PROC_INTRINSIC)
1691 62 : || sym->attr.if_source != IFSRC_UNKNOWN
1692 62 : || sym == sym->ns->proc_name)
1693 : {
1694 : sym = NULL;
1695 : n = NULL;
1696 : }
1697 : else
1698 62 : n = sym->name;
1699 : }
1700 201 : if (n == NULL)
1701 : rop = OMP_REDUCTION_NONE;
1702 682 : else if (strcmp (n, "max") == 0)
1703 : rop = OMP_REDUCTION_MAX;
1704 517 : else if (strcmp (n, "min") == 0)
1705 : rop = OMP_REDUCTION_MIN;
1706 376 : else if (strcmp (n, "iand") == 0)
1707 : rop = OMP_REDUCTION_IAND;
1708 321 : else if (strcmp (n, "ior") == 0)
1709 : rop = OMP_REDUCTION_IOR;
1710 255 : else if (strcmp (n, "ieor") == 0)
1711 : rop = OMP_REDUCTION_IEOR;
1712 : if (rop != OMP_REDUCTION_NONE
1713 477 : && sym != NULL
1714 200 : && ! sym->attr.intrinsic
1715 61 : && ! sym->attr.use_assoc
1716 61 : && ((sym->attr.flavor == FL_UNKNOWN
1717 2 : && !gfc_add_flavor (&sym->attr, FL_PROCEDURE,
1718 : sym->name, NULL))
1719 61 : || !gfc_add_intrinsic (&sym->attr, NULL)))
1720 : rop = OMP_REDUCTION_NONE;
1721 : }
1722 : else
1723 1 : buffer[0] = '\0';
1724 4247 : gfc_omp_udr *udr = (buffer[0] ? gfc_find_omp_udr (gfc_current_ns, buffer, NULL)
1725 : : NULL);
1726 4247 : gfc_omp_namelist **head = NULL;
1727 4247 : if (rop == OMP_REDUCTION_NONE && udr)
1728 250 : rop = OMP_REDUCTION_USER;
1729 :
1730 4247 : if (gfc_match_omp_variable_list (" :", &c->lists[list_idx], false, NULL,
1731 : &head, openacc, allow_derived) != MATCH_YES)
1732 : {
1733 9 : gfc_current_locus = old_loc;
1734 9 : return MATCH_NO;
1735 : }
1736 4238 : gfc_omp_namelist *n;
1737 4238 : if (rop == OMP_REDUCTION_NONE)
1738 : {
1739 6 : n = *head;
1740 6 : *head = NULL;
1741 6 : gfc_error_now ("!$OMP DECLARE REDUCTION %s not found at %L",
1742 : buffer, &old_loc);
1743 6 : gfc_free_omp_namelist (n, OMP_LIST_NONE);
1744 : }
1745 : else
1746 9116 : for (n = *head; n; n = n->next)
1747 : {
1748 4884 : n->u.reduction_op = rop;
1749 4884 : if (udr)
1750 : {
1751 476 : n->u2.udr = gfc_get_omp_namelist_udr ();
1752 476 : n->u2.udr->udr = udr;
1753 : }
1754 4884 : if (openmp_target && list_idx == OMP_LIST_IN_REDUCTION)
1755 : {
1756 40 : gfc_omp_namelist *p = gfc_get_omp_namelist (), **tl;
1757 40 : p->sym = n->sym;
1758 40 : p->where = n->where;
1759 40 : p->u.map.op = OMP_MAP_ALWAYS_TOFROM;
1760 :
1761 40 : tl = &c->lists[OMP_LIST_MAP];
1762 52 : while (*tl)
1763 12 : tl = &((*tl)->next);
1764 40 : *tl = p;
1765 40 : p->next = NULL;
1766 : }
1767 : }
1768 : return MATCH_YES;
1769 : }
1770 :
1771 : static match
1772 40 : gfc_omp_absent_contains_clause (gfc_omp_assumptions **assume, bool is_absent)
1773 : {
1774 40 : if (*assume == NULL)
1775 15 : *assume = gfc_get_omp_assumptions ();
1776 62 : do
1777 : {
1778 51 : gfc_statement st = ST_NONE;
1779 51 : gfc_gobble_whitespace ();
1780 51 : locus old_loc = gfc_current_locus;
1781 51 : char c = gfc_peek_ascii_char ();
1782 51 : enum gfc_omp_directive_kind kind
1783 : = GFC_OMP_DIR_DECLARATIVE; /* Silence warning. */
1784 1585 : for (size_t i = 0; i < ARRAY_SIZE (gfc_omp_directives); i++)
1785 : {
1786 1585 : if (gfc_omp_directives[i].name[0] > c)
1787 : break;
1788 1534 : if (gfc_omp_directives[i].name[0] != c)
1789 1182 : continue;
1790 352 : if (gfc_match (gfc_omp_directives[i].name) == MATCH_YES)
1791 : {
1792 51 : st = gfc_omp_directives[i].st;
1793 51 : kind = gfc_omp_directives[i].kind;
1794 : }
1795 : }
1796 51 : gfc_gobble_whitespace ();
1797 51 : c = gfc_peek_ascii_char ();
1798 51 : if (st == ST_NONE || (c != ',' && c != ')'))
1799 : {
1800 0 : if (st == ST_NONE)
1801 0 : gfc_error ("Unknown directive at %L", &old_loc);
1802 : else
1803 0 : gfc_error ("Invalid combined or composite directive at %L",
1804 : &old_loc);
1805 4 : return MATCH_ERROR;
1806 : }
1807 51 : if (kind == GFC_OMP_DIR_DECLARATIVE
1808 51 : || kind == GFC_OMP_DIR_INFORMATIONAL
1809 : || kind == GFC_OMP_DIR_META)
1810 : {
1811 5 : gfc_error ("Invalid %qs directive at %L in %s clause: declarative, "
1812 : "informational, and meta directives not permitted",
1813 : gfc_ascii_statement (st, true), &old_loc,
1814 : is_absent ? "ABSENT" : "CONTAINS");
1815 4 : return MATCH_ERROR;
1816 : }
1817 47 : if (is_absent)
1818 : {
1819 : /* Use exponential allocation; equivalent to pow2p(x). */
1820 33 : int i = (*assume)->n_absent;
1821 33 : int size = ((i == 0) ? 4
1822 10 : : pow2p_hwi (i) == 1 ? i*2 : 0);
1823 8 : if (size != 0)
1824 31 : (*assume)->absent = XRESIZEVEC (gfc_statement,
1825 : (*assume)->absent, size);
1826 33 : (*assume)->absent[(*assume)->n_absent++] = st;
1827 : }
1828 : else
1829 : {
1830 14 : int i = (*assume)->n_contains;
1831 14 : int size = ((i == 0) ? 4
1832 4 : : pow2p_hwi (i) == 1 ? i*2 : 0);
1833 4 : if (size != 0)
1834 14 : (*assume)->contains = XRESIZEVEC (gfc_statement,
1835 : (*assume)->contains, size);
1836 14 : (*assume)->contains[(*assume)->n_contains++] = st;
1837 : }
1838 47 : gfc_gobble_whitespace ();
1839 47 : if (gfc_match(",") == MATCH_YES)
1840 11 : continue;
1841 36 : if (gfc_match(")") == MATCH_YES)
1842 : break;
1843 0 : gfc_error ("Expected %<,%> or %<)%> at %C");
1844 0 : return MATCH_ERROR;
1845 : }
1846 : while (true);
1847 :
1848 36 : return MATCH_YES;
1849 : }
1850 :
1851 : /* Check 'check' argument for duplicated statements in absent and/or contains
1852 : clauses. If 'merge', merge them from check to 'merge'. */
1853 :
1854 : static match
1855 43 : omp_verify_merge_absent_contains (gfc_statement st, gfc_omp_assumptions *check,
1856 : gfc_omp_assumptions *merge, locus *loc)
1857 : {
1858 43 : if (check == NULL)
1859 : return MATCH_YES;
1860 43 : bitmap_head absent_head, contains_head;
1861 43 : bitmap_obstack_initialize (NULL);
1862 43 : bitmap_initialize (&absent_head, &bitmap_default_obstack);
1863 43 : bitmap_initialize (&contains_head, &bitmap_default_obstack);
1864 :
1865 43 : match m = MATCH_YES;
1866 76 : for (int i = 0; i < check->n_absent; i++)
1867 33 : if (!bitmap_set_bit (&absent_head, check->absent[i]))
1868 : {
1869 2 : gfc_error ("%qs directive mentioned multiple times in %s clause in %s "
1870 : "directive at %L",
1871 2 : gfc_ascii_statement (check->absent[i], true),
1872 : "ABSENT", gfc_ascii_statement (st), loc);
1873 2 : m = MATCH_ERROR;
1874 : }
1875 57 : for (int i = 0; i < check->n_contains; i++)
1876 : {
1877 14 : if (!bitmap_set_bit (&contains_head, check->contains[i]))
1878 : {
1879 2 : gfc_error ("%qs directive mentioned multiple times in %s clause in %s "
1880 : "directive at %L",
1881 2 : gfc_ascii_statement (check->contains[i], true),
1882 : "CONTAINS", gfc_ascii_statement (st), loc);
1883 2 : m = MATCH_ERROR;
1884 : }
1885 14 : if (bitmap_bit_p (&absent_head, check->contains[i]))
1886 : {
1887 2 : gfc_error ("%qs directive mentioned both times in ABSENT and CONTAINS "
1888 : "clauses in %s directive at %L",
1889 2 : gfc_ascii_statement (check->absent[i], true),
1890 : gfc_ascii_statement (st), loc);
1891 2 : m = MATCH_ERROR;
1892 : }
1893 : }
1894 :
1895 43 : if (m == MATCH_ERROR)
1896 : return MATCH_ERROR;
1897 37 : if (merge == NULL)
1898 : return MATCH_YES;
1899 2 : if (merge->absent == NULL && check->absent)
1900 : {
1901 1 : merge->n_absent = check->n_absent;
1902 1 : merge->absent = check->absent;
1903 1 : check->absent = NULL;
1904 : }
1905 1 : else if (merge->absent && check->absent)
1906 : {
1907 0 : check->absent = XRESIZEVEC (gfc_statement, check->absent,
1908 : merge->n_absent + check->n_absent);
1909 0 : for (int i = 0; i < merge->n_absent; i++)
1910 0 : if (!bitmap_bit_p (&absent_head, merge->absent[i]))
1911 0 : check->absent[check->n_absent++] = merge->absent[i];
1912 0 : free (merge->absent);
1913 0 : merge->absent = check->absent;
1914 0 : merge->n_absent = check->n_absent;
1915 0 : check->absent = NULL;
1916 : }
1917 2 : if (merge->contains == NULL && check->contains)
1918 : {
1919 0 : merge->n_contains = check->n_contains;
1920 0 : merge->contains = check->contains;
1921 0 : check->contains = NULL;
1922 : }
1923 2 : else if (merge->contains && check->contains)
1924 : {
1925 0 : check->contains = XRESIZEVEC (gfc_statement, check->contains,
1926 : merge->n_contains + check->n_contains);
1927 0 : for (int i = 0; i < merge->n_contains; i++)
1928 0 : if (!bitmap_bit_p (&contains_head, merge->contains[i]))
1929 0 : check->contains[check->n_contains++] = merge->contains[i];
1930 0 : free (merge->contains);
1931 0 : merge->contains = check->contains;
1932 0 : merge->n_contains = check->n_contains;
1933 0 : check->contains = NULL;
1934 : }
1935 : return MATCH_YES;
1936 : }
1937 :
1938 : /* OpenMP 5.0
1939 : uses_allocators ( allocator-list )
1940 :
1941 : allocator:
1942 : predefined-allocator
1943 : variable ( traits-array )
1944 :
1945 : OpenMP 5.2 deprecated, 6.0 deleted: 'variable ( traits-array )'
1946 :
1947 : OpenMP 5.2:
1948 : uses_allocators ( [modifier-list :] allocator-list )
1949 :
1950 : OpenMP 6.0:
1951 : uses_allocators ( [modifier-list :] allocator-list [; ...])
1952 :
1953 : allocator:
1954 : variable or predefined-allocator
1955 : modifier:
1956 : traits ( traits-array )
1957 : memspace ( mem-space-handle ) */
1958 :
1959 : static match
1960 78 : gfc_match_omp_clause_uses_allocators (gfc_omp_clauses *c)
1961 : {
1962 82 : parse_next:
1963 82 : gfc_symbol *memspace_sym = NULL;
1964 82 : gfc_symbol *traits_sym = NULL;
1965 82 : gfc_omp_namelist *head = NULL;
1966 82 : gfc_omp_namelist *p, *tail, **list;
1967 82 : int ntraits, nmemspace;
1968 82 : bool has_modifiers;
1969 82 : locus old_loc, cur_loc;
1970 :
1971 82 : gfc_gobble_whitespace ();
1972 82 : old_loc = gfc_current_locus;
1973 82 : ntraits = nmemspace = 0;
1974 126 : do
1975 : {
1976 104 : cur_loc = gfc_current_locus;
1977 104 : if (gfc_match ("traits ( %S ) ", &traits_sym) == MATCH_YES)
1978 34 : ntraits++;
1979 70 : else if (gfc_match ("memspace ( %S ) ", &memspace_sym) == MATCH_YES)
1980 33 : nmemspace++;
1981 104 : if (ntraits > 1 || nmemspace > 1)
1982 : {
1983 5 : gfc_error ("Duplicate %s modifier at %L in USES_ALLOCATORS clause",
1984 : ntraits > 1 ? "TRAITS" : "MEMSPACE", &cur_loc);
1985 5 : return MATCH_ERROR;
1986 : }
1987 99 : if (gfc_match (", ") == MATCH_YES)
1988 22 : continue;
1989 77 : if (gfc_match (": ") != MATCH_YES)
1990 : {
1991 : /* Assume no modifier. */
1992 39 : memspace_sym = traits_sym = NULL;
1993 39 : gfc_current_locus = old_loc;
1994 39 : break;
1995 : }
1996 : break;
1997 : } while (true);
1998 :
1999 115 : has_modifiers = traits_sym != NULL || memspace_sym != NULL;
2000 179 : do
2001 : {
2002 128 : p = gfc_get_omp_namelist ();
2003 128 : p->where = gfc_current_locus;
2004 128 : if (head == NULL)
2005 : head = tail = p;
2006 : else
2007 : {
2008 51 : tail->next = p;
2009 51 : tail = tail->next;
2010 : }
2011 128 : if (gfc_match ("%S ", &p->sym) != MATCH_YES)
2012 1 : goto error;
2013 127 : if (!has_modifiers)
2014 : {
2015 83 : if (gfc_match ("( %S ) ", &p->u2.traits_sym) == MATCH_YES)
2016 22 : gfc_warning (OPT_Wdeprecated_openmp,
2017 : "The specification of arguments to "
2018 : "%<uses_allocators%> at %L where each item is of "
2019 : "the form %<allocator(traits)%> is deprecated since "
2020 : "OpenMP 5.2; instead use %<uses_allocators(traits(%s"
2021 22 : "): %s)%>", &p->where, p->u2.traits_sym->name,
2022 22 : p->sym->name);
2023 : }
2024 44 : else if (gfc_peek_ascii_char () == '(')
2025 : {
2026 1 : gfc_error ("Unexpected %<(%> at %C");
2027 1 : goto error;
2028 : }
2029 : else
2030 : {
2031 43 : p->u.memspace_sym = memspace_sym;
2032 43 : p->u2.traits_sym = traits_sym;
2033 : }
2034 126 : gfc_gobble_whitespace ();
2035 126 : const char c = gfc_peek_ascii_char ();
2036 126 : if (c == ';' || c == ')')
2037 : break;
2038 53 : if (c != ',')
2039 : {
2040 2 : gfc_error ("Expected %<,%>, %<)%> or %<;%> at %C");
2041 2 : goto error;
2042 : }
2043 51 : gfc_match_char (',');
2044 51 : gfc_gobble_whitespace ();
2045 51 : } while (true);
2046 :
2047 73 : list = &c->lists[OMP_LIST_USES_ALLOCATORS];
2048 91 : while (*list)
2049 18 : list = &(*list)->next;
2050 73 : *list = head;
2051 :
2052 73 : if (gfc_match_char (';') == MATCH_YES)
2053 4 : goto parse_next;
2054 :
2055 69 : gfc_match_char (')');
2056 69 : return MATCH_YES;
2057 :
2058 4 : error:
2059 4 : gfc_free_omp_namelist (head, OMP_LIST_USES_ALLOCATORS);
2060 4 : return MATCH_ERROR;
2061 : }
2062 :
2063 :
2064 : /* Match the 'prefer_type' modifier of the interop 'init' clause:
2065 : with either OpenMP 5.1's
2066 : prefer_type ( <const-int-expr|string literal> [, ...]
2067 : or
2068 : prefer_type ( '{' <fr(...) | attr (...)>, ...] '}' [, '{' ... '}' ] )
2069 : where 'fr' takes a constant expression or a string literal
2070 : and 'attr takes a list of string literals, starting with 'ompx_')
2071 :
2072 : For the foreign runtime identifiers, string values are converted to
2073 : their integer value; unknown string or integer values are set to
2074 : GOMP_INTEROP_IFR_KNOWN.
2075 :
2076 : Data format:
2077 : For the foreign runtime identifiers, string values are converted to
2078 : their integer value; unknown string or integer values are set to 0.
2079 :
2080 : Each item (a) GOMP_INTEROP_IFR_SEPARATOR
2081 : (b) for any 'fr', its integer value.
2082 : Note: Spec only permits 1 'fr' entry (6.0; changed after TR13)
2083 : (c) GOMP_INTEROP_IFR_SEPARATOR
2084 : (d) list of \0-terminated non-empty strings for 'attr'
2085 : (e) '\0'
2086 : Tailing '\0'. */
2087 :
2088 : static match
2089 82 : gfc_match_omp_prefer_type (char **type_str, int *type_str_len)
2090 : {
2091 82 : gfc_expr *e;
2092 82 : std::string type_string, attr_string;
2093 : /* New syntax. */
2094 82 : if (gfc_peek_ascii_char () == '{')
2095 115 : do
2096 : {
2097 85 : attr_string.clear ();
2098 85 : type_string += (char) GOMP_INTEROP_IFR_SEPARATOR;
2099 85 : if (gfc_match ("{ ") != MATCH_YES)
2100 : {
2101 1 : gfc_error ("Expected %<{%> at %C");
2102 1 : return MATCH_ERROR;
2103 : }
2104 : bool fr_found = false;
2105 148 : do
2106 : {
2107 116 : if (gfc_match ("fr ( ") == MATCH_YES)
2108 : {
2109 62 : if (fr_found)
2110 : {
2111 1 : gfc_error ("Duplicated %<fr%> preference-selector-name "
2112 : "at %C");
2113 1 : return MATCH_ERROR;
2114 : }
2115 61 : fr_found = true;
2116 61 : do
2117 : {
2118 61 : bool found_literal = false;
2119 61 : match m = MATCH_YES;
2120 61 : if (gfc_match_literal_constant (&e, false) == MATCH_YES)
2121 : found_literal = true;
2122 : else
2123 12 : m = gfc_match_expr (&e);
2124 12 : if (m != MATCH_YES
2125 61 : || !gfc_resolve_expr (e)
2126 61 : || e->rank != 0
2127 60 : || e->expr_type != EXPR_CONSTANT
2128 59 : || (e->ts.type != BT_INTEGER
2129 43 : && (!found_literal || e->ts.type != BT_CHARACTER))
2130 58 : || (e->ts.type == BT_INTEGER
2131 16 : && !mpz_fits_sint_p (e->value.integer))
2132 70 : || (e->ts.type == BT_CHARACTER
2133 42 : && (e->ts.kind != gfc_default_character_kind
2134 41 : || e->value.character.length == 0)))
2135 : {
2136 5 : gfc_error ("Expected constant scalar integer expression"
2137 : " or non-empty default-kind character "
2138 5 : "literal at %L", &e->where);
2139 5 : gfc_free_expr (e);
2140 5 : return MATCH_ERROR;
2141 : }
2142 56 : gfc_gobble_whitespace ();
2143 56 : int val;
2144 56 : if (e->ts.type == BT_INTEGER)
2145 : {
2146 16 : val = mpz_get_si (e->value.integer);
2147 16 : if (val < 1 || val > GOMP_INTEROP_IFR_LAST)
2148 : {
2149 0 : gfc_warning_now (OPT_Wopenmp,
2150 : "Unknown foreign runtime "
2151 : "identifier %qd at %L",
2152 : val, &e->where);
2153 0 : val = GOMP_INTEROP_IFR_UNKNOWN;
2154 : }
2155 : }
2156 : else
2157 : {
2158 40 : char *str = XALLOCAVEC (char,
2159 : e->value.character.length+1);
2160 229 : for (int i = 0; i < e->value.character.length + 1; i++)
2161 189 : str[i] = e->value.character.string[i];
2162 40 : if (memchr (str, '\0', e->value.character.length) != 0)
2163 : {
2164 0 : gfc_error ("Unexpected null character in character "
2165 : "literal at %L", &e->where);
2166 0 : return MATCH_ERROR;
2167 : }
2168 40 : val = omp_get_fr_id_from_name (str);
2169 40 : if (val == GOMP_INTEROP_IFR_UNKNOWN)
2170 2 : gfc_warning_now (OPT_Wopenmp,
2171 : "Unknown foreign runtime identifier "
2172 2 : "%qs at %L", str, &e->where);
2173 : }
2174 :
2175 56 : type_string += (char) val;
2176 56 : if (gfc_match (") ") == MATCH_YES)
2177 : break;
2178 4 : gfc_error ("Expected %<)%> at %C");
2179 4 : return MATCH_ERROR;
2180 : }
2181 : while (true);
2182 : }
2183 54 : else if (gfc_match ("attr ( ") == MATCH_YES)
2184 : {
2185 60 : do
2186 : {
2187 57 : if (gfc_match_literal_constant (&e, false) != MATCH_YES
2188 56 : || !gfc_resolve_expr (e)
2189 56 : || e->expr_type != EXPR_CONSTANT
2190 56 : || e->rank != 0
2191 56 : || e->ts.type != BT_CHARACTER
2192 113 : || e->ts.kind != gfc_default_character_kind)
2193 : {
2194 1 : gfc_error ("Expected default-kind character literal "
2195 1 : "at %L", &e->where);
2196 1 : gfc_free_expr (e);
2197 1 : return MATCH_ERROR;
2198 : }
2199 56 : gfc_gobble_whitespace ();
2200 56 : char *str = XALLOCAVEC (char, e->value.character.length+1);
2201 564 : for (int i = 0; i < e->value.character.length + 1; i++)
2202 508 : str[i] = e->value.character.string[i];
2203 56 : if (!startswith (str, "ompx_"))
2204 : {
2205 1 : gfc_error ("Character literal at %L must start with "
2206 : "%<ompx_%>", &e->where);
2207 1 : gfc_free_expr (e);
2208 1 : return MATCH_ERROR;
2209 : }
2210 55 : if (memchr (str, '\0', e->value.character.length) != 0
2211 55 : || memchr (str, ',', e->value.character.length) != 0)
2212 : {
2213 1 : gfc_error ("Unexpected null or %<,%> character in "
2214 : "character literal at %L", &e->where);
2215 1 : return MATCH_ERROR;
2216 : }
2217 54 : attr_string += str;
2218 54 : attr_string += '\0';
2219 54 : if (gfc_match (", ") == MATCH_YES)
2220 3 : continue;
2221 51 : if (gfc_match (") ") == MATCH_YES)
2222 : break;
2223 0 : gfc_error ("Expected %<,%> or %<)%> at %C");
2224 0 : return MATCH_ERROR;
2225 3 : }
2226 : while (true);
2227 : }
2228 : else
2229 : {
2230 0 : gfc_error ("Expected %<fr(%> or %<attr(%> at %C");
2231 0 : return MATCH_ERROR;
2232 : }
2233 103 : if (gfc_match (", ") == MATCH_YES)
2234 32 : continue;
2235 71 : if (gfc_match ("} ") == MATCH_YES)
2236 : break;
2237 2 : gfc_error ("Expected %<,%> or %<}%> at %C");
2238 2 : return MATCH_ERROR;
2239 32 : }
2240 : while (true);
2241 69 : type_string += (char) GOMP_INTEROP_IFR_SEPARATOR;
2242 69 : type_string += attr_string;
2243 69 : type_string += '\0';
2244 69 : if (gfc_match (", ") == MATCH_YES)
2245 30 : continue;
2246 39 : if (gfc_match (") ") == MATCH_YES)
2247 : break;
2248 1 : gfc_error ("Expected %<,%> or %<)%> at %C");
2249 1 : return MATCH_ERROR;
2250 30 : }
2251 : while (true);
2252 : else
2253 75 : do
2254 : {
2255 51 : type_string += (char) GOMP_INTEROP_IFR_SEPARATOR;
2256 51 : bool found_literal = false;
2257 51 : match m = MATCH_YES;
2258 51 : if (gfc_match_literal_constant (&e, false) == MATCH_YES)
2259 : found_literal = true;
2260 : else
2261 19 : m = gfc_match_expr (&e);
2262 19 : if (m != MATCH_YES
2263 51 : || !gfc_resolve_expr (e)
2264 51 : || e->rank != 0
2265 50 : || e->expr_type != EXPR_CONSTANT
2266 49 : || (e->ts.type != BT_INTEGER
2267 28 : && (!found_literal || e->ts.type != BT_CHARACTER))
2268 48 : || (e->ts.type == BT_INTEGER
2269 21 : && !mpz_fits_sint_p (e->value.integer))
2270 67 : || (e->ts.type == BT_CHARACTER
2271 27 : && (e->ts.kind != gfc_default_character_kind
2272 27 : || e->value.character.length == 0)))
2273 : {
2274 3 : gfc_error ("Expected constant scalar integer expression or "
2275 3 : "non-empty default-kind character literal at %L", &e->where);
2276 3 : gfc_free_expr (e);
2277 3 : return MATCH_ERROR;
2278 : }
2279 48 : gfc_gobble_whitespace ();
2280 48 : int val;
2281 48 : if (e->ts.type == BT_INTEGER)
2282 : {
2283 21 : val = mpz_get_si (e->value.integer);
2284 21 : if (val < 1 || val > GOMP_INTEROP_IFR_LAST)
2285 : {
2286 3 : gfc_warning_now (OPT_Wopenmp,
2287 : "Unknown foreign runtime identifier %qd at %L",
2288 : val, &e->where);
2289 3 : val = 0;
2290 : }
2291 : }
2292 : else
2293 : {
2294 27 : char *str = XALLOCAVEC (char, e->value.character.length+1);
2295 169 : for (int i = 0; i < e->value.character.length + 1; i++)
2296 142 : str[i] = e->value.character.string[i];
2297 27 : if (memchr (str, '\0', e->value.character.length) != 0)
2298 : {
2299 0 : gfc_error ("Unexpected null character in character "
2300 : "literal at %L", &e->where);
2301 0 : return MATCH_ERROR;
2302 : }
2303 27 : val = omp_get_fr_id_from_name (str);
2304 27 : if (val == GOMP_INTEROP_IFR_UNKNOWN)
2305 5 : gfc_warning_now (OPT_Wopenmp,
2306 : "Unknown foreign runtime identifier %qs at %L",
2307 5 : str, &e->where);
2308 : }
2309 48 : type_string += (char) val;
2310 48 : type_string += (char) GOMP_INTEROP_IFR_SEPARATOR;
2311 48 : type_string += '\0';
2312 48 : gfc_free_expr (e);
2313 48 : if (gfc_match (", ") == MATCH_YES)
2314 24 : continue;
2315 24 : if (gfc_match (") ") == MATCH_YES)
2316 : break;
2317 2 : gfc_error ("Expected %<,%> or %<)%> at %C");
2318 2 : return MATCH_ERROR;
2319 24 : }
2320 : while (true);
2321 60 : type_string += '\0';
2322 60 : *type_str_len = type_string.length();
2323 60 : *type_str = XNEWVEC (char, type_string.length ());
2324 60 : memcpy (*type_str, type_string.data (), type_string.length ());
2325 60 : return MATCH_YES;
2326 82 : }
2327 :
2328 :
2329 : /* Match OpenMP 5.1's 'init'-clause modifiers, used by the 'init' clause of
2330 : the 'interop' directive and the 'append_args' directive of 'declare variant'.
2331 : [prefer_type(...)][,][<target|targetsync>, ...])
2332 :
2333 : If is_init_clause, the modifier parsing ends with a ':'.
2334 : If not is_init_clause (i.e. append_args), the parsing ends with ')'. */
2335 :
2336 : static match
2337 164 : gfc_parser_omp_clause_init_modifiers (bool &target, bool &targetsync,
2338 : char **type_str, int &type_str_len,
2339 : bool is_init_clause)
2340 : {
2341 164 : target = false;
2342 164 : targetsync = false;
2343 164 : *type_str = NULL;
2344 164 : type_str_len = 0;
2345 286 : match m;
2346 :
2347 286 : do
2348 : {
2349 286 : if (gfc_match ("prefer_type ( ") == MATCH_YES)
2350 : {
2351 83 : if (*type_str)
2352 : {
2353 1 : gfc_error ("Duplicate %<prefer_type%> modifier at %C");
2354 1 : return MATCH_ERROR;
2355 : }
2356 82 : m = gfc_match_omp_prefer_type (type_str, &type_str_len);
2357 82 : if (m != MATCH_YES)
2358 : return m;
2359 60 : if (gfc_match (", ") == MATCH_YES)
2360 14 : continue;
2361 46 : if (is_init_clause)
2362 : {
2363 24 : if (gfc_match (": ") == MATCH_YES)
2364 : break;
2365 0 : gfc_error ("Expected %<,%> or %<:%> at %C");
2366 : }
2367 : else
2368 : {
2369 22 : if (gfc_match (") ") == MATCH_YES)
2370 : break;
2371 0 : gfc_error ("Expected %<,%> or %<)%> at %C");
2372 : }
2373 0 : return MATCH_ERROR;
2374 : }
2375 :
2376 203 : if (gfc_match ("prefer_type ") == MATCH_YES)
2377 : {
2378 2 : gfc_error ("Expected %<(%> after %<prefer_type%> at %C");
2379 2 : return MATCH_ERROR;
2380 : }
2381 :
2382 201 : if (gfc_match ("targetsync ") == MATCH_YES)
2383 : {
2384 57 : if (targetsync)
2385 : {
2386 3 : gfc_error ("Duplicate %<targetsync%> at %C");
2387 3 : return MATCH_ERROR;
2388 : }
2389 54 : targetsync = true;
2390 54 : if (gfc_match (", ") == MATCH_YES)
2391 13 : continue;
2392 41 : if (!is_init_clause)
2393 : {
2394 23 : if (gfc_match (") ") == MATCH_YES)
2395 : break;
2396 0 : gfc_error ("Expected %<,%> or %<)%> at %C");
2397 0 : return MATCH_ERROR;
2398 : }
2399 18 : if (gfc_match (": ") == MATCH_YES)
2400 : break;
2401 1 : gfc_error ("Expected %<,%> or %<:%> at %C");
2402 1 : return MATCH_ERROR;
2403 : }
2404 144 : if (gfc_match ("target ") == MATCH_YES)
2405 : {
2406 135 : if (target)
2407 : {
2408 3 : gfc_error ("Duplicate %<target%> at %C");
2409 3 : return MATCH_ERROR;
2410 : }
2411 132 : target = true;
2412 132 : if (gfc_match (", ") == MATCH_YES)
2413 95 : continue;
2414 37 : if (!is_init_clause)
2415 : {
2416 11 : if (gfc_match (") ") == MATCH_YES)
2417 : break;
2418 0 : gfc_error ("Expected %<,%> or %<)%> at %C");
2419 0 : return MATCH_ERROR;
2420 : }
2421 26 : if (gfc_match (": ") == MATCH_YES)
2422 : break;
2423 1 : gfc_error ("Expected %<,%> or %<:%> at %C");
2424 1 : return MATCH_ERROR;
2425 : }
2426 9 : gfc_error ("Expected %<prefer_type%>, %<target%>, or %<targetsync%> "
2427 : "at %C");
2428 9 : return MATCH_ERROR;
2429 : }
2430 : while (true);
2431 :
2432 122 : if (!target && !targetsync)
2433 : {
2434 4 : gfc_error ("Missing required %<target%> and/or %<targetsync%> "
2435 : "modifier at %C");
2436 4 : return MATCH_ERROR;
2437 : }
2438 : return MATCH_YES;
2439 : }
2440 :
2441 : /* Match OpenMP 5.1's 'init' clause for 'interop' objects:
2442 : init([prefer_type(...)][,][<target|targetsync>, ...] :] interop-obj-list) */
2443 :
2444 : static match
2445 108 : gfc_match_omp_init (gfc_omp_namelist **list)
2446 : {
2447 108 : bool target, targetsync;
2448 108 : char *type_str = NULL;
2449 108 : int type_str_len;
2450 108 : if (gfc_parser_omp_clause_init_modifiers (target, targetsync, &type_str,
2451 : type_str_len, true) == MATCH_ERROR)
2452 : return MATCH_ERROR;
2453 :
2454 64 : gfc_omp_namelist **head = NULL;
2455 64 : if (gfc_match_omp_variable_list ("", list, false, NULL, &head) != MATCH_YES)
2456 : return MATCH_ERROR;
2457 147 : for (gfc_omp_namelist *n = *head; n; n = n->next)
2458 : {
2459 84 : n->u.init.target = target;
2460 84 : n->u.init.targetsync = targetsync;
2461 84 : n->u.init.len = type_str_len;
2462 84 : n->u2.init_interop = type_str;
2463 : }
2464 : return MATCH_YES;
2465 : }
2466 :
2467 :
2468 : /* Match with duplicate check. Matches 'name'. If expr != NULL, it
2469 : then matches '(expr)', otherwise, if open_parens is true,
2470 : it matches a ' ( ' after 'name'.
2471 : dupl_message requires '%qs %L' - and is used by
2472 : gfc_match_dupl_memorder and gfc_match_dupl_atomic. */
2473 :
2474 : static match
2475 23277 : gfc_match_dupl_check (bool not_dupl, const char *name, bool open_parens = false,
2476 : gfc_expr **expr = NULL, const char *dupl_msg = NULL)
2477 : {
2478 23277 : match m;
2479 23277 : char c;
2480 23277 : locus old_loc = gfc_current_locus;
2481 23277 : if ((m = gfc_match (name)) != MATCH_YES)
2482 : return m;
2483 : /* Ensure that no partial string is matched. */
2484 18171 : if (gfc_current_form == FORM_FREE
2485 17673 : && gfc_match_eos () != MATCH_YES
2486 31705 : && ((c = gfc_peek_ascii_char ()) == '_' || ISALNUM (c)))
2487 : {
2488 13 : gfc_current_locus = old_loc;
2489 13 : return MATCH_NO;
2490 : }
2491 18158 : if (!not_dupl)
2492 : {
2493 53 : if (dupl_msg)
2494 2 : gfc_error (dupl_msg, name, &old_loc);
2495 : else
2496 51 : gfc_error ("Duplicated %qs clause at %L", name, &old_loc);
2497 53 : return MATCH_ERROR;
2498 : }
2499 18105 : if (open_parens || expr)
2500 : {
2501 10108 : if (gfc_match (" ( ") != MATCH_YES)
2502 : {
2503 25 : gfc_error ("Expected %<(%> after %qs at %C", name);
2504 25 : return MATCH_ERROR;
2505 : }
2506 10083 : if (expr)
2507 : {
2508 3396 : if (gfc_match ("%e )", expr) != MATCH_YES)
2509 : {
2510 9 : gfc_error ("Invalid expression after %<%s(%> at %C", name);
2511 9 : return MATCH_ERROR;
2512 : }
2513 : }
2514 : }
2515 : return MATCH_YES;
2516 : }
2517 :
2518 : static match
2519 211 : gfc_match_dupl_memorder (bool not_dupl, const char *name)
2520 : {
2521 0 : return gfc_match_dupl_check (not_dupl, name, false, NULL,
2522 : "Duplicated memory-order clause: unexpected %s "
2523 0 : "clause at %L");
2524 : }
2525 :
2526 : static match
2527 1175 : gfc_match_dupl_atomic (bool not_dupl, const char *name)
2528 : {
2529 0 : return gfc_match_dupl_check (not_dupl, name, false, NULL,
2530 : "Duplicated atomic clause: unexpected %s "
2531 0 : "clause at %L");
2532 : }
2533 :
2534 :
2535 : /* Search upwards though namespace NS and its parents to find an
2536 : !$omp declare mapper named MAPPER_ID, for typespec TS. The default
2537 : mapper has mapper_id == "". */
2538 :
2539 : gfc_omp_udm *
2540 999 : gfc_find_omp_udm (gfc_namespace *ns, const char *mapper_id, gfc_typespec *ts)
2541 : {
2542 999 : gfc_symtree *st;
2543 :
2544 999 : if (ns == NULL)
2545 0 : ns = gfc_current_ns;
2546 :
2547 1177 : do
2548 : {
2549 1177 : gfc_omp_udm *omp_udm;
2550 :
2551 1177 : st = gfc_find_symtree (ns->omp_udm_root, mapper_id);
2552 :
2553 1177 : if (st != NULL)
2554 : {
2555 28 : for (omp_udm = st->n.omp_udm; omp_udm; omp_udm = omp_udm->next)
2556 28 : if (gfc_compare_types (&omp_udm->ts, ts))
2557 : return omp_udm;
2558 : }
2559 :
2560 : /* Don't escape an interface block. */
2561 1151 : if (ns && !ns->has_import_set
2562 1151 : && ns->proc_name && ns->proc_name->attr.if_source == IFSRC_IFBODY)
2563 : break;
2564 :
2565 1151 : ns = ns->parent;
2566 : }
2567 1151 : while (ns != NULL);
2568 :
2569 : return NULL;
2570 : }
2571 :
2572 :
2573 : /* Match OpenMP and OpenACC directive clauses. MASK is a bitmask of
2574 : clauses that are allowed for a particular directive. */
2575 :
2576 : static match
2577 35078 : gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
2578 : bool first = true, bool needs_space = true,
2579 : bool openacc = false, bool openmp_target = false,
2580 : gfc_omp_map_op default_map_op = OMP_MAP_TOFROM)
2581 : {
2582 35078 : bool error = false;
2583 35078 : gfc_omp_clauses *c = gfc_get_omp_clauses ();
2584 35078 : locus old_loc;
2585 : /* Determine whether we're dealing with an OpenACC directive that permits
2586 : derived type member accesses. This in particular disallows
2587 : "!$acc declare" from using such accesses, because it's not clear if/how
2588 : that should work. */
2589 35078 : bool allow_derived = (openacc
2590 35078 : && ((mask & OMP_CLAUSE_ATTACH)
2591 6326 : || (mask & OMP_CLAUSE_DETACH)));
2592 :
2593 35078 : gcc_checking_assert (OMP_MASK1_LAST <= 64 && OMP_MASK2_LAST <= 64);
2594 35078 : *cp = NULL;
2595 128862 : while (1)
2596 : {
2597 81970 : match m = MATCH_NO;
2598 61056 : if ((first || (m = gfc_match_char (',')) != MATCH_YES)
2599 142670 : && (needs_space && gfc_match_space () != MATCH_YES))
2600 : break;
2601 77404 : needs_space = false;
2602 77404 : first = false;
2603 77404 : gfc_gobble_whitespace ();
2604 77404 : bool end_colon;
2605 77404 : gfc_omp_namelist **head;
2606 77404 : old_loc = gfc_current_locus;
2607 77404 : char pc = gfc_peek_ascii_char ();
2608 77404 : if (pc == '\n' && m == MATCH_YES)
2609 : {
2610 1 : gfc_error ("Clause expected at %C after trailing comma");
2611 1 : goto error;
2612 : }
2613 77403 : switch (pc)
2614 : {
2615 1317 : case 'a':
2616 1317 : end_colon = false;
2617 1317 : head = NULL;
2618 1341 : if ((mask & OMP_CLAUSE_ASSUMPTIONS)
2619 1317 : && gfc_match ("absent ( ") == MATCH_YES)
2620 : {
2621 27 : if (gfc_omp_absent_contains_clause (&c->assume, true)
2622 : != MATCH_YES)
2623 3 : goto error;
2624 24 : continue;
2625 : }
2626 1290 : if ((mask & OMP_CLAUSE_ALIGNED)
2627 1290 : && gfc_match_omp_variable_list ("aligned (",
2628 : &c->lists[OMP_LIST_ALIGNED],
2629 : false, &end_colon,
2630 : &head) == MATCH_YES)
2631 : {
2632 112 : gfc_expr *alignment = NULL;
2633 112 : gfc_omp_namelist *n;
2634 :
2635 112 : if (end_colon && gfc_match (" %e )", &alignment) != MATCH_YES)
2636 : {
2637 0 : gfc_free_omp_namelist (*head, OMP_LIST_ALIGNED);
2638 0 : gfc_current_locus = old_loc;
2639 0 : *head = NULL;
2640 0 : break;
2641 : }
2642 268 : for (n = *head; n; n = n->next)
2643 156 : if (n->next && alignment)
2644 42 : n->expr = gfc_copy_expr (alignment);
2645 : else
2646 114 : n->expr = alignment;
2647 112 : continue;
2648 112 : }
2649 1188 : if ((mask & OMP_CLAUSE_MEMORDER)
2650 1195 : && (m = gfc_match_dupl_memorder ((c->memorder
2651 17 : == OMP_MEMORDER_UNSET),
2652 : "acq_rel")) != MATCH_NO)
2653 : {
2654 10 : if (m == MATCH_ERROR)
2655 0 : goto error;
2656 10 : c->memorder = OMP_MEMORDER_ACQ_REL;
2657 10 : continue;
2658 : }
2659 1175 : if ((mask & OMP_CLAUSE_MEMORDER)
2660 1175 : && (m = gfc_match_dupl_memorder ((c->memorder
2661 7 : == OMP_MEMORDER_UNSET),
2662 : "acquire")) != MATCH_NO)
2663 : {
2664 7 : if (m == MATCH_ERROR)
2665 0 : goto error;
2666 7 : c->memorder = OMP_MEMORDER_ACQUIRE;
2667 7 : continue;
2668 : }
2669 1161 : if ((mask & OMP_CLAUSE_AFFINITY)
2670 1161 : && gfc_match ("affinity ( ") == MATCH_YES)
2671 : {
2672 41 : gfc_namespace *ns_iter = NULL, *ns_curr = gfc_current_ns;
2673 41 : m = gfc_match_iterator (&ns_iter, true);
2674 41 : if (m == MATCH_ERROR)
2675 : break;
2676 31 : if (m == MATCH_YES && gfc_match (" : ") != MATCH_YES)
2677 : {
2678 1 : gfc_error ("Expected %<:%> at %C");
2679 1 : break;
2680 : }
2681 30 : if (ns_iter)
2682 18 : gfc_current_ns = ns_iter;
2683 30 : head = NULL;
2684 30 : m = gfc_match_omp_variable_list ("", &c->lists[OMP_LIST_AFFINITY],
2685 : false, NULL, &head, true);
2686 30 : gfc_current_ns = ns_curr;
2687 30 : if (m == MATCH_ERROR)
2688 : break;
2689 27 : if (ns_iter)
2690 : {
2691 45 : for (gfc_omp_namelist *n = *head; n; n = n->next)
2692 : {
2693 27 : n->u2.ns = ns_iter;
2694 27 : ns_iter->refs++;
2695 : }
2696 : }
2697 27 : continue;
2698 27 : }
2699 1120 : if ((mask & OMP_CLAUSE_ALLOCATE)
2700 1120 : && gfc_match ("allocate ( ") == MATCH_YES)
2701 : {
2702 281 : gfc_expr *allocator = NULL;
2703 281 : gfc_expr *align = NULL;
2704 281 : old_loc = gfc_current_locus;
2705 281 : if ((m = gfc_match ("allocator ( %e )", &allocator)) == MATCH_YES)
2706 50 : gfc_match (" , align ( %e )", &align);
2707 231 : else if ((m = gfc_match ("align ( %e )", &align)) == MATCH_YES)
2708 29 : gfc_match (" , allocator ( %e )", &allocator);
2709 :
2710 281 : if (m == MATCH_YES)
2711 : {
2712 79 : if (gfc_match (" : ") != MATCH_YES)
2713 : {
2714 5 : gfc_error ("Expected %<:%> at %C");
2715 8 : goto error;
2716 : }
2717 : }
2718 : else
2719 : {
2720 202 : m = gfc_match_expr (&allocator);
2721 202 : if (m == MATCH_YES && gfc_match (" : ") != MATCH_YES)
2722 : {
2723 : /* If no ":" then there is no allocator, we backtrack
2724 : and read the variable list. */
2725 101 : gfc_free_expr (allocator);
2726 101 : allocator = NULL;
2727 101 : gfc_current_locus = old_loc;
2728 : }
2729 : }
2730 276 : gfc_omp_namelist **head = NULL;
2731 276 : m = gfc_match_omp_variable_list ("", &c->lists[OMP_LIST_ALLOCATE],
2732 : true, NULL, &head);
2733 :
2734 276 : if (m != MATCH_YES)
2735 : {
2736 3 : gfc_free_expr (allocator);
2737 3 : gfc_free_expr (align);
2738 3 : gfc_error ("Expected variable list at %C");
2739 3 : goto error;
2740 : }
2741 :
2742 729 : for (gfc_omp_namelist *n = *head; n; n = n->next)
2743 : {
2744 456 : n->u2.allocator = allocator;
2745 456 : n->u.align = (align) ? gfc_copy_expr (align) : NULL;
2746 : }
2747 273 : gfc_free_expr (align);
2748 273 : continue;
2749 273 : }
2750 899 : if ((mask & OMP_CLAUSE_AT)
2751 839 : && (m = gfc_match_dupl_check (c->at == OMP_AT_UNSET, "at", true))
2752 : != MATCH_NO)
2753 : {
2754 66 : if (m == MATCH_ERROR)
2755 2 : goto error;
2756 64 : if (gfc_match ("compilation )") == MATCH_YES)
2757 15 : c->at = OMP_AT_COMPILATION;
2758 49 : else if (gfc_match ("execution )") == MATCH_YES)
2759 45 : c->at = OMP_AT_EXECUTION;
2760 : else
2761 : {
2762 4 : gfc_error ("Expected COMPILATION or EXECUTION in AT clause "
2763 : "at %C");
2764 4 : goto error;
2765 : }
2766 60 : continue;
2767 : }
2768 1416 : if ((mask & OMP_CLAUSE_ASYNC)
2769 773 : && (m = gfc_match_dupl_check (!c->async, "async")) != MATCH_NO)
2770 : {
2771 643 : if (m == MATCH_ERROR)
2772 0 : goto error;
2773 643 : c->async = true;
2774 643 : m = gfc_match (" ( %e )", &c->async_expr);
2775 643 : if (m == MATCH_ERROR)
2776 : {
2777 0 : gfc_current_locus = old_loc;
2778 0 : break;
2779 : }
2780 643 : else if (m == MATCH_NO)
2781 : {
2782 133 : c->async_expr
2783 133 : = gfc_get_constant_expr (BT_INTEGER,
2784 : gfc_default_integer_kind,
2785 : &gfc_current_locus);
2786 133 : mpz_set_si (c->async_expr->value.integer, GOMP_ASYNC_NOVAL);
2787 : }
2788 643 : continue;
2789 : }
2790 193 : if ((mask & OMP_CLAUSE_AUTO)
2791 130 : && (m = gfc_match_dupl_check (!c->par_auto, "auto"))
2792 : != MATCH_NO)
2793 : {
2794 63 : if (m == MATCH_ERROR)
2795 0 : goto error;
2796 63 : c->par_auto = true;
2797 63 : continue;
2798 : }
2799 128 : if ((mask & OMP_CLAUSE_ATTACH)
2800 62 : && gfc_match ("attach ( ") == MATCH_YES
2801 128 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
2802 : OMP_MAP_ATTACH, false,
2803 : allow_derived))
2804 61 : continue;
2805 : break;
2806 36 : case 'b':
2807 70 : if ((mask & OMP_CLAUSE_BIND)
2808 36 : && (m = gfc_match_dupl_check (c->bind == OMP_BIND_UNSET, "bind",
2809 : true)) != MATCH_NO)
2810 : {
2811 36 : if (m == MATCH_ERROR)
2812 1 : goto error;
2813 35 : if (gfc_match ("teams )") == MATCH_YES)
2814 11 : c->bind = OMP_BIND_TEAMS;
2815 24 : else if (gfc_match ("parallel )") == MATCH_YES)
2816 15 : c->bind = OMP_BIND_PARALLEL;
2817 9 : else if (gfc_match ("thread )") == MATCH_YES)
2818 8 : c->bind = OMP_BIND_THREAD;
2819 : else
2820 : {
2821 1 : gfc_error ("Expected TEAMS, PARALLEL or THREAD as binding in "
2822 : "BIND at %C");
2823 1 : break;
2824 : }
2825 34 : continue;
2826 : }
2827 : break;
2828 7110 : case 'c':
2829 7383 : if ((mask & OMP_CLAUSE_CAPTURE)
2830 7110 : && (m = gfc_match_dupl_check (!c->capture, "capture"))
2831 : != MATCH_NO)
2832 : {
2833 274 : if (m == MATCH_ERROR)
2834 1 : goto error;
2835 273 : c->capture = true;
2836 273 : continue;
2837 : }
2838 6836 : if (mask & OMP_CLAUSE_COLLAPSE)
2839 : {
2840 1996 : gfc_expr *cexpr = NULL;
2841 1996 : if ((m = gfc_match_dupl_check (!c->collapse, "collapse", true,
2842 : &cexpr)) != MATCH_NO)
2843 : {
2844 1506 : int collapse;
2845 1506 : if (m == MATCH_ERROR)
2846 0 : goto error;
2847 1506 : if (gfc_extract_int (cexpr, &collapse, -1))
2848 4 : collapse = 1;
2849 1502 : else if (collapse <= 0)
2850 : {
2851 8 : gfc_error_now ("COLLAPSE clause argument not constant "
2852 : "positive integer at %C");
2853 8 : collapse = 1;
2854 : }
2855 1506 : gfc_free_expr (cexpr);
2856 1506 : c->collapse = collapse;
2857 1506 : continue;
2858 1506 : }
2859 : }
2860 5496 : if ((mask & OMP_CLAUSE_COMPARE)
2861 5330 : && (m = gfc_match_dupl_check (!c->compare, "compare"))
2862 : != MATCH_NO)
2863 : {
2864 167 : if (m == MATCH_ERROR)
2865 1 : goto error;
2866 166 : c->compare = true;
2867 166 : continue;
2868 : }
2869 5175 : if ((mask & OMP_CLAUSE_ASSUMPTIONS)
2870 5163 : && gfc_match ("contains ( ") == MATCH_YES)
2871 : {
2872 13 : if (gfc_omp_absent_contains_clause (&c->assume, false)
2873 : != MATCH_YES)
2874 1 : goto error;
2875 12 : continue;
2876 : }
2877 7266 : if ((mask & OMP_CLAUSE_COPY)
2878 3723 : && gfc_match ("copy ( ") == MATCH_YES
2879 7267 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
2880 : OMP_MAP_TOFROM, true,
2881 : allow_derived))
2882 2116 : continue;
2883 3034 : if (mask & OMP_CLAUSE_COPYIN)
2884 : {
2885 2628 : if (openacc)
2886 : {
2887 2529 : if (gfc_match ("copyin ( ") == MATCH_YES)
2888 : {
2889 1458 : bool readonly = gfc_match ("readonly : ") == MATCH_YES;
2890 1458 : head = NULL;
2891 1458 : if (gfc_match_omp_variable_list ("",
2892 : &c->lists[OMP_LIST_MAP],
2893 : true, NULL, &head, true,
2894 : allow_derived)
2895 : == MATCH_YES)
2896 : {
2897 1452 : gfc_omp_namelist *n;
2898 3349 : for (n = *head; n; n = n->next)
2899 : {
2900 1897 : n->u.map.op = OMP_MAP_TO;
2901 1897 : n->u.map.readonly = readonly;
2902 : }
2903 1452 : continue;
2904 1452 : }
2905 : }
2906 : }
2907 99 : else if (gfc_match_omp_variable_list ("copyin (",
2908 : &c->lists[OMP_LIST_COPYIN],
2909 : true) == MATCH_YES)
2910 97 : continue;
2911 : }
2912 2556 : if ((mask & OMP_CLAUSE_COPYOUT)
2913 1216 : && gfc_match ("copyout ( ") == MATCH_YES
2914 2556 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
2915 : OMP_MAP_FROM, true, allow_derived))
2916 1071 : continue;
2917 498 : if ((mask & OMP_CLAUSE_COPYPRIVATE)
2918 414 : && gfc_match_omp_variable_list ("copyprivate (",
2919 : &c->lists[OMP_LIST_COPYPRIVATE],
2920 : true) == MATCH_YES)
2921 84 : continue;
2922 651 : if ((mask & OMP_CLAUSE_CREATE)
2923 328 : && gfc_match ("create ( ") == MATCH_YES
2924 651 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
2925 : OMP_MAP_ALLOC, true, allow_derived))
2926 321 : continue;
2927 : break;
2928 4186 : case 'd':
2929 4186 : if ((mask & OMP_CLAUSE_DEFAULTMAP)
2930 4186 : && gfc_match ("defaultmap ( ") == MATCH_YES)
2931 : {
2932 181 : enum gfc_omp_defaultmap behavior;
2933 181 : gfc_omp_defaultmap_category category
2934 : = OMP_DEFAULTMAP_CAT_UNCATEGORIZED;
2935 181 : if (gfc_match ("alloc ") == MATCH_YES)
2936 : behavior = OMP_DEFAULTMAP_ALLOC;
2937 175 : else if (gfc_match ("tofrom ") == MATCH_YES)
2938 : behavior = OMP_DEFAULTMAP_TOFROM;
2939 143 : else if (gfc_match ("to ") == MATCH_YES)
2940 : behavior = OMP_DEFAULTMAP_TO;
2941 133 : else if (gfc_match ("from ") == MATCH_YES)
2942 : behavior = OMP_DEFAULTMAP_FROM;
2943 130 : else if (gfc_match ("firstprivate ") == MATCH_YES)
2944 : behavior = OMP_DEFAULTMAP_FIRSTPRIVATE;
2945 95 : else if (gfc_match ("present ") == MATCH_YES)
2946 : behavior = OMP_DEFAULTMAP_PRESENT;
2947 91 : else if (gfc_match ("none ") == MATCH_YES)
2948 : behavior = OMP_DEFAULTMAP_NONE;
2949 10 : else if (gfc_match ("default ") == MATCH_YES)
2950 : behavior = OMP_DEFAULTMAP_DEFAULT;
2951 : else
2952 : {
2953 1 : gfc_error ("Expected ALLOC, TO, FROM, TOFROM, FIRSTPRIVATE, "
2954 : "PRESENT, NONE or DEFAULT at %C");
2955 1 : break;
2956 : }
2957 180 : if (')' == gfc_peek_ascii_char ())
2958 : ;
2959 102 : else if (gfc_match (": ") != MATCH_YES)
2960 : break;
2961 : else
2962 : {
2963 102 : if (gfc_match ("scalar ") == MATCH_YES)
2964 : category = OMP_DEFAULTMAP_CAT_SCALAR;
2965 67 : else if (gfc_match ("aggregate ") == MATCH_YES)
2966 : category = OMP_DEFAULTMAP_CAT_AGGREGATE;
2967 43 : else if (gfc_match ("allocatable ") == MATCH_YES)
2968 : category = OMP_DEFAULTMAP_CAT_ALLOCATABLE;
2969 31 : else if (gfc_match ("pointer ") == MATCH_YES)
2970 : category = OMP_DEFAULTMAP_CAT_POINTER;
2971 14 : else if (gfc_match ("all ") == MATCH_YES)
2972 : category = OMP_DEFAULTMAP_CAT_ALL;
2973 : else
2974 : {
2975 1 : gfc_error ("Expected SCALAR, AGGREGATE, ALLOCATABLE, "
2976 : "POINTER or ALL at %C");
2977 1 : break;
2978 : }
2979 : }
2980 1200 : for (int i = 0; i < OMP_DEFAULTMAP_CAT_NUM; ++i)
2981 : {
2982 1034 : if (i != category
2983 1034 : && category != OMP_DEFAULTMAP_CAT_UNCATEGORIZED
2984 486 : && category != OMP_DEFAULTMAP_CAT_ALL
2985 486 : && i != OMP_DEFAULTMAP_CAT_UNCATEGORIZED
2986 341 : && i != OMP_DEFAULTMAP_CAT_ALL)
2987 254 : continue;
2988 780 : if (c->defaultmap[i] != OMP_DEFAULTMAP_UNSET)
2989 : {
2990 13 : const char *pcategory = NULL;
2991 13 : switch (i)
2992 : {
2993 : case OMP_DEFAULTMAP_CAT_UNCATEGORIZED: break;
2994 : case OMP_DEFAULTMAP_CAT_ALL: pcategory = "ALL"; break;
2995 1 : case OMP_DEFAULTMAP_CAT_SCALAR: pcategory = "SCALAR"; break;
2996 2 : case OMP_DEFAULTMAP_CAT_AGGREGATE:
2997 2 : pcategory = "AGGREGATE";
2998 2 : break;
2999 1 : case OMP_DEFAULTMAP_CAT_ALLOCATABLE:
3000 1 : pcategory = "ALLOCATABLE";
3001 1 : break;
3002 2 : case OMP_DEFAULTMAP_CAT_POINTER:
3003 2 : pcategory = "POINTER";
3004 2 : break;
3005 : default: gcc_unreachable ();
3006 : }
3007 6 : if (i == OMP_DEFAULTMAP_CAT_UNCATEGORIZED)
3008 4 : gfc_error ("DEFAULTMAP at %C but prior DEFAULTMAP with "
3009 : "unspecified category");
3010 : else
3011 9 : gfc_error ("DEFAULTMAP at %C but prior DEFAULTMAP for "
3012 : "category %s", pcategory);
3013 13 : goto error;
3014 : }
3015 : }
3016 166 : c->defaultmap[category] = behavior;
3017 166 : if (gfc_match (")") != MATCH_YES)
3018 : break;
3019 166 : continue;
3020 166 : }
3021 4972 : if ((mask & OMP_CLAUSE_DEFAULT)
3022 4005 : && (m = gfc_match_dupl_check (c->default_sharing
3023 : == OMP_DEFAULT_UNKNOWN, "default",
3024 : true)) != MATCH_NO)
3025 : {
3026 1012 : if (m == MATCH_ERROR)
3027 6 : goto error;
3028 1006 : if (gfc_match ("none") == MATCH_YES)
3029 596 : c->default_sharing = OMP_DEFAULT_NONE;
3030 410 : else if (openacc)
3031 : {
3032 225 : if (gfc_match ("present") == MATCH_YES)
3033 195 : c->default_sharing = OMP_DEFAULT_PRESENT;
3034 : }
3035 : else
3036 : {
3037 185 : if (gfc_match ("firstprivate") == MATCH_YES)
3038 8 : c->default_sharing = OMP_DEFAULT_FIRSTPRIVATE;
3039 177 : else if (gfc_match ("private") == MATCH_YES)
3040 24 : c->default_sharing = OMP_DEFAULT_PRIVATE;
3041 153 : else if (gfc_match ("shared") == MATCH_YES)
3042 153 : c->default_sharing = OMP_DEFAULT_SHARED;
3043 : }
3044 1006 : if (c->default_sharing == OMP_DEFAULT_UNKNOWN)
3045 : {
3046 30 : if (openacc)
3047 30 : gfc_error ("Expected NONE or PRESENT in DEFAULT clause "
3048 : "at %C");
3049 : else
3050 0 : gfc_error ("Expected NONE, FIRSTPRIVATE, PRIVATE or SHARED "
3051 : "in DEFAULT clause at %C");
3052 30 : goto error;
3053 : }
3054 976 : if (gfc_match (" )") != MATCH_YES)
3055 9 : goto error;
3056 967 : continue;
3057 : }
3058 3301 : if ((mask & OMP_CLAUSE_DELETE)
3059 345 : && gfc_match ("delete ( ") == MATCH_YES
3060 3301 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
3061 : OMP_MAP_RELEASE, true,
3062 : allow_derived))
3063 308 : continue;
3064 : /* DOACROSS: match 'doacross' and 'depend' with sink/source.
3065 : DEPEND: match 'depend' but not sink/source. */
3066 2685 : m = MATCH_NO;
3067 2685 : if (((mask & OMP_CLAUSE_DOACROSS)
3068 383 : && gfc_match ("doacross ( ") == MATCH_YES)
3069 3041 : || (((mask & OMP_CLAUSE_DEPEND) || (mask & OMP_CLAUSE_DOACROSS))
3070 1600 : && (m = gfc_match ("depend ( ")) == MATCH_YES))
3071 : {
3072 1100 : bool has_omp_all_memory;
3073 1100 : bool is_depend = m == MATCH_YES;
3074 1100 : gfc_namespace *ns_iter = NULL, *ns_curr = gfc_current_ns;
3075 1100 : match m_it = MATCH_NO;
3076 1100 : if (is_depend)
3077 1073 : m_it = gfc_match_iterator (&ns_iter, false);
3078 1073 : if (m_it == MATCH_ERROR)
3079 : break;
3080 1095 : if (m_it == MATCH_YES && gfc_match (" , ") != MATCH_YES)
3081 : break;
3082 1095 : m = MATCH_YES;
3083 1095 : gfc_omp_depend_doacross_op depend_op = OMP_DEPEND_OUT;
3084 1095 : if (gfc_match ("inoutset") == MATCH_YES)
3085 : depend_op = OMP_DEPEND_INOUTSET;
3086 1083 : else if (gfc_match ("inout") == MATCH_YES)
3087 : depend_op = OMP_DEPEND_INOUT;
3088 991 : else if (gfc_match ("in") == MATCH_YES)
3089 : depend_op = OMP_DEPEND_IN;
3090 704 : else if (gfc_match ("out") == MATCH_YES)
3091 : depend_op = OMP_DEPEND_OUT;
3092 442 : else if (gfc_match ("mutexinoutset") == MATCH_YES)
3093 : depend_op = OMP_DEPEND_MUTEXINOUTSET;
3094 424 : else if (gfc_match ("depobj") == MATCH_YES)
3095 : depend_op = OMP_DEPEND_DEPOBJ;
3096 387 : else if (gfc_match ("source") == MATCH_YES)
3097 : {
3098 143 : if (m_it == MATCH_YES)
3099 : {
3100 1 : gfc_error ("ITERATOR may not be combined with SOURCE "
3101 : "at %C");
3102 17 : goto error;
3103 : }
3104 142 : if (!(mask & OMP_CLAUSE_DOACROSS))
3105 : {
3106 1 : gfc_error ("SOURCE at %C not permitted as dependence-type"
3107 : " for this directive");
3108 1 : goto error;
3109 : }
3110 141 : if (c->doacross_source)
3111 : {
3112 0 : gfc_error ("Duplicated clause with SOURCE dependence-type"
3113 : " at %C");
3114 0 : goto error;
3115 : }
3116 141 : gfc_gobble_whitespace ();
3117 141 : m = gfc_match (": ");
3118 141 : if (m != MATCH_YES && !is_depend)
3119 : {
3120 1 : gfc_error ("Expected %<:%> at %C");
3121 1 : goto error;
3122 : }
3123 140 : if (gfc_match (")") != MATCH_YES
3124 146 : && !(m == MATCH_YES
3125 6 : && gfc_match ("omp_cur_iteration )") == MATCH_YES))
3126 : {
3127 2 : gfc_error ("Expected %<)%> or %<omp_cur_iteration)%> "
3128 : "at %C");
3129 2 : goto error;
3130 : }
3131 138 : if (is_depend)
3132 130 : gfc_warning (OPT_Wdeprecated_openmp,
3133 : "%<source%> modifier with %<depend%> clause "
3134 : "at %L deprecated since OpenMP 5.2, use with "
3135 : "%<doacross%>", &old_loc);
3136 138 : c->doacross_source = true;
3137 138 : c->depend_source = is_depend;
3138 1078 : continue;
3139 : }
3140 244 : else if (gfc_match ("sink ") == MATCH_YES)
3141 : {
3142 244 : if (!(mask & OMP_CLAUSE_DOACROSS))
3143 : {
3144 2 : gfc_error ("SINK at %C not permitted as dependence-type "
3145 : "for this directive");
3146 2 : goto error;
3147 : }
3148 242 : if (gfc_match (": ") != MATCH_YES)
3149 : {
3150 1 : gfc_error ("Expected %<:%> at %C");
3151 1 : goto error;
3152 : }
3153 241 : if (m_it == MATCH_YES)
3154 : {
3155 0 : gfc_error ("ITERATOR may not be combined with SINK "
3156 : "at %C");
3157 0 : goto error;
3158 : }
3159 241 : if (is_depend)
3160 226 : gfc_warning (OPT_Wdeprecated_openmp,
3161 : "%<sink%> modifier with %<depend%> clause at "
3162 : "%L deprecated since OpenMP 5.2, use with "
3163 : "%<doacross%>", &old_loc);
3164 241 : m = gfc_match_omp_doacross_sink (&c->lists[OMP_LIST_DEPEND],
3165 : is_depend);
3166 241 : if (m == MATCH_YES)
3167 238 : continue;
3168 3 : goto error;
3169 : }
3170 : else
3171 : m = MATCH_NO;
3172 708 : if (!(mask & OMP_CLAUSE_DEPEND))
3173 : {
3174 0 : gfc_error ("Expected dependence-type SINK or SOURCE at %C");
3175 0 : goto error;
3176 : }
3177 708 : head = NULL;
3178 708 : if (ns_iter)
3179 40 : gfc_current_ns = ns_iter;
3180 708 : if (m == MATCH_YES)
3181 708 : m = gfc_match_omp_variable_list (" : ",
3182 : &c->lists[OMP_LIST_DEPEND],
3183 : false, NULL, &head, true,
3184 : false, &has_omp_all_memory);
3185 708 : if (m != MATCH_YES)
3186 2 : goto error;
3187 706 : gfc_current_ns = ns_curr;
3188 706 : if (has_omp_all_memory && depend_op != OMP_DEPEND_INOUT
3189 21 : && depend_op != OMP_DEPEND_OUT)
3190 : {
3191 4 : gfc_error ("%<omp_all_memory%> used with DEPEND kind "
3192 : "other than OUT or INOUT at %C");
3193 4 : goto error;
3194 : }
3195 702 : gfc_omp_namelist *n;
3196 1435 : for (n = *head; n; n = n->next)
3197 : {
3198 733 : n->u.depend_doacross_op = depend_op;
3199 733 : n->u2.ns = ns_iter;
3200 733 : if (ns_iter)
3201 39 : ns_iter->refs++;
3202 : }
3203 702 : continue;
3204 702 : }
3205 1606 : if ((mask & OMP_CLAUSE_DESTROY)
3206 1585 : && gfc_match_omp_variable_list ("destroy (",
3207 : &c->lists[OMP_LIST_DESTROY],
3208 : true) == MATCH_YES)
3209 21 : continue;
3210 1690 : if ((mask & OMP_CLAUSE_DETACH)
3211 164 : && !openacc
3212 127 : && !c->detach
3213 1690 : && gfc_match_omp_detach (&c->detach) == MATCH_YES)
3214 126 : continue;
3215 1475 : if ((mask & OMP_CLAUSE_DETACH)
3216 38 : && openacc
3217 37 : && gfc_match ("detach ( ") == MATCH_YES
3218 1475 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
3219 : OMP_MAP_DETACH, false,
3220 : allow_derived))
3221 37 : continue;
3222 1437 : if ((mask & OMP_CLAUSE_DEVICEPTR)
3223 87 : && gfc_match ("deviceptr ( ") == MATCH_YES
3224 1439 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
3225 : OMP_MAP_FORCE_DEVICEPTR, false,
3226 : allow_derived))
3227 36 : continue;
3228 820 : if ((mask & OMP_CLAUSE_DEVICE_TYPE) && openacc
3229 444 : && gfc_match_dupl_check (!c->oacc_device_type_present,
3230 : "device_type", true) == MATCH_YES
3231 1697 : && match_oacc_device_type (c) == MATCH_YES)
3232 326 : continue;
3233 494 : if ((mask & OMP_CLAUSE_DEVICE_TYPE) && !openacc
3234 1415 : && gfc_match_dupl_check (c->device_type == OMP_DEVICE_TYPE_UNSET,
3235 : "device_type", true) == MATCH_YES)
3236 : {
3237 92 : if (gfc_match ("host") == MATCH_YES)
3238 32 : c->device_type = OMP_DEVICE_TYPE_HOST;
3239 60 : else if (gfc_match ("nohost") == MATCH_YES)
3240 21 : c->device_type = OMP_DEVICE_TYPE_NOHOST;
3241 39 : else if (gfc_match ("any") == MATCH_YES)
3242 38 : c->device_type = OMP_DEVICE_TYPE_ANY;
3243 : else
3244 : {
3245 1 : gfc_error ("Expected HOST, NOHOST or ANY at %C");
3246 1 : break;
3247 : }
3248 91 : if (gfc_match (" )") != MATCH_YES)
3249 : break;
3250 91 : continue;
3251 : }
3252 1054 : if ((mask & OMP_CLAUSE_DEVICE_NUM)
3253 947 : && (m = gfc_match_dupl_check (!c->device_num_expr,
3254 : "device_num")) != MATCH_NO)
3255 : {
3256 109 : if (m == MATCH_ERROR)
3257 2 : goto error;
3258 107 : if (gfc_match ("( %e )", &c->device_num_expr) != MATCH_YES)
3259 0 : goto error;
3260 107 : continue;
3261 : }
3262 886 : if ((mask & OMP_CLAUSE_DEVICE_RESIDENT)
3263 887 : && gfc_match_omp_variable_list
3264 49 : ("device_resident (",
3265 : &c->lists[OMP_LIST_DEVICE_RESIDENT], true) == MATCH_YES)
3266 48 : continue;
3267 1102 : if ((mask & OMP_CLAUSE_DEVICE)
3268 705 : && openacc
3269 314 : && gfc_match ("device ( ") == MATCH_YES
3270 1103 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
3271 : OMP_MAP_FORCE_TO, true,
3272 : /* allow_derived = */ true))
3273 312 : continue;
3274 478 : if ((mask & OMP_CLAUSE_DEVICE)
3275 393 : && !openacc
3276 869 : && ((m = gfc_match_dupl_check (!c->device, "device", true))
3277 : != MATCH_NO))
3278 : {
3279 351 : if (m == MATCH_ERROR)
3280 0 : goto error;
3281 351 : c->ancestor = false;
3282 351 : if (gfc_match ("device_num : ") == MATCH_YES)
3283 : {
3284 18 : if (gfc_match ("%e )", &c->device) != MATCH_YES)
3285 : {
3286 1 : gfc_error ("Expected integer expression at %C");
3287 1 : break;
3288 : }
3289 : }
3290 333 : else if (gfc_match ("ancestor : ") == MATCH_YES)
3291 : {
3292 45 : bool has_requires = false;
3293 45 : c->ancestor = true;
3294 82 : for (gfc_namespace *ns = gfc_current_ns; ns; ns = ns->parent)
3295 80 : if (ns->omp_requires & OMP_REQ_REVERSE_OFFLOAD)
3296 : {
3297 : has_requires = true;
3298 : break;
3299 : }
3300 45 : if (!has_requires)
3301 : {
3302 2 : gfc_error ("%<ancestor%> device modifier not "
3303 : "preceded by %<requires%> directive "
3304 : "with %<reverse_offload%> clause at %C");
3305 5 : break;
3306 : }
3307 43 : locus old_loc2 = gfc_current_locus;
3308 43 : if (gfc_match ("%e )", &c->device) == MATCH_YES)
3309 : {
3310 43 : int device = 0;
3311 43 : if (!gfc_extract_int (c->device, &device) && device != 1)
3312 : {
3313 1 : gfc_current_locus = old_loc2;
3314 1 : gfc_error ("the %<device%> clause expression must "
3315 : "evaluate to %<1%> at %C");
3316 1 : break;
3317 : }
3318 : }
3319 : else
3320 : {
3321 0 : gfc_error ("Expected integer expression at %C");
3322 0 : break;
3323 : }
3324 : }
3325 288 : else if (gfc_match ("%e )", &c->device) != MATCH_YES)
3326 : {
3327 13 : gfc_error ("Expected integer expression or a single device-"
3328 : "modifier %<device_num%> or %<ancestor%> at %C");
3329 13 : break;
3330 : }
3331 334 : continue;
3332 334 : }
3333 127 : if ((mask & OMP_CLAUSE_DIST_SCHEDULE)
3334 97 : && c->dist_sched_kind == OMP_SCHED_NONE
3335 224 : && gfc_match ("dist_schedule ( static") == MATCH_YES)
3336 : {
3337 97 : m = MATCH_NO;
3338 97 : c->dist_sched_kind = OMP_SCHED_STATIC;
3339 97 : m = gfc_match (" , %e )", &c->dist_chunk_size);
3340 97 : if (m != MATCH_YES)
3341 14 : m = gfc_match_char (')');
3342 14 : if (m != MATCH_YES)
3343 : {
3344 0 : c->dist_sched_kind = OMP_SCHED_NONE;
3345 0 : gfc_current_locus = old_loc;
3346 : }
3347 : else
3348 97 : continue;
3349 : }
3350 41 : if ((mask & OMP_CLAUSE_DYN_GROUPPRIVATE)
3351 30 : && gfc_match_dupl_check (!c->dyn_groupprivate,
3352 : "dyn_groupprivate", true) == MATCH_YES)
3353 : {
3354 12 : if (gfc_match ("fallback ( abort ) : ") == MATCH_YES)
3355 1 : c->fallback = OMP_FALLBACK_ABORT;
3356 11 : else if (gfc_match ("fallback ( default_mem ) : ") == MATCH_YES)
3357 1 : c->fallback = OMP_FALLBACK_DEFAULT_MEM;
3358 10 : else if (gfc_match ("fallback ( null ) : ") == MATCH_YES)
3359 1 : c->fallback = OMP_FALLBACK_NULL;
3360 12 : if (gfc_match_expr (&c->dyn_groupprivate) != MATCH_YES)
3361 0 : return MATCH_ERROR;
3362 12 : if (gfc_match (" )") != MATCH_YES)
3363 1 : goto error;
3364 11 : continue;
3365 : }
3366 : break;
3367 90 : case 'e':
3368 90 : if ((mask & OMP_CLAUSE_ENTER))
3369 : {
3370 90 : m = gfc_match_omp_to_link ("enter (", &c->lists[OMP_LIST_ENTER]);
3371 90 : if (m == MATCH_ERROR)
3372 0 : goto error;
3373 90 : if (m == MATCH_YES)
3374 90 : continue;
3375 : }
3376 : break;
3377 2309 : case 'f':
3378 2358 : if ((mask & OMP_CLAUSE_FAIL)
3379 2309 : && (m = gfc_match_dupl_check (c->fail == OMP_MEMORDER_UNSET,
3380 : "fail", true)) != MATCH_NO)
3381 : {
3382 58 : if (m == MATCH_ERROR)
3383 3 : goto error;
3384 55 : if (gfc_match ("seq_cst") == MATCH_YES)
3385 6 : c->fail = OMP_MEMORDER_SEQ_CST;
3386 49 : else if (gfc_match ("acquire") == MATCH_YES)
3387 14 : c->fail = OMP_MEMORDER_ACQUIRE;
3388 35 : else if (gfc_match ("relaxed") == MATCH_YES)
3389 30 : c->fail = OMP_MEMORDER_RELAXED;
3390 : else
3391 : {
3392 5 : gfc_error ("Expected SEQ_CST, ACQUIRE or RELAXED at %C");
3393 5 : break;
3394 : }
3395 50 : if (gfc_match (" )") != MATCH_YES)
3396 1 : goto error;
3397 49 : continue;
3398 : }
3399 2294 : if ((mask & OMP_CLAUSE_FILTER)
3400 2251 : && (m = gfc_match_dupl_check (!c->filter, "filter", true,
3401 : &c->filter)) != MATCH_NO)
3402 : {
3403 44 : if (m == MATCH_ERROR)
3404 1 : goto error;
3405 43 : continue;
3406 : }
3407 2271 : if ((mask & OMP_CLAUSE_FINAL)
3408 2207 : && (m = gfc_match_dupl_check (!c->final_expr, "final", true,
3409 : &c->final_expr)) != MATCH_NO)
3410 : {
3411 64 : if (m == MATCH_ERROR)
3412 0 : goto error;
3413 64 : continue;
3414 : }
3415 2169 : if ((mask & OMP_CLAUSE_FINALIZE)
3416 2143 : && (m = gfc_match_dupl_check (!c->finalize, "finalize"))
3417 : != MATCH_NO)
3418 : {
3419 26 : if (m == MATCH_ERROR)
3420 0 : goto error;
3421 26 : c->finalize = true;
3422 26 : continue;
3423 : }
3424 3155 : if ((mask & OMP_CLAUSE_FIRSTPRIVATE)
3425 2117 : && gfc_match_omp_variable_list ("firstprivate (",
3426 : &c->lists[OMP_LIST_FIRSTPRIVATE],
3427 : true) == MATCH_YES)
3428 1038 : continue;
3429 2080 : if ((mask & OMP_CLAUSE_FROM)
3430 1079 : && gfc_match_motion_var_list ("from (", &c->lists[OMP_LIST_FROM],
3431 : &head) == MATCH_YES)
3432 1001 : continue;
3433 143 : if ((mask & OMP_CLAUSE_FULL)
3434 78 : && (m = gfc_match_dupl_check (!c->full, "full")) != MATCH_NO)
3435 : {
3436 65 : if (m == MATCH_ERROR)
3437 0 : goto error;
3438 65 : c->full = true;
3439 65 : continue;
3440 : }
3441 : break;
3442 1231 : case 'g':
3443 2423 : if ((mask & OMP_CLAUSE_GANG)
3444 1231 : && (m = gfc_match_dupl_check (!c->gang, "gang")) != MATCH_NO)
3445 : {
3446 1197 : if (m == MATCH_ERROR)
3447 0 : goto error;
3448 1197 : c->gang = true;
3449 1197 : m = match_oacc_clause_gwv (c, GOMP_DIM_GANG);
3450 1197 : if (m == MATCH_ERROR)
3451 : {
3452 5 : gfc_current_locus = old_loc;
3453 5 : break;
3454 : }
3455 1192 : continue;
3456 : }
3457 68 : if ((mask & OMP_CLAUSE_GRAINSIZE)
3458 34 : && (m = gfc_match_dupl_check (!c->grainsize, "grainsize", true))
3459 : != MATCH_NO)
3460 : {
3461 34 : if (m == MATCH_ERROR)
3462 0 : goto error;
3463 34 : if (gfc_match ("strict : ") == MATCH_YES)
3464 1 : c->grainsize_strict = true;
3465 34 : if (gfc_match (" %e )", &c->grainsize) != MATCH_YES)
3466 0 : goto error;
3467 34 : continue;
3468 : }
3469 : break;
3470 465 : case 'h':
3471 513 : if ((mask & OMP_CLAUSE_HAS_DEVICE_ADDR)
3472 513 : && gfc_match_omp_variable_list
3473 48 : ("has_device_addr (", &c->lists[OMP_LIST_HAS_DEVICE_ADDR],
3474 : false, NULL, NULL, true) == MATCH_YES)
3475 48 : continue;
3476 460 : if ((mask & OMP_CLAUSE_HINT)
3477 417 : && (m = gfc_match_dupl_check (!c->hint, "hint", true, &c->hint))
3478 : != MATCH_NO)
3479 : {
3480 43 : if (m == MATCH_ERROR)
3481 0 : goto error;
3482 43 : continue;
3483 : }
3484 374 : if ((mask & OMP_CLAUSE_ASSUMPTIONS)
3485 374 : && gfc_match ("holds ( ") == MATCH_YES)
3486 : {
3487 19 : gfc_expr *e;
3488 19 : if (gfc_match ("%e )", &e) != MATCH_YES)
3489 0 : goto error;
3490 19 : if (c->assume == NULL)
3491 12 : c->assume = gfc_get_omp_assumptions ();
3492 19 : gfc_expr_list *el = XCNEW (gfc_expr_list);
3493 19 : el->expr = e;
3494 19 : el->next = c->assume->holds;
3495 19 : c->assume->holds = el;
3496 19 : continue;
3497 19 : }
3498 709 : if ((mask & OMP_CLAUSE_HOST)
3499 355 : && gfc_match ("host ( ") == MATCH_YES
3500 710 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
3501 : OMP_MAP_FORCE_FROM, true,
3502 : /* allow_derived = */ true))
3503 354 : continue;
3504 : break;
3505 2243 : case 'i':
3506 2266 : if ((mask & OMP_CLAUSE_IF_PRESENT)
3507 2243 : && (m = gfc_match_dupl_check (!c->if_present, "if_present"))
3508 : != MATCH_NO)
3509 : {
3510 23 : if (m == MATCH_ERROR)
3511 0 : goto error;
3512 23 : c->if_present = true;
3513 23 : continue;
3514 : }
3515 2220 : if ((mask & OMP_CLAUSE_IF)
3516 2220 : && (m = gfc_match_dupl_check (!c->if_expr, "if", true))
3517 : != MATCH_NO)
3518 : {
3519 1466 : if (m == MATCH_ERROR)
3520 14 : goto error;
3521 1452 : if (!openacc)
3522 : {
3523 : /* This should match the enum gfc_omp_if_kind order. */
3524 : static const char *ifs[OMP_IF_LAST] = {
3525 : "cancel : %e )",
3526 : "parallel : %e )",
3527 : "simd : %e )",
3528 : "task : %e )",
3529 : "taskloop : %e )",
3530 : "target : %e )",
3531 : "target data : %e )",
3532 : "target update : %e )",
3533 : "target enter data : %e )",
3534 : "target exit data : %e )" };
3535 : int i;
3536 4907 : for (i = 0; i < OMP_IF_LAST; i++)
3537 4503 : if (c->if_exprs[i] == NULL
3538 4503 : && gfc_match (ifs[i], &c->if_exprs[i]) == MATCH_YES)
3539 : break;
3540 542 : if (i < OMP_IF_LAST)
3541 138 : continue;
3542 : }
3543 1314 : if (gfc_match (" %e )", &c->if_expr) == MATCH_YES)
3544 1309 : continue;
3545 5 : goto error;
3546 : }
3547 871 : if ((mask & OMP_CLAUSE_IN_REDUCTION)
3548 754 : && gfc_match_omp_clause_reduction (pc, c, openacc, allow_derived,
3549 : openmp_target) == MATCH_YES)
3550 117 : continue;
3551 662 : if ((mask & OMP_CLAUSE_INBRANCH)
3552 637 : && (m = gfc_match_dupl_check (!c->inbranch && !c->notinbranch,
3553 : "inbranch")) != MATCH_NO)
3554 : {
3555 25 : if (m == MATCH_ERROR)
3556 0 : goto error;
3557 25 : c->inbranch = true;
3558 25 : continue;
3559 : }
3560 854 : if ((mask & OMP_CLAUSE_INDEPENDENT)
3561 612 : && (m = gfc_match_dupl_check (!c->independent, "independent"))
3562 : != MATCH_NO)
3563 : {
3564 242 : if (m == MATCH_ERROR)
3565 0 : goto error;
3566 242 : c->independent = true;
3567 242 : continue;
3568 : }
3569 370 : if ((mask & OMP_CLAUSE_INDIRECT)
3570 370 : && (m = gfc_match_dupl_check (!c->indirect, "indirect"))
3571 : != MATCH_NO)
3572 : {
3573 61 : if (m == MATCH_ERROR)
3574 5 : goto error;
3575 60 : gfc_expr *indirect_expr = NULL;
3576 60 : m = gfc_match (" ( %e )", &indirect_expr);
3577 60 : if (m == MATCH_YES)
3578 : {
3579 13 : if (!gfc_resolve_expr (indirect_expr)
3580 13 : || indirect_expr->ts.type != BT_LOGICAL
3581 23 : || indirect_expr->expr_type != EXPR_CONSTANT)
3582 : {
3583 4 : gfc_error ("INDIRECT clause at %C requires a constant "
3584 : "logical expression");
3585 4 : gfc_free_expr (indirect_expr);
3586 4 : goto error;
3587 : }
3588 9 : c->indirect = indirect_expr->value.logical;
3589 9 : gfc_free_expr (indirect_expr);
3590 : }
3591 : else
3592 47 : c->indirect = 1;
3593 56 : continue;
3594 56 : }
3595 309 : if ((mask & OMP_CLAUSE_INIT)
3596 309 : && gfc_match ("init ( ") == MATCH_YES)
3597 : {
3598 108 : m = gfc_match_omp_init (&c->lists[OMP_LIST_INIT]);
3599 108 : if (m == MATCH_YES)
3600 63 : continue;
3601 45 : goto error;
3602 : }
3603 201 : if ((mask & OMP_CLAUSE_INTEROP)
3604 201 : && (m = gfc_match_dupl_check (!c->lists[OMP_LIST_INTEROP],
3605 : "interop", true)) != MATCH_NO)
3606 : {
3607 : /* Note: the interop objects are saved in reverse order to match
3608 : the order in C/C++. */
3609 125 : if (m == MATCH_YES
3610 63 : && (gfc_match_omp_variable_list ("",
3611 : &c->lists[OMP_LIST_INTEROP],
3612 : false, NULL, NULL, false,
3613 : false, NULL, false, true)
3614 : == MATCH_YES))
3615 62 : continue;
3616 1 : goto error;
3617 : }
3618 258 : if ((mask & OMP_CLAUSE_IS_DEVICE_PTR)
3619 258 : && gfc_match_omp_variable_list
3620 120 : ("is_device_ptr (",
3621 : &c->lists[OMP_LIST_IS_DEVICE_PTR], false) == MATCH_YES)
3622 120 : continue;
3623 : break;
3624 2336 : case 'l':
3625 2336 : if ((mask & OMP_CLAUSE_LASTPRIVATE)
3626 2336 : && gfc_match ("lastprivate ( ") == MATCH_YES)
3627 : {
3628 1433 : bool conditional = gfc_match ("conditional : ") == MATCH_YES;
3629 1433 : head = NULL;
3630 1433 : if (gfc_match_omp_variable_list ("",
3631 : &c->lists[OMP_LIST_LASTPRIVATE],
3632 : false, NULL, &head) == MATCH_YES)
3633 : {
3634 1433 : gfc_omp_namelist *n;
3635 3741 : for (n = *head; n; n = n->next)
3636 2308 : n->u.lastprivate_conditional = conditional;
3637 1433 : continue;
3638 1433 : }
3639 0 : gfc_current_locus = old_loc;
3640 0 : break;
3641 : }
3642 903 : end_colon = false;
3643 903 : head = NULL;
3644 903 : if ((mask & OMP_CLAUSE_LINEAR)
3645 903 : && gfc_match ("linear (") == MATCH_YES)
3646 : {
3647 836 : bool old_linear_modifier = false;
3648 836 : gfc_omp_linear_op linear_op = OMP_LINEAR_DEFAULT;
3649 836 : gfc_expr *step = NULL;
3650 836 : locus saved_loc = gfc_current_locus;
3651 :
3652 836 : if (gfc_match_omp_variable_list (" ref (",
3653 : &c->lists[OMP_LIST_LINEAR],
3654 : false, NULL, &head)
3655 : == MATCH_YES)
3656 : {
3657 : linear_op = OMP_LINEAR_REF;
3658 : old_linear_modifier = true;
3659 : }
3660 808 : else if (gfc_match_omp_variable_list (" val (",
3661 : &c->lists[OMP_LIST_LINEAR],
3662 : false, NULL, &head)
3663 : == MATCH_YES)
3664 : {
3665 : linear_op = OMP_LINEAR_VAL;
3666 : old_linear_modifier = true;
3667 : }
3668 797 : else if (gfc_match_omp_variable_list (" uval (",
3669 : &c->lists[OMP_LIST_LINEAR],
3670 : false, NULL, &head)
3671 : == MATCH_YES)
3672 : {
3673 : linear_op = OMP_LINEAR_UVAL;
3674 : old_linear_modifier = true;
3675 : }
3676 788 : else if (gfc_match_omp_variable_list ("",
3677 : &c->lists[OMP_LIST_LINEAR],
3678 : false, &end_colon, &head)
3679 : == MATCH_YES)
3680 : linear_op = OMP_LINEAR_DEFAULT;
3681 : else
3682 : {
3683 2 : gfc_current_locus = old_loc;
3684 2 : break;
3685 : }
3686 : if (linear_op != OMP_LINEAR_DEFAULT)
3687 : {
3688 48 : if (gfc_match (" :") == MATCH_YES)
3689 31 : end_colon = true;
3690 17 : else if (gfc_match (" )") != MATCH_YES)
3691 : {
3692 0 : gfc_free_omp_namelist (*head, OMP_LIST_LINEAR);
3693 0 : gfc_current_locus = old_loc;
3694 0 : *head = NULL;
3695 0 : break;
3696 : }
3697 : }
3698 834 : gfc_gobble_whitespace ();
3699 834 : if (old_linear_modifier && end_colon)
3700 : {
3701 31 : if (gfc_match (" %e )", &step) != MATCH_YES)
3702 : {
3703 1 : gfc_free_omp_namelist (*head, OMP_LIST_LINEAR);
3704 1 : gfc_current_locus = old_loc;
3705 1 : *head = NULL;
3706 5 : goto error;
3707 : }
3708 : }
3709 833 : if (old_linear_modifier)
3710 : {
3711 47 : char var_names[512]{};
3712 47 : int count, offset = 0;
3713 106 : for (gfc_omp_namelist *n = *head; n; n = n->next)
3714 : {
3715 59 : if (!n->next)
3716 47 : count = snprintf (var_names + offset,
3717 47 : sizeof (var_names) - offset,
3718 47 : "%s", n->sym->name);
3719 : else
3720 12 : count = snprintf (var_names + offset,
3721 12 : sizeof (var_names) - offset,
3722 12 : "%s, ", n->sym->name);
3723 59 : if (count < 0 || count >= ((int)sizeof (var_names))
3724 59 : - offset)
3725 : {
3726 0 : snprintf (var_names, 512, "%s, ..., ",
3727 0 : (*head)->sym->name);
3728 0 : while (n->next)
3729 : n = n->next;
3730 0 : offset = strlen (var_names);
3731 0 : snprintf (var_names + offset,
3732 0 : sizeof (var_names) - offset,
3733 0 : "%s", n->sym->name);
3734 0 : break;
3735 : }
3736 59 : offset += count;
3737 : }
3738 47 : char *var_names_for_warn = var_names;
3739 47 : const char *op_name;
3740 47 : switch (linear_op)
3741 : {
3742 : case OMP_LINEAR_REF: op_name = "ref"; break;
3743 10 : case OMP_LINEAR_VAL: op_name = "val"; break;
3744 9 : case OMP_LINEAR_UVAL: op_name = "uval"; break;
3745 0 : default: gcc_unreachable ();
3746 : }
3747 47 : gfc_warning (OPT_Wdeprecated_openmp,
3748 : "Specification of the list items as "
3749 : "arguments to the modifiers at %L is "
3750 : "deprecated; since OpenMP 5.2, use "
3751 : "%<linear(%s : %s%s)%>", &saved_loc,
3752 : var_names_for_warn, op_name,
3753 47 : step == nullptr ? "" : ", step(...)");
3754 : }
3755 786 : else if (end_colon)
3756 : {
3757 713 : bool has_error = false;
3758 : bool has_modifiers = false;
3759 : bool has_step = false;
3760 713 : bool duplicate_step = false;
3761 713 : bool duplicate_mod = false;
3762 713 : while (true)
3763 : {
3764 713 : old_loc = gfc_current_locus;
3765 713 : bool close_paren = gfc_match ("val )") == MATCH_YES;
3766 713 : if (close_paren || gfc_match ("val , ") == MATCH_YES)
3767 : {
3768 17 : if (linear_op != OMP_LINEAR_DEFAULT)
3769 : {
3770 : duplicate_mod = true;
3771 : break;
3772 : }
3773 16 : linear_op = OMP_LINEAR_VAL;
3774 16 : has_modifiers = true;
3775 16 : if (close_paren)
3776 : break;
3777 10 : continue;
3778 : }
3779 696 : close_paren = gfc_match ("uval )") == MATCH_YES;
3780 696 : if (close_paren || gfc_match ("uval , ") == MATCH_YES)
3781 : {
3782 7 : if (linear_op != OMP_LINEAR_DEFAULT)
3783 : {
3784 : duplicate_mod = true;
3785 : break;
3786 : }
3787 7 : linear_op = OMP_LINEAR_UVAL;
3788 7 : has_modifiers = true;
3789 7 : if (close_paren)
3790 : break;
3791 2 : continue;
3792 : }
3793 689 : close_paren = gfc_match ("ref )") == MATCH_YES;
3794 689 : if (close_paren || gfc_match ("ref , ") == MATCH_YES)
3795 : {
3796 16 : if (linear_op != OMP_LINEAR_DEFAULT)
3797 : {
3798 : duplicate_mod = true;
3799 : break;
3800 : }
3801 15 : linear_op = OMP_LINEAR_REF;
3802 15 : has_modifiers = true;
3803 15 : if (close_paren)
3804 : break;
3805 7 : continue;
3806 : }
3807 673 : close_paren = (gfc_match ("step ( %e ) )", &step)
3808 : == MATCH_YES);
3809 684 : if (close_paren
3810 673 : || gfc_match ("step ( %e ) , ", &step) == MATCH_YES)
3811 : {
3812 38 : if (has_step)
3813 : {
3814 : duplicate_step = true;
3815 : break;
3816 : }
3817 37 : has_modifiers = has_step = true;
3818 37 : if (close_paren)
3819 : break;
3820 11 : continue;
3821 : }
3822 635 : if (!has_modifiers
3823 635 : && gfc_match ("%e )", &step) == MATCH_YES)
3824 : {
3825 635 : if ((step->expr_type == EXPR_FUNCTION
3826 634 : || step->expr_type == EXPR_VARIABLE)
3827 31 : && strcmp (step->symtree->name, "step") == 0)
3828 : {
3829 1 : gfc_current_locus = old_loc;
3830 1 : gfc_match ("step (");
3831 1 : has_error = true;
3832 : }
3833 : break;
3834 : }
3835 : has_error = true;
3836 : break;
3837 : }
3838 49 : if (duplicate_mod || duplicate_step)
3839 : {
3840 3 : gfc_error ("Multiple %qs modifiers specified at %C",
3841 : duplicate_mod ? "linear" : "step");
3842 3 : has_error = true;
3843 : }
3844 683 : if (has_error)
3845 : {
3846 4 : gfc_free_omp_namelist (*head, OMP_LIST_LINEAR);
3847 4 : *head = NULL;
3848 4 : goto error;
3849 : }
3850 : }
3851 829 : if (step == NULL)
3852 : {
3853 130 : step = gfc_get_constant_expr (BT_INTEGER,
3854 : gfc_default_integer_kind,
3855 : &old_loc);
3856 130 : mpz_set_si (step->value.integer, 1);
3857 : }
3858 829 : (*head)->expr = step;
3859 829 : if (linear_op != OMP_LINEAR_DEFAULT || old_linear_modifier)
3860 176 : for (gfc_omp_namelist *n = *head; n; n = n->next)
3861 : {
3862 94 : n->u.linear.op = linear_op;
3863 94 : n->u.linear.old_modifier = old_linear_modifier;
3864 : }
3865 829 : continue;
3866 829 : }
3867 71 : if ((mask & OMP_CLAUSE_LINK)
3868 67 : && openacc
3869 75 : && (gfc_match_oacc_clause_link ("link (",
3870 : &c->lists[OMP_LIST_LINK])
3871 : == MATCH_YES))
3872 4 : continue;
3873 110 : else if ((mask & OMP_CLAUSE_LINK)
3874 63 : && !openacc
3875 122 : && (gfc_match_omp_to_link ("link (",
3876 : &c->lists[OMP_LIST_LINK])
3877 : == MATCH_YES))
3878 47 : continue;
3879 28 : if ((mask & OMP_CLAUSE_LOCAL)
3880 16 : && (gfc_match_omp_to_link ("local (", &c->lists[OMP_LIST_LOCAL])
3881 : == MATCH_YES))
3882 12 : continue;
3883 : break;
3884 5942 : case 'm':
3885 5942 : if ((mask & OMP_CLAUSE_MAP)
3886 5942 : && gfc_match ("map ( ") == MATCH_YES)
3887 : {
3888 5839 : locus old_loc2 = gfc_current_locus;
3889 5839 : int always_modifier = 0;
3890 5839 : int close_modifier = 0;
3891 5839 : int present_modifier = 0;
3892 5839 : int mapper_modifier = 0;
3893 5839 : int iterator_modifier = 0;
3894 5839 : gfc_namespace *ns_iter = NULL, *ns_curr = gfc_current_ns;
3895 5839 : locus second_always_locus = old_loc2;
3896 5839 : locus second_close_locus = old_loc2;
3897 5839 : locus second_mapper_locus = old_loc2;
3898 5839 : locus second_present_locus = old_loc2;
3899 5839 : char mapper_id[GFC_MAX_SYMBOL_LEN + 1] = { '\0' };
3900 5839 : locus second_iterator_locus = old_loc2;
3901 :
3902 6505 : for (;;)
3903 : {
3904 6172 : locus current_locus = gfc_current_locus;
3905 6172 : if (gfc_match ("always ") == MATCH_YES)
3906 : {
3907 148 : if (always_modifier++ == 1)
3908 5 : second_always_locus = current_locus;
3909 : }
3910 6024 : else if (gfc_match ("close ") == MATCH_YES)
3911 : {
3912 69 : if (close_modifier++ == 1)
3913 5 : second_close_locus = current_locus;
3914 : }
3915 5955 : else if (gfc_match ("present ") == MATCH_YES)
3916 : {
3917 67 : if (present_modifier++ == 1)
3918 4 : second_present_locus = current_locus;
3919 : }
3920 5888 : else if (gfc_match ("mapper ( ") == MATCH_YES)
3921 : {
3922 7 : if (mapper_modifier++ == 1)
3923 0 : second_mapper_locus = current_locus;
3924 7 : m = gfc_match (" %n ) ", mapper_id);
3925 7 : if (m != MATCH_YES)
3926 0 : goto error;
3927 7 : if (strcmp (mapper_id, "default") == 0)
3928 3 : mapper_id[0] = '\0';
3929 : }
3930 5881 : else if (gfc_match_iterator (&ns_iter, true) == MATCH_YES)
3931 : {
3932 42 : if (iterator_modifier++ == 1)
3933 1 : second_iterator_locus = current_locus;
3934 : }
3935 : else
3936 : break;
3937 333 : if (gfc_match (", ") != MATCH_YES)
3938 62 : gfc_warning (OPT_Wdeprecated_openmp,
3939 : "The specification of modifiers without "
3940 : "comma separators for the %<map%> clause "
3941 : "at %C has been deprecated since "
3942 : "OpenMP 5.2");
3943 333 : }
3944 :
3945 5839 : gfc_omp_map_op map_op = default_map_op;
3946 5839 : int always_present_modifier
3947 5839 : = always_modifier && present_modifier;
3948 :
3949 5839 : if (gfc_match ("alloc : ") == MATCH_YES)
3950 799 : map_op = (present_modifier ? OMP_MAP_PRESENT_ALLOC
3951 : : OMP_MAP_ALLOC);
3952 5040 : else if (gfc_match ("tofrom : ") == MATCH_YES)
3953 954 : map_op = (always_present_modifier ? OMP_MAP_ALWAYS_PRESENT_TOFROM
3954 950 : : present_modifier ? OMP_MAP_PRESENT_TOFROM
3955 945 : : always_modifier ? OMP_MAP_ALWAYS_TOFROM
3956 : : OMP_MAP_TOFROM);
3957 4086 : else if (gfc_match ("to : ") == MATCH_YES)
3958 1814 : map_op = (always_present_modifier ? OMP_MAP_ALWAYS_PRESENT_TO
3959 1808 : : present_modifier ? OMP_MAP_PRESENT_TO
3960 1796 : : always_modifier ? OMP_MAP_ALWAYS_TO
3961 : : OMP_MAP_TO);
3962 2272 : else if (gfc_match ("from : ") == MATCH_YES)
3963 1654 : map_op = (always_present_modifier ? OMP_MAP_ALWAYS_PRESENT_FROM
3964 1650 : : present_modifier ? OMP_MAP_PRESENT_FROM
3965 1645 : : always_modifier ? OMP_MAP_ALWAYS_FROM
3966 : : OMP_MAP_FROM);
3967 618 : else if (gfc_match ("release : ") == MATCH_YES)
3968 : map_op = OMP_MAP_RELEASE;
3969 564 : else if (gfc_match ("delete : ") == MATCH_YES)
3970 : map_op = OMP_MAP_DELETE;
3971 : else
3972 : {
3973 487 : gfc_current_locus = old_loc2;
3974 487 : always_modifier = 0;
3975 487 : close_modifier = 0;
3976 487 : mapper_modifier = 0;
3977 : }
3978 :
3979 1565 : if (always_modifier > 1)
3980 : {
3981 5 : gfc_error ("too many %<always%> modifiers at %L",
3982 : &second_always_locus);
3983 24 : break;
3984 : }
3985 5834 : if (close_modifier > 1)
3986 : {
3987 4 : gfc_error ("too many %<close%> modifiers at %L",
3988 : &second_close_locus);
3989 4 : break;
3990 : }
3991 5830 : if (present_modifier > 1)
3992 : {
3993 4 : gfc_error ("too many %<present%> modifiers at %L",
3994 : &second_present_locus);
3995 4 : break;
3996 : }
3997 5826 : if (mapper_modifier > 1)
3998 : {
3999 0 : gfc_error ("too many %<mapper%> modifiers at %L",
4000 : &second_mapper_locus);
4001 0 : break;
4002 : }
4003 5826 : if (iterator_modifier > 1)
4004 : {
4005 1 : gfc_error ("too many %<iterator%> modifiers at %L",
4006 : &second_iterator_locus);
4007 1 : break;
4008 : }
4009 :
4010 5825 : head = NULL;
4011 5825 : if (ns_iter)
4012 40 : gfc_current_ns = ns_iter;
4013 5825 : m = gfc_match_omp_variable_list ("", &c->lists[OMP_LIST_MAP],
4014 : false, NULL, &head, true, true);
4015 5825 : gfc_current_ns = ns_curr;
4016 5825 : if (m == MATCH_YES)
4017 : {
4018 5820 : gfc_omp_namelist *n;
4019 13223 : for (n = *head; n; n = n->next)
4020 : {
4021 7403 : n->u.map.op = map_op;
4022 7403 : if (mapper_id[0] != '\0')
4023 : {
4024 4 : n->u3.udm = gfc_get_omp_namelist_udm ();
4025 4 : n->u3.udm->requested_mapper_id
4026 4 : = gfc_get_string ("%s", mapper_id);
4027 : }
4028 7403 : n->u2.ns = ns_iter;
4029 7403 : if (ns_iter)
4030 42 : ns_iter->refs++;
4031 : }
4032 5820 : continue;
4033 5820 : }
4034 5 : gfc_current_locus = old_loc;
4035 5 : break;
4036 : }
4037 137 : if ((mask & OMP_CLAUSE_MERGEABLE)
4038 103 : && (m = gfc_match_dupl_check (!c->mergeable, "mergeable"))
4039 : != MATCH_NO)
4040 : {
4041 34 : if (m == MATCH_ERROR)
4042 0 : goto error;
4043 34 : c->mergeable = true;
4044 34 : continue;
4045 : }
4046 133 : if ((mask & OMP_CLAUSE_MESSAGE)
4047 69 : && (m = gfc_match_dupl_check (!c->message, "message", true,
4048 : &c->message)) != MATCH_NO)
4049 : {
4050 69 : if (m == MATCH_ERROR)
4051 5 : goto error;
4052 64 : continue;
4053 : }
4054 : break;
4055 3013 : case 'n':
4056 3065 : if ((mask & OMP_CLAUSE_NO_CREATE)
4057 1343 : && gfc_match ("no_create ( ") == MATCH_YES
4058 3065 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4059 : OMP_MAP_IF_PRESENT, true,
4060 : allow_derived))
4061 52 : continue;
4062 2962 : if ((mask & OMP_CLAUSE_ASSUMPTIONS)
4063 2987 : && (m = gfc_match_dupl_check (!c->assume
4064 26 : || !c->assume->no_openmp_constructs,
4065 : "no_openmp_constructs")) != MATCH_NO)
4066 : {
4067 2 : if (m == MATCH_ERROR)
4068 1 : goto error;
4069 1 : if (c->assume == NULL)
4070 0 : c->assume = gfc_get_omp_assumptions ();
4071 1 : c->assume->no_openmp_constructs = true;
4072 1 : continue;
4073 : }
4074 2972 : if ((mask & OMP_CLAUSE_ASSUMPTIONS)
4075 2983 : && (m = gfc_match_dupl_check (!c->assume
4076 24 : || !c->assume->no_openmp_routines,
4077 : "no_openmp_routines")) != MATCH_NO)
4078 : {
4079 13 : if (m == MATCH_ERROR)
4080 0 : goto error;
4081 13 : if (c->assume == NULL)
4082 12 : c->assume = gfc_get_omp_assumptions ();
4083 13 : c->assume->no_openmp_routines = true;
4084 13 : continue;
4085 : }
4086 2950 : if ((mask & OMP_CLAUSE_ASSUMPTIONS)
4087 2956 : && (m = gfc_match_dupl_check (!c->assume || !c->assume->no_openmp,
4088 : "no_openmp")) != MATCH_NO)
4089 : {
4090 4 : if (m == MATCH_ERROR)
4091 0 : goto error;
4092 4 : if (c->assume == NULL)
4093 4 : c->assume = gfc_get_omp_assumptions ();
4094 4 : c->assume->no_openmp = true;
4095 4 : continue;
4096 : }
4097 2948 : if ((mask & OMP_CLAUSE_ASSUMPTIONS)
4098 2949 : && (m = gfc_match_dupl_check (!c->assume
4099 7 : || !c->assume->no_parallelism,
4100 : "no_parallelism")) != MATCH_NO)
4101 : {
4102 6 : if (m == MATCH_ERROR)
4103 0 : goto error;
4104 6 : if (c->assume == NULL)
4105 6 : c->assume = gfc_get_omp_assumptions ();
4106 6 : c->assume->no_parallelism = true;
4107 6 : continue;
4108 : }
4109 :
4110 2946 : if ((mask & OMP_CLAUSE_NOVARIANTS)
4111 2936 : && (m = gfc_match_dupl_check (!c->novariants, "novariants", true,
4112 : &c->novariants))
4113 : != MATCH_NO)
4114 : {
4115 12 : if (m == MATCH_ERROR)
4116 2 : goto error;
4117 10 : continue;
4118 : }
4119 2937 : if ((mask & OMP_CLAUSE_NOCONTEXT)
4120 2924 : && (m = gfc_match_dupl_check (!c->nocontext, "nocontext", true,
4121 : &c->nocontext))
4122 : != MATCH_NO)
4123 : {
4124 15 : if (m == MATCH_ERROR)
4125 2 : goto error;
4126 13 : continue;
4127 : }
4128 2923 : if ((mask & OMP_CLAUSE_NOGROUP)
4129 2909 : && (m = gfc_match_dupl_check (!c->nogroup, "nogroup"))
4130 : != MATCH_NO)
4131 : {
4132 14 : if (m == MATCH_ERROR)
4133 0 : goto error;
4134 14 : c->nogroup = true;
4135 14 : continue;
4136 : }
4137 3045 : if ((mask & OMP_CLAUSE_NOHOST)
4138 2895 : && (m = gfc_match_dupl_check (!c->nohost, "nohost")) != MATCH_NO)
4139 : {
4140 151 : if (m == MATCH_ERROR)
4141 1 : goto error;
4142 150 : c->nohost = true;
4143 150 : continue;
4144 : }
4145 2786 : if ((mask & OMP_CLAUSE_NOTEMPORAL)
4146 2744 : && gfc_match_omp_variable_list ("nontemporal (",
4147 : &c->lists[OMP_LIST_NONTEMPORAL],
4148 : true) == MATCH_YES)
4149 42 : continue;
4150 2726 : if ((mask & OMP_CLAUSE_NOTINBRANCH)
4151 2703 : && (m = gfc_match_dupl_check (!c->notinbranch && !c->inbranch,
4152 : "notinbranch")) != MATCH_NO)
4153 : {
4154 25 : if (m == MATCH_ERROR)
4155 1 : goto error;
4156 24 : c->notinbranch = true;
4157 24 : continue;
4158 : }
4159 2806 : if ((mask & OMP_CLAUSE_NOWAIT)
4160 2677 : && (m = gfc_match_dupl_check (!c->nowait, "nowait")) != MATCH_NO)
4161 : {
4162 132 : if (m == MATCH_ERROR)
4163 3 : goto error;
4164 129 : c->nowait = true;
4165 129 : continue;
4166 : }
4167 3227 : if ((mask & OMP_CLAUSE_NUM_GANGS)
4168 2545 : && (m = gfc_match_dupl_check (!c->num_gangs_expr, "num_gangs",
4169 : true)) != MATCH_NO)
4170 : {
4171 686 : if (m == MATCH_ERROR)
4172 2 : goto error;
4173 684 : if (gfc_match (" %e )", &c->num_gangs_expr) != MATCH_YES)
4174 2 : goto error;
4175 682 : continue;
4176 : }
4177 1885 : if ((mask & OMP_CLAUSE_NUM_TASKS)
4178 1859 : && (m = gfc_match_dupl_check (!c->num_tasks, "num_tasks", true))
4179 : != MATCH_NO)
4180 : {
4181 26 : if (m == MATCH_ERROR)
4182 0 : goto error;
4183 26 : if (gfc_match ("strict : ") == MATCH_YES)
4184 1 : c->num_tasks_strict = true;
4185 26 : if (gfc_match (" %e )", &c->num_tasks) != MATCH_YES)
4186 0 : goto error;
4187 26 : continue;
4188 : }
4189 1833 : if ((mask & OMP_CLAUSE_NUM_TEAMS)
4190 1833 : && (m = gfc_match_dupl_check (!c->num_teams_list,
4191 : "num_teams", true)) != MATCH_NO)
4192 : {
4193 174 : if (m == MATCH_ERROR)
4194 20 : goto error;
4195 172 : gfc_expr *expr;
4196 172 : if (gfc_match ("dims ( %e ) : ", &expr) == MATCH_YES
4197 172 : && match_omp_oacc_expr_list (NULL, &c->num_teams_list,
4198 : false, true) == MATCH_YES)
4199 : {
4200 19 : int num = 0;
4201 19 : gfc_expr_list *el;
4202 55 : for (el = c->num_teams_list; el; el = el->next)
4203 36 : ++num;
4204 19 : if (!gfc_resolve_expr (expr)
4205 19 : || expr->ts.type != BT_INTEGER
4206 18 : || expr->rank != 0
4207 17 : || expr->expr_type != EXPR_CONSTANT
4208 34 : || mpz_sgn (expr->value.integer) <= 0)
4209 : {
4210 5 : gfc_error ("DIMS must be a constant positive integer "
4211 5 : "at %L", &expr->where);
4212 5 : goto error;
4213 : }
4214 14 : if (mpz_cmp_si (expr->value.integer, num) != 0)
4215 : {
4216 1 : gfc_error ("The number of arguments (%d) must be the same"
4217 : " as specified for DIMS at %L", num,
4218 : &expr->where);
4219 1 : goto error;
4220 : }
4221 13 : c->num_teams_dims = true;
4222 154 : continue;
4223 13 : }
4224 153 : else if (gfc_match ("%e ", &expr) == MATCH_YES)
4225 : {
4226 150 : c->num_teams_list = gfc_get_expr_list();
4227 150 : c->num_teams_list->expr = expr;
4228 150 : if (gfc_peek_ascii_char () == ':')
4229 : {
4230 30 : expr = NULL;
4231 30 : if (gfc_match (": %e ", &expr) == MATCH_YES)
4232 : {
4233 29 : c->num_teams_list->next = gfc_get_expr_list();
4234 29 : c->num_teams_list->next->expr = expr;
4235 29 : if (gfc_match (") ") == MATCH_YES)
4236 27 : continue;
4237 : }
4238 : }
4239 120 : else if (gfc_match (") ") == MATCH_YES)
4240 114 : continue;
4241 : }
4242 12 : gfc_error ("Expected either %<[lower-expr : ] upper-expr%> or "
4243 : "%<dims(N): expr-list%> at %C");
4244 12 : goto error;
4245 : }
4246 1659 : if ((mask & OMP_CLAUSE_NUM_THREADS)
4247 1659 : && (m = gfc_match_dupl_check (!c->num_threads_list,
4248 : "num_threads", true, NULL))
4249 : != MATCH_NO)
4250 : {
4251 1018 : int nstrict = 0, nrelaxed = 0, ndims = 0;
4252 1018 : bool fail = false;
4253 1018 : gfc_expr *dims = NULL;
4254 1018 : locus old_loc = gfc_current_locus;
4255 :
4256 1018 : if (m == MATCH_ERROR)
4257 27 : goto error;
4258 1068 : while (true)
4259 : {
4260 1042 : if (gfc_match ("strict ") == MATCH_YES)
4261 16 : nstrict++;
4262 1026 : else if (gfc_match ("relaxed ") == MATCH_YES)
4263 21 : nrelaxed++;
4264 1005 : else if (gfc_match ("dims ") == MATCH_YES)
4265 : {
4266 32 : ndims++;
4267 32 : if (dims)
4268 3 : gfc_free_expr (dims);
4269 32 : if (gfc_match ("( %e ) ", &dims) != MATCH_YES)
4270 : break;
4271 : }
4272 : else
4273 : {
4274 : fail = true;
4275 : break;
4276 : }
4277 68 : if (gfc_match (", ") == MATCH_YES)
4278 26 : continue;
4279 : break;
4280 : }
4281 1016 : if (gfc_match (" : ") == MATCH_YES)
4282 : {
4283 40 : if (nstrict + nrelaxed + ndims == 0 || fail)
4284 : {
4285 1 : gfc_error ("Expected STRICT, RELAXED or DIMS modifier at "
4286 : "%C");
4287 1 : goto error;
4288 : }
4289 39 : else if (nstrict + nrelaxed > 1)
4290 : {
4291 8 : gfc_error ("Only one STRICT or RELAXED modifier permitted"
4292 : " at %L", &old_loc);
4293 8 : goto error;
4294 : }
4295 31 : if (ndims > 1)
4296 : {
4297 3 : gfc_error ("Duplicated DIMS expression at %L",
4298 3 : &dims->where);
4299 3 : goto error;
4300 : }
4301 28 : if (nstrict || (dims && !nrelaxed))
4302 17 : c->num_threads_strict = true;
4303 : }
4304 : else
4305 : {
4306 976 : gfc_free_expr (dims);
4307 976 : dims = NULL;
4308 976 : gfc_current_locus = old_loc;
4309 : }
4310 :
4311 1004 : m = match_omp_oacc_expr_list (NULL, &c->num_threads_list, false,
4312 : true);
4313 1004 : if (m != MATCH_YES)
4314 : {
4315 7 : gfc_error ("Expected a list of integer expressions followed "
4316 : "by a %<)%> and optionally preceded by the STRICT,"
4317 : " RELAXED, or DIMS as modifiers and a colon at %C");
4318 7 : goto error;
4319 : }
4320 997 : if (dims)
4321 : {
4322 17 : int num = 0;
4323 17 : gfc_expr_list *el;
4324 46 : for (el = c->num_threads_list; el; el = el->next)
4325 29 : ++num;
4326 17 : if (!gfc_resolve_expr (dims)
4327 17 : || dims->ts.type != BT_INTEGER
4328 16 : || dims->rank != 0
4329 15 : || dims->expr_type != EXPR_CONSTANT
4330 30 : || mpz_sgn (dims->value.integer) <= 0)
4331 : {
4332 5 : gfc_error ("DIMS must be a constant positive integer "
4333 5 : "at %L", &dims->where);
4334 5 : goto error;
4335 : }
4336 12 : if (mpz_cmp_si (dims->value.integer, num) != 0)
4337 : {
4338 1 : gfc_error ("The number of arguments (%d) must be the same"
4339 : " as specified for DIMS at %L", num,
4340 : &dims->where);
4341 1 : goto error;
4342 : }
4343 11 : c->num_threads_dims = true;
4344 : }
4345 991 : continue;
4346 991 : }
4347 1240 : if ((mask & OMP_CLAUSE_NUM_WORKERS)
4348 641 : && (m = gfc_match_dupl_check (!c->num_workers_expr, "num_workers",
4349 : true, &c->num_workers_expr))
4350 : != MATCH_NO)
4351 : {
4352 603 : if (m == MATCH_ERROR)
4353 4 : goto error;
4354 599 : continue;
4355 : }
4356 : break;
4357 591 : case 'o':
4358 591 : if ((mask & OMP_CLAUSE_ORDERED)
4359 591 : && (m = gfc_match_dupl_check (!c->ordered, "ordered"))
4360 : != MATCH_NO)
4361 : {
4362 343 : if (m == MATCH_ERROR)
4363 0 : goto error;
4364 343 : gfc_expr *cexpr = NULL;
4365 343 : m = gfc_match (" ( %e )", &cexpr);
4366 :
4367 343 : c->ordered = true;
4368 343 : if (m == MATCH_YES)
4369 : {
4370 144 : int ordered = 0;
4371 144 : if (gfc_extract_int (cexpr, &ordered, -1))
4372 0 : ordered = 0;
4373 144 : else if (ordered <= 0)
4374 : {
4375 0 : gfc_error_now ("ORDERED clause argument not"
4376 : " constant positive integer at %C");
4377 0 : ordered = 0;
4378 : }
4379 144 : c->orderedc = ordered;
4380 144 : gfc_free_expr (cexpr);
4381 144 : continue;
4382 144 : }
4383 :
4384 199 : continue;
4385 199 : }
4386 482 : if ((mask & OMP_CLAUSE_ORDER)
4387 248 : && (m = gfc_match_dupl_check (!c->order_concurrent, "order", true))
4388 : != MATCH_NO)
4389 : {
4390 247 : if (m == MATCH_ERROR)
4391 10 : goto error;
4392 237 : if (gfc_match (" reproducible : concurrent )") == MATCH_YES)
4393 55 : c->order_reproducible = true;
4394 182 : else if (gfc_match (" concurrent )") == MATCH_YES)
4395 : ;
4396 50 : else if (gfc_match (" unconstrained : concurrent )") == MATCH_YES)
4397 47 : c->order_unconstrained = true;
4398 : else
4399 : {
4400 3 : gfc_error ("Expected ORDER(CONCURRENT) at %C "
4401 : "with optional %<reproducible%> or "
4402 : "%<unconstrained%> modifier");
4403 3 : goto error;
4404 : }
4405 234 : c->order_concurrent = true;
4406 234 : continue;
4407 : }
4408 : break;
4409 3101 : case 'p':
4410 3101 : if (mask & OMP_CLAUSE_PARTIAL)
4411 : {
4412 276 : if ((m = gfc_match_dupl_check (!c->partial, "partial"))
4413 : != MATCH_NO)
4414 : {
4415 276 : int expr;
4416 276 : if (m == MATCH_ERROR)
4417 0 : goto error;
4418 :
4419 276 : c->partial = -1;
4420 :
4421 276 : gfc_expr *cexpr = NULL;
4422 276 : m = gfc_match (" ( %e )", &cexpr);
4423 276 : if (m == MATCH_NO)
4424 : ;
4425 251 : else if (m == MATCH_YES
4426 251 : && !gfc_extract_int (cexpr, &expr, -1)
4427 502 : && expr > 0)
4428 247 : c->partial = expr;
4429 : else
4430 4 : gfc_error_now ("PARTIAL clause argument not constant "
4431 : "positive integer at %C");
4432 276 : gfc_free_expr (cexpr);
4433 276 : continue;
4434 276 : }
4435 : }
4436 2894 : if ((mask & OMP_CLAUSE_COPY)
4437 877 : && gfc_match ("pcopy ( ") == MATCH_YES
4438 2895 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4439 : OMP_MAP_TOFROM, true, allow_derived))
4440 69 : continue;
4441 2830 : if ((mask & OMP_CLAUSE_COPYIN)
4442 1910 : && gfc_match ("pcopyin ( ") == MATCH_YES
4443 2830 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4444 : OMP_MAP_TO, true, allow_derived))
4445 74 : continue;
4446 2755 : if ((mask & OMP_CLAUSE_COPYOUT)
4447 735 : && gfc_match ("pcopyout ( ") == MATCH_YES
4448 2755 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4449 : OMP_MAP_FROM, true, allow_derived))
4450 73 : continue;
4451 2624 : if ((mask & OMP_CLAUSE_CREATE)
4452 672 : && gfc_match ("pcreate ( ") == MATCH_YES
4453 2624 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4454 : OMP_MAP_ALLOC, true, allow_derived))
4455 15 : continue;
4456 3010 : if ((mask & OMP_CLAUSE_PRESENT)
4457 647 : && gfc_match ("present ( ") == MATCH_YES
4458 3012 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4459 : OMP_MAP_FORCE_PRESENT, false,
4460 : allow_derived))
4461 416 : continue;
4462 2201 : if ((mask & OMP_CLAUSE_COPY)
4463 231 : && gfc_match ("present_or_copy ( ") == MATCH_YES
4464 2201 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4465 : OMP_MAP_TOFROM, true,
4466 : allow_derived))
4467 23 : continue;
4468 2195 : if ((mask & OMP_CLAUSE_COPYIN)
4469 1309 : && gfc_match ("present_or_copyin ( ") == MATCH_YES
4470 2195 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4471 : OMP_MAP_TO, true, allow_derived))
4472 40 : continue;
4473 2150 : if ((mask & OMP_CLAUSE_COPYOUT)
4474 173 : && gfc_match ("present_or_copyout ( ") == MATCH_YES
4475 2150 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4476 : OMP_MAP_FROM, true, allow_derived))
4477 35 : continue;
4478 2108 : if ((mask & OMP_CLAUSE_CREATE)
4479 143 : && gfc_match ("present_or_create ( ") == MATCH_YES
4480 2108 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4481 : OMP_MAP_ALLOC, true, allow_derived))
4482 28 : continue;
4483 2086 : if ((mask & OMP_CLAUSE_PRIORITY)
4484 2052 : && (m = gfc_match_dupl_check (!c->priority, "priority", true,
4485 : &c->priority)) != MATCH_NO)
4486 : {
4487 34 : if (m == MATCH_ERROR)
4488 0 : goto error;
4489 34 : continue;
4490 : }
4491 3959 : if ((mask & OMP_CLAUSE_PRIVATE)
4492 2018 : && gfc_match_omp_variable_list ("private (",
4493 : &c->lists[OMP_LIST_PRIVATE],
4494 : true) == MATCH_YES)
4495 1941 : continue;
4496 141 : if ((mask & OMP_CLAUSE_PROC_BIND)
4497 141 : && (m = gfc_match_dupl_check ((c->proc_bind
4498 64 : == OMP_PROC_BIND_UNKNOWN),
4499 : "proc_bind", true)) != MATCH_NO)
4500 : {
4501 64 : if (m == MATCH_ERROR)
4502 0 : goto error;
4503 64 : if (gfc_match ("primary )") == MATCH_YES)
4504 1 : c->proc_bind = OMP_PROC_BIND_PRIMARY;
4505 63 : else if (gfc_match ("master )") == MATCH_YES)
4506 : {
4507 9 : gfc_warning (OPT_Wdeprecated_openmp,
4508 : "%<master%> affinity policy at %C deprecated "
4509 : "since OpenMP 5.1, use %<primary%>");
4510 9 : c->proc_bind = OMP_PROC_BIND_MASTER;
4511 : }
4512 54 : else if (gfc_match ("spread )") == MATCH_YES)
4513 53 : c->proc_bind = OMP_PROC_BIND_SPREAD;
4514 1 : else if (gfc_match ("close )") == MATCH_YES)
4515 1 : c->proc_bind = OMP_PROC_BIND_CLOSE;
4516 : else
4517 0 : goto error;
4518 64 : continue;
4519 : }
4520 : break;
4521 4583 : case 'r':
4522 5073 : if ((mask & OMP_CLAUSE_ATOMIC)
4523 4583 : && (m = gfc_match_dupl_atomic ((c->atomic_op
4524 : == GFC_OMP_ATOMIC_UNSET),
4525 : "read")) != MATCH_NO)
4526 : {
4527 490 : if (m == MATCH_ERROR)
4528 0 : goto error;
4529 490 : c->atomic_op = GFC_OMP_ATOMIC_READ;
4530 490 : continue;
4531 : }
4532 8149 : if ((mask & OMP_CLAUSE_REDUCTION)
4533 4093 : && gfc_match_omp_clause_reduction (pc, c, openacc,
4534 : allow_derived) == MATCH_YES)
4535 4056 : continue;
4536 47 : if ((mask & OMP_CLAUSE_MEMORDER)
4537 65 : && (m = gfc_match_dupl_memorder ((c->memorder
4538 28 : == OMP_MEMORDER_UNSET),
4539 : "relaxed")) != MATCH_NO)
4540 : {
4541 10 : if (m == MATCH_ERROR)
4542 0 : goto error;
4543 10 : c->memorder = OMP_MEMORDER_RELAXED;
4544 10 : continue;
4545 : }
4546 44 : if ((mask & OMP_CLAUSE_MEMORDER)
4547 45 : && (m = gfc_match_dupl_memorder ((c->memorder
4548 18 : == OMP_MEMORDER_UNSET),
4549 : "release")) != MATCH_NO)
4550 : {
4551 18 : if (m == MATCH_ERROR)
4552 1 : goto error;
4553 17 : c->memorder = OMP_MEMORDER_RELEASE;
4554 17 : continue;
4555 : }
4556 : break;
4557 3048 : case 's':
4558 3141 : if ((mask & OMP_CLAUSE_SAFELEN)
4559 3048 : && (m = gfc_match_dupl_check (!c->safelen_expr, "safelen",
4560 : true, &c->safelen_expr))
4561 : != MATCH_NO)
4562 : {
4563 93 : if (m == MATCH_ERROR)
4564 0 : goto error;
4565 93 : continue;
4566 : }
4567 2955 : if ((mask & OMP_CLAUSE_SCHEDULE)
4568 2955 : && (m = gfc_match_dupl_check (c->sched_kind == OMP_SCHED_NONE,
4569 : "schedule", true)) != MATCH_NO)
4570 : {
4571 809 : if (m == MATCH_ERROR)
4572 0 : goto error;
4573 809 : int nmodifiers = 0;
4574 809 : locus old_loc2 = gfc_current_locus;
4575 827 : do
4576 : {
4577 818 : if (gfc_match ("simd") == MATCH_YES)
4578 : {
4579 18 : c->sched_simd = true;
4580 18 : nmodifiers++;
4581 : }
4582 800 : else if (gfc_match ("monotonic") == MATCH_YES)
4583 : {
4584 30 : c->sched_monotonic = true;
4585 30 : nmodifiers++;
4586 : }
4587 770 : else if (gfc_match ("nonmonotonic") == MATCH_YES)
4588 : {
4589 35 : c->sched_nonmonotonic = true;
4590 35 : nmodifiers++;
4591 : }
4592 : else
4593 : {
4594 735 : if (nmodifiers)
4595 0 : gfc_current_locus = old_loc2;
4596 : break;
4597 : }
4598 92 : if (nmodifiers == 1
4599 83 : && gfc_match (" , ") == MATCH_YES)
4600 9 : continue;
4601 74 : else if (gfc_match (" : ") == MATCH_YES)
4602 : break;
4603 0 : gfc_current_locus = old_loc2;
4604 0 : break;
4605 : }
4606 : while (1);
4607 809 : if (gfc_match ("static") == MATCH_YES)
4608 425 : c->sched_kind = OMP_SCHED_STATIC;
4609 384 : else if (gfc_match ("dynamic") == MATCH_YES)
4610 164 : c->sched_kind = OMP_SCHED_DYNAMIC;
4611 220 : else if (gfc_match ("guided") == MATCH_YES)
4612 127 : c->sched_kind = OMP_SCHED_GUIDED;
4613 93 : else if (gfc_match ("runtime") == MATCH_YES)
4614 85 : c->sched_kind = OMP_SCHED_RUNTIME;
4615 8 : else if (gfc_match ("auto") == MATCH_YES)
4616 8 : c->sched_kind = OMP_SCHED_AUTO;
4617 809 : if (c->sched_kind != OMP_SCHED_NONE)
4618 : {
4619 809 : m = MATCH_NO;
4620 809 : if (c->sched_kind != OMP_SCHED_RUNTIME
4621 724 : && c->sched_kind != OMP_SCHED_AUTO)
4622 716 : m = gfc_match (" , %e )", &c->chunk_size);
4623 716 : if (m != MATCH_YES)
4624 299 : m = gfc_match_char (')');
4625 299 : if (m != MATCH_YES)
4626 0 : c->sched_kind = OMP_SCHED_NONE;
4627 : }
4628 809 : if (c->sched_kind != OMP_SCHED_NONE)
4629 809 : continue;
4630 : else
4631 0 : gfc_current_locus = old_loc;
4632 : }
4633 2329 : if ((mask & OMP_CLAUSE_SELF)
4634 335 : && !(mask & OMP_CLAUSE_HOST) /* OpenACC compute construct */
4635 2386 : && (m = gfc_match_dupl_check (!c->self_expr, "self"))
4636 : != MATCH_NO)
4637 : {
4638 186 : if (m == MATCH_ERROR)
4639 3 : goto error;
4640 183 : m = gfc_match (" ( %e )", &c->self_expr);
4641 183 : if (m == MATCH_ERROR)
4642 : {
4643 0 : gfc_current_locus = old_loc;
4644 0 : break;
4645 : }
4646 183 : else if (m == MATCH_NO)
4647 9 : c->self_expr = gfc_get_logical_expr (gfc_default_logical_kind,
4648 : NULL, true);
4649 183 : continue;
4650 : }
4651 2054 : if ((mask & OMP_CLAUSE_SELF)
4652 149 : && (mask & OMP_CLAUSE_HOST) /* OpenACC 'update' directive */
4653 95 : && gfc_match ("self ( ") == MATCH_YES
4654 2055 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4655 : OMP_MAP_FORCE_FROM, true,
4656 : /* allow_derived = */ true))
4657 94 : continue;
4658 2214 : if ((mask & OMP_CLAUSE_SEQ)
4659 1866 : && (m = gfc_match_dupl_check (!c->seq, "seq")) != MATCH_NO)
4660 : {
4661 348 : if (m == MATCH_ERROR)
4662 0 : goto error;
4663 348 : c->seq = true;
4664 348 : continue;
4665 : }
4666 1659 : if ((mask & OMP_CLAUSE_MEMORDER)
4667 1659 : && (m = gfc_match_dupl_memorder ((c->memorder
4668 141 : == OMP_MEMORDER_UNSET),
4669 : "seq_cst")) != MATCH_NO)
4670 : {
4671 141 : if (m == MATCH_ERROR)
4672 0 : goto error;
4673 141 : c->memorder = OMP_MEMORDER_SEQ_CST;
4674 141 : continue;
4675 : }
4676 2352 : if ((mask & OMP_CLAUSE_SHARED)
4677 1377 : && gfc_match_omp_variable_list ("shared (",
4678 : &c->lists[OMP_LIST_SHARED],
4679 : true) == MATCH_YES)
4680 975 : continue;
4681 520 : if ((mask & OMP_CLAUSE_SIMDLEN)
4682 402 : && (m = gfc_match_dupl_check (!c->simdlen_expr, "simdlen", true,
4683 : &c->simdlen_expr)) != MATCH_NO)
4684 : {
4685 118 : if (m == MATCH_ERROR)
4686 0 : goto error;
4687 118 : continue;
4688 : }
4689 306 : if ((mask & OMP_CLAUSE_SIMD)
4690 284 : && (m = gfc_match_dupl_check (!c->simd, "simd")) != MATCH_NO)
4691 : {
4692 22 : if (m == MATCH_ERROR)
4693 0 : goto error;
4694 22 : c->simd = true;
4695 22 : continue;
4696 : }
4697 313 : if ((mask & OMP_CLAUSE_SEVERITY)
4698 262 : && (m = gfc_match_dupl_check (!c->severity, "severity", true))
4699 : != MATCH_NO)
4700 : {
4701 57 : if (m == MATCH_ERROR)
4702 2 : goto error;
4703 55 : if (gfc_match ("fatal )") == MATCH_YES)
4704 15 : c->severity = OMP_SEVERITY_FATAL;
4705 40 : else if (gfc_match ("warning )") == MATCH_YES)
4706 36 : c->severity = OMP_SEVERITY_WARNING;
4707 : else
4708 : {
4709 4 : gfc_error ("Expected FATAL or WARNING in SEVERITY clause "
4710 : "at %C");
4711 4 : goto error;
4712 : }
4713 51 : continue;
4714 : }
4715 205 : if ((mask & OMP_CLAUSE_SIZES)
4716 205 : && ((m = gfc_match_dupl_check (!c->sizes_list, "sizes"))
4717 : != MATCH_NO))
4718 : {
4719 203 : if (m == MATCH_ERROR)
4720 0 : goto error;
4721 203 : m = match_omp_oacc_expr_list (" (", &c->sizes_list, false, true);
4722 203 : if (m == MATCH_ERROR)
4723 7 : goto error;
4724 196 : if (m == MATCH_YES)
4725 195 : continue;
4726 1 : gfc_error ("Expected %<(%> after %qs at %C", "sizes");
4727 1 : goto error;
4728 : }
4729 : break;
4730 1281 : case 't':
4731 1346 : if ((mask & OMP_CLAUSE_TASK_REDUCTION)
4732 1281 : && gfc_match_omp_clause_reduction (pc, c, openacc,
4733 : allow_derived) == MATCH_YES)
4734 65 : continue;
4735 1216 : if ((mask & OMP_CLAUSE_THREAD_LIMIT)
4736 1216 : && (m = gfc_match_dupl_check (!c->thread_limit_list, "thread_limit",
4737 : true, NULL)) != MATCH_NO)
4738 : {
4739 131 : int nstrict = 0, nrelaxed = 0, ndims = 0;
4740 131 : bool fail = false;
4741 131 : gfc_expr *dims = NULL;
4742 131 : locus old_loc = gfc_current_locus;
4743 :
4744 131 : if (m == MATCH_ERROR)
4745 28 : goto error;
4746 177 : while (true)
4747 : {
4748 153 : if (gfc_match ("strict ") == MATCH_YES)
4749 15 : nstrict++;
4750 138 : else if (gfc_match ("relaxed ") == MATCH_YES)
4751 25 : nrelaxed++;
4752 113 : else if (gfc_match ("dims ") == MATCH_YES)
4753 : {
4754 31 : ndims++;
4755 31 : if (dims)
4756 3 : gfc_free_expr (dims);
4757 31 : if (gfc_match ("( %e ) ", &dims) != MATCH_YES)
4758 : break;
4759 : }
4760 : else
4761 : {
4762 : fail = true;
4763 : break;
4764 : }
4765 70 : if (gfc_match (", ") == MATCH_YES)
4766 24 : continue;
4767 : break;
4768 : }
4769 129 : if (gfc_match (" : ") == MATCH_YES)
4770 : {
4771 44 : if (nstrict + nrelaxed + ndims == 0 || fail)
4772 : {
4773 1 : gfc_error ("Expected STRICT, RELAXED or DIMS modifier at "
4774 : "%C");
4775 1 : goto error;
4776 : }
4777 43 : else if (nstrict + nrelaxed > 1)
4778 : {
4779 8 : gfc_error ("Only one STRICT or RELAXED modifier permitted"
4780 : " at %L", &old_loc);
4781 8 : goto error;
4782 : }
4783 35 : if (ndims > 1)
4784 : {
4785 3 : gfc_error ("Duplicated DIMS expression at %L",
4786 3 : &dims->where);
4787 3 : goto error;
4788 : }
4789 : }
4790 : else
4791 : {
4792 85 : gfc_free_expr (dims);
4793 85 : dims = NULL;
4794 85 : gfc_current_locus = old_loc;
4795 : }
4796 :
4797 117 : m = match_omp_oacc_expr_list (NULL, &c->thread_limit_list,
4798 : false, true);
4799 117 : if (m != MATCH_YES)
4800 : {
4801 7 : gfc_error ("Expected a list of integer expressions followed "
4802 : "by a %<)%> and optionally preceded by the STRICT,"
4803 : " RELAXED, or DIMS as modifiers and a colon at %C");
4804 7 : goto error;
4805 : }
4806 110 : c->thread_limit_strict = (nstrict != 0) || (dims && !nrelaxed);
4807 :
4808 110 : if (!dims && c->thread_limit_list->next)
4809 : {
4810 1 : gfc_error ("Without the DIM modifier, only a single integer "
4811 : "expression may be specified at %L",
4812 1 : &c->thread_limit_list->next->expr->where);
4813 1 : goto error;
4814 : }
4815 109 : else if (dims)
4816 : {
4817 16 : int num = 0;
4818 16 : gfc_expr_list *el;
4819 53 : for (el = c->thread_limit_list; el; el = el->next)
4820 37 : ++num;
4821 16 : if (!gfc_resolve_expr (dims)
4822 16 : || dims->ts.type != BT_INTEGER
4823 15 : || dims->rank != 0
4824 14 : || dims->expr_type != EXPR_CONSTANT
4825 28 : || mpz_sgn (dims->value.integer) <= 0)
4826 : {
4827 5 : gfc_error ("DIMS must be a constant positive integer "
4828 5 : "at %L", &dims->where);
4829 5 : goto error;
4830 : }
4831 11 : if (mpz_cmp_si (dims->value.integer, num) != 0)
4832 : {
4833 1 : gfc_error ("The number of arguments (%d) must be the same"
4834 : " as specified for DIMS at %L", num,
4835 : &dims->where);
4836 1 : goto error;
4837 : }
4838 10 : c->thread_limit_dims = true;
4839 : }
4840 103 : continue;
4841 103 : }
4842 1098 : if ((mask & OMP_CLAUSE_THREADS)
4843 1085 : && (m = gfc_match_dupl_check (!c->threads, "threads"))
4844 : != MATCH_NO)
4845 : {
4846 13 : if (m == MATCH_ERROR)
4847 0 : goto error;
4848 13 : c->threads = true;
4849 13 : continue;
4850 : }
4851 1269 : if ((mask & OMP_CLAUSE_TILE)
4852 221 : && !c->tile_list
4853 1293 : && match_omp_oacc_expr_list ("tile (", &c->tile_list,
4854 : true, false) == MATCH_YES)
4855 197 : continue;
4856 875 : if ((mask & OMP_CLAUSE_TO) && (mask & OMP_CLAUSE_LINK))
4857 : {
4858 : /* Declare target: 'to' is an alias for 'enter';
4859 : 'to' is deprecated since 5.2. */
4860 116 : m = gfc_match_omp_to_link ("to (", &c->lists[OMP_LIST_TO]);
4861 116 : if (m == MATCH_ERROR)
4862 0 : goto error;
4863 116 : if (m == MATCH_YES)
4864 : {
4865 116 : gfc_warning (OPT_Wdeprecated_openmp,
4866 : "%<to%> clause with %<declare target%> at %L "
4867 : "deprecated since OpenMP 5.2, use %<enter%>",
4868 : &old_loc);
4869 116 : continue;
4870 : }
4871 : }
4872 1487 : else if ((mask & OMP_CLAUSE_TO)
4873 759 : && gfc_match_motion_var_list ("to (", &c->lists[OMP_LIST_TO],
4874 : &head) == MATCH_YES)
4875 728 : continue;
4876 : break;
4877 1538 : case 'u':
4878 1596 : if ((mask & OMP_CLAUSE_UNIFORM)
4879 1538 : && gfc_match_omp_variable_list ("uniform (",
4880 : &c->lists[OMP_LIST_UNIFORM],
4881 : false) == MATCH_YES)
4882 58 : continue;
4883 1621 : if ((mask & OMP_CLAUSE_UNTIED)
4884 1480 : && (m = gfc_match_dupl_check (!c->untied, "untied")) != MATCH_NO)
4885 : {
4886 141 : if (m == MATCH_ERROR)
4887 0 : goto error;
4888 141 : c->untied = true;
4889 141 : continue;
4890 : }
4891 1583 : if ((mask & OMP_CLAUSE_ATOMIC)
4892 1339 : && (m = gfc_match_dupl_atomic ((c->atomic_op
4893 : == GFC_OMP_ATOMIC_UNSET),
4894 : "update")) != MATCH_NO)
4895 : {
4896 245 : if (m == MATCH_ERROR)
4897 1 : goto error;
4898 244 : c->atomic_op = GFC_OMP_ATOMIC_UPDATE;
4899 244 : continue;
4900 : }
4901 1116 : if ((mask & OMP_CLAUSE_USE)
4902 1094 : && gfc_match_omp_variable_list ("use (",
4903 : &c->lists[OMP_LIST_USE],
4904 : true) == MATCH_YES)
4905 22 : continue;
4906 1132 : if ((mask & OMP_CLAUSE_USE_DEVICE)
4907 1072 : && gfc_match_omp_variable_list ("use_device (",
4908 : &c->lists[OMP_LIST_USE_DEVICE],
4909 : true) == MATCH_YES)
4910 60 : continue;
4911 1175 : if ((mask & OMP_CLAUSE_USE_DEVICE_PTR)
4912 1940 : && gfc_match_omp_variable_list
4913 928 : ("use_device_ptr (",
4914 : &c->lists[OMP_LIST_USE_DEVICE_PTR], false) == MATCH_YES)
4915 163 : continue;
4916 1614 : if ((mask & OMP_CLAUSE_USE_DEVICE_ADDR)
4917 1614 : && gfc_match_omp_variable_list
4918 765 : ("use_device_addr (", &c->lists[OMP_LIST_USE_DEVICE_ADDR],
4919 : false, NULL, NULL, true) == MATCH_YES)
4920 765 : continue;
4921 153 : if ((mask & OMP_CLAUSE_USES_ALLOCATORS)
4922 84 : && (gfc_match ("uses_allocators ( ") == MATCH_YES))
4923 : {
4924 78 : if (gfc_match_omp_clause_uses_allocators (c) != MATCH_YES)
4925 9 : goto error;
4926 69 : continue;
4927 : }
4928 : break;
4929 1570 : case 'v':
4930 : /* VECTOR_LENGTH must be matched before VECTOR, because the latter
4931 : doesn't unconditionally match '('. */
4932 2139 : if ((mask & OMP_CLAUSE_VECTOR_LENGTH)
4933 1570 : && (m = gfc_match_dupl_check (!c->vector_length_expr,
4934 : "vector_length", true,
4935 : &c->vector_length_expr))
4936 : != MATCH_NO)
4937 : {
4938 573 : if (m == MATCH_ERROR)
4939 4 : goto error;
4940 569 : continue;
4941 : }
4942 1989 : if ((mask & OMP_CLAUSE_VECTOR)
4943 997 : && (m = gfc_match_dupl_check (!c->vector, "vector")) != MATCH_NO)
4944 : {
4945 995 : if (m == MATCH_ERROR)
4946 0 : goto error;
4947 995 : c->vector = true;
4948 995 : m = match_oacc_clause_gwv (c, GOMP_DIM_VECTOR);
4949 995 : if (m == MATCH_ERROR)
4950 3 : goto error;
4951 992 : continue;
4952 : }
4953 : break;
4954 1485 : case 'w':
4955 1485 : if ((mask & OMP_CLAUSE_WAIT)
4956 1485 : && gfc_match ("wait") == MATCH_YES)
4957 : {
4958 192 : m = match_omp_oacc_expr_list (" (", &c->wait_list, false, false);
4959 192 : if (m == MATCH_ERROR)
4960 9 : goto error;
4961 183 : else if (m == MATCH_NO)
4962 : {
4963 47 : gfc_expr *expr
4964 47 : = gfc_get_constant_expr (BT_INTEGER,
4965 : gfc_default_integer_kind,
4966 : &gfc_current_locus);
4967 47 : mpz_set_si (expr->value.integer, GOMP_ASYNC_NOVAL);
4968 47 : gfc_expr_list **expr_list = &c->wait_list;
4969 56 : while (*expr_list)
4970 9 : expr_list = &(*expr_list)->next;
4971 47 : *expr_list = gfc_get_expr_list ();
4972 47 : (*expr_list)->expr = expr;
4973 47 : needs_space = true;
4974 : }
4975 183 : continue;
4976 183 : }
4977 1306 : if ((mask & OMP_CLAUSE_WEAK)
4978 1293 : && (m = gfc_match_dupl_check (!c->weak, "weak"))
4979 : != MATCH_NO)
4980 : {
4981 14 : if (m == MATCH_ERROR)
4982 1 : goto error;
4983 13 : c->weak = true;
4984 13 : continue;
4985 : }
4986 2140 : if ((mask & OMP_CLAUSE_WORKER)
4987 1279 : && (m = gfc_match_dupl_check (!c->worker, "worker")) != MATCH_NO)
4988 : {
4989 864 : if (m == MATCH_ERROR)
4990 0 : goto error;
4991 864 : c->worker = true;
4992 864 : m = match_oacc_clause_gwv (c, GOMP_DIM_WORKER);
4993 864 : if (m == MATCH_ERROR)
4994 3 : goto error;
4995 861 : continue;
4996 : }
4997 827 : if ((mask & OMP_CLAUSE_ATOMIC)
4998 415 : && (m = gfc_match_dupl_atomic ((c->atomic_op
4999 : == GFC_OMP_ATOMIC_UNSET),
5000 : "write")) != MATCH_NO)
5001 : {
5002 412 : if (m == MATCH_ERROR)
5003 0 : goto error;
5004 412 : c->atomic_op = GFC_OMP_ATOMIC_WRITE;
5005 412 : continue;
5006 : }
5007 : break;
5008 : }
5009 : break;
5010 46892 : }
5011 :
5012 35078 : end:
5013 34739 : if (error || gfc_match_omp_eos () != MATCH_YES)
5014 : {
5015 636 : if (!gfc_error_flag_test ())
5016 149 : gfc_error ("Failed to match clause at %C");
5017 636 : gfc_free_omp_clauses (c);
5018 636 : return MATCH_ERROR;
5019 : }
5020 :
5021 34442 : *cp = c;
5022 34442 : return MATCH_YES;
5023 :
5024 339 : error:
5025 339 : error = true;
5026 339 : goto end;
5027 : }
5028 :
5029 :
5030 : #define OACC_PARALLEL_CLAUSES \
5031 : (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_NUM_GANGS \
5032 : | OMP_CLAUSE_NUM_WORKERS | OMP_CLAUSE_VECTOR_LENGTH | OMP_CLAUSE_REDUCTION \
5033 : | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT \
5034 : | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT \
5035 : | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE \
5036 : | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH \
5037 : | OMP_CLAUSE_SELF)
5038 : #define OACC_KERNELS_CLAUSES \
5039 : (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_NUM_GANGS \
5040 : | OMP_CLAUSE_NUM_WORKERS | OMP_CLAUSE_VECTOR_LENGTH | OMP_CLAUSE_DEVICEPTR \
5041 : | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT \
5042 : | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT \
5043 : | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH \
5044 : | OMP_CLAUSE_SELF)
5045 : #define OACC_SERIAL_CLAUSES \
5046 : (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_REDUCTION \
5047 : | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT \
5048 : | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT \
5049 : | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE \
5050 : | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH \
5051 : | OMP_CLAUSE_SELF)
5052 : #define OACC_DATA_CLAUSES \
5053 : (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_COPY \
5054 : | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_CREATE \
5055 : | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT | OMP_CLAUSE_ATTACH \
5056 : | OMP_CLAUSE_DEFAULT)
5057 : #define OACC_LOOP_CLAUSES \
5058 : (omp_mask (OMP_CLAUSE_COLLAPSE) | OMP_CLAUSE_GANG | OMP_CLAUSE_WORKER \
5059 : | OMP_CLAUSE_VECTOR | OMP_CLAUSE_SEQ | OMP_CLAUSE_INDEPENDENT \
5060 : | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_AUTO \
5061 : | OMP_CLAUSE_TILE)
5062 : #define OACC_PARALLEL_LOOP_CLAUSES \
5063 : (OACC_LOOP_CLAUSES | OACC_PARALLEL_CLAUSES)
5064 : #define OACC_KERNELS_LOOP_CLAUSES \
5065 : (OACC_LOOP_CLAUSES | OACC_KERNELS_CLAUSES)
5066 : #define OACC_SERIAL_LOOP_CLAUSES \
5067 : (OACC_LOOP_CLAUSES | OACC_SERIAL_CLAUSES)
5068 : #define OACC_HOST_DATA_CLAUSES \
5069 : (omp_mask (OMP_CLAUSE_USE_DEVICE) \
5070 : | OMP_CLAUSE_IF \
5071 : | OMP_CLAUSE_IF_PRESENT)
5072 : #define OACC_DECLARE_CLAUSES \
5073 : (omp_mask (OMP_CLAUSE_COPY) | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT \
5074 : | OMP_CLAUSE_CREATE | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_DEVICE_RESIDENT \
5075 : | OMP_CLAUSE_PRESENT \
5076 : | OMP_CLAUSE_LINK)
5077 : #define OACC_UPDATE_CLAUSES \
5078 : (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_HOST \
5079 : | OMP_CLAUSE_DEVICE | OMP_CLAUSE_WAIT | OMP_CLAUSE_IF_PRESENT \
5080 : | OMP_CLAUSE_SELF)
5081 : #define OACC_ENTER_DATA_CLAUSES \
5082 : (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_WAIT \
5083 : | OMP_CLAUSE_COPYIN | OMP_CLAUSE_CREATE | OMP_CLAUSE_ATTACH)
5084 : #define OACC_EXIT_DATA_CLAUSES \
5085 : (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_WAIT \
5086 : | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_DELETE | OMP_CLAUSE_FINALIZE \
5087 : | OMP_CLAUSE_DETACH)
5088 : #define OACC_WAIT_CLAUSES \
5089 : omp_mask (OMP_CLAUSE_ASYNC) | OMP_CLAUSE_IF
5090 : #define OACC_ROUTINE_CLAUSES \
5091 : (omp_mask (OMP_CLAUSE_GANG) | OMP_CLAUSE_WORKER | OMP_CLAUSE_VECTOR \
5092 : | OMP_CLAUSE_SEQ \
5093 : | OMP_CLAUSE_NOHOST)
5094 : #define OACC_INIT_CLAUSES \
5095 : (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_DEVICE_NUM | OMP_CLAUSE_DEVICE_TYPE)
5096 : #define OACC_SHUTDOWN_CLAUSES \
5097 : (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_DEVICE_NUM | OMP_CLAUSE_DEVICE_TYPE)
5098 : #define OACC_SET_CLAUSES \
5099 : (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_DEVICE_NUM | OMP_CLAUSE_DEVICE_TYPE)
5100 :
5101 :
5102 : static match
5103 12198 : match_acc (gfc_exec_op op, const omp_mask mask)
5104 : {
5105 12198 : gfc_omp_clauses *c;
5106 12198 : if (gfc_match_omp_clauses (&c, mask, false, false, true) != MATCH_YES)
5107 : return MATCH_ERROR;
5108 11969 : new_st.op = op;
5109 11969 : new_st.ext.omp_clauses = c;
5110 11969 : return MATCH_YES;
5111 : }
5112 :
5113 : match
5114 1378 : gfc_match_oacc_parallel_loop (void)
5115 : {
5116 1378 : return match_acc (EXEC_OACC_PARALLEL_LOOP, OACC_PARALLEL_LOOP_CLAUSES);
5117 : }
5118 :
5119 :
5120 : match
5121 2974 : gfc_match_oacc_parallel (void)
5122 : {
5123 2974 : return match_acc (EXEC_OACC_PARALLEL, OACC_PARALLEL_CLAUSES);
5124 : }
5125 :
5126 :
5127 : match
5128 129 : gfc_match_oacc_kernels_loop (void)
5129 : {
5130 129 : return match_acc (EXEC_OACC_KERNELS_LOOP, OACC_KERNELS_LOOP_CLAUSES);
5131 : }
5132 :
5133 :
5134 : match
5135 906 : gfc_match_oacc_kernels (void)
5136 : {
5137 906 : return match_acc (EXEC_OACC_KERNELS, OACC_KERNELS_CLAUSES);
5138 : }
5139 :
5140 :
5141 : match
5142 230 : gfc_match_oacc_serial_loop (void)
5143 : {
5144 230 : return match_acc (EXEC_OACC_SERIAL_LOOP, OACC_SERIAL_LOOP_CLAUSES);
5145 : }
5146 :
5147 :
5148 : match
5149 359 : gfc_match_oacc_serial (void)
5150 : {
5151 359 : return match_acc (EXEC_OACC_SERIAL, OACC_SERIAL_CLAUSES);
5152 : }
5153 :
5154 :
5155 : match
5156 689 : gfc_match_oacc_data (void)
5157 : {
5158 689 : return match_acc (EXEC_OACC_DATA, OACC_DATA_CLAUSES);
5159 : }
5160 :
5161 :
5162 : match
5163 65 : gfc_match_oacc_host_data (void)
5164 : {
5165 65 : return match_acc (EXEC_OACC_HOST_DATA, OACC_HOST_DATA_CLAUSES);
5166 : }
5167 :
5168 :
5169 : match
5170 3585 : gfc_match_oacc_loop (void)
5171 : {
5172 3585 : return match_acc (EXEC_OACC_LOOP, OACC_LOOP_CLAUSES);
5173 : }
5174 :
5175 :
5176 : match
5177 178 : gfc_match_oacc_declare (void)
5178 : {
5179 178 : gfc_omp_clauses *c;
5180 178 : gfc_omp_namelist *n;
5181 178 : gfc_namespace *ns = gfc_current_ns;
5182 178 : gfc_oacc_declare *new_oc;
5183 178 : bool module_var = false;
5184 178 : locus where = gfc_current_locus;
5185 :
5186 178 : if (gfc_match_omp_clauses (&c, OACC_DECLARE_CLAUSES, false, false, true)
5187 : != MATCH_YES)
5188 : return MATCH_ERROR;
5189 :
5190 262 : for (n = c->lists[OMP_LIST_DEVICE_RESIDENT]; n != NULL; n = n->next)
5191 90 : n->sym->attr.oacc_declare_device_resident = 1;
5192 :
5193 192 : for (n = c->lists[OMP_LIST_LINK]; n != NULL; n = n->next)
5194 20 : n->sym->attr.oacc_declare_link = 1;
5195 :
5196 318 : for (n = c->lists[OMP_LIST_MAP]; n != NULL; n = n->next)
5197 : {
5198 156 : gfc_symbol *s = n->sym;
5199 :
5200 156 : if (gfc_current_ns->proc_name
5201 156 : && gfc_current_ns->proc_name->attr.flavor == FL_MODULE)
5202 : {
5203 52 : if (n->u.map.op != OMP_MAP_ALLOC && n->u.map.op != OMP_MAP_TO)
5204 : {
5205 6 : gfc_error ("Invalid clause in module with !$ACC DECLARE at %L",
5206 : &where);
5207 6 : return MATCH_ERROR;
5208 : }
5209 :
5210 : module_var = true;
5211 : }
5212 :
5213 150 : if (s->attr.use_assoc)
5214 : {
5215 0 : gfc_error ("Variable is USE-associated with !$ACC DECLARE at %L",
5216 : &where);
5217 0 : return MATCH_ERROR;
5218 : }
5219 :
5220 150 : if ((s->result == s && s->ns->contained != gfc_current_ns)
5221 150 : || ((s->attr.flavor == FL_UNKNOWN || s->attr.flavor == FL_VARIABLE)
5222 135 : && s->ns != gfc_current_ns))
5223 : {
5224 2 : gfc_error ("Variable %qs shall be declared in the same scoping unit "
5225 : "as !$ACC DECLARE at %L", s->name, &where);
5226 2 : return MATCH_ERROR;
5227 : }
5228 :
5229 148 : if ((s->attr.dimension || s->attr.codimension)
5230 76 : && s->attr.dummy && s->as->type != AS_EXPLICIT)
5231 : {
5232 2 : gfc_error ("Assumed-size dummy array with !$ACC DECLARE at %L",
5233 : &where);
5234 2 : return MATCH_ERROR;
5235 : }
5236 :
5237 146 : switch (n->u.map.op)
5238 : {
5239 49 : case OMP_MAP_FORCE_ALLOC:
5240 49 : case OMP_MAP_ALLOC:
5241 49 : s->attr.oacc_declare_create = 1;
5242 49 : break;
5243 :
5244 63 : case OMP_MAP_FORCE_TO:
5245 63 : case OMP_MAP_TO:
5246 63 : s->attr.oacc_declare_copyin = 1;
5247 63 : break;
5248 :
5249 1 : case OMP_MAP_FORCE_DEVICEPTR:
5250 1 : s->attr.oacc_declare_deviceptr = 1;
5251 1 : break;
5252 :
5253 : default:
5254 : break;
5255 : }
5256 : }
5257 :
5258 162 : new_oc = gfc_get_oacc_declare ();
5259 162 : new_oc->next = ns->oacc_declare;
5260 162 : new_oc->module_var = module_var;
5261 162 : new_oc->clauses = c;
5262 162 : new_oc->loc = gfc_current_locus;
5263 162 : ns->oacc_declare = new_oc;
5264 :
5265 162 : return MATCH_YES;
5266 : }
5267 :
5268 :
5269 : match
5270 760 : gfc_match_oacc_update (void)
5271 : {
5272 760 : gfc_omp_clauses *c;
5273 760 : locus here = gfc_current_locus;
5274 :
5275 760 : if (gfc_match_omp_clauses (&c, OACC_UPDATE_CLAUSES, false, false, true)
5276 : != MATCH_YES)
5277 : return MATCH_ERROR;
5278 :
5279 756 : if (!c->lists[OMP_LIST_MAP])
5280 : {
5281 1 : gfc_error ("%<acc update%> must contain at least one "
5282 : "%<device%> or %<host%> or %<self%> clause at %L", &here);
5283 1 : return MATCH_ERROR;
5284 : }
5285 :
5286 755 : new_st.op = EXEC_OACC_UPDATE;
5287 755 : new_st.ext.omp_clauses = c;
5288 755 : return MATCH_YES;
5289 : }
5290 :
5291 :
5292 : match
5293 877 : gfc_match_oacc_enter_data (void)
5294 : {
5295 877 : return match_acc (EXEC_OACC_ENTER_DATA, OACC_ENTER_DATA_CLAUSES);
5296 : }
5297 :
5298 :
5299 : match
5300 612 : gfc_match_oacc_exit_data (void)
5301 : {
5302 612 : return match_acc (EXEC_OACC_EXIT_DATA, OACC_EXIT_DATA_CLAUSES);
5303 : }
5304 :
5305 :
5306 : match
5307 202 : gfc_match_oacc_wait (void)
5308 : {
5309 202 : gfc_omp_clauses *c = gfc_get_omp_clauses ();
5310 202 : gfc_expr_list *wait_list = NULL, *el;
5311 202 : bool space = true;
5312 202 : match m;
5313 :
5314 202 : m = match_omp_oacc_expr_list (" (", &wait_list, true, false);
5315 202 : if (m == MATCH_ERROR)
5316 : return m;
5317 196 : else if (m == MATCH_YES)
5318 126 : space = false;
5319 :
5320 196 : if (gfc_match_omp_clauses (&c, OACC_WAIT_CLAUSES, space, space, true)
5321 : == MATCH_ERROR)
5322 : return MATCH_ERROR;
5323 :
5324 184 : if (wait_list)
5325 261 : for (el = wait_list; el; el = el->next)
5326 : {
5327 140 : if (el->expr == NULL)
5328 : {
5329 2 : gfc_error ("Invalid argument to !$ACC WAIT at %C");
5330 2 : return MATCH_ERROR;
5331 : }
5332 :
5333 138 : if (!gfc_resolve_expr (el->expr)
5334 138 : || el->expr->ts.type != BT_INTEGER || el->expr->rank != 0)
5335 : {
5336 3 : gfc_error ("WAIT clause at %L requires a scalar INTEGER expression",
5337 3 : &el->expr->where);
5338 :
5339 3 : return MATCH_ERROR;
5340 : }
5341 : }
5342 179 : c->wait_list = wait_list;
5343 179 : new_st.op = EXEC_OACC_WAIT;
5344 179 : new_st.ext.omp_clauses = c;
5345 179 : return MATCH_YES;
5346 : }
5347 :
5348 :
5349 : match
5350 97 : gfc_match_oacc_cache (void)
5351 : {
5352 97 : bool readonly = false;
5353 97 : gfc_omp_clauses *c = gfc_get_omp_clauses ();
5354 : /* The OpenACC cache directive explicitly only allows "array elements or
5355 : subarrays", which we're currently not checking here. Either check this
5356 : after the call of gfc_match_omp_variable_list, or add something like a
5357 : only_sections variant next to its allow_sections parameter. */
5358 97 : match m = gfc_match (" ( ");
5359 97 : if (m != MATCH_YES)
5360 : {
5361 0 : gfc_free_omp_clauses(c);
5362 0 : return m;
5363 : }
5364 :
5365 97 : if (gfc_match ("readonly : ") == MATCH_YES)
5366 8 : readonly = true;
5367 :
5368 97 : gfc_omp_namelist **head = NULL;
5369 97 : m = gfc_match_omp_variable_list ("", &c->lists[OMP_LIST_CACHE], true,
5370 : NULL, &head, true);
5371 97 : if (m != MATCH_YES)
5372 : {
5373 2 : gfc_free_omp_clauses(c);
5374 2 : return m;
5375 : }
5376 :
5377 95 : if (readonly)
5378 24 : for (gfc_omp_namelist *n = *head; n; n = n->next)
5379 16 : n->u.map.readonly = true;
5380 :
5381 95 : if (gfc_current_state() != COMP_DO
5382 56 : && gfc_current_state() != COMP_DO_CONCURRENT)
5383 : {
5384 2 : gfc_error ("ACC CACHE directive must be inside of loop %C");
5385 2 : gfc_free_omp_clauses(c);
5386 2 : return MATCH_ERROR;
5387 : }
5388 :
5389 93 : new_st.op = EXEC_OACC_CACHE;
5390 93 : new_st.ext.omp_clauses = c;
5391 93 : return MATCH_YES;
5392 : }
5393 :
5394 : match
5395 134 : gfc_match_oacc_init (void)
5396 : {
5397 134 : return match_acc (EXEC_OACC_INIT, OACC_INIT_CLAUSES);
5398 : }
5399 :
5400 : match
5401 130 : gfc_match_oacc_shutdown (void)
5402 : {
5403 130 : return match_acc (EXEC_OACC_SHUTDOWN, OACC_SHUTDOWN_CLAUSES);
5404 : }
5405 :
5406 : match
5407 130 : gfc_match_oacc_set (void)
5408 : {
5409 130 : return match_acc (EXEC_OACC_SET, OACC_SET_CLAUSES);
5410 : }
5411 :
5412 : /* Determine the OpenACC 'routine' directive's level of parallelism. */
5413 :
5414 : static oacc_routine_lop
5415 734 : gfc_oacc_routine_lop (gfc_omp_clauses *clauses)
5416 : {
5417 734 : oacc_routine_lop ret = OACC_ROUTINE_LOP_SEQ;
5418 :
5419 734 : if (clauses)
5420 : {
5421 584 : unsigned n_lop_clauses = 0;
5422 :
5423 584 : if (clauses->gang)
5424 : {
5425 164 : ++n_lop_clauses;
5426 164 : ret = OACC_ROUTINE_LOP_GANG;
5427 : }
5428 584 : if (clauses->worker)
5429 : {
5430 114 : ++n_lop_clauses;
5431 114 : ret = OACC_ROUTINE_LOP_WORKER;
5432 : }
5433 584 : if (clauses->vector)
5434 : {
5435 116 : ++n_lop_clauses;
5436 116 : ret = OACC_ROUTINE_LOP_VECTOR;
5437 : }
5438 584 : if (clauses->seq)
5439 : {
5440 206 : ++n_lop_clauses;
5441 206 : ret = OACC_ROUTINE_LOP_SEQ;
5442 : }
5443 :
5444 584 : if (n_lop_clauses > 1)
5445 47 : ret = OACC_ROUTINE_LOP_ERROR;
5446 : }
5447 :
5448 734 : return ret;
5449 : }
5450 :
5451 : match
5452 698 : gfc_match_oacc_routine (void)
5453 : {
5454 698 : locus old_loc;
5455 698 : match m;
5456 698 : gfc_intrinsic_sym *isym = NULL;
5457 698 : gfc_symbol *sym = NULL;
5458 698 : gfc_omp_clauses *c = NULL;
5459 698 : gfc_oacc_routine_name *n = NULL;
5460 698 : oacc_routine_lop lop = OACC_ROUTINE_LOP_NONE;
5461 698 : bool nohost;
5462 :
5463 698 : old_loc = gfc_current_locus;
5464 :
5465 698 : m = gfc_match (" (");
5466 :
5467 698 : if (gfc_current_ns->proc_name
5468 696 : && gfc_current_ns->proc_name->attr.if_source == IFSRC_IFBODY
5469 90 : && m == MATCH_YES)
5470 : {
5471 3 : gfc_error ("Only the !$ACC ROUTINE form without "
5472 : "list is allowed in interface block at %C");
5473 3 : goto cleanup;
5474 : }
5475 :
5476 608 : if (m == MATCH_YES)
5477 : {
5478 295 : char buffer[GFC_MAX_SYMBOL_LEN + 1];
5479 :
5480 295 : m = gfc_match_name (buffer);
5481 295 : if (m == MATCH_YES)
5482 : {
5483 294 : gfc_symtree *st = NULL;
5484 :
5485 : /* First look for an intrinsic symbol. */
5486 294 : isym = gfc_find_function (buffer);
5487 294 : if (!isym)
5488 294 : isym = gfc_find_subroutine (buffer);
5489 : /* If no intrinsic symbol found, search the current namespace. */
5490 294 : if (!isym)
5491 276 : st = gfc_find_symtree (gfc_current_ns->sym_root, buffer);
5492 276 : if (st)
5493 : {
5494 270 : sym = st->n.sym;
5495 : /* If the name in a 'routine' directive refers to the containing
5496 : subroutine or function, then make sure that we'll later handle
5497 : this accordingly. */
5498 270 : if (gfc_current_ns->proc_name != NULL
5499 270 : && strcmp (sym->name, gfc_current_ns->proc_name->name) == 0)
5500 294 : sym = NULL;
5501 : }
5502 :
5503 294 : if (isym == NULL && st == NULL)
5504 : {
5505 6 : gfc_error ("Invalid NAME %qs in !$ACC ROUTINE ( NAME ) at %C",
5506 : buffer);
5507 6 : gfc_current_locus = old_loc;
5508 9 : return MATCH_ERROR;
5509 : }
5510 : }
5511 : else
5512 : {
5513 1 : gfc_error ("Syntax error in !$ACC ROUTINE ( NAME ) at %C");
5514 1 : gfc_current_locus = old_loc;
5515 1 : return MATCH_ERROR;
5516 : }
5517 :
5518 288 : if (gfc_match_char (')') != MATCH_YES)
5519 : {
5520 2 : gfc_error ("Syntax error in !$ACC ROUTINE ( NAME ) at %C, expecting"
5521 : " %<)%> after NAME");
5522 2 : gfc_current_locus = old_loc;
5523 2 : return MATCH_ERROR;
5524 : }
5525 : }
5526 :
5527 686 : if (gfc_match_omp_eos () != MATCH_YES
5528 686 : && (gfc_match_omp_clauses (&c, OACC_ROUTINE_CLAUSES, false, false, true)
5529 : != MATCH_YES))
5530 : return MATCH_ERROR;
5531 :
5532 683 : lop = gfc_oacc_routine_lop (c);
5533 683 : if (lop == OACC_ROUTINE_LOP_ERROR)
5534 : {
5535 47 : gfc_error ("Multiple loop axes specified for routine at %C");
5536 47 : goto cleanup;
5537 : }
5538 636 : nohost = c ? c->nohost : false;
5539 :
5540 636 : if (isym != NULL)
5541 : {
5542 : /* Diagnose any OpenACC 'routine' directive that doesn't match the
5543 : (implicit) one with a 'seq' clause. */
5544 16 : if (c && (c->gang || c->worker || c->vector))
5545 : {
5546 10 : gfc_error ("Intrinsic symbol specified in !$ACC ROUTINE ( NAME )"
5547 : " at %C marked with incompatible GANG, WORKER, or VECTOR"
5548 : " clause");
5549 10 : goto cleanup;
5550 : }
5551 : /* ..., and no 'nohost' clause. */
5552 6 : if (nohost)
5553 : {
5554 2 : gfc_error ("Intrinsic symbol specified in !$ACC ROUTINE ( NAME )"
5555 : " at %C marked with incompatible NOHOST clause");
5556 2 : goto cleanup;
5557 : }
5558 : }
5559 620 : else if (sym != NULL)
5560 : {
5561 151 : bool add = true;
5562 :
5563 : /* For a repeated OpenACC 'routine' directive, diagnose if it doesn't
5564 : match the first one. */
5565 151 : for (gfc_oacc_routine_name *n_p = gfc_current_ns->oacc_routine_names;
5566 346 : n_p;
5567 195 : n_p = n_p->next)
5568 235 : if (n_p->sym == sym)
5569 : {
5570 51 : add = false;
5571 51 : bool nohost_p = n_p->clauses ? n_p->clauses->nohost : false;
5572 51 : if (lop != gfc_oacc_routine_lop (n_p->clauses)
5573 51 : || nohost != nohost_p)
5574 : {
5575 40 : gfc_error ("!$ACC ROUTINE already applied at %C");
5576 40 : goto cleanup;
5577 : }
5578 : }
5579 :
5580 111 : if (add)
5581 : {
5582 100 : sym->attr.oacc_routine_lop = lop;
5583 100 : sym->attr.oacc_routine_nohost = nohost;
5584 :
5585 100 : n = gfc_get_oacc_routine_name ();
5586 100 : n->sym = sym;
5587 100 : n->clauses = c;
5588 100 : n->next = gfc_current_ns->oacc_routine_names;
5589 100 : n->loc = old_loc;
5590 100 : gfc_current_ns->oacc_routine_names = n;
5591 : }
5592 : }
5593 469 : else if (gfc_current_ns->proc_name)
5594 : {
5595 : /* For a repeated OpenACC 'routine' directive, diagnose if it doesn't
5596 : match the first one. */
5597 468 : oacc_routine_lop lop_p = gfc_current_ns->proc_name->attr.oacc_routine_lop;
5598 468 : bool nohost_p = gfc_current_ns->proc_name->attr.oacc_routine_nohost;
5599 468 : if (lop_p != OACC_ROUTINE_LOP_NONE
5600 86 : && (lop != lop_p
5601 86 : || nohost != nohost_p))
5602 : {
5603 56 : gfc_error ("!$ACC ROUTINE already applied at %C");
5604 56 : goto cleanup;
5605 : }
5606 :
5607 412 : if (!gfc_add_omp_declare_target (&gfc_current_ns->proc_name->attr,
5608 : gfc_current_ns->proc_name->name,
5609 : &old_loc))
5610 1 : goto cleanup;
5611 411 : gfc_current_ns->proc_name->attr.oacc_routine_lop = lop;
5612 411 : gfc_current_ns->proc_name->attr.oacc_routine_nohost = nohost;
5613 : }
5614 : else
5615 : /* Something has gone wrong, possibly a syntax error. */
5616 1 : goto cleanup;
5617 :
5618 526 : if (gfc_pure (NULL) && c && (c->gang || c->worker || c->vector))
5619 : {
5620 6 : gfc_error ("!$ACC ROUTINE with GANG, WORKER, or VECTOR clause is not "
5621 : "permitted in PURE procedure at %C");
5622 6 : goto cleanup;
5623 : }
5624 :
5625 :
5626 520 : if (n)
5627 100 : n->clauses = c;
5628 420 : else if (gfc_current_ns->oacc_routine)
5629 0 : gfc_current_ns->oacc_routine_clauses = c;
5630 :
5631 520 : new_st.op = EXEC_OACC_ROUTINE;
5632 520 : new_st.ext.omp_clauses = c;
5633 520 : return MATCH_YES;
5634 :
5635 166 : cleanup:
5636 166 : gfc_current_locus = old_loc;
5637 166 : return MATCH_ERROR;
5638 : }
5639 :
5640 :
5641 : #define OMP_PARALLEL_CLAUSES \
5642 : (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
5643 : | OMP_CLAUSE_SHARED | OMP_CLAUSE_COPYIN | OMP_CLAUSE_REDUCTION \
5644 : | OMP_CLAUSE_IF | OMP_CLAUSE_NUM_THREADS | OMP_CLAUSE_DEFAULT \
5645 : | OMP_CLAUSE_PROC_BIND | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_MESSAGE \
5646 : | OMP_CLAUSE_SEVERITY)
5647 : #define OMP_DECLARE_SIMD_CLAUSES \
5648 : (omp_mask (OMP_CLAUSE_SIMDLEN) | OMP_CLAUSE_LINEAR \
5649 : | OMP_CLAUSE_UNIFORM | OMP_CLAUSE_ALIGNED | OMP_CLAUSE_INBRANCH \
5650 : | OMP_CLAUSE_NOTINBRANCH)
5651 : #define OMP_DO_CLAUSES \
5652 : (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
5653 : | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION \
5654 : | OMP_CLAUSE_SCHEDULE | OMP_CLAUSE_ORDERED | OMP_CLAUSE_COLLAPSE \
5655 : | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ORDER | OMP_CLAUSE_ALLOCATE \
5656 : | OMP_CLAUSE_NOWAIT)
5657 : #define OMP_LOOP_CLAUSES \
5658 : (omp_mask (OMP_CLAUSE_BIND) | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_ORDER \
5659 : | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION)
5660 :
5661 : #define OMP_SCOPE_CLAUSES \
5662 : (omp_mask (OMP_CLAUSE_PRIVATE) |OMP_CLAUSE_FIRSTPRIVATE \
5663 : | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT)
5664 : #define OMP_SECTIONS_CLAUSES \
5665 : (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
5666 : | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION \
5667 : | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT)
5668 : #define OMP_SIMD_CLAUSES \
5669 : (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_LASTPRIVATE \
5670 : | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_SAFELEN \
5671 : | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ALIGNED | OMP_CLAUSE_SIMDLEN \
5672 : | OMP_CLAUSE_IF | OMP_CLAUSE_ORDER | OMP_CLAUSE_NOTEMPORAL)
5673 : #define OMP_TASK_CLAUSES \
5674 : (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
5675 : | OMP_CLAUSE_SHARED | OMP_CLAUSE_IF | OMP_CLAUSE_DEFAULT \
5676 : | OMP_CLAUSE_UNTIED | OMP_CLAUSE_FINAL | OMP_CLAUSE_MERGEABLE \
5677 : | OMP_CLAUSE_DEPEND | OMP_CLAUSE_PRIORITY | OMP_CLAUSE_IN_REDUCTION \
5678 : | OMP_CLAUSE_DETACH | OMP_CLAUSE_AFFINITY | OMP_CLAUSE_ALLOCATE)
5679 : #define OMP_TASKLOOP_CLAUSES \
5680 : (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
5681 : | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_IF \
5682 : | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_UNTIED | OMP_CLAUSE_FINAL \
5683 : | OMP_CLAUSE_MERGEABLE | OMP_CLAUSE_PRIORITY | OMP_CLAUSE_GRAINSIZE \
5684 : | OMP_CLAUSE_NUM_TASKS | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_NOGROUP \
5685 : | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_IN_REDUCTION | OMP_CLAUSE_ALLOCATE)
5686 : #define OMP_TASKGROUP_CLAUSES \
5687 : (omp_mask (OMP_CLAUSE_TASK_REDUCTION) | OMP_CLAUSE_ALLOCATE)
5688 : #define OMP_TARGET_CLAUSES \
5689 : (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF \
5690 : | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_PRIVATE \
5691 : | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_DEFAULTMAP \
5692 : | OMP_CLAUSE_IS_DEVICE_PTR | OMP_CLAUSE_IN_REDUCTION \
5693 : | OMP_CLAUSE_THREAD_LIMIT | OMP_CLAUSE_ALLOCATE \
5694 : | OMP_CLAUSE_HAS_DEVICE_ADDR | OMP_CLAUSE_USES_ALLOCATORS \
5695 : | OMP_CLAUSE_DYN_GROUPPRIVATE | OMP_CLAUSE_DEVICE_TYPE \
5696 : | OMP_CLAUSE_MESSAGE | OMP_CLAUSE_SEVERITY)
5697 : #define OMP_TARGET_DATA_CLAUSES \
5698 : (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF \
5699 : | OMP_CLAUSE_USE_DEVICE_PTR | OMP_CLAUSE_USE_DEVICE_ADDR)
5700 : #define OMP_TARGET_ENTER_DATA_CLAUSES \
5701 : (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF \
5702 : | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT)
5703 : #define OMP_TARGET_EXIT_DATA_CLAUSES \
5704 : (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF \
5705 : | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT)
5706 : #define OMP_TARGET_UPDATE_CLAUSES \
5707 : (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_IF | OMP_CLAUSE_TO \
5708 : | OMP_CLAUSE_FROM | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT)
5709 : #define OMP_TEAMS_CLAUSES \
5710 : (omp_mask (OMP_CLAUSE_NUM_TEAMS) | OMP_CLAUSE_THREAD_LIMIT \
5711 : | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE \
5712 : | OMP_CLAUSE_SHARED | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_ALLOCATE \
5713 : | OMP_CLAUSE_MESSAGE | OMP_CLAUSE_SEVERITY)
5714 : #define OMP_DISTRIBUTE_CLAUSES \
5715 : (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
5716 : | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_DIST_SCHEDULE \
5717 : | OMP_CLAUSE_ORDER | OMP_CLAUSE_ALLOCATE)
5718 : #define OMP_SINGLE_CLAUSES \
5719 : (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
5720 : | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_COPYPRIVATE)
5721 : #define OMP_ORDERED_CLAUSES \
5722 : (omp_mask (OMP_CLAUSE_THREADS) | OMP_CLAUSE_SIMD)
5723 : #define OMP_DECLARE_TARGET_CLAUSES \
5724 : (omp_mask (OMP_CLAUSE_ENTER) | OMP_CLAUSE_LINK | OMP_CLAUSE_DEVICE_TYPE \
5725 : | OMP_CLAUSE_TO | OMP_CLAUSE_INDIRECT | OMP_CLAUSE_LOCAL)
5726 : #define OMP_ATOMIC_CLAUSES \
5727 : (omp_mask (OMP_CLAUSE_ATOMIC) | OMP_CLAUSE_CAPTURE | OMP_CLAUSE_HINT \
5728 : | OMP_CLAUSE_MEMORDER | OMP_CLAUSE_COMPARE | OMP_CLAUSE_FAIL \
5729 : | OMP_CLAUSE_WEAK)
5730 : #define OMP_MASKED_CLAUSES \
5731 : (omp_mask (OMP_CLAUSE_FILTER))
5732 : #define OMP_ERROR_CLAUSES \
5733 : (omp_mask (OMP_CLAUSE_AT) | OMP_CLAUSE_MESSAGE | OMP_CLAUSE_SEVERITY)
5734 : #define OMP_WORKSHARE_CLAUSES \
5735 : omp_mask (OMP_CLAUSE_NOWAIT)
5736 : #define OMP_UNROLL_CLAUSES \
5737 : (omp_mask (OMP_CLAUSE_FULL) | OMP_CLAUSE_PARTIAL)
5738 : #define OMP_TILE_CLAUSES \
5739 : (omp_mask (OMP_CLAUSE_SIZES))
5740 : #define OMP_ALLOCATORS_CLAUSES \
5741 : omp_mask (OMP_CLAUSE_ALLOCATE)
5742 : #define OMP_INTEROP_CLAUSES \
5743 : (omp_mask (OMP_CLAUSE_DEPEND) | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_DEVICE \
5744 : | OMP_CLAUSE_INIT | OMP_CLAUSE_DESTROY | OMP_CLAUSE_USE)
5745 : #define OMP_DISPATCH_CLAUSES \
5746 : (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOVARIANTS \
5747 : | OMP_CLAUSE_NOCONTEXT | OMP_CLAUSE_IS_DEVICE_PTR | OMP_CLAUSE_NOWAIT \
5748 : | OMP_CLAUSE_HAS_DEVICE_ADDR | OMP_CLAUSE_INTEROP)
5749 :
5750 :
5751 : static match
5752 17341 : match_omp (gfc_exec_op op, const omp_mask mask)
5753 : {
5754 17341 : gfc_omp_clauses *c;
5755 17341 : if (gfc_match_omp_clauses (&c, mask, true, true, false,
5756 : op == EXEC_OMP_TARGET) != MATCH_YES)
5757 : return MATCH_ERROR;
5758 17003 : new_st.op = op;
5759 17003 : new_st.ext.omp_clauses = c;
5760 17003 : return MATCH_YES;
5761 : }
5762 :
5763 : /* Handles both declarative and (deprecated) executable ALLOCATE directive;
5764 : accepts optional list (for executable) and common blocks.
5765 : If no variables have been provided, the single omp namelist has sym == NULL.
5766 :
5767 : Note that the executable ALLOCATE directive permits structure elements only
5768 : in OpenMP 5.0 and 5.1 but not longer in 5.2. See also the comment on the
5769 : 'omp allocators' directive below. The accidental change was reverted for
5770 : OpenMP TR12, permitting them again. See also gfc_match_omp_allocators.
5771 :
5772 : Hence, structure elements are rejected for now, also to make resolving
5773 : OMP_LIST_ALLOCATE simpler (check for duplicates, same symbol in
5774 : Fortran allocate stmt). TODO: Permit structure elements. */
5775 :
5776 : match
5777 274 : gfc_match_omp_allocate (void)
5778 : {
5779 274 : match m;
5780 274 : bool first = true;
5781 274 : gfc_omp_namelist *vars = NULL;
5782 274 : gfc_expr *align = NULL;
5783 274 : gfc_expr *allocator = NULL;
5784 274 : locus loc = gfc_current_locus;
5785 :
5786 274 : m = gfc_match_omp_variable_list (" (", &vars, true, NULL, NULL, true, true,
5787 : NULL, true);
5788 :
5789 274 : if (m == MATCH_ERROR)
5790 : return m;
5791 :
5792 502 : while (true)
5793 : {
5794 502 : gfc_gobble_whitespace ();
5795 502 : if (gfc_match_omp_eos () == MATCH_YES)
5796 : break;
5797 234 : if (!first)
5798 28 : gfc_match (", ");
5799 234 : first = false;
5800 234 : if ((m = gfc_match_dupl_check (!align, "align", true, &align))
5801 : != MATCH_NO)
5802 : {
5803 62 : if (m == MATCH_ERROR)
5804 1 : goto error;
5805 61 : continue;
5806 : }
5807 172 : if ((m = gfc_match_dupl_check (!allocator, "allocator",
5808 : true, &allocator)) != MATCH_NO)
5809 : {
5810 171 : if (m == MATCH_ERROR)
5811 1 : goto error;
5812 170 : continue;
5813 : }
5814 1 : gfc_error ("Expected ALIGN or ALLOCATOR clause at %C");
5815 1 : return MATCH_ERROR;
5816 : }
5817 541 : for (gfc_omp_namelist *n = vars; n; n = n->next)
5818 276 : if (n->expr)
5819 : {
5820 3 : if ((n->expr->ref && n->expr->ref->type == REF_COMPONENT)
5821 3 : || (n->expr->ref->next && n->expr->ref->type == REF_COMPONENT))
5822 1 : gfc_error ("Sorry, structure-element list item at %L in ALLOCATE "
5823 : "directive is not yet supported", &n->expr->where);
5824 : else
5825 2 : gfc_error ("Unexpected expression as list item at %L in ALLOCATE "
5826 : "directive", &n->expr->where);
5827 :
5828 3 : gfc_free_omp_namelist (vars, OMP_LIST_ALLOCATE);
5829 3 : goto error;
5830 : }
5831 :
5832 265 : new_st.op = EXEC_OMP_ALLOCATE;
5833 265 : new_st.ext.omp_clauses = gfc_get_omp_clauses ();
5834 265 : if (vars == NULL)
5835 : {
5836 27 : vars = gfc_get_omp_namelist ();
5837 27 : vars->where = loc;
5838 27 : vars->u.align = align;
5839 27 : vars->u2.allocator = allocator;
5840 27 : new_st.ext.omp_clauses->lists[OMP_LIST_ALLOCATE] = vars;
5841 : }
5842 : else
5843 : {
5844 238 : new_st.ext.omp_clauses->lists[OMP_LIST_ALLOCATE] = vars;
5845 511 : for (; vars; vars = vars->next)
5846 : {
5847 273 : vars->u.align = (align) ? gfc_copy_expr (align) : NULL;
5848 273 : vars->u2.allocator = allocator;
5849 : }
5850 238 : gfc_free_expr (align);
5851 : }
5852 : return MATCH_YES;
5853 :
5854 5 : error:
5855 5 : gfc_free_expr (align);
5856 5 : gfc_free_expr (allocator);
5857 5 : return MATCH_ERROR;
5858 : }
5859 :
5860 : /* In line with OpenMP 5.2 derived-type components are rejected.
5861 : See also comment before gfc_match_omp_allocate. */
5862 :
5863 : match
5864 26 : gfc_match_omp_allocators (void)
5865 : {
5866 26 : return match_omp (EXEC_OMP_ALLOCATORS, OMP_ALLOCATORS_CLAUSES);
5867 : }
5868 :
5869 :
5870 : match
5871 23 : gfc_match_omp_assume (void)
5872 : {
5873 23 : gfc_omp_clauses *c;
5874 23 : locus loc = gfc_current_locus;
5875 23 : if ((gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_ASSUMPTIONS))
5876 : != MATCH_YES)
5877 23 : || (omp_verify_merge_absent_contains (ST_OMP_ASSUME, c->assume, NULL,
5878 : &loc) != MATCH_YES))
5879 7 : return MATCH_ERROR;
5880 16 : new_st.op = EXEC_OMP_ASSUME;
5881 16 : new_st.ext.omp_clauses = c;
5882 16 : return MATCH_YES;
5883 : }
5884 :
5885 :
5886 : match
5887 28 : gfc_match_omp_assumes (void)
5888 : {
5889 28 : gfc_omp_clauses *c;
5890 28 : locus loc = gfc_current_locus;
5891 28 : if (!gfc_current_ns->proc_name
5892 27 : || (gfc_current_ns->proc_name->attr.flavor != FL_MODULE
5893 23 : && !gfc_current_ns->proc_name->attr.subroutine
5894 10 : && !gfc_current_ns->proc_name->attr.function))
5895 : {
5896 2 : gfc_error ("!$OMP ASSUMES at %C must be in the specification part of a "
5897 : "subprogram or module");
5898 2 : return MATCH_ERROR;
5899 : }
5900 26 : if ((gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_ASSUMPTIONS))
5901 : != MATCH_YES)
5902 50 : || (omp_verify_merge_absent_contains (ST_OMP_ASSUMES, c->assume,
5903 24 : gfc_current_ns->omp_assumes, &loc)
5904 : != MATCH_YES))
5905 5 : return MATCH_ERROR;
5906 21 : if (gfc_current_ns->omp_assumes == NULL)
5907 : {
5908 19 : gfc_current_ns->omp_assumes = c->assume;
5909 19 : c->assume = NULL;
5910 : }
5911 2 : else if (gfc_current_ns->omp_assumes && c->assume)
5912 : {
5913 2 : gfc_current_ns->omp_assumes->no_openmp |= c->assume->no_openmp;
5914 2 : gfc_current_ns->omp_assumes->no_openmp_routines
5915 2 : |= c->assume->no_openmp_routines;
5916 2 : gfc_current_ns->omp_assumes->no_openmp_constructs
5917 2 : |= c->assume->no_openmp_constructs;
5918 2 : gfc_current_ns->omp_assumes->no_parallelism |= c->assume->no_parallelism;
5919 2 : if (gfc_current_ns->omp_assumes->holds && c->assume->holds)
5920 : {
5921 : gfc_expr_list *el = gfc_current_ns->omp_assumes->holds;
5922 1 : for ( ; el->next ; el = el->next)
5923 : ;
5924 1 : el->next = c->assume->holds;
5925 1 : }
5926 1 : else if (c->assume->holds)
5927 0 : gfc_current_ns->omp_assumes->holds = c->assume->holds;
5928 2 : c->assume->holds = NULL;
5929 : }
5930 21 : gfc_free_omp_clauses (c);
5931 21 : return MATCH_YES;
5932 : }
5933 :
5934 :
5935 : match
5936 162 : gfc_match_omp_critical (void)
5937 : {
5938 162 : char n[GFC_MAX_SYMBOL_LEN+1];
5939 162 : gfc_omp_clauses *c = NULL;
5940 :
5941 162 : if (gfc_match (" ( %n )", n) != MATCH_YES)
5942 115 : n[0] = '\0';
5943 :
5944 162 : if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_HINT),
5945 162 : /* first = */ n[0] == '\0') != MATCH_YES)
5946 : return MATCH_ERROR;
5947 :
5948 160 : new_st.op = EXEC_OMP_CRITICAL;
5949 160 : new_st.ext.omp_clauses = c;
5950 160 : if (n[0])
5951 47 : c->critical_name = xstrdup (n);
5952 : return MATCH_YES;
5953 : }
5954 :
5955 :
5956 : match
5957 160 : gfc_match_omp_end_critical (void)
5958 : {
5959 160 : char n[GFC_MAX_SYMBOL_LEN+1];
5960 :
5961 160 : if (gfc_match (" ( %n )", n) != MATCH_YES)
5962 113 : n[0] = '\0';
5963 160 : if (gfc_match_omp_eos () != MATCH_YES)
5964 : {
5965 1 : gfc_error ("Unexpected junk after $OMP CRITICAL statement at %C");
5966 1 : return MATCH_ERROR;
5967 : }
5968 :
5969 159 : new_st.op = EXEC_OMP_END_CRITICAL;
5970 159 : new_st.ext.omp_name = n[0] ? xstrdup (n) : NULL;
5971 159 : return MATCH_YES;
5972 : }
5973 :
5974 : /* depobj(depobj) depend(dep-type:loc)|destroy|update(dep-type)
5975 : dep-type = in/out/inout/mutexinoutset/depobj/source/sink
5976 : depend: !source, !sink
5977 : update: !source, !sink, !depobj
5978 : locator = exactly one list item .*/
5979 : match
5980 125 : gfc_match_omp_depobj (void)
5981 : {
5982 125 : gfc_omp_clauses *c = NULL;
5983 125 : gfc_expr *depobj;
5984 :
5985 125 : if (gfc_match (" ( %v ) ", &depobj) != MATCH_YES)
5986 : {
5987 2 : gfc_error ("Expected %<( depobj )%> at %C");
5988 2 : return MATCH_ERROR;
5989 : }
5990 123 : if (gfc_match ("update ( ") == MATCH_YES)
5991 : {
5992 12 : c = gfc_get_omp_clauses ();
5993 12 : if (gfc_match ("inoutset )") == MATCH_YES)
5994 2 : c->depobj_update = OMP_DEPEND_INOUTSET;
5995 10 : else if (gfc_match ("inout )") == MATCH_YES)
5996 1 : c->depobj_update = OMP_DEPEND_INOUT;
5997 9 : else if (gfc_match ("in )") == MATCH_YES)
5998 2 : c->depobj_update = OMP_DEPEND_IN;
5999 7 : else if (gfc_match ("out )") == MATCH_YES)
6000 2 : c->depobj_update = OMP_DEPEND_OUT;
6001 5 : else if (gfc_match ("mutexinoutset )") == MATCH_YES)
6002 2 : c->depobj_update = OMP_DEPEND_MUTEXINOUTSET;
6003 : else
6004 : {
6005 3 : gfc_error ("Expected IN, OUT, INOUT, INOUTSET or MUTEXINOUTSET "
6006 : "followed by %<)%> at %C");
6007 3 : goto error;
6008 : }
6009 : }
6010 111 : else if (gfc_match ("destroy ") == MATCH_YES)
6011 : {
6012 16 : gfc_expr *destroyobj = NULL;
6013 16 : c = gfc_get_omp_clauses ();
6014 16 : c->destroy = true;
6015 :
6016 16 : if (gfc_match (" ( %v ) ", &destroyobj) == MATCH_YES)
6017 : {
6018 3 : if (destroyobj->symtree != depobj->symtree)
6019 2 : gfc_warning (OPT_Wopenmp, "The same depend object should be used as"
6020 : " DEPOBJ argument at %L and as DESTROY argument at %L",
6021 : &depobj->where, &destroyobj->where);
6022 3 : gfc_free_expr (destroyobj);
6023 : }
6024 : }
6025 95 : else if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_DEPEND), true, false)
6026 : != MATCH_YES)
6027 2 : goto error;
6028 :
6029 118 : if (c->depobj_update == OMP_DEPEND_UNSET && !c->destroy)
6030 : {
6031 93 : if (!c->doacross_source && !c->lists[OMP_LIST_DEPEND])
6032 : {
6033 1 : gfc_error ("Expected DEPEND, UPDATE, or DESTROY clause at %C");
6034 1 : goto error;
6035 : }
6036 92 : if (c->lists[OMP_LIST_DEPEND]->u.depend_doacross_op == OMP_DEPEND_DEPOBJ)
6037 : {
6038 1 : gfc_error ("DEPEND clause at %L of OMP DEPOBJ construct shall not "
6039 : "have dependence-type DEPOBJ",
6040 : c->lists[OMP_LIST_DEPEND]
6041 : ? &c->lists[OMP_LIST_DEPEND]->where : &gfc_current_locus);
6042 1 : goto error;
6043 : }
6044 91 : if (c->lists[OMP_LIST_DEPEND]->next)
6045 : {
6046 1 : gfc_error ("DEPEND clause at %L of OMP DEPOBJ construct shall have "
6047 : "only a single locator",
6048 : &c->lists[OMP_LIST_DEPEND]->next->where);
6049 1 : goto error;
6050 : }
6051 : }
6052 :
6053 115 : c->depobj = depobj;
6054 115 : new_st.op = EXEC_OMP_DEPOBJ;
6055 115 : new_st.ext.omp_clauses = c;
6056 115 : return MATCH_YES;
6057 :
6058 8 : error:
6059 8 : gfc_free_expr (depobj);
6060 8 : gfc_free_omp_clauses (c);
6061 8 : return MATCH_ERROR;
6062 : }
6063 :
6064 : match
6065 160 : gfc_match_omp_dispatch (void)
6066 : {
6067 160 : return match_omp (EXEC_OMP_DISPATCH, OMP_DISPATCH_CLAUSES);
6068 : }
6069 :
6070 : match
6071 57 : gfc_match_omp_distribute (void)
6072 : {
6073 57 : return match_omp (EXEC_OMP_DISTRIBUTE, OMP_DISTRIBUTE_CLAUSES);
6074 : }
6075 :
6076 :
6077 : match
6078 44 : gfc_match_omp_distribute_parallel_do (void)
6079 : {
6080 44 : return match_omp (EXEC_OMP_DISTRIBUTE_PARALLEL_DO,
6081 44 : (OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
6082 44 : | OMP_DO_CLAUSES)
6083 44 : & ~(omp_mask (OMP_CLAUSE_ORDERED)
6084 44 : | OMP_CLAUSE_LINEAR | OMP_CLAUSE_NOWAIT));
6085 : }
6086 :
6087 :
6088 : match
6089 34 : gfc_match_omp_distribute_parallel_do_simd (void)
6090 : {
6091 34 : return match_omp (EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD,
6092 34 : (OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
6093 34 : | OMP_DO_CLAUSES | OMP_SIMD_CLAUSES)
6094 34 : & ~(omp_mask (OMP_CLAUSE_ORDERED) | OMP_CLAUSE_NOWAIT));
6095 : }
6096 :
6097 :
6098 : match
6099 52 : gfc_match_omp_distribute_simd (void)
6100 : {
6101 52 : return match_omp (EXEC_OMP_DISTRIBUTE_SIMD,
6102 52 : OMP_DISTRIBUTE_CLAUSES | OMP_SIMD_CLAUSES);
6103 : }
6104 :
6105 :
6106 : match
6107 1253 : gfc_match_omp_do (void)
6108 : {
6109 1253 : return match_omp (EXEC_OMP_DO, OMP_DO_CLAUSES);
6110 : }
6111 :
6112 :
6113 : match
6114 137 : gfc_match_omp_do_simd (void)
6115 : {
6116 137 : return match_omp (EXEC_OMP_DO_SIMD, OMP_DO_CLAUSES | OMP_SIMD_CLAUSES);
6117 : }
6118 :
6119 :
6120 : match
6121 70 : gfc_match_omp_loop (void)
6122 : {
6123 70 : return match_omp (EXEC_OMP_LOOP, OMP_LOOP_CLAUSES);
6124 : }
6125 :
6126 :
6127 : match
6128 35 : gfc_match_omp_teams_loop (void)
6129 : {
6130 35 : return match_omp (EXEC_OMP_TEAMS_LOOP, OMP_TEAMS_CLAUSES | OMP_LOOP_CLAUSES);
6131 : }
6132 :
6133 :
6134 : match
6135 18 : gfc_match_omp_target_teams_loop (void)
6136 : {
6137 18 : return match_omp (EXEC_OMP_TARGET_TEAMS_LOOP,
6138 18 : OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES | OMP_LOOP_CLAUSES);
6139 : }
6140 :
6141 :
6142 : match
6143 31 : gfc_match_omp_parallel_loop (void)
6144 : {
6145 31 : return match_omp (EXEC_OMP_PARALLEL_LOOP,
6146 31 : OMP_PARALLEL_CLAUSES | OMP_LOOP_CLAUSES);
6147 : }
6148 :
6149 :
6150 : match
6151 16 : gfc_match_omp_target_parallel_loop (void)
6152 : {
6153 16 : return match_omp (EXEC_OMP_TARGET_PARALLEL_LOOP,
6154 16 : (OMP_TARGET_CLAUSES | OMP_PARALLEL_CLAUSES
6155 16 : | OMP_LOOP_CLAUSES));
6156 : }
6157 :
6158 :
6159 : match
6160 101 : gfc_match_omp_error (void)
6161 : {
6162 101 : locus loc = gfc_current_locus;
6163 101 : match m = match_omp (EXEC_OMP_ERROR, OMP_ERROR_CLAUSES);
6164 101 : if (m != MATCH_YES)
6165 : return m;
6166 :
6167 82 : gfc_omp_clauses *c = new_st.ext.omp_clauses;
6168 82 : if (c->severity == OMP_SEVERITY_UNSET)
6169 45 : c->severity = OMP_SEVERITY_FATAL;
6170 82 : if (new_st.ext.omp_clauses->at == OMP_AT_EXECUTION)
6171 : return MATCH_YES;
6172 37 : if (c->message
6173 37 : && (!gfc_resolve_expr (c->message)
6174 16 : || c->message->ts.type != BT_CHARACTER
6175 14 : || c->message->ts.kind != gfc_default_character_kind
6176 13 : || c->message->rank != 0))
6177 : {
6178 4 : gfc_error ("MESSAGE clause at %L requires a scalar default-kind "
6179 : "CHARACTER expression",
6180 4 : &new_st.ext.omp_clauses->message->where);
6181 4 : return MATCH_ERROR;
6182 : }
6183 33 : if (c->message && !gfc_is_constant_expr (c->message))
6184 : {
6185 2 : gfc_error ("Constant character expression required in MESSAGE clause "
6186 2 : "at %L", &new_st.ext.omp_clauses->message->where);
6187 2 : return MATCH_ERROR;
6188 : }
6189 31 : if (c->message)
6190 : {
6191 10 : const char *msg = G_("$OMP ERROR encountered at %L: %s");
6192 10 : gcc_assert (c->message->expr_type == EXPR_CONSTANT);
6193 10 : gfc_charlen_t slen = c->message->value.character.length;
6194 10 : int i = gfc_validate_kind (BT_CHARACTER, gfc_default_character_kind,
6195 : false);
6196 10 : size_t size = slen * gfc_character_kinds[i].bit_size / 8;
6197 10 : unsigned char *s = XCNEWVAR (unsigned char, size + 1);
6198 10 : gfc_encode_character (gfc_default_character_kind, slen,
6199 10 : c->message->value.character.string,
6200 : (unsigned char *) s, size);
6201 10 : s[size] = '\0';
6202 10 : if (c->severity == OMP_SEVERITY_WARNING)
6203 6 : gfc_warning_now (0, msg, &loc, s);
6204 : else
6205 4 : gfc_error_now (msg, &loc, s);
6206 10 : free (s);
6207 : }
6208 : else
6209 : {
6210 21 : const char *msg = G_("$OMP ERROR encountered at %L");
6211 21 : if (c->severity == OMP_SEVERITY_WARNING)
6212 7 : gfc_warning_now (0, msg, &loc);
6213 : else
6214 14 : gfc_error_now (msg, &loc);
6215 : }
6216 : return MATCH_YES;
6217 : }
6218 :
6219 : match
6220 86 : gfc_match_omp_flush (void)
6221 : {
6222 86 : gfc_omp_namelist *list = NULL;
6223 86 : gfc_omp_clauses *c = NULL;
6224 86 : gfc_gobble_whitespace ();
6225 86 : enum gfc_omp_memorder mo = OMP_MEMORDER_UNSET;
6226 86 : if (gfc_match_omp_eos () == MATCH_NO && gfc_peek_ascii_char () != '(')
6227 : {
6228 14 : if (gfc_match ("seq_cst") == MATCH_YES)
6229 : mo = OMP_MEMORDER_SEQ_CST;
6230 11 : else if (gfc_match ("acq_rel") == MATCH_YES)
6231 : mo = OMP_MEMORDER_ACQ_REL;
6232 8 : else if (gfc_match ("release") == MATCH_YES)
6233 : mo = OMP_MEMORDER_RELEASE;
6234 5 : else if (gfc_match ("acquire") == MATCH_YES)
6235 : mo = OMP_MEMORDER_ACQUIRE;
6236 : else
6237 : {
6238 2 : gfc_error ("Expected SEQ_CST, AQC_REL, RELEASE, or ACQUIRE at %C");
6239 2 : return MATCH_ERROR;
6240 : }
6241 12 : c = gfc_get_omp_clauses ();
6242 12 : c->memorder = mo;
6243 : }
6244 84 : gfc_match_omp_variable_list (" (", &list, true);
6245 84 : if (list && mo != OMP_MEMORDER_UNSET)
6246 : {
6247 4 : gfc_error ("List specified together with memory order clause in FLUSH "
6248 : "directive at %C");
6249 4 : gfc_free_omp_namelist (list, OMP_LIST_NONE);
6250 4 : gfc_free_omp_clauses (c);
6251 4 : return MATCH_ERROR;
6252 : }
6253 80 : if (gfc_match_omp_eos () != MATCH_YES)
6254 : {
6255 0 : gfc_error ("Unexpected junk after $OMP FLUSH statement at %C");
6256 0 : gfc_free_omp_namelist (list, OMP_LIST_NONE);
6257 0 : gfc_free_omp_clauses (c);
6258 0 : return MATCH_ERROR;
6259 : }
6260 80 : new_st.op = EXEC_OMP_FLUSH;
6261 80 : new_st.ext.omp_namelist = list;
6262 80 : new_st.ext.omp_clauses = c;
6263 80 : return MATCH_YES;
6264 : }
6265 :
6266 :
6267 : match
6268 188 : gfc_match_omp_declare_simd (void)
6269 : {
6270 188 : locus where = gfc_current_locus;
6271 188 : gfc_symbol *proc_name;
6272 188 : gfc_omp_clauses *c;
6273 188 : gfc_omp_declare_simd *ods;
6274 188 : bool needs_space = false;
6275 :
6276 188 : switch (gfc_match (" ( "))
6277 : {
6278 144 : case MATCH_YES:
6279 144 : if (gfc_match_symbol (&proc_name, /* host assoc = */ true) != MATCH_YES
6280 144 : || gfc_match (" ) ") != MATCH_YES)
6281 0 : return MATCH_ERROR;
6282 : break;
6283 44 : case MATCH_NO: proc_name = NULL; needs_space = true; break;
6284 : case MATCH_ERROR: return MATCH_ERROR;
6285 : }
6286 :
6287 188 : if (gfc_match_omp_clauses (&c, OMP_DECLARE_SIMD_CLAUSES, true,
6288 : needs_space) != MATCH_YES)
6289 : return MATCH_ERROR;
6290 :
6291 183 : if (gfc_current_ns->is_block_data)
6292 : {
6293 1 : gfc_free_omp_clauses (c);
6294 1 : return MATCH_YES;
6295 : }
6296 :
6297 182 : ods = gfc_get_omp_declare_simd ();
6298 182 : ods->where = where;
6299 182 : ods->proc_name = proc_name;
6300 182 : ods->clauses = c;
6301 182 : ods->next = gfc_current_ns->omp_declare_simd;
6302 182 : gfc_current_ns->omp_declare_simd = ods;
6303 182 : return MATCH_YES;
6304 : }
6305 :
6306 :
6307 : /* Find a matching "!$omp declare mapper" for typespec TS in symtree ST. */
6308 :
6309 : gfc_omp_udm *
6310 30 : gfc_omp_udm_find (gfc_symtree *st, gfc_typespec *ts)
6311 : {
6312 30 : gfc_omp_udm *omp_udm;
6313 :
6314 30 : if (st == NULL)
6315 : return NULL;
6316 :
6317 14 : gfc_symbol *dt = (ts->type == BT_CLASS
6318 0 : ? CLASS_DATA (ts->u.derived)->ts.u.derived
6319 : : ts->u.derived);
6320 15 : for (omp_udm = st->n.omp_udm; omp_udm; omp_udm = omp_udm->next)
6321 : {
6322 5 : if (dt == omp_udm->ts.u.derived)
6323 : return omp_udm;
6324 : /* Special case for comparing derived types across namespaces. If the
6325 : true names and module names are the same and the module name is
6326 : nonnull, then they are equal. */
6327 1 : if (dt->module && omp_udm->ts.u.derived->module
6328 1 : && strcmp (dt->name, omp_udm->ts.u.derived->name) == 0
6329 1 : && strcmp (dt->module, omp_udm->ts.u.derived->module) == 0)
6330 : return omp_udm;
6331 : }
6332 :
6333 : return NULL;
6334 : }
6335 :
6336 :
6337 : /* Match !$omp declare mapper([ mapper-identifier : ] type :: var) clauses-list */
6338 :
6339 : match
6340 28 : gfc_match_omp_declare_mapper (void)
6341 : {
6342 28 : match m;
6343 28 : gfc_typespec ts;
6344 28 : char mapper_id[GFC_MAX_SYMBOL_LEN + 1];
6345 28 : char var[GFC_MAX_SYMBOL_LEN + 1];
6346 28 : gfc_namespace *mapper_ns = NULL;
6347 28 : gfc_symtree *var_st;
6348 28 : gfc_symtree *st;
6349 28 : gfc_omp_udm *omp_udm = NULL, *prev_udm = NULL;
6350 28 : locus where = gfc_current_locus;
6351 :
6352 28 : if (gfc_match_char ('(') != MATCH_YES)
6353 : {
6354 1 : gfc_error ("Expected %<(%> at %C");
6355 1 : return MATCH_ERROR;
6356 : }
6357 :
6358 27 : locus old_locus = gfc_current_locus;
6359 :
6360 27 : m = gfc_match (" %n : ", mapper_id);
6361 :
6362 27 : if (m == MATCH_ERROR)
6363 : return MATCH_ERROR;
6364 :
6365 : /* As a special case, a mapper named "default" and an unnamed mapper are
6366 : both the default mapper for a given type. */
6367 27 : if (strcmp (mapper_id, "default") == 0)
6368 0 : mapper_id[0] = '\0';
6369 :
6370 27 : if (gfc_peek_ascii_char () == ':')
6371 : {
6372 : /* If we see '::', the user did not name the mapper, and instead we just
6373 : saw the type. So backtrack and try parsing as a type instead. */
6374 14 : mapper_id[0] = '\0';
6375 14 : gfc_current_locus = old_locus;
6376 : }
6377 27 : old_locus = gfc_current_locus;
6378 :
6379 27 : m = gfc_match_type_spec (&ts);
6380 27 : if (m != MATCH_YES)
6381 : {
6382 4 : gfc_error ("Expected either a type name at %L or a map-type "
6383 : "identifier, a colon, or a type name", &old_locus);
6384 4 : return MATCH_ERROR;
6385 : }
6386 :
6387 23 : if (ts.type != BT_DERIVED)
6388 : {
6389 1 : gfc_error ("!$OMP DECLARE MAPPER with non-derived type at %L", &old_locus);
6390 1 : return MATCH_ERROR;
6391 : }
6392 :
6393 22 : if (gfc_match (" :: ") != MATCH_YES)
6394 : {
6395 0 : gfc_error ("Expected %<::%> at %C");
6396 0 : return MATCH_ERROR;
6397 : }
6398 :
6399 22 : if (gfc_match_name (var) != MATCH_YES)
6400 : {
6401 1 : gfc_error ("Expected variable name at %C");
6402 1 : return MATCH_ERROR;
6403 : }
6404 :
6405 21 : if (gfc_match_char (')') != MATCH_YES)
6406 : {
6407 2 : gfc_error ("Expected %<)%> at %C");
6408 2 : return MATCH_ERROR;
6409 : }
6410 :
6411 19 : st = gfc_find_symtree (gfc_current_ns->omp_udm_root, mapper_id);
6412 :
6413 : /* Now we need to set up a new namespace, and create a new sym_tree for our
6414 : dummy variable so we can use it in the following list of mapping
6415 : clauses. */
6416 :
6417 19 : gfc_current_ns = mapper_ns = gfc_get_namespace (gfc_current_ns, 1);
6418 19 : mapper_ns->proc_name = mapper_ns->parent->proc_name;
6419 19 : mapper_ns->omp_udm_ns = 1;
6420 :
6421 19 : gfc_get_sym_tree (var, mapper_ns, &var_st, false);
6422 19 : var_st->n.sym->ts = ts;
6423 19 : var_st->n.sym->attr.omp_udm_artificial_var = 1;
6424 19 : var_st->n.sym->attr.flavor = FL_VARIABLE;
6425 19 : gfc_commit_symbols ();
6426 :
6427 19 : gfc_omp_clauses *clauses = NULL;
6428 :
6429 19 : m = gfc_match_omp_clauses (&clauses, omp_mask (OMP_CLAUSE_MAP), true, true,
6430 : false, false, OMP_MAP_UNSET);
6431 19 : if (m != MATCH_YES)
6432 1 : goto failure;
6433 :
6434 18 : omp_udm = gfc_get_omp_udm ();
6435 18 : omp_udm->next = NULL;
6436 18 : omp_udm->where = where;
6437 18 : omp_udm->mapper_id = gfc_get_string ("%s", mapper_id);
6438 18 : omp_udm->ts = ts;
6439 18 : omp_udm->var_sym = var_st->n.sym;
6440 18 : omp_udm->mapper_ns = mapper_ns;
6441 18 : omp_udm->clauses = clauses;
6442 :
6443 18 : gfc_current_ns = mapper_ns->parent;
6444 :
6445 18 : prev_udm = gfc_omp_udm_find (st, &ts);
6446 18 : if (prev_udm)
6447 : {
6448 2 : if (mapper_id[0])
6449 1 : gfc_error ("Redefinition of !$OMP DECLARE MAPPER at %L for type %qs with id %qs",
6450 : &where, gfc_typename (&ts), mapper_id);
6451 : else
6452 1 : gfc_error ("Redefinition of !$OMP DECLARE MAPPER at %L for type %qs",
6453 : &where, gfc_typename (&ts));
6454 2 : inform (gfc_get_location (&prev_udm->where),
6455 : "Previous !$OMP DECLARE MAPPER here");
6456 2 : return MATCH_ERROR;
6457 : }
6458 16 : else if (st)
6459 : {
6460 0 : omp_udm->next = st->n.omp_udm;
6461 0 : st->n.omp_udm = omp_udm;
6462 : }
6463 : else
6464 : {
6465 16 : st = gfc_new_symtree (&gfc_current_ns->omp_udm_root, mapper_id);
6466 16 : st->n.omp_udm = omp_udm;
6467 : }
6468 :
6469 : return MATCH_YES;
6470 :
6471 1 : failure:
6472 1 : if (mapper_ns)
6473 1 : gfc_current_ns = mapper_ns->parent;
6474 1 : gfc_free_omp_udm (omp_udm);
6475 :
6476 1 : return MATCH_ERROR;
6477 : }
6478 :
6479 : /* For 'declare reduction', matches either the combiner or initializer
6480 : expression, either can be an assignment of 'omp_sym1 = ...'
6481 : or a subroutine call, i.e. 'subroutine-name(argument-list)'. */
6482 :
6483 : static bool
6484 922 : match_udr_expr (gfc_symtree *omp_sym1, gfc_symtree *omp_sym2)
6485 : {
6486 922 : match m;
6487 922 : locus old_loc = gfc_current_locus;
6488 922 : char sname[GFC_MAX_SYMBOL_LEN + 1];
6489 922 : gfc_symbol *sym;
6490 922 : gfc_namespace *ns = gfc_current_ns;
6491 922 : gfc_expr *lvalue = NULL, *rvalue = NULL;
6492 922 : gfc_symtree *st;
6493 922 : gfc_actual_arglist *arglist;
6494 :
6495 922 : m = gfc_match (" %v =", &lvalue);
6496 922 : if (m != MATCH_YES)
6497 210 : gfc_current_locus = old_loc;
6498 : else
6499 : {
6500 712 : m = gfc_match (" %e )", &rvalue);
6501 712 : if (m == MATCH_YES)
6502 : {
6503 702 : ns->code = gfc_get_code (EXEC_ASSIGN);
6504 702 : ns->code->expr1 = lvalue;
6505 702 : ns->code->expr2 = rvalue;
6506 702 : ns->code->loc = old_loc;
6507 702 : return true;
6508 : }
6509 :
6510 10 : gfc_current_locus = old_loc;
6511 10 : gfc_free_expr (lvalue);
6512 : }
6513 :
6514 220 : m = gfc_match (" %n", sname);
6515 220 : if (m != MATCH_YES)
6516 4 : goto syntax;
6517 :
6518 216 : if (strcmp (sname, omp_sym1->name) == 0
6519 203 : || strcmp (sname, omp_sym2->name) == 0)
6520 14 : goto syntax;
6521 :
6522 202 : gfc_current_ns = ns->parent;
6523 202 : if (gfc_get_ha_sym_tree (sname, &st))
6524 0 : goto syntax;
6525 :
6526 202 : sym = st->n.sym;
6527 202 : if (sym->attr.flavor != FL_PROCEDURE
6528 74 : && sym->attr.flavor != FL_UNKNOWN)
6529 1 : goto syntax;
6530 :
6531 201 : if (!sym->attr.generic
6532 191 : && !sym->attr.subroutine
6533 73 : && !sym->attr.function)
6534 : {
6535 73 : if (!(sym->attr.external && !sym->attr.referenced))
6536 : {
6537 : /* ...create a symbol in this scope... */
6538 73 : if (sym->ns != gfc_current_ns
6539 73 : && gfc_get_sym_tree (sname, NULL, &st, false) == 1)
6540 0 : goto syntax;
6541 :
6542 73 : if (sym != st->n.sym)
6543 73 : sym = st->n.sym;
6544 : }
6545 :
6546 : /* ...and then to try to make the symbol into a subroutine. */
6547 73 : if (!gfc_add_subroutine (&sym->attr, sym->name, NULL))
6548 0 : goto syntax;
6549 : }
6550 :
6551 201 : gfc_set_sym_referenced (sym);
6552 201 : gfc_gobble_whitespace ();
6553 201 : if (gfc_peek_ascii_char () != '(')
6554 6 : goto syntax;
6555 :
6556 195 : gfc_current_ns = ns;
6557 195 : m = gfc_match_actual_arglist (1, &arglist);
6558 195 : if (m != MATCH_YES)
6559 0 : goto syntax;
6560 :
6561 195 : if (gfc_match_char (')') != MATCH_YES)
6562 0 : goto syntax;
6563 :
6564 195 : gfc_clear_error ();
6565 195 : ns->code = gfc_get_code (EXEC_CALL);
6566 195 : ns->code->symtree = st;
6567 195 : ns->code->ext.actual = arglist;
6568 195 : ns->code->loc = old_loc;
6569 195 : return true;
6570 25 : syntax:
6571 25 : gfc_clear_error ();
6572 25 : gfc_error ("Expected either %<%s = expr%> or %<subroutine-name(argument-list)"
6573 : "%> followed by %<)%> at %L", omp_sym1->name, &old_loc);
6574 25 : return false;
6575 : }
6576 :
6577 : static bool
6578 1203 : gfc_omp_udr_predef (gfc_omp_reduction_op rop, const char *name,
6579 : gfc_typespec *ts, const char **n)
6580 : {
6581 1203 : if (!gfc_numeric_ts (ts) && ts->type != BT_LOGICAL)
6582 : return false;
6583 :
6584 673 : switch (rop)
6585 : {
6586 19 : case OMP_REDUCTION_PLUS:
6587 19 : case OMP_REDUCTION_MINUS:
6588 19 : case OMP_REDUCTION_TIMES:
6589 19 : return ts->type != BT_LOGICAL;
6590 12 : case OMP_REDUCTION_AND:
6591 12 : case OMP_REDUCTION_OR:
6592 12 : case OMP_REDUCTION_EQV:
6593 12 : case OMP_REDUCTION_NEQV:
6594 12 : return ts->type == BT_LOGICAL;
6595 641 : case OMP_REDUCTION_USER:
6596 641 : if (name[0] != '.' && (ts->type == BT_INTEGER || ts->type == BT_REAL))
6597 : {
6598 569 : gfc_symbol *sym;
6599 :
6600 569 : gfc_find_symbol (name, NULL, 1, &sym);
6601 569 : if (sym != NULL)
6602 : {
6603 93 : if (sym->attr.intrinsic)
6604 0 : *n = sym->name;
6605 93 : else if ((sym->attr.flavor != FL_UNKNOWN
6606 81 : && sym->attr.flavor != FL_PROCEDURE)
6607 69 : || sym->attr.external
6608 54 : || sym->attr.generic
6609 54 : || sym->attr.entry
6610 54 : || sym->attr.result
6611 54 : || sym->attr.dummy
6612 54 : || sym->attr.subroutine
6613 50 : || sym->attr.pointer
6614 50 : || sym->attr.target
6615 50 : || sym->attr.cray_pointer
6616 50 : || sym->attr.cray_pointee
6617 50 : || (sym->attr.proc != PROC_UNKNOWN
6618 0 : && sym->attr.proc != PROC_INTRINSIC)
6619 50 : || sym->attr.if_source != IFSRC_UNKNOWN
6620 50 : || sym == sym->ns->proc_name)
6621 43 : *n = NULL;
6622 : else
6623 50 : *n = sym->name;
6624 : }
6625 : else
6626 476 : *n = name;
6627 569 : if (*n
6628 526 : && (strcmp (*n, "max") == 0 || strcmp (*n, "min") == 0))
6629 56 : return true;
6630 531 : else if (*n
6631 488 : && ts->type == BT_INTEGER
6632 402 : && (strcmp (*n, "iand") == 0
6633 396 : || strcmp (*n, "ior") == 0
6634 390 : || strcmp (*n, "ieor") == 0))
6635 : return true;
6636 : }
6637 : break;
6638 : default:
6639 : break;
6640 : }
6641 : return false;
6642 : }
6643 :
6644 : gfc_omp_udr *
6645 666 : gfc_omp_udr_find (gfc_symtree *st, gfc_typespec *ts)
6646 : {
6647 666 : gfc_omp_udr *omp_udr;
6648 :
6649 666 : if (st == NULL)
6650 : return NULL;
6651 :
6652 112 : gfc_symbol *dt = NULL;
6653 112 : if (ts->type == BT_DERIVED || ts->type == BT_CLASS)
6654 25 : dt = (ts->type == BT_CLASS
6655 0 : ? CLASS_DATA (ts->u.derived)->ts.u.derived : ts->u.derived);
6656 260 : for (omp_udr = st->n.omp_udr; omp_udr; omp_udr = omp_udr->next)
6657 161 : if (omp_udr->ts.type == ts->type
6658 91 : || (dt && omp_udr->ts.type == BT_DERIVED))
6659 : {
6660 70 : if (dt && omp_udr->ts.type == BT_DERIVED)
6661 : {
6662 15 : gfc_symbol *dtu = omp_udr->ts.u.derived;
6663 15 : if (dt == dtu)
6664 : return omp_udr;
6665 : /* Special case for comparing derived types across namespaces. If
6666 : the true names and module names are the same and the module name
6667 : is nonnull, then they are equal. */
6668 7 : if (dt->module && dtu->module
6669 1 : && strcmp (dt->name, dtu->name) == 0
6670 1 : && strcmp (dt->module, dtu->module) == 0)
6671 : return omp_udr;
6672 : }
6673 55 : else if (omp_udr->ts.kind == ts->kind)
6674 : {
6675 20 : if (omp_udr->ts.type == BT_CHARACTER)
6676 : {
6677 17 : if (omp_udr->ts.u.cl->length == NULL
6678 15 : || ts->u.cl->length == NULL)
6679 : return omp_udr;
6680 15 : if (omp_udr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
6681 : return omp_udr;
6682 15 : if (ts->u.cl->length->expr_type != EXPR_CONSTANT)
6683 : return omp_udr;
6684 15 : if (omp_udr->ts.u.cl->length->ts.type != BT_INTEGER)
6685 : return omp_udr;
6686 15 : if (ts->u.cl->length->ts.type != BT_INTEGER)
6687 : return omp_udr;
6688 15 : if (gfc_compare_expr (omp_udr->ts.u.cl->length,
6689 : ts->u.cl->length, INTRINSIC_EQ) != 0)
6690 15 : continue;
6691 : }
6692 3 : return omp_udr;
6693 : }
6694 : }
6695 : return NULL;
6696 : }
6697 :
6698 : match
6699 587 : gfc_match_omp_declare_reduction (void)
6700 : {
6701 587 : match m;
6702 587 : gfc_intrinsic_op op;
6703 587 : char name[GFC_MAX_SYMBOL_LEN + 3];
6704 587 : auto_vec<gfc_typespec, 5> tss;
6705 587 : gfc_typespec ts;
6706 587 : unsigned int i;
6707 587 : gfc_symtree *st;
6708 587 : locus where = gfc_current_locus;
6709 587 : locus end_loc = gfc_current_locus;
6710 587 : bool end_loc_set = false;
6711 587 : gfc_omp_reduction_op rop = OMP_REDUCTION_NONE;
6712 :
6713 587 : if (gfc_match_char ('(') != MATCH_YES)
6714 : {
6715 4 : gfc_error ("Expected %<(%> at %C");
6716 4 : return MATCH_ERROR;
6717 : }
6718 :
6719 583 : m = gfc_match (" %o : ", &op);
6720 583 : if (m == MATCH_ERROR)
6721 : return MATCH_ERROR;
6722 583 : if (m == MATCH_YES)
6723 : {
6724 142 : snprintf (name, sizeof name, "operator %s", gfc_op2string (op));
6725 142 : rop = (gfc_omp_reduction_op) op;
6726 : }
6727 : else
6728 : {
6729 441 : m = gfc_match_defined_op_name (name + 1, 1);
6730 441 : if (m == MATCH_ERROR)
6731 : return MATCH_ERROR;
6732 440 : if (m == MATCH_YES)
6733 : {
6734 41 : name[0] = '.';
6735 41 : strcat (name, ".");
6736 41 : if (gfc_match (" : ") != MATCH_YES)
6737 : {
6738 0 : gfc_error ("Expected %<:%> at %C");
6739 0 : return MATCH_ERROR;
6740 : }
6741 : }
6742 : else
6743 : {
6744 399 : if (gfc_match (" %n : ", name) != MATCH_YES)
6745 : {
6746 4 : gfc_error ("Expected an identfifier or operator as reduction "
6747 : "identifier followed by a colon at %C");
6748 4 : return MATCH_ERROR;
6749 : }
6750 : }
6751 : rop = OMP_REDUCTION_USER;
6752 : }
6753 :
6754 578 : m = gfc_match_type_spec (&ts);
6755 578 : if (m != MATCH_YES)
6756 : {
6757 4 : gfc_error ("Expected type spec at %C");
6758 4 : return MATCH_ERROR;
6759 : }
6760 : /* Treat len=: the same as len=*. */
6761 574 : if (ts.type == BT_CHARACTER)
6762 61 : ts.deferred = false;
6763 574 : tss.safe_push (ts);
6764 :
6765 1189 : while (gfc_match_char (',') == MATCH_YES)
6766 : {
6767 42 : m = gfc_match_type_spec (&ts);
6768 42 : if (m != MATCH_YES)
6769 : {
6770 1 : gfc_error ("Expected type spec at %C");
6771 1 : return MATCH_ERROR;
6772 : }
6773 41 : tss.safe_push (ts);
6774 : }
6775 573 : if (gfc_match_char (':') != MATCH_YES)
6776 : {
6777 6 : gfc_error ("Expected %<:%> or %<,%> at %C");
6778 6 : return MATCH_ERROR;
6779 : }
6780 :
6781 567 : st = gfc_find_symtree (gfc_current_ns->omp_udr_root, name);
6782 1111 : for (i = 0; i < tss.length (); i++)
6783 : {
6784 603 : gfc_symtree *omp_out, *omp_in;
6785 603 : gfc_symtree *omp_priv = NULL, *omp_orig = NULL;
6786 603 : gfc_namespace *combiner_ns, *initializer_ns = NULL;
6787 603 : gfc_omp_udr *prev_udr, *omp_udr;
6788 603 : const char *predef_name = NULL;
6789 :
6790 603 : omp_udr = gfc_get_omp_udr ();
6791 603 : omp_udr->name = gfc_get_string ("%s", name);
6792 603 : omp_udr->rop = rop;
6793 603 : omp_udr->ts = tss[i];
6794 603 : omp_udr->where = where;
6795 :
6796 603 : gfc_current_ns = combiner_ns = gfc_get_namespace (gfc_current_ns, 1);
6797 603 : combiner_ns->proc_name = combiner_ns->parent->proc_name;
6798 :
6799 603 : gfc_get_sym_tree ("omp_out", combiner_ns, &omp_out, false);
6800 603 : gfc_get_sym_tree ("omp_in", combiner_ns, &omp_in, false);
6801 603 : combiner_ns->omp_udr_ns = 1;
6802 603 : omp_out->n.sym->ts = tss[i];
6803 603 : omp_in->n.sym->ts = tss[i];
6804 603 : omp_out->n.sym->attr.omp_udr_artificial_var = 1;
6805 603 : omp_in->n.sym->attr.omp_udr_artificial_var = 1;
6806 603 : omp_out->n.sym->attr.flavor = FL_VARIABLE;
6807 603 : omp_in->n.sym->attr.flavor = FL_VARIABLE;
6808 603 : gfc_commit_symbols ();
6809 603 : omp_udr->combiner_ns = combiner_ns;
6810 603 : omp_udr->omp_out = omp_out->n.sym;
6811 603 : omp_udr->omp_in = omp_in->n.sym;
6812 :
6813 603 : locus old_loc = gfc_current_locus;
6814 :
6815 603 : if (!match_udr_expr (omp_out, omp_in))
6816 : {
6817 19 : syntax:
6818 59 : gfc_current_ns = combiner_ns->parent;
6819 59 : gfc_undo_symbols ();
6820 59 : gfc_free_omp_udr (omp_udr);
6821 59 : return MATCH_ERROR;
6822 : }
6823 :
6824 584 : if (gfc_match (" initializer ( ") == MATCH_YES)
6825 : {
6826 319 : gfc_current_ns = combiner_ns->parent;
6827 319 : initializer_ns = gfc_get_namespace (gfc_current_ns, 1);
6828 319 : gfc_current_ns = initializer_ns;
6829 319 : initializer_ns->proc_name = initializer_ns->parent->proc_name;
6830 :
6831 319 : gfc_get_sym_tree ("omp_priv", initializer_ns, &omp_priv, false);
6832 319 : gfc_get_sym_tree ("omp_orig", initializer_ns, &omp_orig, false);
6833 319 : initializer_ns->omp_udr_ns = 1;
6834 319 : omp_priv->n.sym->ts = tss[i];
6835 319 : omp_orig->n.sym->ts = tss[i];
6836 319 : omp_priv->n.sym->attr.omp_udr_artificial_var = 1;
6837 319 : omp_orig->n.sym->attr.omp_udr_artificial_var = 1;
6838 319 : omp_priv->n.sym->attr.flavor = FL_VARIABLE;
6839 319 : omp_orig->n.sym->attr.flavor = FL_VARIABLE;
6840 319 : gfc_commit_symbols ();
6841 319 : omp_udr->initializer_ns = initializer_ns;
6842 319 : omp_udr->omp_priv = omp_priv->n.sym;
6843 319 : omp_udr->omp_orig = omp_orig->n.sym;
6844 :
6845 319 : if (!match_udr_expr (omp_priv, omp_orig))
6846 6 : goto syntax;
6847 : }
6848 :
6849 578 : gfc_current_ns = combiner_ns->parent;
6850 578 : if (!end_loc_set)
6851 : {
6852 542 : end_loc_set = true;
6853 542 : end_loc = gfc_current_locus;
6854 : }
6855 578 : gfc_current_locus = old_loc;
6856 :
6857 578 : prev_udr = gfc_omp_udr_find (st, &tss[i]);
6858 578 : if (gfc_omp_udr_predef (rop, name, &tss[i], &predef_name)
6859 : /* Don't error on !$omp declare reduction (min : integer : ...)
6860 : just yet, there could be integer :: min afterwards,
6861 : making it valid. When the UDR is resolved, we'll get
6862 : to it again. */
6863 578 : && (rop != OMP_REDUCTION_USER || name[0] == '.'))
6864 : {
6865 27 : if (predef_name)
6866 0 : gfc_error_now ("Redefinition of predefined %qs in "
6867 : "!$OMP DECLARE REDUCTION at %L",
6868 : predef_name, &where);
6869 : else
6870 27 : gfc_error_now ("Redefinition of predefined %qs in "
6871 : "!$OMP DECLARE REDUCTION at %L", name, &where);
6872 27 : goto syntax;
6873 : }
6874 551 : else if (prev_udr)
6875 : {
6876 7 : gfc_error_now ("Redefinition of %qs in !$OMP DECLARE REDUCTION at %L",
6877 : name, &where);
6878 7 : inform (gfc_get_location (&prev_udr->where),
6879 : "Previous !$OMP DECLARE REDUCTION");
6880 7 : goto syntax;
6881 : }
6882 544 : else if (st)
6883 : {
6884 98 : omp_udr->next = st->n.omp_udr;
6885 98 : st->n.omp_udr = omp_udr;
6886 : }
6887 : else
6888 : {
6889 446 : st = gfc_new_symtree (&gfc_current_ns->omp_udr_root, name);
6890 446 : st->n.omp_udr = omp_udr;
6891 : }
6892 : }
6893 :
6894 508 : if (end_loc_set)
6895 : {
6896 508 : gfc_current_locus = end_loc;
6897 508 : if (gfc_match_omp_eos () != MATCH_YES)
6898 : {
6899 4 : gfc_error ("Unexpected junk at %C");
6900 4 : return MATCH_ERROR;
6901 : }
6902 : return MATCH_YES;
6903 : }
6904 : return MATCH_ERROR;
6905 587 : }
6906 :
6907 :
6908 : match
6909 472 : gfc_match_omp_declare_target (void)
6910 : {
6911 472 : locus old_loc;
6912 472 : match m;
6913 472 : gfc_omp_clauses *c = NULL;
6914 472 : enum gfc_omp_list_type list;
6915 472 : gfc_omp_namelist *n;
6916 472 : gfc_symbol *s;
6917 :
6918 472 : old_loc = gfc_current_locus;
6919 :
6920 472 : if (gfc_current_ns->proc_name
6921 472 : && gfc_match_omp_eos () == MATCH_YES)
6922 : {
6923 138 : if (!gfc_add_omp_declare_target (&gfc_current_ns->proc_name->attr,
6924 138 : gfc_current_ns->proc_name->name,
6925 : &old_loc))
6926 0 : goto cleanup;
6927 : return MATCH_YES;
6928 : }
6929 :
6930 334 : if (gfc_current_ns->proc_name
6931 334 : && gfc_current_ns->proc_name->attr.if_source == IFSRC_IFBODY)
6932 : {
6933 2 : gfc_error ("Only the !$OMP DECLARE TARGET form without "
6934 : "clauses is allowed in interface block at %C");
6935 2 : goto cleanup;
6936 : }
6937 :
6938 332 : m = gfc_match (" (");
6939 332 : if (m == MATCH_YES)
6940 : {
6941 86 : c = gfc_get_omp_clauses ();
6942 86 : gfc_current_locus = old_loc;
6943 86 : m = gfc_match_omp_to_link (" (", &c->lists[OMP_LIST_ENTER]);
6944 86 : if (m != MATCH_YES)
6945 0 : goto syntax;
6946 86 : if (gfc_match_omp_eos () != MATCH_YES)
6947 : {
6948 0 : gfc_error ("Unexpected junk after !$OMP DECLARE TARGET at %C");
6949 0 : goto cleanup;
6950 : }
6951 : }
6952 246 : else if (gfc_match_omp_clauses (&c, OMP_DECLARE_TARGET_CLAUSES) != MATCH_YES)
6953 : return MATCH_ERROR;
6954 :
6955 326 : gfc_buffer_error (false);
6956 :
6957 326 : static const enum gfc_omp_list_type to_enter_link_lists[]
6958 : = { OMP_LIST_TO, OMP_LIST_ENTER, OMP_LIST_LINK, OMP_LIST_LOCAL };
6959 1630 : for (size_t listn = 0; listn < ARRAY_SIZE (to_enter_link_lists)
6960 1630 : && (list = to_enter_link_lists[listn], true); ++listn)
6961 1849 : for (n = c->lists[list]; n; n = n->next)
6962 545 : if (n->sym)
6963 504 : n->sym->mark = 0;
6964 41 : else if (n->u.common->head)
6965 41 : n->u.common->head->mark = 0;
6966 :
6967 326 : if (c->device_type == OMP_DEVICE_TYPE_UNSET)
6968 258 : c->device_type = OMP_DEVICE_TYPE_ANY;
6969 1304 : for (size_t listn = 0; listn < ARRAY_SIZE (to_enter_link_lists)
6970 1630 : && (list = to_enter_link_lists[listn], true); ++listn)
6971 1849 : for (n = c->lists[list]; n; n = n->next)
6972 545 : if (n->sym)
6973 : {
6974 504 : if (n->sym->attr.in_common)
6975 1 : gfc_error_now ("OMP DECLARE TARGET variable at %L is an "
6976 : "element of a COMMON block", &n->where);
6977 503 : else if (n->sym->attr.omp_groupprivate && list != OMP_LIST_LOCAL)
6978 12 : gfc_error_now ("List item %qs at %L not appear in the %qs clause "
6979 : "as it was previously specified in a GROUPPRIVATE "
6980 : "directive", n->sym->name, &n->where,
6981 : list == OMP_LIST_LINK
6982 5 : ? "link" : list == OMP_LIST_TO ? "to" : "enter");
6983 496 : else if (n->sym->mark)
6984 9 : gfc_error_now ("Variable at %L mentioned multiple times in "
6985 : "clauses of the same OMP DECLARE TARGET directive",
6986 : &n->where);
6987 487 : else if ((n->sym->attr.omp_declare_target_link
6988 482 : || n->sym->attr.omp_declare_target_local)
6989 : && list != OMP_LIST_LINK
6990 7 : && list != OMP_LIST_LOCAL)
6991 1 : gfc_error_now ("OMP DECLARE TARGET variable at %L previously "
6992 : "mentioned in %s clause and later in %s clause",
6993 : &n->where,
6994 : n->sym->attr.omp_declare_target_link ? "LINK"
6995 : : "LOCAL",
6996 : list == OMP_LIST_TO ? "TO" : "ENTER");
6997 486 : else if (n->sym->attr.omp_declare_target
6998 14 : && (list == OMP_LIST_LINK || list == OMP_LIST_LOCAL))
6999 1 : gfc_error_now ("OMP DECLARE TARGET variable at %L previously "
7000 : "mentioned in TO or ENTER clause and later in "
7001 : "%s clause", &n->where,
7002 : list == OMP_LIST_LINK ? "LINK" : "LOCAL");
7003 : else
7004 : {
7005 485 : if (list == OMP_LIST_TO || list == OMP_LIST_ENTER)
7006 446 : gfc_add_omp_declare_target (&n->sym->attr, n->sym->name,
7007 : &n->sym->declared_at);
7008 485 : if (list == OMP_LIST_LINK)
7009 30 : gfc_add_omp_declare_target_link (&n->sym->attr, n->sym->name,
7010 30 : &n->sym->declared_at);
7011 485 : if (list == OMP_LIST_LOCAL)
7012 9 : gfc_add_omp_declare_target_local (&n->sym->attr, n->sym->name,
7013 9 : &n->sym->declared_at);
7014 : }
7015 504 : if (n->sym->attr.omp_device_type != OMP_DEVICE_TYPE_UNSET
7016 36 : && n->sym->attr.omp_device_type != c->device_type)
7017 : {
7018 12 : const char *dt = "any";
7019 12 : if (n->sym->attr.omp_device_type == OMP_DEVICE_TYPE_NOHOST)
7020 : dt = "nohost";
7021 8 : else if (n->sym->attr.omp_device_type == OMP_DEVICE_TYPE_HOST)
7022 4 : dt = "host";
7023 12 : if (n->sym->attr.omp_groupprivate)
7024 1 : gfc_error_now ("List item %qs at %L set in previous OMP "
7025 : "GROUPPRIVATE directive to the different "
7026 : "DEVICE_TYPE %qs", n->sym->name, &n->where, dt);
7027 : else
7028 11 : gfc_error_now ("List item %qs at %L set in previous OMP "
7029 : "DECLARE TARGET directive to the different "
7030 : "DEVICE_TYPE %qs", n->sym->name, &n->where, dt);
7031 : }
7032 504 : n->sym->attr.omp_device_type = c->device_type;
7033 504 : if (c->indirect && c->device_type != OMP_DEVICE_TYPE_ANY)
7034 : {
7035 1 : gfc_error_now ("DEVICE_TYPE must be ANY when used with INDIRECT "
7036 : "at %L", &n->where);
7037 1 : c->indirect = 0;
7038 : }
7039 504 : n->sym->attr.omp_declare_target_indirect = c->indirect;
7040 504 : if (list == OMP_LIST_LINK && c->device_type == OMP_DEVICE_TYPE_NOHOST)
7041 3 : gfc_error_now ("List item %qs at %L set with NOHOST specified may "
7042 : "not appear in a LINK clause", n->sym->name,
7043 : &n->where);
7044 504 : n->sym->mark = 1;
7045 : }
7046 : else /* common block */
7047 : {
7048 41 : if (n->u.common->omp_groupprivate && list != OMP_LIST_LOCAL)
7049 7 : gfc_error_now ("Common block %</%s/%> at %L not appear in the %qs "
7050 : "clause as it was previously specified in a "
7051 : "GROUPPRIVATE directive",
7052 7 : n->u.common->name, &n->where,
7053 : list == OMP_LIST_LINK
7054 5 : ? "link" : list == OMP_LIST_TO ? "to" : "enter");
7055 34 : else if (n->u.common->head && n->u.common->head->mark)
7056 4 : gfc_error_now ("Common block %</%s/%> at %L mentioned multiple "
7057 : "times in clauses of the same OMP DECLARE TARGET "
7058 4 : "directive", n->u.common->name, &n->where);
7059 30 : else if ((n->u.common->omp_declare_target_link
7060 26 : || n->u.common->omp_declare_target_local)
7061 : && list != OMP_LIST_LINK
7062 6 : && list != OMP_LIST_LOCAL)
7063 2 : gfc_error_now ("Common block %</%s/%> at %L previously mentioned "
7064 : "in %s clause and later in %s clause",
7065 1 : n->u.common->name, &n->where,
7066 : n->u.common->omp_declare_target_link ? "LINK"
7067 : : "LOCAL",
7068 : list == OMP_LIST_TO ? "TO" : "ENTER");
7069 29 : else if (n->u.common->omp_declare_target
7070 4 : && (list == OMP_LIST_LINK || list == OMP_LIST_LOCAL))
7071 1 : gfc_error_now ("Common block %</%s/%> at %L previously mentioned "
7072 : "in TO or ENTER clause and later in %s clause",
7073 1 : n->u.common->name, &n->where,
7074 : list == OMP_LIST_LINK ? "LINK" : "LOCAL");
7075 41 : if (n->u.common->omp_device_type != OMP_DEVICE_TYPE_UNSET
7076 21 : && n->u.common->omp_device_type != c->device_type)
7077 : {
7078 1 : const char *dt = "any";
7079 1 : if (n->u.common->omp_device_type == OMP_DEVICE_TYPE_NOHOST)
7080 : dt = "nohost";
7081 0 : else if (n->u.common->omp_device_type == OMP_DEVICE_TYPE_HOST)
7082 0 : dt = "host";
7083 1 : if (n->u.common->omp_groupprivate)
7084 1 : gfc_error_now ("Common block %</%s/%> at %L set in previous OMP "
7085 : "GROUPPRIVATE directive to the different "
7086 1 : "DEVICE_TYPE %qs", n->u.common->name, &n->where,
7087 : dt);
7088 : else
7089 0 : gfc_error_now ("Common block %</%s/%> at %L set in previous OMP "
7090 : "DECLARE TARGET directive to the different "
7091 0 : "DEVICE_TYPE %qs", n->u.common->name, &n->where,
7092 : dt);
7093 : }
7094 41 : n->u.common->omp_device_type = c->device_type;
7095 :
7096 41 : if (c->indirect && c->device_type != OMP_DEVICE_TYPE_ANY)
7097 : {
7098 0 : gfc_error_now ("DEVICE_TYPE must be ANY when used with INDIRECT "
7099 : "at %L", &n->where);
7100 0 : c->indirect = 0;
7101 : }
7102 41 : if (list == OMP_LIST_LINK && c->device_type == OMP_DEVICE_TYPE_NOHOST)
7103 1 : gfc_error_now ("Common block %</%s/%> at %L set with NOHOST "
7104 : "specified may not appear in a LINK clause",
7105 1 : n->u.common->name, &n->where);
7106 :
7107 41 : if (list == OMP_LIST_TO || list == OMP_LIST_ENTER)
7108 21 : n->u.common->omp_declare_target = 1;
7109 41 : if (list == OMP_LIST_LINK)
7110 15 : n->u.common->omp_declare_target_link = 1;
7111 41 : if (list == OMP_LIST_LOCAL)
7112 5 : n->u.common->omp_declare_target_local = 1;
7113 :
7114 110 : for (s = n->u.common->head; s; s = s->common_next)
7115 : {
7116 69 : s->mark = 1;
7117 69 : if (list == OMP_LIST_TO || list == OMP_LIST_ENTER)
7118 33 : gfc_add_omp_declare_target (&s->attr, s->name, &n->where);
7119 69 : if (list == OMP_LIST_LINK)
7120 31 : gfc_add_omp_declare_target_link (&s->attr, s->name, &n->where);
7121 69 : if (list == OMP_LIST_LOCAL)
7122 5 : gfc_add_omp_declare_target_local (&s->attr, s->name, &n->where);
7123 69 : s->attr.omp_device_type = c->device_type;
7124 69 : s->attr.omp_declare_target_indirect = c->indirect;
7125 : }
7126 : }
7127 326 : if ((c->device_type || c->indirect)
7128 326 : && !c->lists[OMP_LIST_ENTER]
7129 151 : && !c->lists[OMP_LIST_TO]
7130 47 : && !c->lists[OMP_LIST_LINK]
7131 10 : && !c->lists[OMP_LIST_LOCAL])
7132 2 : gfc_warning_now (OPT_Wopenmp,
7133 : "OMP DECLARE TARGET directive at %L with only "
7134 : "DEVICE_TYPE or INDIRECT clauses is ignored",
7135 : &old_loc);
7136 :
7137 326 : gfc_buffer_error (true);
7138 :
7139 326 : if (c)
7140 326 : gfc_free_omp_clauses (c);
7141 326 : return MATCH_YES;
7142 :
7143 0 : syntax:
7144 0 : gfc_error ("Syntax error in !$OMP DECLARE TARGET list at %C");
7145 :
7146 2 : cleanup:
7147 2 : gfc_current_locus = old_loc;
7148 2 : if (c)
7149 0 : gfc_free_omp_clauses (c);
7150 : return MATCH_ERROR;
7151 : }
7152 :
7153 : /* Skip over and ignore trait-property-extensions.
7154 :
7155 : trait-property-extension :
7156 : trait-property-name
7157 : identifier (trait-property-extension[, trait-property-extension[, ...]])
7158 : constant integer expression
7159 : */
7160 :
7161 : static match gfc_ignore_trait_property_extension_list (void);
7162 :
7163 : static match
7164 7 : gfc_ignore_trait_property_extension (void)
7165 : {
7166 7 : char buf[GFC_MAX_SYMBOL_LEN + 1];
7167 7 : gfc_expr *expr;
7168 :
7169 : /* Identifier form of trait-property name, possibly followed by
7170 : a list of (recursive) trait-property-extensions. */
7171 7 : if (gfc_match_name (buf) == MATCH_YES)
7172 : {
7173 0 : if (gfc_match (" (") == MATCH_YES)
7174 0 : return gfc_ignore_trait_property_extension_list ();
7175 : return MATCH_YES;
7176 : }
7177 :
7178 : /* Literal constant. */
7179 7 : if (gfc_match_literal_constant (&expr, 0) == MATCH_YES)
7180 : return MATCH_YES;
7181 :
7182 : /* FIXME: constant integer expressions. */
7183 0 : gfc_error ("Expected trait-property-extension at %C");
7184 0 : return MATCH_ERROR;
7185 : }
7186 :
7187 : static match
7188 5 : gfc_ignore_trait_property_extension_list (void)
7189 : {
7190 9 : while (1)
7191 : {
7192 7 : if (gfc_ignore_trait_property_extension () != MATCH_YES)
7193 : return MATCH_ERROR;
7194 7 : if (gfc_match (" ,") == MATCH_YES)
7195 2 : continue;
7196 5 : if (gfc_match (" )") == MATCH_YES)
7197 : return MATCH_YES;
7198 0 : gfc_error ("expected %<)%> at %C");
7199 0 : return MATCH_ERROR;
7200 : }
7201 : }
7202 :
7203 :
7204 : match
7205 110 : gfc_match_omp_interop (void)
7206 : {
7207 110 : return match_omp (EXEC_OMP_INTEROP, OMP_INTEROP_CLAUSES);
7208 : }
7209 :
7210 :
7211 : /* OpenMP 5.0:
7212 :
7213 : trait-selector:
7214 : trait-selector-name[([trait-score:]trait-property[,trait-property[,...]])]
7215 :
7216 : trait-score:
7217 : score(score-expression) */
7218 :
7219 : static match
7220 637 : gfc_match_omp_context_selector (gfc_omp_set_selector *oss)
7221 : {
7222 775 : do
7223 : {
7224 775 : char selector[GFC_MAX_SYMBOL_LEN + 1];
7225 :
7226 775 : if (gfc_match_name (selector) != MATCH_YES)
7227 : {
7228 2 : gfc_error ("expected trait selector name at %C");
7229 39 : return MATCH_ERROR;
7230 : }
7231 :
7232 773 : gfc_omp_selector *os = gfc_get_omp_selector ();
7233 773 : if (oss->code == OMP_TRAIT_SET_CONSTRUCT
7234 335 : && !strcmp (selector, "do"))
7235 48 : os->code = OMP_TRAIT_CONSTRUCT_FOR;
7236 725 : else if (oss->code == OMP_TRAIT_SET_CONSTRUCT
7237 287 : && !strcmp (selector, "for"))
7238 1 : os->code = OMP_TRAIT_INVALID;
7239 : else
7240 724 : os->code = omp_lookup_ts_code (oss->code, selector);
7241 773 : os->next = oss->trait_selectors;
7242 773 : oss->trait_selectors = os;
7243 :
7244 773 : if (os->code == OMP_TRAIT_INVALID)
7245 : {
7246 18 : gfc_warning (OPT_Wopenmp,
7247 : "unknown selector %qs for context selector set %qs "
7248 : "at %C",
7249 18 : selector, omp_tss_map[oss->code]);
7250 18 : if (gfc_match (" (") == MATCH_YES
7251 18 : && gfc_ignore_trait_property_extension_list () != MATCH_YES)
7252 : return MATCH_ERROR;
7253 18 : if (gfc_match (" ,") == MATCH_YES)
7254 1 : continue;
7255 598 : break;
7256 : }
7257 :
7258 755 : enum omp_tp_type property_kind = omp_ts_map[os->code].tp_type;
7259 755 : bool allow_score = omp_ts_map[os->code].allow_score;
7260 :
7261 755 : if (gfc_match (" (") == MATCH_YES)
7262 : {
7263 431 : if (property_kind == OMP_TRAIT_PROPERTY_NONE)
7264 : {
7265 6 : gfc_error ("selector %qs does not accept any properties at %C",
7266 : selector);
7267 6 : return MATCH_ERROR;
7268 : }
7269 :
7270 425 : if (gfc_match (" score") == MATCH_YES)
7271 : {
7272 63 : if (!allow_score)
7273 : {
7274 10 : gfc_error ("%<score%> cannot be specified in traits "
7275 : "in the %qs trait-selector-set at %C",
7276 10 : omp_tss_map[oss->code]);
7277 10 : return MATCH_ERROR;
7278 : }
7279 53 : if (gfc_match (" (") != MATCH_YES)
7280 : {
7281 0 : gfc_error ("expected %<(%> at %C");
7282 0 : return MATCH_ERROR;
7283 : }
7284 53 : if (gfc_match_expr (&os->score) != MATCH_YES)
7285 : return MATCH_ERROR;
7286 :
7287 52 : if (gfc_match (" )") != MATCH_YES)
7288 : {
7289 0 : gfc_error ("expected %<)%> at %C");
7290 0 : return MATCH_ERROR;
7291 : }
7292 :
7293 52 : if (gfc_match (" :") != MATCH_YES)
7294 : {
7295 0 : gfc_error ("expected : at %C");
7296 0 : return MATCH_ERROR;
7297 : }
7298 : }
7299 :
7300 414 : gfc_omp_trait_property *otp = gfc_get_omp_trait_property ();
7301 414 : otp->property_kind = property_kind;
7302 414 : otp->next = os->properties;
7303 414 : os->properties = otp;
7304 :
7305 414 : switch (property_kind)
7306 : {
7307 25 : case OMP_TRAIT_PROPERTY_ID:
7308 25 : {
7309 25 : char buf[GFC_MAX_SYMBOL_LEN + 1];
7310 25 : if (gfc_match_name (buf) == MATCH_YES)
7311 : {
7312 24 : otp->name = XNEWVEC (char, strlen (buf) + 1);
7313 24 : strcpy (otp->name, buf);
7314 : }
7315 : else
7316 : {
7317 1 : gfc_error ("expected identifier at %C");
7318 1 : free (otp);
7319 1 : os->properties = nullptr;
7320 1 : return MATCH_ERROR;
7321 : }
7322 : }
7323 24 : break;
7324 290 : case OMP_TRAIT_PROPERTY_NAME_LIST:
7325 343 : do
7326 : {
7327 290 : char buf[GFC_MAX_SYMBOL_LEN + 1];
7328 290 : if (gfc_match_name (buf) == MATCH_YES)
7329 : {
7330 170 : otp->name = XNEWVEC (char, strlen (buf) + 1);
7331 170 : strcpy (otp->name, buf);
7332 170 : otp->is_name = true;
7333 : }
7334 120 : else if (gfc_match_literal_constant (&otp->expr, 0)
7335 : != MATCH_YES
7336 120 : || otp->expr->ts.type != BT_CHARACTER)
7337 : {
7338 5 : gfc_error ("expected identifier or string literal "
7339 : "at %C");
7340 5 : free (otp);
7341 5 : os->properties = nullptr;
7342 5 : return MATCH_ERROR;
7343 : }
7344 :
7345 285 : if (gfc_match (" ,") == MATCH_YES)
7346 : {
7347 53 : otp = gfc_get_omp_trait_property ();
7348 53 : otp->property_kind = property_kind;
7349 53 : otp->next = os->properties;
7350 53 : os->properties = otp;
7351 : }
7352 : else
7353 : break;
7354 53 : }
7355 : while (1);
7356 232 : break;
7357 137 : case OMP_TRAIT_PROPERTY_DEV_NUM_EXPR:
7358 137 : case OMP_TRAIT_PROPERTY_BOOL_EXPR:
7359 137 : if (gfc_match_expr (&otp->expr) != MATCH_YES)
7360 : {
7361 3 : gfc_error ("expected expression at %C");
7362 3 : free (otp);
7363 3 : os->properties = nullptr;
7364 3 : return MATCH_ERROR;
7365 : }
7366 : break;
7367 15 : case OMP_TRAIT_PROPERTY_CLAUSE_LIST:
7368 15 : {
7369 15 : if (os->code == OMP_TRAIT_CONSTRUCT_SIMD)
7370 : {
7371 15 : gfc_matching_omp_context_selector = true;
7372 15 : if (gfc_match_omp_clauses (&otp->clauses,
7373 15 : OMP_DECLARE_SIMD_CLAUSES,
7374 : true, false, false)
7375 : != MATCH_YES)
7376 : {
7377 1 : gfc_matching_omp_context_selector = false;
7378 1 : gfc_error ("expected simd clause at %C");
7379 1 : return MATCH_ERROR;
7380 : }
7381 14 : gfc_matching_omp_context_selector = false;
7382 : }
7383 0 : else if (os->code == OMP_TRAIT_IMPLEMENTATION_REQUIRES)
7384 : {
7385 : /* FIXME: The "requires" selector was added in OpenMP 5.1.
7386 : Currently only the now-deprecated syntax
7387 : from OpenMP 5.0 is supported.
7388 : TODO: When implementing, update modules.cc as well. */
7389 0 : sorry_at (gfc_get_location (&gfc_current_locus),
7390 : "%<requires%> selector is not supported yet");
7391 0 : return MATCH_ERROR;
7392 : }
7393 : else
7394 0 : gcc_unreachable ();
7395 14 : break;
7396 : }
7397 0 : default:
7398 0 : gcc_unreachable ();
7399 : }
7400 :
7401 404 : if (gfc_match (" )") != MATCH_YES)
7402 : {
7403 2 : gfc_error ("expected %<)%> at %C");
7404 2 : return MATCH_ERROR;
7405 : }
7406 : }
7407 324 : else if (property_kind != OMP_TRAIT_PROPERTY_NONE
7408 324 : && property_kind != OMP_TRAIT_PROPERTY_CLAUSE_LIST
7409 8 : && property_kind != OMP_TRAIT_PROPERTY_EXTENSION)
7410 : {
7411 8 : if (gfc_match (" (") != MATCH_YES)
7412 : {
7413 8 : gfc_error ("expected %<(%> at %C");
7414 8 : return MATCH_ERROR;
7415 : }
7416 : }
7417 :
7418 718 : if (gfc_match (" ,") != MATCH_YES)
7419 : break;
7420 : }
7421 : while (1);
7422 :
7423 598 : return MATCH_YES;
7424 : }
7425 :
7426 : /* OpenMP 5.0:
7427 :
7428 : trait-set-selector[,trait-set-selector[,...]]
7429 :
7430 : trait-set-selector:
7431 : trait-set-selector-name = { trait-selector[, trait-selector[, ...]] }
7432 :
7433 : trait-set-selector-name:
7434 : constructor
7435 : device
7436 : implementation
7437 : user */
7438 :
7439 : static match
7440 577 : gfc_match_omp_context_selector_specification (gfc_omp_set_selector **oss_head)
7441 : {
7442 713 : do
7443 : {
7444 645 : match m;
7445 645 : char buf[GFC_MAX_SYMBOL_LEN + 1];
7446 645 : enum omp_tss_code set = OMP_TRAIT_SET_INVALID;
7447 :
7448 645 : m = gfc_match_name (buf);
7449 645 : if (m == MATCH_YES)
7450 643 : set = omp_lookup_tss_code (buf);
7451 :
7452 643 : if (set == OMP_TRAIT_SET_INVALID)
7453 : {
7454 5 : gfc_error ("expected context selector set name at %C");
7455 47 : return MATCH_ERROR;
7456 : }
7457 :
7458 640 : m = gfc_match (" =");
7459 640 : if (m != MATCH_YES)
7460 : {
7461 1 : gfc_error ("expected %<=%> at %C");
7462 1 : return MATCH_ERROR;
7463 : }
7464 :
7465 639 : m = gfc_match (" {");
7466 639 : if (m != MATCH_YES)
7467 : {
7468 2 : gfc_error ("expected %<{%> at %C");
7469 2 : return MATCH_ERROR;
7470 : }
7471 :
7472 637 : gfc_omp_set_selector *oss = gfc_get_omp_set_selector ();
7473 637 : oss->next = *oss_head;
7474 637 : oss->code = set;
7475 637 : *oss_head = oss;
7476 :
7477 637 : if (gfc_match_omp_context_selector (oss) != MATCH_YES)
7478 : return MATCH_ERROR;
7479 :
7480 598 : m = gfc_match (" }");
7481 598 : if (m != MATCH_YES)
7482 : {
7483 0 : gfc_error ("expected %<}%> at %C");
7484 0 : return MATCH_ERROR;
7485 : }
7486 :
7487 598 : m = gfc_match (" ,");
7488 598 : if (m != MATCH_YES)
7489 : break;
7490 68 : }
7491 : while (1);
7492 :
7493 530 : return MATCH_YES;
7494 : }
7495 :
7496 :
7497 : match
7498 419 : gfc_match_omp_declare_variant (void)
7499 : {
7500 419 : char buf[GFC_MAX_SYMBOL_LEN + 1];
7501 :
7502 419 : if (gfc_match (" (") != MATCH_YES)
7503 : {
7504 2 : gfc_error ("expected %<(%> at %C");
7505 2 : return MATCH_ERROR;
7506 : }
7507 :
7508 417 : gfc_symtree *base_proc_st, *variant_proc_st;
7509 417 : if (gfc_match_name (buf) != MATCH_YES)
7510 : {
7511 2 : gfc_error ("expected name at %C");
7512 2 : return MATCH_ERROR;
7513 : }
7514 :
7515 415 : if (gfc_get_ha_sym_tree (buf, &base_proc_st))
7516 : return MATCH_ERROR;
7517 :
7518 415 : if (gfc_match (" :") == MATCH_YES)
7519 : {
7520 16 : if (gfc_match_name (buf) != MATCH_YES)
7521 : {
7522 0 : gfc_error ("expected variant name at %C");
7523 0 : return MATCH_ERROR;
7524 : }
7525 :
7526 16 : if (gfc_get_ha_sym_tree (buf, &variant_proc_st))
7527 : return MATCH_ERROR;
7528 : }
7529 : else
7530 : {
7531 : /* Base procedure not specified. */
7532 399 : variant_proc_st = base_proc_st;
7533 399 : base_proc_st = NULL;
7534 : }
7535 :
7536 415 : gfc_omp_declare_variant *odv;
7537 415 : odv = gfc_get_omp_declare_variant ();
7538 415 : odv->where = gfc_current_locus;
7539 415 : odv->variant_proc_symtree = variant_proc_st;
7540 415 : odv->adjust_args_list = NULL;
7541 415 : odv->base_proc_symtree = base_proc_st;
7542 415 : odv->next = NULL;
7543 415 : odv->error_p = false;
7544 :
7545 : /* Add the new declare variant to the end of the list. */
7546 415 : gfc_omp_declare_variant **prev_next = &gfc_current_ns->omp_declare_variant;
7547 555 : while (*prev_next)
7548 140 : prev_next = &((*prev_next)->next);
7549 415 : *prev_next = odv;
7550 :
7551 415 : if (gfc_match (" )") != MATCH_YES)
7552 : {
7553 1 : gfc_error ("expected %<)%> at %C");
7554 1 : return MATCH_ERROR;
7555 : }
7556 :
7557 414 : bool has_match = false, has_adjust_args = false, has_append_args = false;
7558 414 : bool error_p = false;
7559 414 : locus adjust_args_loc;
7560 414 : locus append_args_loc;
7561 :
7562 414 : gfc_gobble_whitespace ();
7563 414 : gfc_match_char (',');
7564 632 : for (;;)
7565 : {
7566 523 : gfc_gobble_whitespace ();
7567 :
7568 523 : enum clause
7569 : {
7570 : clause_match,
7571 : clause_adjust_args,
7572 : clause_append_args
7573 : } ccode;
7574 :
7575 523 : if (gfc_match ("match") == MATCH_YES)
7576 : ccode = clause_match;
7577 119 : else if (gfc_match ("adjust_args") == MATCH_YES)
7578 : {
7579 517 : ccode = clause_adjust_args;
7580 : adjust_args_loc = gfc_current_locus;
7581 : }
7582 38 : else if (gfc_match ("append_args") == MATCH_YES)
7583 : {
7584 517 : ccode = clause_append_args;
7585 : append_args_loc = gfc_current_locus;
7586 : }
7587 : else
7588 : {
7589 : error_p = true;
7590 : break;
7591 : }
7592 :
7593 517 : if (gfc_match (" ( ") != MATCH_YES)
7594 : {
7595 1 : gfc_error ("expected %<(%> at %C");
7596 1 : return MATCH_ERROR;
7597 : }
7598 :
7599 516 : if (ccode == clause_match)
7600 : {
7601 403 : if (has_match)
7602 : {
7603 1 : gfc_error ("%qs clause at %L specified more than once",
7604 : "match", &gfc_current_locus);
7605 1 : return MATCH_ERROR;
7606 : }
7607 402 : has_match = true;
7608 402 : if (gfc_match_omp_context_selector_specification (&odv->set_selectors)
7609 : != MATCH_YES)
7610 : return MATCH_ERROR;
7611 362 : if (gfc_match (" )") != MATCH_YES)
7612 : {
7613 0 : gfc_error ("expected %<)%> at %C");
7614 0 : return MATCH_ERROR;
7615 : }
7616 : }
7617 113 : else if (ccode == clause_adjust_args)
7618 : {
7619 81 : has_adjust_args = true;
7620 81 : bool need_device_ptr_p = false;
7621 81 : bool need_device_addr_p = false;
7622 81 : if (gfc_match ("nothing ") == MATCH_YES)
7623 : ;
7624 58 : else if (gfc_match ("need_device_ptr ") == MATCH_YES)
7625 : need_device_ptr_p = true;
7626 9 : else if (gfc_match ("need_device_addr ") == MATCH_YES)
7627 : need_device_addr_p = true;
7628 : else
7629 : {
7630 2 : gfc_error ("expected %<nothing%>, %<need_device_ptr%> or "
7631 : "%<need_device_addr%> at %C");
7632 2 : return MATCH_ERROR;
7633 : }
7634 79 : if (gfc_match (": ") != MATCH_YES)
7635 : {
7636 1 : gfc_error ("expected %<:%> at %C");
7637 1 : return MATCH_ERROR;
7638 : }
7639 : gfc_omp_namelist *tail = NULL;
7640 : bool need_range = false, have_range = false;
7641 125 : while (true)
7642 : {
7643 125 : gfc_omp_namelist *p = gfc_get_omp_namelist ();
7644 125 : p->where = gfc_current_locus;
7645 125 : p->u.adj_args.need_ptr = need_device_ptr_p;
7646 125 : p->u.adj_args.need_addr = need_device_addr_p;
7647 125 : if (tail)
7648 : {
7649 47 : tail->next = p;
7650 47 : tail = tail->next;
7651 : }
7652 : else
7653 : {
7654 78 : gfc_omp_namelist **q = &odv->adjust_args_list;
7655 78 : if (*q)
7656 : {
7657 50 : for (; (*q)->next; q = &(*q)->next)
7658 : ;
7659 28 : (*q)->next = p;
7660 : }
7661 : else
7662 50 : *q = p;
7663 : tail = p;
7664 : }
7665 125 : if (gfc_match (": ") == MATCH_YES)
7666 : {
7667 2 : if (have_range)
7668 : {
7669 0 : gfc_error ("unexpected %<:%> at %C");
7670 2 : return MATCH_ERROR;
7671 : }
7672 2 : p->u.adj_args.range_start = have_range = true;
7673 2 : need_range = false;
7674 49 : continue;
7675 : }
7676 123 : if (have_range && gfc_match (", ") == MATCH_YES)
7677 : {
7678 1 : have_range = false;
7679 1 : continue;
7680 : }
7681 122 : if (have_range && gfc_match (") ") == MATCH_YES)
7682 : break;
7683 121 : locus saved_loc = gfc_current_locus;
7684 :
7685 : /* Without ranges, only arg names or integer literals permitted;
7686 : handle literals here as gfc_match_expr simplifies the expr. */
7687 121 : if (gfc_match_literal_constant (&p->expr, true) == MATCH_YES)
7688 : {
7689 17 : gfc_gobble_whitespace ();
7690 17 : char c = gfc_peek_ascii_char ();
7691 17 : if (c != ')' && c != ',' && c != ':')
7692 : {
7693 1 : gfc_free_expr (p->expr);
7694 1 : p->expr = NULL;
7695 1 : gfc_current_locus = saved_loc;
7696 : }
7697 : }
7698 121 : if (!p->expr && gfc_match ("omp_num_args") == MATCH_YES)
7699 : {
7700 6 : if (!have_range)
7701 3 : p->u.adj_args.range_start = need_range = true;
7702 : else
7703 : need_range = false;
7704 :
7705 6 : locus saved_loc2 = gfc_current_locus;
7706 6 : gfc_gobble_whitespace ();
7707 6 : char c = gfc_peek_ascii_char ();
7708 6 : if (c == '+' || c == '-')
7709 : {
7710 5 : if (gfc_match ("+ %e", &p->expr) == MATCH_YES)
7711 1 : p->u.adj_args.omp_num_args_plus = true;
7712 4 : else if (gfc_match ("- %e", &p->expr) == MATCH_YES)
7713 4 : p->u.adj_args.omp_num_args_minus = true;
7714 0 : else if (!gfc_error_check ())
7715 : {
7716 0 : gfc_error ("expected constant integer expression "
7717 : "at %C");
7718 0 : p->u.adj_args.error_p = true;
7719 0 : return MATCH_ERROR;
7720 : }
7721 5 : p->where = gfc_get_location_range (&saved_loc, 1,
7722 : &saved_loc, 1,
7723 : &gfc_current_locus);
7724 : }
7725 : else
7726 : {
7727 1 : p->where = gfc_get_location_range (&saved_loc, 1,
7728 : &saved_loc, 1,
7729 : &saved_loc2);
7730 1 : p->u.adj_args.omp_num_args_plus = true;
7731 : }
7732 : }
7733 115 : else if (!p->expr)
7734 : {
7735 99 : match m = gfc_match_expr (&p->expr);
7736 99 : if (m != MATCH_YES)
7737 : {
7738 1 : gfc_error ("expected dummy parameter name, "
7739 : "%<omp_num_args%> or constant positive integer"
7740 : " at %C");
7741 1 : p->u.adj_args.error_p = true;
7742 1 : return MATCH_ERROR;
7743 : }
7744 98 : if (p->expr->expr_type == EXPR_CONSTANT && !have_range)
7745 98 : need_range = true; /* Constant expr but not literal. */
7746 98 : p->where = p->expr->where;
7747 : }
7748 : else
7749 16 : p->where = p->expr->where;
7750 120 : gfc_gobble_whitespace ();
7751 120 : match m = gfc_match (": ");
7752 120 : if (need_range && m != MATCH_YES)
7753 : {
7754 1 : gfc_error ("expected %<:%> at %C");
7755 1 : return MATCH_ERROR;
7756 : }
7757 119 : if (m == MATCH_YES)
7758 : {
7759 6 : p->u.adj_args.range_start = have_range = true;
7760 6 : need_range = false;
7761 6 : continue;
7762 : }
7763 113 : need_range = have_range = false;
7764 113 : if (gfc_match (", ") == MATCH_YES)
7765 38 : continue;
7766 75 : if (gfc_match (") ") == MATCH_YES)
7767 : break;
7768 : }
7769 : }
7770 32 : else if (ccode == clause_append_args)
7771 : {
7772 32 : if (has_append_args)
7773 : {
7774 1 : gfc_error ("%qs clause at %L specified more than once",
7775 : "append_args", &gfc_current_locus);
7776 1 : return MATCH_ERROR;
7777 : }
7778 56 : has_append_args = true;
7779 : gfc_omp_namelist *append_args_last = NULL;
7780 81 : do
7781 : {
7782 56 : gfc_gobble_whitespace ();
7783 56 : if (gfc_match ("interop ") != MATCH_YES)
7784 : {
7785 0 : gfc_error ("expected %<interop%> at %C");
7786 3 : return MATCH_ERROR;
7787 : }
7788 56 : if (gfc_match ("( ") != MATCH_YES)
7789 : {
7790 0 : gfc_error ("expected %<(%> at %C");
7791 0 : return MATCH_ERROR;
7792 : }
7793 :
7794 56 : bool target, targetsync;
7795 56 : char *type_str = NULL;
7796 56 : int type_str_len;
7797 56 : locus loc = gfc_current_locus;
7798 56 : if (gfc_parser_omp_clause_init_modifiers (target, targetsync,
7799 : &type_str, type_str_len,
7800 : false) == MATCH_ERROR)
7801 : return MATCH_ERROR;
7802 :
7803 54 : gfc_omp_namelist *n = gfc_get_omp_namelist();
7804 54 : n->where = loc;
7805 54 : n->u.init.target = target;
7806 54 : n->u.init.targetsync = targetsync;
7807 54 : n->u.init.len = type_str_len;
7808 54 : n->u2.init_interop = type_str;
7809 54 : if (odv->append_args_list)
7810 : {
7811 25 : append_args_last->next = n;
7812 25 : append_args_last = n;
7813 : }
7814 : else
7815 29 : append_args_last = odv->append_args_list = n;
7816 :
7817 54 : gfc_gobble_whitespace ();
7818 54 : if (gfc_match_char (',') == MATCH_YES)
7819 25 : continue;
7820 29 : if (gfc_match_char (')') == MATCH_YES)
7821 : break;
7822 1 : gfc_error ("Expected %<,%> or %<)%> at %C");
7823 1 : return MATCH_ERROR;
7824 : }
7825 : while (true);
7826 : }
7827 466 : gfc_gobble_whitespace ();
7828 466 : if (gfc_match_omp_eos () == MATCH_YES)
7829 : break;
7830 109 : gfc_match_char (',');
7831 109 : }
7832 :
7833 363 : if (error_p || (!has_match && !has_adjust_args && !has_append_args))
7834 : {
7835 6 : gfc_error ("expected %<match%>, %<adjust_args%> or %<append_args%> at %C");
7836 6 : return MATCH_ERROR;
7837 : }
7838 :
7839 357 : if (!has_match)
7840 : {
7841 3 : gfc_error ("expected %<match%> clause at %C");
7842 3 : return MATCH_ERROR;
7843 : }
7844 :
7845 : return MATCH_YES;
7846 : }
7847 :
7848 :
7849 : static match
7850 160 : match_omp_metadirective (bool begin_p)
7851 : {
7852 160 : locus old_loc = gfc_current_locus;
7853 160 : gfc_omp_variant *variants_head;
7854 160 : gfc_omp_variant **next_variant = &variants_head;
7855 160 : bool default_seen = false;
7856 :
7857 : /* Parse the context selectors. */
7858 656 : for (;;)
7859 : {
7860 408 : bool default_p = false;
7861 408 : gfc_omp_set_selector *selectors = NULL;
7862 :
7863 408 : gfc_gobble_whitespace ();
7864 408 : if (gfc_match_eos () == MATCH_YES)
7865 : break;
7866 266 : gfc_match_char (',');
7867 266 : gfc_gobble_whitespace ();
7868 :
7869 266 : locus variant_locus = gfc_current_locus;
7870 :
7871 266 : if (gfc_match ("default ( ") == MATCH_YES)
7872 : {
7873 82 : default_p = true;
7874 82 : gfc_warning (OPT_Wdeprecated_openmp,
7875 : "%<default%> clause with metadirective at %L "
7876 : "deprecated since OpenMP 5.2", &variant_locus);
7877 : }
7878 184 : else if (gfc_match ("otherwise ( ") == MATCH_YES)
7879 : default_p = true;
7880 177 : else if (gfc_match ("when ( ") != MATCH_YES)
7881 : {
7882 1 : gfc_error ("expected %<when%>, %<otherwise%>, or %<default%> at %C");
7883 1 : gfc_current_locus = old_loc;
7884 18 : return MATCH_ERROR;
7885 : }
7886 89 : if (default_p && default_seen)
7887 : {
7888 3 : gfc_error ("too many %<otherwise%> or %<default%> clauses "
7889 : "in %<metadirective%> at %C");
7890 3 : gfc_current_locus = old_loc;
7891 3 : return MATCH_ERROR;
7892 : }
7893 262 : else if (default_seen)
7894 : {
7895 1 : gfc_error ("%<otherwise%> or %<default%> clause "
7896 : "must appear last in %<metadirective%> at %C");
7897 1 : gfc_current_locus = old_loc;
7898 1 : return MATCH_ERROR;
7899 : }
7900 :
7901 261 : if (!default_p)
7902 : {
7903 175 : if (gfc_match_omp_context_selector_specification (&selectors)
7904 : != MATCH_YES)
7905 : return MATCH_ERROR;
7906 :
7907 168 : if (gfc_match (" : ") != MATCH_YES)
7908 : {
7909 1 : gfc_error ("expected %<:%> at %C");
7910 1 : gfc_current_locus = old_loc;
7911 1 : return MATCH_ERROR;
7912 : }
7913 :
7914 167 : gfc_commit_symbols ();
7915 : }
7916 :
7917 253 : gfc_matching_omp_context_selector = true;
7918 253 : gfc_statement directive = match_omp_directive ();
7919 253 : gfc_matching_omp_context_selector = false;
7920 :
7921 253 : if (is_omp_declarative_stmt (directive))
7922 0 : sorry_at (gfc_get_location (&gfc_current_locus),
7923 : "declarative directive variants are not supported");
7924 :
7925 253 : if (gfc_error_flag_test ())
7926 : {
7927 2 : gfc_current_locus = old_loc;
7928 2 : return MATCH_ERROR;
7929 : }
7930 :
7931 251 : if (gfc_match (" )") != MATCH_YES)
7932 : {
7933 0 : gfc_error ("Expected %<)%> at %C");
7934 0 : gfc_current_locus = old_loc;
7935 0 : return MATCH_ERROR;
7936 : }
7937 :
7938 251 : gfc_commit_symbols ();
7939 :
7940 251 : if (begin_p
7941 251 : && directive != ST_NONE
7942 251 : && gfc_omp_end_stmt (directive) == ST_NONE)
7943 : {
7944 3 : gfc_error ("variant directive used in OMP BEGIN METADIRECTIVE "
7945 : "at %C must have a corresponding end directive");
7946 3 : gfc_current_locus = old_loc;
7947 3 : return MATCH_ERROR;
7948 : }
7949 :
7950 248 : if (default_p)
7951 : default_seen = true;
7952 :
7953 248 : gfc_omp_variant *omv = gfc_get_omp_variant ();
7954 248 : omv->selectors = selectors;
7955 248 : omv->stmt = directive;
7956 248 : omv->where = variant_locus;
7957 :
7958 248 : if (directive == ST_NONE)
7959 : {
7960 : /* The directive was a 'nothing' directive. */
7961 15 : omv->code = gfc_get_code (EXEC_CONTINUE);
7962 15 : omv->code->ext.omp_clauses = NULL;
7963 : }
7964 : else
7965 : {
7966 233 : omv->code = gfc_get_code (new_st.op);
7967 233 : omv->code->ext.omp_clauses = new_st.ext.omp_clauses;
7968 : /* Prevent the OpenMP clauses from being freed via NEW_ST. */
7969 233 : new_st.ext.omp_clauses = NULL;
7970 : }
7971 :
7972 248 : *next_variant = omv;
7973 248 : next_variant = &omv->next;
7974 248 : }
7975 :
7976 142 : if (gfc_match_omp_eos () != MATCH_YES)
7977 : {
7978 0 : gfc_error ("Unexpected junk after OMP METADIRECTIVE at %C");
7979 0 : gfc_current_locus = old_loc;
7980 0 : return MATCH_ERROR;
7981 : }
7982 :
7983 : /* Add a 'default (nothing)' clause if no default is explicitly given. */
7984 142 : if (!default_seen)
7985 : {
7986 65 : gfc_omp_variant *omv = gfc_get_omp_variant ();
7987 65 : omv->stmt = ST_NONE;
7988 65 : omv->code = gfc_get_code (EXEC_CONTINUE);
7989 65 : omv->code->ext.omp_clauses = NULL;
7990 65 : omv->where = old_loc;
7991 65 : omv->selectors = NULL;
7992 :
7993 65 : *next_variant = omv;
7994 65 : next_variant = &omv->next;
7995 : }
7996 :
7997 142 : new_st.op = EXEC_OMP_METADIRECTIVE;
7998 142 : new_st.ext.omp_variants = variants_head;
7999 :
8000 142 : return MATCH_YES;
8001 : }
8002 :
8003 : match
8004 43 : gfc_match_omp_begin_metadirective (void)
8005 : {
8006 43 : return match_omp_metadirective (true);
8007 : }
8008 :
8009 : match
8010 117 : gfc_match_omp_metadirective (void)
8011 : {
8012 117 : return match_omp_metadirective (false);
8013 : }
8014 :
8015 : /* Match 'omp threadprivate' or 'omp groupprivate'. */
8016 : static match
8017 259 : gfc_match_omp_thread_group_private (bool is_groupprivate)
8018 : {
8019 259 : locus old_loc;
8020 259 : char n[GFC_MAX_SYMBOL_LEN+1];
8021 259 : gfc_symbol *sym;
8022 259 : match m;
8023 259 : gfc_symtree *st;
8024 259 : struct sym_loc_t { gfc_symbol *sym; gfc_common_head *com; locus loc; };
8025 259 : auto_vec<sym_loc_t> syms;
8026 :
8027 259 : old_loc = gfc_current_locus;
8028 :
8029 259 : m = gfc_match (" ( ");
8030 259 : if (m != MATCH_YES)
8031 : return m;
8032 :
8033 369 : for (;;)
8034 : {
8035 314 : locus sym_loc = gfc_current_locus;
8036 314 : m = gfc_match_symbol (&sym, 0);
8037 314 : switch (m)
8038 : {
8039 209 : case MATCH_YES:
8040 209 : if (sym->attr.in_common)
8041 0 : gfc_error_now ("%qs variable at %L is an element of a COMMON block",
8042 : is_groupprivate ? "groupprivate" : "threadprivate",
8043 : &sym_loc);
8044 209 : else if (!is_groupprivate
8045 209 : && !gfc_add_threadprivate (&sym->attr, sym->name, &sym_loc))
8046 16 : goto cleanup;
8047 207 : else if (is_groupprivate)
8048 : {
8049 30 : if (!gfc_add_omp_groupprivate (&sym->attr, sym->name, &sym_loc))
8050 4 : goto cleanup;
8051 26 : syms.safe_push ({sym, nullptr, sym_loc});
8052 : }
8053 203 : goto next_item;
8054 : case MATCH_NO:
8055 : break;
8056 0 : case MATCH_ERROR:
8057 0 : goto cleanup;
8058 : }
8059 :
8060 105 : m = gfc_match (" / %n /", n);
8061 105 : if (m == MATCH_ERROR)
8062 0 : goto cleanup;
8063 105 : if (m == MATCH_NO || n[0] == '\0')
8064 0 : goto syntax;
8065 :
8066 105 : st = gfc_find_symtree (gfc_current_ns->common_root, n);
8067 105 : if (st == NULL)
8068 : {
8069 2 : gfc_error ("COMMON block /%s/ not found at %L", n, &sym_loc);
8070 2 : goto cleanup;
8071 : }
8072 103 : syms.safe_push ({nullptr, st->n.common, sym_loc});
8073 103 : if (is_groupprivate)
8074 30 : st->n.common->omp_groupprivate = 1;
8075 : else
8076 73 : st->n.common->threadprivate = 1;
8077 236 : for (sym = st->n.common->head; sym; sym = sym->common_next)
8078 141 : if (!is_groupprivate
8079 141 : && !gfc_add_threadprivate (&sym->attr, sym->name, &sym_loc))
8080 3 : goto cleanup;
8081 138 : else if (is_groupprivate
8082 138 : && !gfc_add_omp_groupprivate (&sym->attr, sym->name, &sym_loc))
8083 5 : goto cleanup;
8084 :
8085 95 : next_item:
8086 298 : if (gfc_match_char (')') == MATCH_YES)
8087 : break;
8088 55 : if (gfc_match_char (',') != MATCH_YES)
8089 0 : goto syntax;
8090 55 : }
8091 :
8092 243 : if (is_groupprivate)
8093 : {
8094 39 : gfc_omp_clauses *c;
8095 39 : m = gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_DEVICE_TYPE));
8096 39 : if (m == MATCH_ERROR)
8097 0 : return MATCH_ERROR;
8098 :
8099 39 : if (c->device_type == OMP_DEVICE_TYPE_UNSET)
8100 19 : c->device_type = OMP_DEVICE_TYPE_ANY;
8101 :
8102 86 : for (size_t i = 0; i < syms.length (); i++)
8103 47 : if (syms[i].sym)
8104 : {
8105 24 : sym_loc_t &n = syms[i];
8106 24 : if (n.sym->attr.in_common)
8107 0 : gfc_error_now ("Variable %qs at %L is an element of a COMMON "
8108 : "block", n.sym->name, &n.loc);
8109 24 : else if (n.sym->attr.omp_declare_target
8110 23 : || n.sym->attr.omp_declare_target_link)
8111 2 : gfc_error_now ("List item %qs at %L implies OMP DECLARE TARGET "
8112 : "with the LOCAL clause, but it has been specified"
8113 : " with a different clause before",
8114 : n.sym->name, &n.loc);
8115 24 : if (n.sym->attr.omp_device_type != OMP_DEVICE_TYPE_UNSET
8116 5 : && n.sym->attr.omp_device_type != c->device_type)
8117 : {
8118 2 : const char *dt = "any";
8119 2 : if (n.sym->attr.omp_device_type == OMP_DEVICE_TYPE_HOST)
8120 : dt = "host";
8121 0 : else if (n.sym->attr.omp_device_type == OMP_DEVICE_TYPE_NOHOST)
8122 0 : dt = "nohost";
8123 2 : gfc_error_now ("List item %qs at %L set in previous OMP DECLARE "
8124 : "TARGET directive to the different DEVICE_TYPE %qs",
8125 : n.sym->name, &n.loc, dt);
8126 : }
8127 24 : gfc_add_omp_declare_target_local (&n.sym->attr, n.sym->name,
8128 : &n.loc);
8129 24 : n.sym->attr.omp_device_type = c->device_type;
8130 : }
8131 : else /* Common block. */
8132 : {
8133 23 : sym_loc_t &n = syms[i];
8134 23 : if (n.com->omp_declare_target
8135 22 : || n.com->omp_declare_target_link)
8136 2 : gfc_error_now ("List item %</%s/%> at %L implies OMP DECLARE "
8137 : "TARGET with the LOCAL clause, but it has been "
8138 : "specified with a different clause before",
8139 2 : n.com->name, &n.loc);
8140 23 : if (n.com->omp_device_type != OMP_DEVICE_TYPE_UNSET
8141 5 : && n.com->omp_device_type != c->device_type)
8142 : {
8143 2 : const char *dt = "any";
8144 2 : if (n.com->omp_device_type == OMP_DEVICE_TYPE_HOST)
8145 : dt = "host";
8146 0 : else if (n.com->omp_device_type == OMP_DEVICE_TYPE_NOHOST)
8147 0 : dt = "nohost";
8148 2 : gfc_error_now ("List item %qs at %L set in previous OMP DECLARE"
8149 : " TARGET directive to the different DEVICE_TYPE "
8150 2 : "%qs", n.com->name, &n.loc, dt);
8151 : }
8152 23 : n.com->omp_declare_target_local = 1;
8153 23 : n.com->omp_device_type = c->device_type;
8154 46 : for (gfc_symbol *s = n.com->head; s; s = s->common_next)
8155 : {
8156 23 : gfc_add_omp_declare_target_local (&s->attr, s->name, &n.loc);
8157 23 : s->attr.omp_device_type = c->device_type;
8158 : }
8159 : }
8160 39 : free (c);
8161 : }
8162 :
8163 243 : if (gfc_match_omp_eos () != MATCH_YES)
8164 : {
8165 0 : gfc_error ("Unexpected junk after OMP %s at %C",
8166 : is_groupprivate ? "GROUPPRIVATE" : "THREADPRIVATE");
8167 0 : goto cleanup;
8168 : }
8169 :
8170 : return MATCH_YES;
8171 :
8172 0 : syntax:
8173 0 : gfc_error ("Syntax error in !$OMP %s list at %C",
8174 : is_groupprivate ? "GROUPPRIVATE" : "THREADPRIVATE");
8175 :
8176 16 : cleanup:
8177 16 : gfc_current_locus = old_loc;
8178 16 : return MATCH_ERROR;
8179 259 : }
8180 :
8181 :
8182 : match
8183 48 : gfc_match_omp_groupprivate (void)
8184 : {
8185 48 : return gfc_match_omp_thread_group_private (true);
8186 : }
8187 :
8188 :
8189 : match
8190 211 : gfc_match_omp_threadprivate (void)
8191 : {
8192 211 : return gfc_match_omp_thread_group_private (false);
8193 : }
8194 :
8195 :
8196 : match
8197 2207 : gfc_match_omp_parallel (void)
8198 : {
8199 2207 : return match_omp (EXEC_OMP_PARALLEL, OMP_PARALLEL_CLAUSES);
8200 : }
8201 :
8202 :
8203 : match
8204 1203 : gfc_match_omp_parallel_do (void)
8205 : {
8206 1203 : return match_omp (EXEC_OMP_PARALLEL_DO,
8207 1203 : (OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES)
8208 1203 : & ~(omp_mask (OMP_CLAUSE_NOWAIT)));
8209 : }
8210 :
8211 :
8212 : match
8213 298 : gfc_match_omp_parallel_do_simd (void)
8214 : {
8215 298 : return match_omp (EXEC_OMP_PARALLEL_DO_SIMD,
8216 298 : (OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES | OMP_SIMD_CLAUSES)
8217 298 : & ~(omp_mask (OMP_CLAUSE_NOWAIT)));
8218 : }
8219 :
8220 :
8221 : match
8222 14 : gfc_match_omp_parallel_masked (void)
8223 : {
8224 14 : return match_omp (EXEC_OMP_PARALLEL_MASKED,
8225 14 : OMP_PARALLEL_CLAUSES | OMP_MASKED_CLAUSES);
8226 : }
8227 :
8228 : match
8229 10 : gfc_match_omp_parallel_masked_taskloop (void)
8230 : {
8231 10 : return match_omp (EXEC_OMP_PARALLEL_MASKED_TASKLOOP,
8232 10 : (OMP_PARALLEL_CLAUSES | OMP_MASKED_CLAUSES
8233 10 : | OMP_TASKLOOP_CLAUSES)
8234 10 : & ~(omp_mask (OMP_CLAUSE_IN_REDUCTION)));
8235 : }
8236 :
8237 : match
8238 13 : gfc_match_omp_parallel_masked_taskloop_simd (void)
8239 : {
8240 13 : return match_omp (EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD,
8241 13 : (OMP_PARALLEL_CLAUSES | OMP_MASKED_CLAUSES
8242 13 : | OMP_TASKLOOP_CLAUSES | OMP_SIMD_CLAUSES)
8243 13 : & ~(omp_mask (OMP_CLAUSE_IN_REDUCTION)));
8244 : }
8245 :
8246 : match
8247 14 : gfc_match_omp_parallel_master (void)
8248 : {
8249 14 : gfc_warning (OPT_Wdeprecated_openmp,
8250 : "%<master%> construct at %C deprecated since OpenMP 5.1, use "
8251 : "%<masked%>");
8252 14 : return match_omp (EXEC_OMP_PARALLEL_MASTER, OMP_PARALLEL_CLAUSES);
8253 : }
8254 :
8255 : match
8256 15 : gfc_match_omp_parallel_master_taskloop (void)
8257 : {
8258 15 : gfc_warning (OPT_Wdeprecated_openmp,
8259 : "%<master%> construct at %C deprecated since OpenMP 5.1, "
8260 : "use %<masked%>");
8261 15 : return match_omp (EXEC_OMP_PARALLEL_MASTER_TASKLOOP,
8262 15 : (OMP_PARALLEL_CLAUSES | OMP_TASKLOOP_CLAUSES)
8263 15 : & ~(omp_mask (OMP_CLAUSE_IN_REDUCTION)));
8264 : }
8265 :
8266 : match
8267 21 : gfc_match_omp_parallel_master_taskloop_simd (void)
8268 : {
8269 21 : gfc_warning (OPT_Wdeprecated_openmp,
8270 : "%<master%> construct at %C deprecated since OpenMP 5.1, "
8271 : "use %<masked%>");
8272 21 : return match_omp (EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD,
8273 21 : (OMP_PARALLEL_CLAUSES | OMP_TASKLOOP_CLAUSES
8274 21 : | OMP_SIMD_CLAUSES)
8275 21 : & ~(omp_mask (OMP_CLAUSE_IN_REDUCTION)));
8276 : }
8277 :
8278 : match
8279 59 : gfc_match_omp_parallel_sections (void)
8280 : {
8281 59 : return match_omp (EXEC_OMP_PARALLEL_SECTIONS,
8282 59 : (OMP_PARALLEL_CLAUSES | OMP_SECTIONS_CLAUSES)
8283 59 : & ~(omp_mask (OMP_CLAUSE_NOWAIT)));
8284 : }
8285 :
8286 :
8287 : match
8288 56 : gfc_match_omp_parallel_workshare (void)
8289 : {
8290 56 : return match_omp (EXEC_OMP_PARALLEL_WORKSHARE, OMP_PARALLEL_CLAUSES);
8291 : }
8292 :
8293 : void
8294 49895 : gfc_check_omp_requires (gfc_namespace *ns, int ref_omp_requires)
8295 : {
8296 49895 : const char *msg = G_("Program unit at %L has OpenMP device "
8297 : "constructs/routines but does not set !$OMP REQUIRES %s "
8298 : "but other program units do");
8299 49895 : if (ns->omp_target_seen
8300 1295 : && (ns->omp_requires & OMP_REQ_TARGET_MASK)
8301 1295 : != (ref_omp_requires & OMP_REQ_TARGET_MASK))
8302 : {
8303 6 : gcc_assert (ns->proc_name);
8304 6 : if ((ref_omp_requires & OMP_REQ_REVERSE_OFFLOAD)
8305 5 : && !(ns->omp_requires & OMP_REQ_REVERSE_OFFLOAD))
8306 4 : gfc_error (msg, &ns->proc_name->declared_at, "REVERSE_OFFLOAD");
8307 6 : if ((ref_omp_requires & OMP_REQ_UNIFIED_ADDRESS)
8308 1 : && !(ns->omp_requires & OMP_REQ_UNIFIED_ADDRESS))
8309 1 : gfc_error (msg, &ns->proc_name->declared_at, "UNIFIED_ADDRESS");
8310 6 : if ((ref_omp_requires & OMP_REQ_UNIFIED_SHARED_MEMORY)
8311 4 : && !(ns->omp_requires & OMP_REQ_UNIFIED_SHARED_MEMORY))
8312 2 : gfc_error (msg, &ns->proc_name->declared_at, "UNIFIED_SHARED_MEMORY");
8313 6 : if ((ref_omp_requires & OMP_REQ_SELF_MAPS)
8314 1 : && !(ns->omp_requires & OMP_REQ_UNIFIED_SHARED_MEMORY))
8315 1 : gfc_error (msg, &ns->proc_name->declared_at, "SELF_MAPS");
8316 : }
8317 49895 : }
8318 :
8319 : bool
8320 126 : gfc_omp_requires_add_clause (gfc_omp_requires_kind clause,
8321 : const char *clause_name, locus *loc,
8322 : const char *module_name)
8323 : {
8324 126 : gfc_namespace *prog_unit = gfc_current_ns;
8325 150 : while (prog_unit->parent)
8326 : {
8327 26 : if (gfc_state_stack->previous
8328 26 : && gfc_state_stack->previous->state == COMP_INTERFACE)
8329 : break;
8330 : /* A submodule namespace may have its parent set to the ancestor module
8331 : for host-association purposes. Do not escape the submodule boundary:
8332 : the submodule itself is the program unit for OMP REQUIRES purposes. */
8333 25 : if (prog_unit->proc_name
8334 25 : && prog_unit->proc_name->attr.flavor == FL_MODULE)
8335 : break;
8336 : prog_unit = prog_unit->parent;
8337 : }
8338 :
8339 : /* Requires added after use. */
8340 126 : if (prog_unit->omp_target_seen
8341 24 : && (clause & OMP_REQ_TARGET_MASK)
8342 24 : && !(prog_unit->omp_requires & clause))
8343 : {
8344 0 : if (module_name)
8345 0 : gfc_error ("!$OMP REQUIRES clause %qs specified via module %qs use "
8346 : "at %L comes after using a device construct/routine",
8347 : clause_name, module_name, loc);
8348 : else
8349 0 : gfc_error ("!$OMP REQUIRES clause %qs specified at %L comes after "
8350 : "using a device construct/routine", clause_name, loc);
8351 0 : return false;
8352 : }
8353 :
8354 : /* Overriding atomic_default_mem_order clause value. */
8355 126 : if ((clause & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
8356 34 : && (prog_unit->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
8357 6 : && (prog_unit->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
8358 6 : != (int) clause)
8359 : {
8360 3 : const char *other;
8361 3 : switch (prog_unit->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
8362 : {
8363 : case OMP_REQ_ATOMIC_MEM_ORDER_SEQ_CST: other = "seq_cst"; break;
8364 0 : case OMP_REQ_ATOMIC_MEM_ORDER_ACQ_REL: other = "acq_rel"; break;
8365 1 : case OMP_REQ_ATOMIC_MEM_ORDER_ACQUIRE: other = "acquire"; break;
8366 1 : case OMP_REQ_ATOMIC_MEM_ORDER_RELAXED: other = "relaxed"; break;
8367 0 : case OMP_REQ_ATOMIC_MEM_ORDER_RELEASE: other = "release"; break;
8368 0 : default: gcc_unreachable ();
8369 : }
8370 :
8371 3 : if (module_name)
8372 0 : gfc_error ("!$OMP REQUIRES clause %<atomic_default_mem_order(%s)%> "
8373 : "specified via module %qs use at %L overrides a previous "
8374 : "%<atomic_default_mem_order(%s)%> (which might be through "
8375 : "using a module)", clause_name, module_name, loc, other);
8376 : else
8377 3 : gfc_error ("!$OMP REQUIRES clause %<atomic_default_mem_order(%s)%> "
8378 : "specified at %L overrides a previous "
8379 : "%<atomic_default_mem_order(%s)%> (which might be through "
8380 : "using a module)", clause_name, loc, other);
8381 3 : return false;
8382 : }
8383 :
8384 : /* Requires via module not at program-unit level and not repeating clause. */
8385 123 : if (prog_unit != gfc_current_ns && !(prog_unit->omp_requires & clause))
8386 : {
8387 0 : if (clause & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
8388 0 : gfc_error ("!$OMP REQUIRES clause %<atomic_default_mem_order(%s)%> "
8389 : "specified via module %qs use at %L but same clause is "
8390 : "not specified for the program unit", clause_name,
8391 : module_name, loc);
8392 : else
8393 0 : gfc_error ("!$OMP REQUIRES clause %qs specified via module %qs use at "
8394 : "%L but same clause is not specified for the program unit",
8395 : clause_name, module_name, loc);
8396 0 : return false;
8397 : }
8398 :
8399 123 : if (!gfc_state_stack->previous
8400 115 : || gfc_state_stack->previous->state != COMP_INTERFACE)
8401 122 : prog_unit->omp_requires |= clause;
8402 : return true;
8403 : }
8404 :
8405 : match
8406 98 : gfc_match_omp_requires (void)
8407 : {
8408 98 : static const char *clauses[] = {"reverse_offload",
8409 : "unified_address",
8410 : "unified_shared_memory",
8411 : "self_maps",
8412 : "dynamic_allocators",
8413 : "atomic_default"};
8414 98 : const char *clause = NULL;
8415 98 : int requires_clauses = 0;
8416 98 : bool first = true;
8417 98 : locus old_loc;
8418 :
8419 : /* A submodule's namespace may have its parent pointer set to the ancestor
8420 : module namespace for host-association purposes. The submodule spec part
8421 : is still a valid program-unit spec part for OMP REQUIRES. Only reject
8422 : the directive when we are genuinely nested inside a procedure. */
8423 98 : if (gfc_current_ns->parent
8424 8 : && !(gfc_current_ns->proc_name
8425 8 : && gfc_current_ns->proc_name->attr.flavor == FL_MODULE)
8426 7 : && (!gfc_state_stack->previous
8427 7 : || gfc_state_stack->previous->state != COMP_INTERFACE))
8428 : {
8429 6 : gfc_error ("!$OMP REQUIRES at %C must appear in the specification part "
8430 : "of a program unit");
8431 6 : return MATCH_ERROR;
8432 : }
8433 :
8434 276 : while (true)
8435 : {
8436 184 : old_loc = gfc_current_locus;
8437 184 : gfc_omp_requires_kind requires_clause;
8438 92 : if ((first || gfc_match_char (',') != MATCH_YES)
8439 184 : && (first && gfc_match_space () != MATCH_YES))
8440 0 : goto error;
8441 184 : first = false;
8442 184 : gfc_gobble_whitespace ();
8443 184 : old_loc = gfc_current_locus;
8444 :
8445 184 : if (gfc_match_omp_eos () != MATCH_NO)
8446 : break;
8447 103 : if (gfc_match (clauses[0]) == MATCH_YES)
8448 : {
8449 34 : clause = clauses[0];
8450 34 : requires_clause = OMP_REQ_REVERSE_OFFLOAD;
8451 34 : if (requires_clauses & OMP_REQ_REVERSE_OFFLOAD)
8452 1 : goto duplicate_clause;
8453 : }
8454 69 : else if (gfc_match (clauses[1]) == MATCH_YES)
8455 : {
8456 9 : clause = clauses[1];
8457 9 : requires_clause = OMP_REQ_UNIFIED_ADDRESS;
8458 9 : if (requires_clauses & OMP_REQ_UNIFIED_ADDRESS)
8459 1 : goto duplicate_clause;
8460 : }
8461 60 : else if (gfc_match (clauses[2]) == MATCH_YES)
8462 : {
8463 14 : clause = clauses[2];
8464 14 : requires_clause = OMP_REQ_UNIFIED_SHARED_MEMORY;
8465 14 : if (requires_clauses & OMP_REQ_UNIFIED_SHARED_MEMORY)
8466 1 : goto duplicate_clause;
8467 : }
8468 46 : else if (gfc_match (clauses[3]) == MATCH_YES)
8469 : {
8470 7 : clause = clauses[3];
8471 7 : requires_clause = OMP_REQ_SELF_MAPS;
8472 7 : if (requires_clauses & OMP_REQ_SELF_MAPS)
8473 0 : goto duplicate_clause;
8474 : }
8475 39 : else if (gfc_match (clauses[4]) == MATCH_YES)
8476 : {
8477 7 : clause = clauses[4];
8478 7 : requires_clause = OMP_REQ_DYNAMIC_ALLOCATORS;
8479 7 : if (requires_clauses & OMP_REQ_DYNAMIC_ALLOCATORS)
8480 1 : goto duplicate_clause;
8481 : }
8482 32 : else if (gfc_match ("atomic_default_mem_order (") == MATCH_YES)
8483 : {
8484 31 : clause = clauses[5];
8485 31 : if (requires_clauses & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
8486 1 : goto duplicate_clause;
8487 30 : if (gfc_match (" seq_cst )") == MATCH_YES)
8488 : {
8489 : clause = "seq_cst";
8490 : requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_SEQ_CST;
8491 : }
8492 18 : else if (gfc_match (" acq_rel )") == MATCH_YES)
8493 : {
8494 : clause = "acq_rel";
8495 : requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_ACQ_REL;
8496 : }
8497 12 : else if (gfc_match (" acquire )") == MATCH_YES)
8498 : {
8499 : clause = "acquire";
8500 : requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_ACQUIRE;
8501 : }
8502 9 : else if (gfc_match (" relaxed )") == MATCH_YES)
8503 : {
8504 : clause = "relaxed";
8505 : requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_RELAXED;
8506 : }
8507 5 : else if (gfc_match (" release )") == MATCH_YES)
8508 : {
8509 : clause = "release";
8510 : requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_RELEASE;
8511 : }
8512 : else
8513 : {
8514 2 : gfc_error ("Expected ACQ_REL, ACQUIRE, RELAXED, RELEASE or "
8515 : "SEQ_CST for ATOMIC_DEFAULT_MEM_ORDER clause at %C");
8516 2 : goto error;
8517 : }
8518 : }
8519 : else
8520 1 : goto error;
8521 :
8522 95 : if (!gfc_omp_requires_add_clause (requires_clause, clause, &old_loc, NULL))
8523 3 : goto error;
8524 92 : requires_clauses |= requires_clause;
8525 92 : }
8526 :
8527 81 : if (requires_clauses == 0)
8528 : {
8529 1 : if (!gfc_error_flag_test ())
8530 1 : gfc_error ("Clause expected at %C");
8531 1 : goto error;
8532 : }
8533 : return MATCH_YES;
8534 :
8535 5 : duplicate_clause:
8536 5 : gfc_error ("%qs clause at %L specified more than once", clause, &old_loc);
8537 12 : error:
8538 12 : if (!gfc_error_flag_test ())
8539 1 : gfc_error ("Expected UNIFIED_ADDRESS, UNIFIED_SHARED_MEMORY, SELF_MAPS, "
8540 : "DYNAMIC_ALLOCATORS, REVERSE_OFFLOAD, or "
8541 : "ATOMIC_DEFAULT_MEM_ORDER clause at %L", &old_loc);
8542 : return MATCH_ERROR;
8543 : }
8544 :
8545 :
8546 : match
8547 51 : gfc_match_omp_scan (void)
8548 : {
8549 51 : bool incl;
8550 51 : gfc_omp_clauses *c = gfc_get_omp_clauses ();
8551 51 : gfc_gobble_whitespace ();
8552 51 : if ((incl = (gfc_match ("inclusive") == MATCH_YES))
8553 51 : || gfc_match ("exclusive") == MATCH_YES)
8554 : {
8555 70 : if (gfc_match_omp_variable_list (" (", &c->lists[incl ? OMP_LIST_SCAN_IN
8556 : : OMP_LIST_SCAN_EX],
8557 : false) != MATCH_YES)
8558 : {
8559 0 : gfc_free_omp_clauses (c);
8560 0 : return MATCH_ERROR;
8561 : }
8562 : }
8563 : else
8564 : {
8565 1 : gfc_error ("Expected INCLUSIVE or EXCLUSIVE clause at %C");
8566 1 : gfc_free_omp_clauses (c);
8567 1 : return MATCH_ERROR;
8568 : }
8569 50 : if (gfc_match_omp_eos () != MATCH_YES)
8570 : {
8571 1 : gfc_error ("Unexpected junk after !$OMP SCAN at %C");
8572 1 : gfc_free_omp_clauses (c);
8573 1 : return MATCH_ERROR;
8574 : }
8575 :
8576 49 : new_st.op = EXEC_OMP_SCAN;
8577 49 : new_st.ext.omp_clauses = c;
8578 49 : return MATCH_YES;
8579 : }
8580 :
8581 :
8582 : match
8583 58 : gfc_match_omp_scope (void)
8584 : {
8585 58 : return match_omp (EXEC_OMP_SCOPE, OMP_SCOPE_CLAUSES);
8586 : }
8587 :
8588 :
8589 : match
8590 82 : gfc_match_omp_sections (void)
8591 : {
8592 82 : return match_omp (EXEC_OMP_SECTIONS, OMP_SECTIONS_CLAUSES);
8593 : }
8594 :
8595 :
8596 : match
8597 782 : gfc_match_omp_simd (void)
8598 : {
8599 782 : return match_omp (EXEC_OMP_SIMD, OMP_SIMD_CLAUSES);
8600 : }
8601 :
8602 :
8603 : match
8604 570 : gfc_match_omp_single (void)
8605 : {
8606 570 : return match_omp (EXEC_OMP_SINGLE, OMP_SINGLE_CLAUSES);
8607 : }
8608 :
8609 :
8610 : match
8611 2247 : gfc_match_omp_target (void)
8612 : {
8613 2247 : return match_omp (EXEC_OMP_TARGET, OMP_TARGET_CLAUSES);
8614 : }
8615 :
8616 :
8617 : match
8618 1399 : gfc_match_omp_target_data (void)
8619 : {
8620 1399 : return match_omp (EXEC_OMP_TARGET_DATA, OMP_TARGET_DATA_CLAUSES);
8621 : }
8622 :
8623 :
8624 : match
8625 468 : gfc_match_omp_target_enter_data (void)
8626 : {
8627 468 : return match_omp (EXEC_OMP_TARGET_ENTER_DATA, OMP_TARGET_ENTER_DATA_CLAUSES);
8628 : }
8629 :
8630 :
8631 : match
8632 365 : gfc_match_omp_target_exit_data (void)
8633 : {
8634 365 : return match_omp (EXEC_OMP_TARGET_EXIT_DATA, OMP_TARGET_EXIT_DATA_CLAUSES);
8635 : }
8636 :
8637 :
8638 : match
8639 27 : gfc_match_omp_target_parallel (void)
8640 : {
8641 27 : return match_omp (EXEC_OMP_TARGET_PARALLEL,
8642 27 : (OMP_TARGET_CLAUSES | OMP_PARALLEL_CLAUSES)
8643 27 : & ~(omp_mask (OMP_CLAUSE_COPYIN)));
8644 : }
8645 :
8646 :
8647 : match
8648 81 : gfc_match_omp_target_parallel_do (void)
8649 : {
8650 81 : return match_omp (EXEC_OMP_TARGET_PARALLEL_DO,
8651 81 : (OMP_TARGET_CLAUSES | OMP_PARALLEL_CLAUSES
8652 81 : | OMP_DO_CLAUSES) & ~(omp_mask (OMP_CLAUSE_COPYIN)));
8653 : }
8654 :
8655 :
8656 : match
8657 20 : gfc_match_omp_target_parallel_do_simd (void)
8658 : {
8659 20 : return match_omp (EXEC_OMP_TARGET_PARALLEL_DO_SIMD,
8660 20 : (OMP_TARGET_CLAUSES | OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES
8661 20 : | OMP_SIMD_CLAUSES) & ~(omp_mask (OMP_CLAUSE_COPYIN)));
8662 : }
8663 :
8664 :
8665 : match
8666 34 : gfc_match_omp_target_simd (void)
8667 : {
8668 34 : return match_omp (EXEC_OMP_TARGET_SIMD,
8669 34 : OMP_TARGET_CLAUSES | OMP_SIMD_CLAUSES);
8670 : }
8671 :
8672 :
8673 : match
8674 76 : gfc_match_omp_target_teams (void)
8675 : {
8676 76 : return match_omp (EXEC_OMP_TARGET_TEAMS,
8677 76 : OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES);
8678 : }
8679 :
8680 :
8681 : match
8682 19 : gfc_match_omp_target_teams_distribute (void)
8683 : {
8684 19 : return match_omp (EXEC_OMP_TARGET_TEAMS_DISTRIBUTE,
8685 19 : OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES
8686 19 : | OMP_DISTRIBUTE_CLAUSES);
8687 : }
8688 :
8689 :
8690 : match
8691 66 : gfc_match_omp_target_teams_distribute_parallel_do (void)
8692 : {
8693 66 : return match_omp (EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO,
8694 66 : (OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES
8695 66 : | OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
8696 66 : | OMP_DO_CLAUSES)
8697 66 : & ~(omp_mask (OMP_CLAUSE_ORDERED))
8698 66 : & ~(omp_mask (OMP_CLAUSE_LINEAR)));
8699 : }
8700 :
8701 :
8702 : match
8703 36 : gfc_match_omp_target_teams_distribute_parallel_do_simd (void)
8704 : {
8705 36 : return match_omp (EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD,
8706 36 : (OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES
8707 36 : | OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
8708 36 : | OMP_DO_CLAUSES | OMP_SIMD_CLAUSES)
8709 36 : & ~(omp_mask (OMP_CLAUSE_ORDERED)));
8710 : }
8711 :
8712 :
8713 : match
8714 21 : gfc_match_omp_target_teams_distribute_simd (void)
8715 : {
8716 21 : return match_omp (EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD,
8717 21 : OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES
8718 21 : | OMP_DISTRIBUTE_CLAUSES | OMP_SIMD_CLAUSES);
8719 : }
8720 :
8721 :
8722 : match
8723 1725 : gfc_match_omp_target_update (void)
8724 : {
8725 1725 : return match_omp (EXEC_OMP_TARGET_UPDATE, OMP_TARGET_UPDATE_CLAUSES);
8726 : }
8727 :
8728 :
8729 : match
8730 1182 : gfc_match_omp_task (void)
8731 : {
8732 1182 : return match_omp (EXEC_OMP_TASK, OMP_TASK_CLAUSES);
8733 : }
8734 :
8735 :
8736 : match
8737 72 : gfc_match_omp_taskloop (void)
8738 : {
8739 72 : return match_omp (EXEC_OMP_TASKLOOP, OMP_TASKLOOP_CLAUSES);
8740 : }
8741 :
8742 :
8743 : match
8744 40 : gfc_match_omp_taskloop_simd (void)
8745 : {
8746 40 : return match_omp (EXEC_OMP_TASKLOOP_SIMD,
8747 40 : OMP_TASKLOOP_CLAUSES | OMP_SIMD_CLAUSES);
8748 : }
8749 :
8750 :
8751 : match
8752 147 : gfc_match_omp_taskwait (void)
8753 : {
8754 147 : if (gfc_match_omp_eos () == MATCH_YES)
8755 : {
8756 133 : new_st.op = EXEC_OMP_TASKWAIT;
8757 133 : new_st.ext.omp_clauses = NULL;
8758 133 : return MATCH_YES;
8759 : }
8760 14 : return match_omp (EXEC_OMP_TASKWAIT,
8761 14 : omp_mask (OMP_CLAUSE_DEPEND) | OMP_CLAUSE_NOWAIT);
8762 : }
8763 :
8764 :
8765 : match
8766 10 : gfc_match_omp_taskyield (void)
8767 : {
8768 10 : if (gfc_match_omp_eos () != MATCH_YES)
8769 : {
8770 0 : gfc_error ("Unexpected junk after TASKYIELD clause at %C");
8771 0 : return MATCH_ERROR;
8772 : }
8773 10 : new_st.op = EXEC_OMP_TASKYIELD;
8774 10 : new_st.ext.omp_clauses = NULL;
8775 10 : return MATCH_YES;
8776 : }
8777 :
8778 :
8779 : match
8780 218 : gfc_match_omp_teams (void)
8781 : {
8782 218 : return match_omp (EXEC_OMP_TEAMS, OMP_TEAMS_CLAUSES);
8783 : }
8784 :
8785 :
8786 : match
8787 22 : gfc_match_omp_teams_distribute (void)
8788 : {
8789 22 : return match_omp (EXEC_OMP_TEAMS_DISTRIBUTE,
8790 22 : OMP_TEAMS_CLAUSES | OMP_DISTRIBUTE_CLAUSES);
8791 : }
8792 :
8793 :
8794 : match
8795 41 : gfc_match_omp_teams_distribute_parallel_do (void)
8796 : {
8797 41 : return match_omp (EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO,
8798 41 : (OMP_TEAMS_CLAUSES | OMP_DISTRIBUTE_CLAUSES
8799 41 : | OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES)
8800 41 : & ~(omp_mask (OMP_CLAUSE_ORDERED)
8801 41 : | OMP_CLAUSE_LINEAR | OMP_CLAUSE_NOWAIT));
8802 : }
8803 :
8804 :
8805 : match
8806 63 : gfc_match_omp_teams_distribute_parallel_do_simd (void)
8807 : {
8808 63 : return match_omp (EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD,
8809 63 : (OMP_TEAMS_CLAUSES | OMP_DISTRIBUTE_CLAUSES
8810 63 : | OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES
8811 63 : | OMP_SIMD_CLAUSES)
8812 63 : & ~(omp_mask (OMP_CLAUSE_ORDERED) | OMP_CLAUSE_NOWAIT));
8813 : }
8814 :
8815 :
8816 : match
8817 44 : gfc_match_omp_teams_distribute_simd (void)
8818 : {
8819 44 : return match_omp (EXEC_OMP_TEAMS_DISTRIBUTE_SIMD,
8820 44 : OMP_TEAMS_CLAUSES | OMP_DISTRIBUTE_CLAUSES
8821 44 : | OMP_SIMD_CLAUSES);
8822 : }
8823 :
8824 : match
8825 203 : gfc_match_omp_tile (void)
8826 : {
8827 203 : return match_omp (EXEC_OMP_TILE, OMP_TILE_CLAUSES);
8828 : }
8829 :
8830 : match
8831 415 : gfc_match_omp_unroll (void)
8832 : {
8833 415 : return match_omp (EXEC_OMP_UNROLL, OMP_UNROLL_CLAUSES);
8834 : }
8835 :
8836 : match
8837 39 : gfc_match_omp_workshare (void)
8838 : {
8839 39 : return match_omp (EXEC_OMP_WORKSHARE, OMP_WORKSHARE_CLAUSES);
8840 : }
8841 :
8842 :
8843 : match
8844 55 : gfc_match_omp_masked (void)
8845 : {
8846 55 : return match_omp (EXEC_OMP_MASKED, OMP_MASKED_CLAUSES);
8847 : }
8848 :
8849 : match
8850 10 : gfc_match_omp_masked_taskloop (void)
8851 : {
8852 10 : return match_omp (EXEC_OMP_MASKED_TASKLOOP,
8853 10 : OMP_MASKED_CLAUSES | OMP_TASKLOOP_CLAUSES);
8854 : }
8855 :
8856 : match
8857 16 : gfc_match_omp_masked_taskloop_simd (void)
8858 : {
8859 16 : return match_omp (EXEC_OMP_MASKED_TASKLOOP_SIMD,
8860 16 : (OMP_MASKED_CLAUSES | OMP_TASKLOOP_CLAUSES
8861 16 : | OMP_SIMD_CLAUSES));
8862 : }
8863 :
8864 : match
8865 111 : gfc_match_omp_master (void)
8866 : {
8867 111 : gfc_warning (OPT_Wdeprecated_openmp,
8868 : "%<master%> construct at %C deprecated since OpenMP 5.1, "
8869 : "use %<masked%>");
8870 111 : if (gfc_match_omp_eos () != MATCH_YES)
8871 : {
8872 1 : gfc_error ("Unexpected junk after $OMP MASTER statement at %C");
8873 1 : return MATCH_ERROR;
8874 : }
8875 110 : new_st.op = EXEC_OMP_MASTER;
8876 110 : new_st.ext.omp_clauses = NULL;
8877 110 : return MATCH_YES;
8878 : }
8879 :
8880 : match
8881 16 : gfc_match_omp_master_taskloop (void)
8882 : {
8883 16 : gfc_warning (OPT_Wdeprecated_openmp,
8884 : "%<master%> construct at %C deprecated since OpenMP 5.1, "
8885 : "use %<masked%>");
8886 16 : return match_omp (EXEC_OMP_MASTER_TASKLOOP, OMP_TASKLOOP_CLAUSES);
8887 : }
8888 :
8889 : match
8890 21 : gfc_match_omp_master_taskloop_simd (void)
8891 : {
8892 21 : gfc_warning (OPT_Wdeprecated_openmp,
8893 : "%<master%> construct at %C deprecated since OpenMP 5.1, use "
8894 : "%<masked%>");
8895 21 : return match_omp (EXEC_OMP_MASTER_TASKLOOP_SIMD,
8896 21 : OMP_TASKLOOP_CLAUSES | OMP_SIMD_CLAUSES);
8897 : }
8898 :
8899 : match
8900 235 : gfc_match_omp_ordered (void)
8901 : {
8902 235 : return match_omp (EXEC_OMP_ORDERED, OMP_ORDERED_CLAUSES);
8903 : }
8904 :
8905 : match
8906 24 : gfc_match_omp_nothing (void)
8907 : {
8908 24 : if (gfc_match_omp_eos () != MATCH_YES)
8909 : {
8910 1 : gfc_error ("Unexpected junk after $OMP NOTHING statement at %C");
8911 1 : return MATCH_ERROR;
8912 : }
8913 : /* Will use ST_NONE; therefore, no EXEC_OMP_ is needed. */
8914 : return MATCH_YES;
8915 : }
8916 :
8917 : match
8918 317 : gfc_match_omp_ordered_depend (void)
8919 : {
8920 317 : return match_omp (EXEC_OMP_ORDERED, omp_mask (OMP_CLAUSE_DOACROSS));
8921 : }
8922 :
8923 :
8924 : /* omp atomic [clause-list]
8925 : - atomic-clause: read | write | update
8926 : - capture
8927 : - memory-order-clause: seq_cst | acq_rel | release | acquire | relaxed
8928 : - hint(hint-expr)
8929 : - OpenMP 5.1: compare | fail (seq_cst | acquire | relaxed ) | weak
8930 : */
8931 :
8932 : match
8933 2171 : gfc_match_omp_atomic (void)
8934 : {
8935 2171 : gfc_omp_clauses *c;
8936 2171 : locus loc = gfc_current_locus;
8937 :
8938 2171 : if (gfc_match_omp_clauses (&c, OMP_ATOMIC_CLAUSES, true, true) != MATCH_YES)
8939 : return MATCH_ERROR;
8940 :
8941 2153 : if (c->atomic_op == GFC_OMP_ATOMIC_UNSET)
8942 1011 : c->atomic_op = GFC_OMP_ATOMIC_UPDATE;
8943 :
8944 2153 : if (c->capture && c->atomic_op != GFC_OMP_ATOMIC_UPDATE)
8945 3 : gfc_error ("!$OMP ATOMIC at %L with %s clause is incompatible with "
8946 : "READ or WRITE", &loc, "CAPTURE");
8947 2153 : if (c->compare && c->atomic_op != GFC_OMP_ATOMIC_UPDATE)
8948 3 : gfc_error ("!$OMP ATOMIC at %L with %s clause is incompatible with "
8949 : "READ or WRITE", &loc, "COMPARE");
8950 2153 : if (c->fail != OMP_MEMORDER_UNSET && c->atomic_op != GFC_OMP_ATOMIC_UPDATE)
8951 2 : gfc_error ("!$OMP ATOMIC at %L with %s clause is incompatible with "
8952 : "READ or WRITE", &loc, "FAIL");
8953 2153 : if (c->weak && !c->compare)
8954 : {
8955 5 : gfc_error ("!$OMP ATOMIC at %L with %s clause requires %s clause", &loc,
8956 : "WEAK", "COMPARE");
8957 5 : c->weak = false;
8958 : }
8959 :
8960 2153 : if (c->memorder == OMP_MEMORDER_UNSET)
8961 : {
8962 1969 : gfc_namespace *prog_unit = gfc_current_ns;
8963 1969 : while (prog_unit->parent
8964 2525 : && !(prog_unit->proc_name
8965 556 : && prog_unit->proc_name->attr.flavor == FL_MODULE))
8966 : prog_unit = prog_unit->parent;
8967 1969 : switch (prog_unit->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
8968 : {
8969 1936 : case 0:
8970 1936 : case OMP_REQ_ATOMIC_MEM_ORDER_RELAXED:
8971 1936 : c->memorder = OMP_MEMORDER_RELAXED;
8972 1936 : break;
8973 7 : case OMP_REQ_ATOMIC_MEM_ORDER_SEQ_CST:
8974 7 : c->memorder = OMP_MEMORDER_SEQ_CST;
8975 7 : break;
8976 16 : case OMP_REQ_ATOMIC_MEM_ORDER_ACQ_REL:
8977 16 : if (c->capture)
8978 5 : c->memorder = OMP_MEMORDER_ACQ_REL;
8979 11 : else if (c->atomic_op == GFC_OMP_ATOMIC_READ)
8980 3 : c->memorder = OMP_MEMORDER_ACQUIRE;
8981 : else
8982 8 : c->memorder = OMP_MEMORDER_RELEASE;
8983 : break;
8984 5 : case OMP_REQ_ATOMIC_MEM_ORDER_ACQUIRE:
8985 5 : if (c->atomic_op == GFC_OMP_ATOMIC_WRITE)
8986 : {
8987 1 : gfc_error ("!$OMP ATOMIC WRITE at %L incompatible with "
8988 : "ACQUIRES clause implicitly provided by a "
8989 : "REQUIRES directive", &loc);
8990 1 : c->memorder = OMP_MEMORDER_SEQ_CST;
8991 : }
8992 : else
8993 4 : c->memorder = OMP_MEMORDER_ACQUIRE;
8994 : break;
8995 5 : case OMP_REQ_ATOMIC_MEM_ORDER_RELEASE:
8996 5 : if (c->atomic_op == GFC_OMP_ATOMIC_READ)
8997 : {
8998 1 : gfc_error ("!$OMP ATOMIC READ at %L incompatible with "
8999 : "RELEASE clause implicitly provided by a "
9000 : "REQUIRES directive", &loc);
9001 1 : c->memorder = OMP_MEMORDER_SEQ_CST;
9002 : }
9003 : else
9004 4 : c->memorder = OMP_MEMORDER_RELEASE;
9005 : break;
9006 0 : default:
9007 0 : gcc_unreachable ();
9008 : }
9009 : }
9010 : else
9011 184 : switch (c->atomic_op)
9012 : {
9013 29 : case GFC_OMP_ATOMIC_READ:
9014 29 : if (c->memorder == OMP_MEMORDER_RELEASE)
9015 : {
9016 1 : gfc_error ("!$OMP ATOMIC READ at %L incompatible with "
9017 : "RELEASE clause", &loc);
9018 1 : c->memorder = OMP_MEMORDER_SEQ_CST;
9019 : }
9020 28 : else if (c->memorder == OMP_MEMORDER_ACQ_REL)
9021 1 : c->memorder = OMP_MEMORDER_ACQUIRE;
9022 : break;
9023 35 : case GFC_OMP_ATOMIC_WRITE:
9024 35 : if (c->memorder == OMP_MEMORDER_ACQUIRE)
9025 : {
9026 1 : gfc_error ("!$OMP ATOMIC WRITE at %L incompatible with "
9027 : "ACQUIRE clause", &loc);
9028 1 : c->memorder = OMP_MEMORDER_SEQ_CST;
9029 : }
9030 34 : else if (c->memorder == OMP_MEMORDER_ACQ_REL)
9031 1 : c->memorder = OMP_MEMORDER_RELEASE;
9032 : break;
9033 : default:
9034 : break;
9035 : }
9036 2153 : gfc_error_check ();
9037 2153 : new_st.ext.omp_clauses = c;
9038 2153 : new_st.op = EXEC_OMP_ATOMIC;
9039 2153 : return MATCH_YES;
9040 : }
9041 :
9042 :
9043 : /* acc atomic [ read | write | update | capture] */
9044 :
9045 : match
9046 552 : gfc_match_oacc_atomic (void)
9047 : {
9048 552 : gfc_omp_clauses *c = gfc_get_omp_clauses ();
9049 552 : c->atomic_op = GFC_OMP_ATOMIC_UPDATE;
9050 552 : c->memorder = OMP_MEMORDER_RELAXED;
9051 552 : gfc_gobble_whitespace ();
9052 552 : if (gfc_match ("update") == MATCH_YES)
9053 : ;
9054 373 : else if (gfc_match ("read") == MATCH_YES)
9055 17 : c->atomic_op = GFC_OMP_ATOMIC_READ;
9056 356 : else if (gfc_match ("write") == MATCH_YES)
9057 13 : c->atomic_op = GFC_OMP_ATOMIC_WRITE;
9058 343 : else if (gfc_match ("capture") == MATCH_YES)
9059 319 : c->capture = true;
9060 552 : gfc_gobble_whitespace ();
9061 552 : if (gfc_match_omp_eos () != MATCH_YES)
9062 : {
9063 9 : gfc_error ("Unexpected junk after !$ACC ATOMIC statement at %C");
9064 9 : gfc_free_omp_clauses (c);
9065 9 : return MATCH_ERROR;
9066 : }
9067 543 : new_st.ext.omp_clauses = c;
9068 543 : new_st.op = EXEC_OACC_ATOMIC;
9069 543 : return MATCH_YES;
9070 : }
9071 :
9072 :
9073 : match
9074 614 : gfc_match_omp_barrier (void)
9075 : {
9076 614 : if (gfc_match_omp_eos () != MATCH_YES)
9077 : {
9078 0 : gfc_error ("Unexpected junk after $OMP BARRIER statement at %C");
9079 0 : return MATCH_ERROR;
9080 : }
9081 614 : new_st.op = EXEC_OMP_BARRIER;
9082 614 : new_st.ext.omp_clauses = NULL;
9083 614 : return MATCH_YES;
9084 : }
9085 :
9086 :
9087 : match
9088 188 : gfc_match_omp_taskgroup (void)
9089 : {
9090 188 : return match_omp (EXEC_OMP_TASKGROUP, OMP_TASKGROUP_CLAUSES);
9091 : }
9092 :
9093 :
9094 : static enum gfc_omp_cancel_kind
9095 492 : gfc_match_omp_cancel_kind (void)
9096 : {
9097 492 : if (gfc_match_space () != MATCH_YES)
9098 : return OMP_CANCEL_UNKNOWN;
9099 492 : if (gfc_match ("parallel") == MATCH_YES)
9100 : return OMP_CANCEL_PARALLEL;
9101 352 : if (gfc_match ("sections") == MATCH_YES)
9102 : return OMP_CANCEL_SECTIONS;
9103 253 : if (gfc_match ("do") == MATCH_YES)
9104 : return OMP_CANCEL_DO;
9105 123 : if (gfc_match ("taskgroup") == MATCH_YES)
9106 : return OMP_CANCEL_TASKGROUP;
9107 : return OMP_CANCEL_UNKNOWN;
9108 : }
9109 :
9110 :
9111 : match
9112 319 : gfc_match_omp_cancel (void)
9113 : {
9114 319 : gfc_omp_clauses *c;
9115 319 : enum gfc_omp_cancel_kind kind = gfc_match_omp_cancel_kind ();
9116 319 : if (kind == OMP_CANCEL_UNKNOWN)
9117 : return MATCH_ERROR;
9118 319 : if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_IF), false) != MATCH_YES)
9119 : return MATCH_ERROR;
9120 316 : c->cancel = kind;
9121 316 : new_st.op = EXEC_OMP_CANCEL;
9122 316 : new_st.ext.omp_clauses = c;
9123 316 : return MATCH_YES;
9124 : }
9125 :
9126 :
9127 : match
9128 173 : gfc_match_omp_cancellation_point (void)
9129 : {
9130 173 : gfc_omp_clauses *c;
9131 173 : enum gfc_omp_cancel_kind kind = gfc_match_omp_cancel_kind ();
9132 173 : if (kind == OMP_CANCEL_UNKNOWN)
9133 : {
9134 2 : gfc_error ("Expected construct-type PARALLEL, SECTIONS, DO or TASKGROUP "
9135 : "in $OMP CANCELLATION POINT statement at %C");
9136 2 : return MATCH_ERROR;
9137 : }
9138 171 : if (gfc_match_omp_eos () != MATCH_YES)
9139 : {
9140 0 : gfc_error ("Unexpected junk after $OMP CANCELLATION POINT statement "
9141 : "at %C");
9142 0 : return MATCH_ERROR;
9143 : }
9144 171 : c = gfc_get_omp_clauses ();
9145 171 : c->cancel = kind;
9146 171 : new_st.op = EXEC_OMP_CANCELLATION_POINT;
9147 171 : new_st.ext.omp_clauses = c;
9148 171 : return MATCH_YES;
9149 : }
9150 :
9151 :
9152 : match
9153 2733 : gfc_match_omp_end_nowait (void)
9154 : {
9155 2733 : bool nowait = false;
9156 2733 : if (gfc_match ("% nowait") == MATCH_YES)
9157 258 : nowait = true;
9158 2733 : if (gfc_match_omp_eos () != MATCH_YES)
9159 : {
9160 4 : if (nowait)
9161 3 : gfc_error ("Unexpected junk after NOWAIT clause at %C");
9162 : else
9163 1 : gfc_error ("Unexpected junk at %C");
9164 4 : return MATCH_ERROR;
9165 : }
9166 2729 : new_st.op = EXEC_OMP_END_NOWAIT;
9167 2729 : new_st.ext.omp_bool = nowait;
9168 2729 : return MATCH_YES;
9169 : }
9170 :
9171 :
9172 : match
9173 566 : gfc_match_omp_end_single (void)
9174 : {
9175 566 : gfc_omp_clauses *c;
9176 566 : if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_COPYPRIVATE)
9177 : | OMP_CLAUSE_NOWAIT) != MATCH_YES)
9178 : return MATCH_ERROR;
9179 566 : new_st.op = EXEC_OMP_END_SINGLE;
9180 566 : new_st.ext.omp_clauses = c;
9181 566 : return MATCH_YES;
9182 : }
9183 :
9184 :
9185 : static bool
9186 37142 : oacc_is_loop (gfc_code *code)
9187 : {
9188 37142 : return code->op == EXEC_OACC_PARALLEL_LOOP
9189 : || code->op == EXEC_OACC_KERNELS_LOOP
9190 20087 : || code->op == EXEC_OACC_SERIAL_LOOP
9191 13457 : || code->op == EXEC_OACC_LOOP;
9192 : }
9193 :
9194 : static void
9195 5982 : resolve_scalar_int_expr (gfc_expr *expr, const char *clause)
9196 : {
9197 5982 : if (!gfc_resolve_expr (expr)
9198 5982 : || expr->ts.type != BT_INTEGER
9199 11893 : || expr->rank != 0)
9200 89 : gfc_error ("%s clause at %L requires a scalar INTEGER expression",
9201 : clause, &expr->where);
9202 5982 : }
9203 :
9204 : static void
9205 4090 : resolve_positive_int_expr (gfc_expr *expr, const char *clause)
9206 : {
9207 4090 : resolve_scalar_int_expr (expr, clause);
9208 4090 : if (expr->expr_type == EXPR_CONSTANT
9209 3660 : && expr->ts.type == BT_INTEGER
9210 3627 : && mpz_sgn (expr->value.integer) <= 0)
9211 54 : gfc_warning ((flag_openmp || flag_openmp_simd) ? OPT_Wopenmp : 0,
9212 : "INTEGER expression of %s clause at %L must be positive",
9213 : clause, &expr->where);
9214 4090 : }
9215 :
9216 : static void
9217 86 : resolve_nonnegative_int_expr (gfc_expr *expr, const char *clause)
9218 : {
9219 86 : resolve_scalar_int_expr (expr, clause);
9220 86 : if (expr->expr_type == EXPR_CONSTANT
9221 13 : && expr->ts.type == BT_INTEGER
9222 11 : && mpz_sgn (expr->value.integer) < 0)
9223 6 : gfc_warning ((flag_openmp || flag_openmp_simd) ? OPT_Wopenmp : 0,
9224 : "INTEGER expression of %s clause at %L must be non-negative",
9225 : clause, &expr->where);
9226 86 : }
9227 :
9228 : /* Emits error when symbol is pointer, cray pointer or cray pointee
9229 : of derived of polymorphic type. */
9230 :
9231 : static void
9232 98 : check_symbol_not_pointer (gfc_symbol *sym, locus loc, const char *name)
9233 : {
9234 98 : if (sym->ts.type == BT_DERIVED && sym->attr.cray_pointer)
9235 0 : gfc_error ("Cray pointer object %qs of derived type in %s clause at %L",
9236 : sym->name, name, &loc);
9237 98 : if (sym->ts.type == BT_DERIVED && sym->attr.cray_pointee)
9238 0 : gfc_error ("Cray pointee object %qs of derived type in %s clause at %L",
9239 : sym->name, name, &loc);
9240 :
9241 98 : if ((sym->ts.type == BT_ASSUMED && sym->attr.pointer)
9242 98 : || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
9243 0 : && CLASS_DATA (sym)->attr.pointer))
9244 0 : gfc_error ("POINTER object %qs of polymorphic type in %s clause at %L",
9245 : sym->name, name, &loc);
9246 98 : if ((sym->ts.type == BT_ASSUMED && sym->attr.cray_pointer)
9247 98 : || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
9248 0 : && CLASS_DATA (sym)->attr.cray_pointer))
9249 0 : gfc_error ("Cray pointer object %qs of polymorphic type in %s clause at %L",
9250 : sym->name, name, &loc);
9251 98 : if ((sym->ts.type == BT_ASSUMED && sym->attr.cray_pointee)
9252 98 : || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
9253 0 : && CLASS_DATA (sym)->attr.cray_pointee))
9254 0 : gfc_error ("Cray pointee object %qs of polymorphic type in %s clause at %L",
9255 : sym->name, name, &loc);
9256 98 : }
9257 :
9258 : /* Emits error when symbol represents assumed size/rank array. */
9259 :
9260 : static void
9261 14844 : check_array_not_assumed (gfc_symbol *sym, locus loc, const char *name)
9262 : {
9263 14844 : if (sym->as && sym->as->type == AS_ASSUMED_SIZE)
9264 13 : gfc_error ("Assumed size array %qs in %s clause at %L",
9265 : sym->name, name, &loc);
9266 14844 : if (sym->as && sym->as->type == AS_ASSUMED_RANK)
9267 11 : gfc_error ("Assumed rank array %qs in %s clause at %L",
9268 : sym->name, name, &loc);
9269 14844 : }
9270 :
9271 : static void
9272 5850 : resolve_oacc_data_clauses (gfc_symbol *sym, locus loc, const char *name)
9273 : {
9274 0 : check_array_not_assumed (sym, loc, name);
9275 0 : }
9276 :
9277 : static void
9278 65 : resolve_oacc_deviceptr_clause (gfc_symbol *sym, locus loc, const char *name)
9279 : {
9280 65 : if (sym->attr.pointer
9281 64 : || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
9282 0 : && CLASS_DATA (sym)->attr.class_pointer))
9283 1 : gfc_error ("POINTER object %qs in %s clause at %L",
9284 : sym->name, name, &loc);
9285 65 : if (sym->attr.cray_pointer
9286 63 : || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
9287 0 : && CLASS_DATA (sym)->attr.cray_pointer))
9288 2 : gfc_error ("Cray pointer object %qs in %s clause at %L",
9289 : sym->name, name, &loc);
9290 65 : if (sym->attr.cray_pointee
9291 63 : || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
9292 0 : && CLASS_DATA (sym)->attr.cray_pointee))
9293 2 : gfc_error ("Cray pointee object %qs in %s clause at %L",
9294 : sym->name, name, &loc);
9295 65 : if (sym->attr.allocatable
9296 64 : || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
9297 0 : && CLASS_DATA (sym)->attr.allocatable))
9298 1 : gfc_error ("ALLOCATABLE object %qs in %s clause at %L",
9299 : sym->name, name, &loc);
9300 65 : if (sym->attr.value)
9301 1 : gfc_error ("VALUE object %qs in %s clause at %L",
9302 : sym->name, name, &loc);
9303 65 : check_array_not_assumed (sym, loc, name);
9304 65 : }
9305 :
9306 :
9307 : struct resolve_omp_udr_callback_data
9308 : {
9309 : gfc_symbol *sym1, *sym2;
9310 : };
9311 :
9312 :
9313 : static int
9314 1413 : resolve_omp_udr_callback (gfc_expr **e, int *, void *data)
9315 : {
9316 1413 : struct resolve_omp_udr_callback_data *rcd
9317 : = (struct resolve_omp_udr_callback_data *) data;
9318 1413 : if ((*e)->expr_type == EXPR_VARIABLE
9319 801 : && ((*e)->symtree->n.sym == rcd->sym1
9320 255 : || (*e)->symtree->n.sym == rcd->sym2))
9321 : {
9322 801 : gfc_ref *ref = gfc_get_ref ();
9323 801 : ref->type = REF_ARRAY;
9324 801 : ref->u.ar.where = (*e)->where;
9325 801 : ref->u.ar.as = (*e)->symtree->n.sym->as;
9326 801 : ref->u.ar.type = AR_FULL;
9327 801 : ref->u.ar.dimen = 0;
9328 801 : ref->next = (*e)->ref;
9329 801 : (*e)->ref = ref;
9330 : }
9331 1413 : return 0;
9332 : }
9333 :
9334 :
9335 : static int
9336 3004 : resolve_omp_udr_callback2 (gfc_expr **e, int *, void *)
9337 : {
9338 3004 : if ((*e)->expr_type == EXPR_FUNCTION
9339 360 : && (*e)->value.function.isym == NULL)
9340 : {
9341 174 : gfc_symbol *sym = (*e)->symtree->n.sym;
9342 174 : if (!sym->attr.intrinsic
9343 174 : && sym->attr.if_source == IFSRC_UNKNOWN)
9344 4 : gfc_error ("Implicitly declared function %s used in "
9345 : "!$OMP DECLARE REDUCTION at %L", sym->name, &(*e)->where);
9346 : }
9347 3004 : return 0;
9348 : }
9349 :
9350 :
9351 : static gfc_code *
9352 801 : resolve_omp_udr_clause (gfc_omp_namelist *n, gfc_namespace *ns,
9353 : gfc_symbol *sym1, gfc_symbol *sym2)
9354 : {
9355 801 : gfc_code *copy;
9356 801 : gfc_symbol sym1_copy, sym2_copy;
9357 :
9358 801 : if (ns->code->op == EXEC_ASSIGN)
9359 : {
9360 629 : copy = gfc_get_code (EXEC_ASSIGN);
9361 629 : copy->expr1 = gfc_copy_expr (ns->code->expr1);
9362 629 : copy->expr2 = gfc_copy_expr (ns->code->expr2);
9363 : }
9364 : else
9365 : {
9366 172 : copy = gfc_get_code (EXEC_CALL);
9367 172 : copy->symtree = ns->code->symtree;
9368 172 : copy->ext.actual = gfc_copy_actual_arglist (ns->code->ext.actual);
9369 : }
9370 801 : copy->loc = ns->code->loc;
9371 801 : sym1_copy = *sym1;
9372 801 : sym2_copy = *sym2;
9373 801 : *sym1 = *n->sym;
9374 801 : *sym2 = *n->sym;
9375 801 : sym1->name = sym1_copy.name;
9376 801 : sym2->name = sym2_copy.name;
9377 801 : ns->proc_name = ns->parent->proc_name;
9378 801 : if (n->sym->attr.dimension)
9379 : {
9380 348 : struct resolve_omp_udr_callback_data rcd;
9381 348 : rcd.sym1 = sym1;
9382 348 : rcd.sym2 = sym2;
9383 348 : gfc_code_walker (©, gfc_dummy_code_callback,
9384 : resolve_omp_udr_callback, &rcd);
9385 : }
9386 801 : gfc_resolve_code (copy, gfc_current_ns);
9387 801 : if (copy->op == EXEC_CALL && copy->resolved_isym == NULL)
9388 : {
9389 172 : gfc_symbol *sym = copy->resolved_sym;
9390 172 : if (sym
9391 170 : && !sym->attr.intrinsic
9392 170 : && sym->attr.if_source == IFSRC_UNKNOWN)
9393 4 : gfc_error ("Implicitly declared subroutine %s used in "
9394 : "!$OMP DECLARE REDUCTION at %L", sym->name,
9395 : ©->loc);
9396 : }
9397 801 : gfc_code_walker (©, gfc_dummy_code_callback,
9398 : resolve_omp_udr_callback2, NULL);
9399 801 : *sym1 = sym1_copy;
9400 801 : *sym2 = sym2_copy;
9401 801 : return copy;
9402 : }
9403 :
9404 : /* Assume that a constant expression in the range 1 (omp_default_mem_alloc)
9405 : to GOMP_OMP_PREDEF_ALLOC_MAX, or GOMP_OMPX_PREDEF_ALLOC_MIN to
9406 : GOMP_OMPX_PREDEF_ALLOC_MAX is fine. The original symbol name is already
9407 : lost during matching via gfc_match_expr. */
9408 : static bool
9409 130 : is_predefined_allocator (gfc_expr *expr)
9410 : {
9411 130 : return (gfc_resolve_expr (expr)
9412 129 : && expr->rank == 0
9413 124 : && expr->ts.type == BT_INTEGER
9414 119 : && expr->ts.kind == gfc_c_intptr_kind
9415 114 : && expr->expr_type == EXPR_CONSTANT
9416 239 : && ((mpz_sgn (expr->value.integer) > 0
9417 107 : && mpz_cmp_si (expr->value.integer,
9418 : GOMP_OMP_PREDEF_ALLOC_MAX) <= 0)
9419 4 : || (mpz_cmp_si (expr->value.integer,
9420 : GOMP_OMPX_PREDEF_ALLOC_MIN) >= 0
9421 1 : && mpz_cmp_si (expr->value.integer,
9422 130 : GOMP_OMPX_PREDEF_ALLOC_MAX) <= 0)));
9423 : }
9424 :
9425 : /* Resolve declarative ALLOCATE statement. Note: Common block vars only appear
9426 : as /block/ not individual, which is ensured during parsing. */
9427 :
9428 : void
9429 62 : gfc_resolve_omp_allocate (gfc_namespace *ns, gfc_omp_namelist *list)
9430 : {
9431 278 : for (gfc_omp_namelist *n = list; n; n = n->next)
9432 : {
9433 216 : if (n->sym->attr.result || n->sym->result == n->sym)
9434 : {
9435 1 : gfc_error ("Unexpected function-result variable %qs at %L in "
9436 : "declarative !$OMP ALLOCATE", n->sym->name, &n->where);
9437 31 : continue;
9438 : }
9439 215 : if (ns->omp_allocate->sym->attr.proc_pointer)
9440 : {
9441 0 : gfc_error ("Procedure pointer %qs not supported with !$OMP "
9442 : "ALLOCATE at %L", n->sym->name, &n->where);
9443 0 : continue;
9444 : }
9445 215 : if (n->sym->attr.flavor != FL_VARIABLE)
9446 : {
9447 3 : gfc_error ("Argument %qs at %L to declarative !$OMP ALLOCATE "
9448 : "directive must be a variable", n->sym->name,
9449 : &n->where);
9450 3 : continue;
9451 : }
9452 212 : if (ns != n->sym->ns || n->sym->attr.use_assoc || n->sym->attr.imported)
9453 : {
9454 8 : gfc_error ("Argument %qs at %L to declarative !$OMP ALLOCATE shall be"
9455 : " in the same scope as the variable declaration",
9456 : n->sym->name, &n->where);
9457 8 : continue;
9458 : }
9459 204 : if (n->sym->attr.dummy)
9460 : {
9461 3 : gfc_error ("Unexpected dummy argument %qs as argument at %L to "
9462 : "declarative !$OMP ALLOCATE", n->sym->name, &n->where);
9463 3 : continue;
9464 : }
9465 201 : if (n->sym->attr.codimension)
9466 : {
9467 0 : gfc_error ("Unexpected coarray argument %qs as argument at %L to "
9468 : "declarative !$OMP ALLOCATE", n->sym->name, &n->where);
9469 0 : continue;
9470 : }
9471 201 : if (n->sym->attr.omp_allocate)
9472 : {
9473 5 : if (n->sym->attr.in_common)
9474 : {
9475 1 : gfc_error ("Duplicated common block %</%s/%> in !$OMP ALLOCATE "
9476 1 : "at %L", n->sym->common_head->name, &n->where);
9477 3 : while (n->next && n->next->sym
9478 3 : && n->sym->common_head == n->next->sym->common_head)
9479 : n = n->next;
9480 : }
9481 : else
9482 4 : gfc_error ("Duplicated variable %qs in !$OMP ALLOCATE at %L",
9483 : n->sym->name, &n->where);
9484 5 : continue;
9485 : }
9486 : /* For 'equivalence(a,b)', a 'union_type {<type> a,b} equiv.0' is created
9487 : with a value expression for 'a' as 'equiv.0.a' (likewise for b); while
9488 : this can be handled, EQUIVALENCE is marked as obsolescent since Fortran
9489 : 2018 and also not widely used. However, it could be supported,
9490 : if needed. */
9491 196 : if (n->sym->attr.in_equivalence)
9492 : {
9493 2 : gfc_error ("Sorry, EQUIVALENCE object %qs not supported with !$OMP "
9494 : "ALLOCATE at %L", n->sym->name, &n->where);
9495 2 : continue;
9496 : }
9497 : /* Similar for Cray pointer/pointee - they could be implemented but as
9498 : common vendor extension but nowadays rarely used and requiring
9499 : -fcray-pointer, there is no need to support them. */
9500 194 : if (n->sym->attr.cray_pointer || n->sym->attr.cray_pointee)
9501 : {
9502 2 : gfc_error ("Sorry, Cray pointers and pointees such as %qs are not "
9503 : "supported with !$OMP ALLOCATE at %L",
9504 : n->sym->name, &n->where);
9505 2 : continue;
9506 : }
9507 192 : n->sym->attr.omp_allocate = 1;
9508 192 : if ((n->sym->ts.type == BT_CLASS && n->sym->attr.class_ok
9509 0 : && CLASS_DATA (n->sym)->attr.allocatable)
9510 192 : || (n->sym->ts.type != BT_CLASS && n->sym->attr.allocatable))
9511 1 : gfc_error ("Unexpected allocatable variable %qs at %L in declarative "
9512 : "!$OMP ALLOCATE directive", n->sym->name, &n->where);
9513 191 : else if ((n->sym->ts.type == BT_CLASS && n->sym->attr.class_ok
9514 0 : && CLASS_DATA (n->sym)->attr.class_pointer)
9515 191 : || (n->sym->ts.type != BT_CLASS && n->sym->attr.pointer))
9516 1 : gfc_error ("Unexpected pointer variable %qs at %L in declarative "
9517 : "!$OMP ALLOCATE directive", n->sym->name, &n->where);
9518 192 : HOST_WIDE_INT alignment = 0;
9519 198 : if (n->u.align
9520 192 : && (!gfc_resolve_expr (n->u.align)
9521 27 : || n->u.align->ts.type != BT_INTEGER
9522 26 : || n->u.align->rank != 0
9523 24 : || n->u.align->expr_type != EXPR_CONSTANT
9524 23 : || gfc_extract_hwi (n->u.align, &alignment)
9525 23 : || !pow2p_hwi (alignment)))
9526 : {
9527 6 : gfc_error ("ALIGN requires a scalar positive constant integer "
9528 : "alignment expression at %L that is a power of two",
9529 6 : &n->u.align->where);
9530 6 : while (n->sym->attr.in_common && n->next && n->next->sym
9531 6 : && n->sym->common_head == n->next->sym->common_head)
9532 : n = n->next;
9533 6 : continue;
9534 : }
9535 186 : if (n->sym->attr.in_common || n->sym->attr.save || n->sym->ns->save_all
9536 63 : || (n->sym->ns->proc_name
9537 63 : && (n->sym->ns->proc_name->attr.flavor == FL_PROGRAM
9538 55 : || n->sym->ns->proc_name->attr.flavor == FL_MODULE
9539 55 : || n->sym->ns->proc_name->attr.flavor == FL_BLOCK_DATA)))
9540 : {
9541 131 : bool com = n->sym->attr.in_common;
9542 131 : if (!n->u2.allocator)
9543 1 : gfc_error ("An ALLOCATOR clause is required as the list item "
9544 : "%<%s%s%s%> at %L has the SAVE attribute", com ? "/" : "",
9545 0 : com ? n->sym->common_head->name : n->sym->name,
9546 : com ? "/" : "", &n->where);
9547 130 : else if (!is_predefined_allocator (n->u2.allocator))
9548 24 : gfc_error ("Predefined allocator required in ALLOCATOR clause at %L"
9549 : " as the list item %<%s%s%s%> at %L has the SAVE attribute",
9550 24 : &n->u2.allocator->where, com ? "/" : "",
9551 24 : com ? n->sym->common_head->name : n->sym->name,
9552 : com ? "/" : "", &n->where);
9553 : /* Static variables may not use omp_cgroup_mem_alloc (6),
9554 : omp_pteam_mem_alloc (7), or omp_thread_mem_alloc (8). */
9555 106 : else if (mpz_cmp_si (n->u2.allocator->value.integer,
9556 : 6 /* cgroup */) >= 0
9557 34 : && mpz_cmp_si (n->u2.allocator->value.integer,
9558 : 8 /* thread */) <= 0)
9559 : {
9560 33 : STATIC_ASSERT (GOMP_OMP_PREDEF_ALLOC_CGROUP == 6);
9561 33 : STATIC_ASSERT (GOMP_OMP_PREDEF_ALLOC_PTEAM == 7);
9562 33 : STATIC_ASSERT (GOMP_OMP_PREDEF_ALLOC_THREAD == 8);
9563 33 : const char *alloc_name[] = {"omp_cgroup_mem_alloc",
9564 : "omp_pteam_mem_alloc",
9565 : "omp_thread_mem_alloc" };
9566 33 : gfc_error ("Predefined allocator %qs in ALLOCATOR clause at %L, "
9567 : "used for list item %<%s%s%s%> at %L, may not be used"
9568 : " for static variables",
9569 33 : alloc_name[mpz_get_ui (n->u2.allocator->value.integer)
9570 33 : - 6 /* cgroup */], &n->u2.allocator->where,
9571 : com ? "/" : "",
9572 33 : com ? n->sym->common_head->name : n->sym->name,
9573 : com ? "/" : "", &n->where);
9574 : }
9575 67 : while (n->sym->attr.in_common && n->next && n->next->sym
9576 186 : && n->sym->common_head == n->next->sym->common_head)
9577 : n = n->next;
9578 : }
9579 55 : else if (n->u2.allocator
9580 55 : && (!gfc_resolve_expr (n->u2.allocator)
9581 20 : || n->u2.allocator->ts.type != BT_INTEGER
9582 19 : || n->u2.allocator->rank != 0
9583 18 : || n->u2.allocator->ts.kind != gfc_c_intptr_kind))
9584 3 : gfc_error ("Expected integer expression of the "
9585 : "%<omp_allocator_handle_kind%> kind at %L",
9586 3 : &n->u2.allocator->where);
9587 : }
9588 62 : }
9589 :
9590 : /* Resolve ASSUME's and ASSUMES' assumption clauses. Note that absent/contains
9591 : is handled during parse time in omp_verify_merge_absent_contains. */
9592 :
9593 : void
9594 29 : gfc_resolve_omp_assumptions (gfc_omp_assumptions *assume)
9595 : {
9596 46 : for (gfc_expr_list *el = assume->holds; el; el = el->next)
9597 17 : if (!gfc_resolve_expr (el->expr)
9598 17 : || el->expr->ts.type != BT_LOGICAL
9599 32 : || el->expr->rank != 0)
9600 4 : gfc_error ("HOLDS expression at %L must be a scalar logical expression",
9601 4 : &el->expr->where);
9602 29 : }
9603 :
9604 :
9605 : /* Resolve the OpenMP ALLOCATE clauses. */
9606 :
9607 : static void
9608 33042 : resolve_omp_allocate_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
9609 : gfc_namespace *ns)
9610 : {
9611 33042 : gfc_omp_namelist *n;
9612 33042 : enum gfc_omp_list_type list;
9613 :
9614 33042 : if (!omp_clauses->lists[OMP_LIST_ALLOCATE])
9615 : return;
9616 795 : for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; n = n->next)
9617 : {
9618 515 : if (n->u2.allocator
9619 515 : && (!gfc_resolve_expr (n->u2.allocator)
9620 290 : || n->u2.allocator->ts.type != BT_INTEGER
9621 288 : || n->u2.allocator->rank != 0
9622 287 : || n->u2.allocator->ts.kind != gfc_c_intptr_kind))
9623 : {
9624 8 : gfc_error ("Expected integer expression of the "
9625 : "%<omp_allocator_handle_kind%> kind at %L",
9626 8 : &n->u2.allocator->where);
9627 28 : break;
9628 : }
9629 507 : if (!n->u.align)
9630 399 : continue;
9631 108 : HOST_WIDE_INT alignment = 0;
9632 108 : if (!gfc_resolve_expr (n->u.align)
9633 108 : || n->u.align->ts.type != BT_INTEGER
9634 105 : || n->u.align->rank != 0
9635 102 : || n->u.align->expr_type != EXPR_CONSTANT
9636 99 : || gfc_extract_hwi (n->u.align, &alignment)
9637 99 : || alignment <= 0
9638 207 : || !pow2p_hwi (alignment))
9639 : {
9640 12 : gfc_error ("ALIGN requires a scalar positive constant integer "
9641 : "alignment expression at %L that is a power of two",
9642 12 : &n->u.align->where);
9643 12 : break;
9644 : }
9645 : }
9646 :
9647 : /* Check for 2 things here.
9648 : 1. There is no duplication of variable in allocate clause.
9649 : 2. Variable in allocate clause are also present in some
9650 : privatization clase (non-composite case). */
9651 815 : for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; n = n->next)
9652 515 : if (n->sym)
9653 489 : n->sym->mark = 0;
9654 :
9655 : gfc_omp_namelist *prev = NULL;
9656 815 : for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; )
9657 : {
9658 515 : if (n->sym == NULL)
9659 : {
9660 26 : n = n->next;
9661 26 : continue;
9662 : }
9663 489 : if (n->sym->mark == 1)
9664 : {
9665 3 : gfc_warning (OPT_Wopenmp, "%qs appears more than once in "
9666 : "%<allocate%> at %L" , n->sym->name, &n->where);
9667 : /* We have already seen this variable so it is a duplicate.
9668 : Remove it. */
9669 3 : if (prev != NULL && prev->next == n)
9670 : {
9671 3 : prev->next = n->next;
9672 3 : n->next = NULL;
9673 3 : gfc_free_omp_namelist (n, OMP_LIST_ALLOCATE);
9674 3 : n = prev->next;
9675 : }
9676 3 : continue;
9677 : }
9678 486 : n->sym->mark = 1;
9679 486 : prev = n;
9680 486 : n = n->next;
9681 : }
9682 :
9683 : /* Non-composite constructs. */
9684 300 : if (code && code->op < EXEC_OMP_DO_SIMD)
9685 : {
9686 4760 : for (list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
9687 4641 : list = gfc_omp_list_type (list + 1))
9688 4641 : switch (list)
9689 : {
9690 1071 : case OMP_LIST_PRIVATE:
9691 1071 : case OMP_LIST_FIRSTPRIVATE:
9692 1071 : case OMP_LIST_LASTPRIVATE:
9693 1071 : case OMP_LIST_REDUCTION:
9694 1071 : case OMP_LIST_REDUCTION_INSCAN:
9695 1071 : case OMP_LIST_REDUCTION_TASK:
9696 1071 : case OMP_LIST_IN_REDUCTION:
9697 1071 : case OMP_LIST_TASK_REDUCTION:
9698 1071 : case OMP_LIST_LINEAR:
9699 1370 : for (n = omp_clauses->lists[list]; n; n = n->next)
9700 299 : n->sym->mark = 0;
9701 : break;
9702 : default:
9703 : break;
9704 : }
9705 :
9706 410 : for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; n = n->next)
9707 291 : if (n->sym->mark == 1)
9708 4 : gfc_error ("%qs specified in %<allocate%> clause at %L but not "
9709 : "in an explicit privatization clause",
9710 : n->sym->name, &n->where);
9711 : }
9712 71 : if (!(code
9713 300 : && (code->op == EXEC_OMP_ALLOCATORS || code->op == EXEC_OMP_ALLOCATE)
9714 73 : && code->block
9715 72 : && code->block->next
9716 71 : && code->block->next->op == EXEC_ALLOCATE))
9717 232 : return;
9718 :
9719 68 : if (code->op == EXEC_OMP_ALLOCATE)
9720 49 : gfc_warning (OPT_Wdeprecated_openmp,
9721 : "The use of one or more %<allocate%> directives with "
9722 : "an associated %<allocate%> statement at %L is "
9723 : "deprecated since OpenMP 5.2, use an %<allocators%> "
9724 : "directive", &code->loc);
9725 68 : gfc_alloc *a;
9726 68 : gfc_omp_namelist *n_null = NULL;
9727 68 : bool missing_allocator = false;
9728 68 : gfc_symbol *missing_allocator_sym = NULL;
9729 161 : for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; n = n->next)
9730 : {
9731 93 : if (n->u2.allocator == NULL)
9732 : {
9733 77 : if (!missing_allocator_sym)
9734 59 : missing_allocator_sym = n->sym;
9735 : missing_allocator = true;
9736 : }
9737 93 : if (n->sym == NULL)
9738 : {
9739 26 : n_null = n;
9740 26 : continue;
9741 : }
9742 67 : if (n->sym->attr.codimension)
9743 2 : gfc_error ("Unexpected coarray %qs in %<allocate%> at %L",
9744 : n->sym->name, &n->where);
9745 103 : for (a = code->block->next->ext.alloc.list; a; a = a->next)
9746 101 : if (a->expr->expr_type == EXPR_VARIABLE
9747 101 : && a->expr->symtree->n.sym == n->sym)
9748 : {
9749 65 : gfc_ref *ref;
9750 82 : for (ref = a->expr->ref; ref; ref = ref->next)
9751 17 : if (ref->type == REF_COMPONENT)
9752 : break;
9753 : if (ref == NULL)
9754 : break;
9755 : }
9756 67 : if (a == NULL)
9757 2 : gfc_error ("%qs specified in %<allocate%> at %L but not "
9758 : "in the associated ALLOCATE statement",
9759 2 : n->sym->name, &n->where);
9760 : }
9761 : /* If there is an ALLOCATE directive without list argument, a
9762 : namelist with its allocator/align clauses and n->sym = NULL is
9763 : created during parsing; here, we add all not otherwise specified
9764 : items from the Fortran allocate to that list.
9765 : For an ALLOCATORS directive, not listed items use the normal
9766 : Fortran way.
9767 : The behavior of an ALLOCATE directive that does not list all
9768 : arguments but there is no directive without list argument is not
9769 : well specified. Thus, we reject such code below. In OpenMP 5.2
9770 : the executable ALLOCATE directive is deprecated and in 6.0
9771 : deleted such that no spec clarification is to be expected. */
9772 125 : for (a = code->block->next->ext.alloc.list; a; a = a->next)
9773 89 : if (a->expr->expr_type == EXPR_VARIABLE)
9774 : {
9775 154 : for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; n = n->next)
9776 122 : if (a->expr->symtree->n.sym == n->sym)
9777 : {
9778 57 : gfc_ref *ref;
9779 72 : for (ref = a->expr->ref; ref; ref = ref->next)
9780 15 : if (ref->type == REF_COMPONENT)
9781 : break;
9782 : if (ref == NULL)
9783 : break;
9784 : }
9785 89 : if (n == NULL && n_null == NULL)
9786 : {
9787 : /* OK for ALLOCATORS but for ALLOCATE: Unspecified whether
9788 : that should use the default allocator of OpenMP or the
9789 : Fortran allocator. Thus, just reject it. */
9790 7 : if (code->op == EXEC_OMP_ALLOCATE)
9791 1 : gfc_error ("%qs listed in %<allocate%> statement at %L "
9792 : "but it is neither explicitly in listed in "
9793 : "the %<!$OMP ALLOCATE%> directive nor exists"
9794 : " a directive without argument list",
9795 1 : a->expr->symtree->n.sym->name,
9796 : &a->expr->where);
9797 : break;
9798 : }
9799 82 : if (n == NULL)
9800 : {
9801 25 : if (a->expr->symtree->n.sym->attr.codimension)
9802 1 : gfc_error ("Unexpected coarray %qs in %<allocate%> at "
9803 : "%L, implicitly listed in %<!$OMP ALLOCATE%>"
9804 : " at %L", a->expr->symtree->n.sym->name,
9805 : &a->expr->where, &n_null->where);
9806 : break;
9807 : }
9808 : }
9809 68 : gfc_namespace *prog_unit = ns;
9810 87 : while (prog_unit->parent)
9811 : prog_unit = prog_unit->parent;
9812 : gfc_namespace *fn_ns = ns;
9813 72 : while (fn_ns)
9814 : {
9815 70 : if (ns->proc_name
9816 70 : && (ns->proc_name->attr.subroutine
9817 6 : || ns->proc_name->attr.function))
9818 : break;
9819 4 : fn_ns = fn_ns->parent;
9820 : }
9821 68 : if (missing_allocator
9822 58 : && !(prog_unit->omp_requires & OMP_REQ_DYNAMIC_ALLOCATORS)
9823 58 : && ((fn_ns && fn_ns->proc_name->attr.omp_declare_target)
9824 55 : || omp_clauses->contained_in_target_construct))
9825 : {
9826 6 : if (code->op == EXEC_OMP_ALLOCATORS)
9827 2 : gfc_error ("ALLOCATORS directive at %L inside a target region "
9828 : "must specify an ALLOCATOR modifier for %qs",
9829 : &code->loc, missing_allocator_sym->name);
9830 4 : else if (missing_allocator_sym)
9831 2 : gfc_error ("ALLOCATE directive at %L inside a target region "
9832 : "must specify an ALLOCATOR clause for %qs",
9833 : &code->loc, missing_allocator_sym->name);
9834 : else
9835 2 : gfc_error ("ALLOCATE directive at %L inside a target region "
9836 : "must specify an ALLOCATOR clause", &code->loc);
9837 : }
9838 : }
9839 :
9840 :
9841 : /* Diagnose list items that appear multiple times in OpenMP or OpenACC clauses,
9842 : unless permitted by the specification. */
9843 :
9844 : static void
9845 33042 : check_omp_clauses_dupl_syms (gfc_code *code, gfc_omp_clauses *omp_clauses,
9846 : bool openacc)
9847 : {
9848 33042 : gfc_omp_namelist *n;
9849 33042 : enum gfc_omp_list_type list;
9850 :
9851 : /* Check that no symbol appears on multiple clauses, except that
9852 : a symbol can appear on both firstprivate and lastprivate. */
9853 1321680 : for (list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
9854 1288638 : list = gfc_omp_list_type (list + 1))
9855 1334473 : for (n = omp_clauses->lists[list]; n; n = n->next)
9856 : {
9857 45835 : if (!n->sym) /* omp_all_memory. */
9858 47 : continue;
9859 45788 : n->sym->mark = 0;
9860 45788 : n->sym->comp_mark = 0;
9861 45788 : n->sym->data_mark = 0;
9862 45788 : n->sym->dev_mark = 0;
9863 45788 : n->sym->gen_mark = 0;
9864 45788 : n->sym->reduc_mark = 0;
9865 : }
9866 1321680 : for (list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
9867 1288638 : list = gfc_omp_list_type (list + 1))
9868 1288638 : if (list != OMP_LIST_FIRSTPRIVATE
9869 1288638 : && list != OMP_LIST_LASTPRIVATE
9870 1288638 : && list != OMP_LIST_ALIGNED
9871 1189512 : && list != OMP_LIST_DEPEND
9872 1189512 : && list != OMP_LIST_FROM
9873 1123428 : && list != OMP_LIST_TO
9874 1123428 : && list != OMP_LIST_INTEROP
9875 1057344 : && (list != OMP_LIST_REDUCTION || !openacc)
9876 1044349 : && list != OMP_LIST_ALLOCATE)
9877 1046234 : for (n = omp_clauses->lists[list]; n; n = n->next)
9878 : {
9879 34927 : bool component_ref_p = false;
9880 :
9881 : /* Allow multiple components of the same (e.g. derived-type)
9882 : variable here. Duplicate components are detected elsewhere. */
9883 34927 : if (n->expr && n->expr->expr_type == EXPR_VARIABLE)
9884 16007 : for (gfc_ref *ref = n->expr->ref; ref; ref = ref->next)
9885 9737 : if (ref->type == REF_COMPONENT)
9886 3190 : component_ref_p = true;
9887 34927 : if ((list == OMP_LIST_IS_DEVICE_PTR
9888 34927 : || list == OMP_LIST_HAS_DEVICE_ADDR)
9889 313 : && !component_ref_p)
9890 : {
9891 313 : if (n->sym->gen_mark
9892 311 : || n->sym->dev_mark
9893 310 : || n->sym->reduc_mark
9894 310 : || n->sym->mark)
9895 5 : gfc_error ("Symbol %qs present on multiple clauses at %L",
9896 : n->sym->name, &n->where);
9897 : else
9898 308 : n->sym->dev_mark = 1;
9899 : }
9900 34614 : else if ((list == OMP_LIST_USE_DEVICE_PTR
9901 34614 : || list == OMP_LIST_USE_DEVICE_ADDR
9902 34614 : || list == OMP_LIST_PRIVATE
9903 : || list == OMP_LIST_SHARED)
9904 12855 : && !component_ref_p)
9905 : {
9906 12855 : if (n->sym->gen_mark || n->sym->dev_mark || n->sym->reduc_mark)
9907 13 : gfc_error ("Symbol %qs present on multiple clauses at %L",
9908 : n->sym->name, &n->where);
9909 : else
9910 : {
9911 12842 : n->sym->gen_mark = 1;
9912 : /* Set both generic and device bits if we have
9913 : use_device_*(x) or shared(x). This allows us to diagnose
9914 : "map(x) private(x)" below. */
9915 12842 : if (list != OMP_LIST_PRIVATE)
9916 3456 : n->sym->dev_mark = 1;
9917 : }
9918 : }
9919 21759 : else if ((list == OMP_LIST_REDUCTION
9920 21759 : || list == OMP_LIST_REDUCTION_TASK
9921 19299 : || list == OMP_LIST_REDUCTION_INSCAN
9922 19299 : || list == OMP_LIST_IN_REDUCTION
9923 19086 : || list == OMP_LIST_TASK_REDUCTION)
9924 2673 : && !component_ref_p)
9925 : {
9926 : /* Attempts to mix reduction types are diagnosed below. */
9927 2673 : if (n->sym->gen_mark || n->sym->dev_mark)
9928 2 : gfc_error ("Symbol %qs present on multiple clauses at %L",
9929 : n->sym->name, &n->where);
9930 2673 : n->sym->reduc_mark = 1;
9931 : }
9932 19086 : else if ((!component_ref_p && n->sym->comp_mark)
9933 19085 : || (component_ref_p && n->sym->mark))
9934 : {
9935 42 : if (openacc)
9936 3 : gfc_error ("Symbol %qs has mixed component and non-component "
9937 3 : "accesses at %L", n->sym->name, &n->where);
9938 : }
9939 19044 : else if ((openacc || list != OMP_LIST_MAP) && n->sym->mark)
9940 88 : gfc_error ("Symbol %qs present on multiple clauses at %L",
9941 : n->sym->name, &n->where);
9942 : else
9943 : {
9944 18956 : if (component_ref_p)
9945 2466 : n->sym->comp_mark = 1;
9946 : else
9947 16490 : n->sym->mark = 1;
9948 : }
9949 : }
9950 :
9951 : /* Detect specifically the case where we have "map(x) private(x)" and raise
9952 : an error. If we have "...simd" combined directives though, the "private"
9953 : applies to the simd part, so this is permitted though. */
9954 42436 : for (n = omp_clauses->lists[OMP_LIST_PRIVATE]; n; n = n->next)
9955 9394 : if (n->sym->mark
9956 6 : && n->sym->gen_mark
9957 6 : && !n->sym->dev_mark
9958 6 : && !n->sym->reduc_mark
9959 5 : && code->op != EXEC_OMP_TARGET_SIMD
9960 : && code->op != EXEC_OMP_TARGET_PARALLEL_DO_SIMD
9961 : && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD
9962 : && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD)
9963 1 : gfc_error ("Symbol %qs present on multiple clauses at %L",
9964 : n->sym->name, &n->where);
9965 :
9966 : gcc_assert (OMP_LIST_LASTPRIVATE == OMP_LIST_FIRSTPRIVATE + 1);
9967 99126 : for (list = OMP_LIST_FIRSTPRIVATE; list <= OMP_LIST_LASTPRIVATE;
9968 66084 : list = gfc_omp_list_type (list + 1))
9969 70307 : for (n = omp_clauses->lists[list]; n; n = n->next)
9970 4223 : if (n->sym->data_mark || n->sym->gen_mark || n->sym->dev_mark)
9971 : {
9972 9 : gfc_error ("Symbol %qs present on multiple clauses at %L",
9973 : n->sym->name, &n->where);
9974 9 : n->sym->data_mark = n->sym->gen_mark = n->sym->dev_mark = 0;
9975 : }
9976 4214 : else if (n->sym->mark
9977 18 : && code->op != EXEC_OMP_TARGET_TEAMS
9978 : && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE
9979 : && code->op != EXEC_OMP_TARGET_TEAMS_LOOP
9980 : && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD
9981 : && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO
9982 : && code->op != EXEC_OMP_TARGET_PARALLEL
9983 : && code->op != EXEC_OMP_TARGET_PARALLEL_DO
9984 : && code->op != EXEC_OMP_TARGET_PARALLEL_LOOP
9985 : && code->op != EXEC_OMP_TARGET_PARALLEL_DO_SIMD
9986 : && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD)
9987 7 : gfc_error ("Symbol %qs present on both data and map clauses "
9988 : "at %L", n->sym->name, &n->where);
9989 :
9990 34957 : for (n = omp_clauses->lists[OMP_LIST_FIRSTPRIVATE]; n; n = n->next)
9991 : {
9992 1915 : if (n->sym->data_mark || n->sym->gen_mark || n->sym->dev_mark)
9993 7 : gfc_error ("Symbol %qs present on multiple clauses at %L",
9994 : n->sym->name, &n->where);
9995 : else
9996 1908 : n->sym->data_mark = 1;
9997 : }
9998 :
9999 : /* LASTPRIVATE clauses. */
10000 35350 : for (n = omp_clauses->lists[OMP_LIST_LASTPRIVATE]; n; n = n->next)
10001 2308 : n->sym->data_mark = 0;
10002 35350 : for (n = omp_clauses->lists[OMP_LIST_LASTPRIVATE]; n; n = n->next)
10003 : {
10004 2308 : if (n->sym->data_mark || n->sym->gen_mark || n->sym->dev_mark)
10005 0 : gfc_error ("Symbol %qs present on multiple clauses at %L",
10006 : n->sym->name, &n->where);
10007 : else
10008 2308 : n->sym->data_mark = 1;
10009 : }
10010 :
10011 : /* ALIGNED clauses. */
10012 33192 : for (n = omp_clauses->lists[OMP_LIST_ALIGNED]; n; n = n->next)
10013 150 : n->sym->mark = 0;
10014 :
10015 33192 : for (n = omp_clauses->lists[OMP_LIST_ALIGNED]; n; n = n->next)
10016 : {
10017 150 : if (n->sym->mark)
10018 0 : gfc_error ("Symbol %qs present on multiple clauses at %L",
10019 : n->sym->name, &n->where);
10020 : else
10021 150 : n->sym->mark = 1;
10022 : }
10023 :
10024 : /* FROM and TO clauses. */
10025 33812 : for (n = omp_clauses->lists[OMP_LIST_TO]; n; n = n->next)
10026 770 : n->sym->mark = 0;
10027 34075 : for (n = omp_clauses->lists[OMP_LIST_FROM]; n; n = n->next)
10028 1033 : if (n->expr == NULL)
10029 1015 : n->sym->mark = 1;
10030 33812 : for (n = omp_clauses->lists[OMP_LIST_TO]; n; n = n->next)
10031 : {
10032 770 : if (n->expr == NULL && n->sym->mark)
10033 0 : gfc_error ("Symbol %qs present on both FROM and TO clauses at %L",
10034 : n->sym->name, &n->where);
10035 : else
10036 770 : n->sym->mark = 1;
10037 : }
10038 :
10039 : /* OpenACC reductions. */
10040 33042 : if (openacc)
10041 : {
10042 15131 : for (n = omp_clauses->lists[OMP_LIST_REDUCTION]; n; n = n->next)
10043 2136 : n->sym->mark = 0;
10044 15131 : for (n = omp_clauses->lists[OMP_LIST_REDUCTION]; n; n = n->next)
10045 : {
10046 2136 : if (n->sym->mark)
10047 0 : gfc_error ("Symbol %qs present on multiple clauses at %L",
10048 : n->sym->name, &n->where);
10049 : else
10050 2136 : n->sym->mark = 1;
10051 :
10052 : /* OpenACC does not support reductions on arrays. */
10053 2136 : if (n->sym->as)
10054 71 : gfc_error ("Array %qs is not permitted in reduction at %L",
10055 : n->sym->name, &n->where);
10056 : }
10057 : }
10058 33042 : }
10059 :
10060 : /* OpenMP/OpenACC: Resolve the list item of a MAP, TO, FROM, CACHE, AFFINITY
10061 : or DEPEND clause. */
10062 :
10063 : static void
10064 20943 : resolve_omp_clauses_aff_dep_map_cache (gfc_code *code,
10065 : gfc_omp_namelist *n,
10066 : const char *name,
10067 : enum gfc_omp_list_type list,
10068 : gfc_omp_clauses *omp_clauses,
10069 : bool openacc)
10070 : {
10071 20943 : gcc_checking_assert (list == OMP_LIST_AFFINITY || list == OMP_LIST_DEPEND
10072 : || list == OMP_LIST_MAP || list == OMP_LIST_TO
10073 : || list == OMP_LIST_FROM || list == OMP_LIST_CACHE);
10074 :
10075 20943 : if (list != OMP_LIST_CACHE && n->u2.ns && !n->u2.ns->resolved)
10076 : {
10077 109 : n->u2.ns->resolved = 1;
10078 109 : for (gfc_symbol *sym = n->u2.ns->omp_affinity_iterators;
10079 235 : sym; sym = sym->tlink)
10080 : {
10081 126 : gfc_constructor *c;
10082 126 : c = gfc_constructor_first (sym->value->value.constructor);
10083 126 : if (!gfc_resolve_expr (c->expr)
10084 126 : || c->expr->ts.type != BT_INTEGER
10085 250 : || c->expr->rank != 0)
10086 2 : gfc_error ("Scalar integer expression for range begin expected "
10087 2 : "at %L", &c->expr->where);
10088 126 : c = gfc_constructor_next (c);
10089 126 : if (!gfc_resolve_expr (c->expr)
10090 126 : || c->expr->ts.type != BT_INTEGER
10091 250 : || c->expr->rank != 0)
10092 2 : gfc_error ("Scalar integer expression for range end expected at %L",
10093 2 : &c->expr->where);
10094 126 : c = gfc_constructor_next (c);
10095 126 : if (c && (!gfc_resolve_expr (c->expr)
10096 16 : || c->expr->ts.type != BT_INTEGER
10097 14 : || c->expr->rank != 0))
10098 2 : gfc_error ("Scalar integer expression for range step expected "
10099 2 : "at %L", &c->expr->where);
10100 124 : else if (c
10101 14 : && c->expr->expr_type == EXPR_CONSTANT
10102 12 : && mpz_cmp_si (c->expr->value.integer, 0) == 0)
10103 2 : gfc_error ("Nonzero range step expected at %L", &c->expr->where);
10104 : }
10105 : }
10106 20842 : if (list == OMP_LIST_DEPEND)
10107 : {
10108 1963 : if (n->u.depend_doacross_op == OMP_DEPEND_SINK_FIRST
10109 : || n->u.depend_doacross_op == OMP_DOACROSS_SINK_FIRST
10110 1963 : || n->u.depend_doacross_op == OMP_DOACROSS_SINK)
10111 : {
10112 1233 : if (omp_clauses->doacross_source)
10113 : {
10114 0 : gfc_error ("Dependence-type SINK used together with SOURCE on "
10115 : "the same construct at %L", &n->where);
10116 0 : omp_clauses->doacross_source = false;
10117 : }
10118 1233 : else if (n->expr)
10119 : {
10120 571 : if (!gfc_resolve_expr (n->expr)
10121 571 : || n->expr->ts.type != BT_INTEGER
10122 1142 : || n->expr->rank != 0)
10123 0 : gfc_error ("SINK addend not a constant integer at %L",
10124 : &n->where);
10125 : }
10126 1233 : if (n->sym == NULL
10127 4 : && (n->expr == NULL
10128 3 : || mpz_cmp_si (n->expr->value.integer, -1) != 0))
10129 2 : gfc_error ("omp_cur_iteration at %L requires %<-1%> as "
10130 : "logical offset", &n->where);
10131 1233 : return;
10132 : }
10133 730 : if (n->u.depend_doacross_op == OMP_DEPEND_DEPOBJ
10134 38 : && !n->expr
10135 22 : && (n->sym->ts.type != BT_INTEGER
10136 22 : || n->sym->ts.kind != 2 * gfc_index_integer_kind
10137 22 : || n->sym->attr.dimension))
10138 0 : gfc_error ("Locator %qs at %L in DEPEND clause of depobj type shall be "
10139 : "a scalar integer of OMP_DEPEND_KIND kind",
10140 : n->sym->name, &n->where);
10141 730 : else if (n->u.depend_doacross_op == OMP_DEPEND_DEPOBJ
10142 38 : && n->expr
10143 746 : && (!gfc_resolve_expr (n->expr)
10144 16 : || n->expr->ts.type != BT_INTEGER
10145 16 : || n->expr->ts.kind != 2 * gfc_index_integer_kind
10146 16 : || n->expr->rank != 0))
10147 0 : gfc_error ("Locator at %L in DEPEND clause of depobj type shall be a "
10148 0 : "scalar integer of OMP_DEPEND_KIND kind", &n->expr->where);
10149 : }
10150 19710 : gfc_ref *lastref = NULL, *lastslice = NULL;
10151 19710 : bool resolved = false;
10152 19710 : if (n->expr)
10153 : {
10154 6539 : lastref = n->expr->ref;
10155 6539 : resolved = gfc_resolve_expr (n->expr);
10156 :
10157 : /* Look through component refs to find last array reference. */
10158 6539 : if (resolved)
10159 : {
10160 16571 : for (gfc_ref *ref = n->expr->ref; ref; ref = ref->next)
10161 10050 : if (ref->type == REF_COMPONENT
10162 : || ref->type == REF_SUBSTRING
10163 10050 : || ref->type == REF_INQUIRY)
10164 : lastref = ref;
10165 6799 : else if (ref->type == REF_ARRAY)
10166 : {
10167 14290 : for (int i = 0; i < ref->u.ar.dimen; i++)
10168 7491 : if (ref->u.ar.dimen_type[i] == DIMEN_RANGE)
10169 6277 : lastslice = ref;
10170 : lastref = ref;
10171 : }
10172 :
10173 : /* The "!$acc cache" directive allows rectangular subarrays to be
10174 : specified, with some restrictions on the form of bounds (not
10175 : implemented). Only raise an error here if we're really sure the
10176 : array isn't contiguous. An expression such as arr(-n:n,-n:n)
10177 : could be contiguous even if it looks like it may not be. */
10178 6521 : if (code
10179 6502 : && code->op != EXEC_OACC_UPDATE
10180 5720 : && list != OMP_LIST_CACHE
10181 5720 : && list != OMP_LIST_DEPEND
10182 5398 : && !gfc_is_simply_contiguous (n->expr, false, true)
10183 1517 : && gfc_is_not_contiguous (n->expr)
10184 6534 : && !(lastslice && (lastslice->next
10185 3 : || lastslice->type != REF_ARRAY)))
10186 3 : gfc_error ("Array is not contiguous at %L", &n->where);
10187 : }
10188 : }
10189 19710 : if (list == OMP_LIST_MAP
10190 17041 : && (n->sym->attr.omp_groupprivate
10191 17040 : || n->sym->attr.omp_declare_target_local))
10192 2 : gfc_error ("%qs argument to MAP clause at %L must not be a device-local "
10193 : "variable, including GROUPPRIVATE", n->sym->name, &n->where);
10194 19710 : if (openacc
10195 19710 : && list == OMP_LIST_MAP
10196 9571 : && (n->u.map.op == OMP_MAP_ATTACH || n->u.map.op == OMP_MAP_DETACH))
10197 : {
10198 117 : symbol_attribute attr;
10199 117 : if (n->expr)
10200 99 : attr = gfc_expr_attr (n->expr);
10201 : else
10202 18 : attr = n->sym->attr;
10203 117 : if (!attr.pointer && !attr.allocatable)
10204 7 : gfc_error ("%qs clause argument must be ALLOCATABLE or a POINTER at %L",
10205 7 : (n->u.map.op == OMP_MAP_ATTACH) ? "attach" : "detach",
10206 : &n->where);
10207 : }
10208 19710 : if (lastref
10209 13183 : || (n->expr && (!resolved || n->expr->expr_type != EXPR_VARIABLE)))
10210 : {
10211 6539 : if (!lastslice && lastref && lastref->type == REF_SUBSTRING)
10212 11 : gfc_error ("Unexpected substring reference in %s clause at %L",
10213 : name, &n->where);
10214 6528 : else if (!lastslice && lastref && lastref->type == REF_INQUIRY)
10215 : {
10216 12 : gcc_assert (lastref->u.i == INQUIRY_RE || lastref->u.i == INQUIRY_IM);
10217 12 : gfc_error ("Unexpected complex-parts designator reference in %s "
10218 : "clause at %L", name, &n->where);
10219 : }
10220 6516 : else if (!resolved
10221 6498 : || n->expr->expr_type != EXPR_VARIABLE
10222 6486 : || (lastslice
10223 5615 : && (lastslice->next || lastslice->type != REF_ARRAY)))
10224 46 : gfc_error ("%qs in %s clause at %L is not a proper array section",
10225 46 : n->sym->name, name, &n->where);
10226 : else if (lastslice)
10227 : {
10228 : int i;
10229 : gfc_array_ref *ar = &lastslice->u.ar;
10230 11873 : for (i = 0; i < ar->dimen; i++)
10231 6275 : if (ar->stride[i] && code && code->op != EXEC_OACC_UPDATE)
10232 : {
10233 1 : gfc_error ("Stride should not be specified for array section "
10234 : "in %s clause at %L", name, &n->where);
10235 1 : break;
10236 : }
10237 6274 : else if (ar->dimen_type[i] != DIMEN_ELEMENT
10238 6274 : && ar->dimen_type[i] != DIMEN_RANGE)
10239 : {
10240 0 : gfc_error ("%qs in %s clause at %L is not a proper array "
10241 0 : "section", n->sym->name, name, &n->where);
10242 0 : break;
10243 : }
10244 6274 : else if ((list == OMP_LIST_DEPEND || list == OMP_LIST_AFFINITY)
10245 161 : && ar->start[i]
10246 133 : && ar->start[i]->expr_type == EXPR_CONSTANT
10247 97 : && ar->end[i]
10248 72 : && ar->end[i]->expr_type == EXPR_CONSTANT
10249 72 : && mpz_cmp (ar->start[i]->value.integer,
10250 72 : ar->end[i]->value.integer) > 0)
10251 : {
10252 0 : gfc_error ("%qs in %s clause at %L is a zero size array "
10253 0 : "section", n->sym->name,
10254 : list == OMP_LIST_DEPEND ? "DEPEND" : "AFFINITY",
10255 : &n->where);
10256 0 : break;
10257 : }
10258 : }
10259 : }
10260 13171 : else if (openacc)
10261 : {
10262 5915 : if (list == OMP_LIST_MAP && n->u.map.op == OMP_MAP_FORCE_DEVICEPTR)
10263 65 : resolve_oacc_deviceptr_clause (n->sym, n->where, name);
10264 : else
10265 5850 : resolve_oacc_data_clauses (n->sym, n->where, name);
10266 : }
10267 7256 : else if (list != OMP_LIST_DEPEND
10268 6763 : && n->sym->as
10269 3339 : && n->sym->as->type == AS_ASSUMED_SIZE)
10270 5 : gfc_error ("Assumed size array %qs in %s clause at %L",
10271 : n->sym->name, name, &n->where);
10272 19710 : if (code && list == OMP_LIST_MAP && !openacc)
10273 7432 : switch (code->op)
10274 : {
10275 6157 : case EXEC_OMP_TARGET:
10276 6157 : case EXEC_OMP_TARGET_PARALLEL:
10277 6157 : case EXEC_OMP_TARGET_PARALLEL_DO:
10278 6157 : case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
10279 6157 : case EXEC_OMP_TARGET_PARALLEL_LOOP:
10280 6157 : case EXEC_OMP_TARGET_SIMD:
10281 6157 : case EXEC_OMP_TARGET_TEAMS:
10282 6157 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
10283 6157 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
10284 6157 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
10285 6157 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
10286 6157 : case EXEC_OMP_TARGET_TEAMS_LOOP:
10287 6157 : case EXEC_OMP_TARGET_DATA:
10288 6157 : 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_FROM:
10295 : case OMP_MAP_ALWAYS_FROM:
10296 : case OMP_MAP_PRESENT_FROM:
10297 : case OMP_MAP_ALWAYS_PRESENT_FROM:
10298 : case OMP_MAP_TOFROM:
10299 : case OMP_MAP_ALWAYS_TOFROM:
10300 : case OMP_MAP_PRESENT_TOFROM:
10301 : case OMP_MAP_ALWAYS_PRESENT_TOFROM:
10302 : case OMP_MAP_ALLOC:
10303 : case OMP_MAP_PRESENT_ALLOC:
10304 : break;
10305 2 : default:
10306 2 : gfc_error ("TARGET%s with map-type other than TO, "
10307 : "FROM, TOFROM, or ALLOC on MAP clause "
10308 : "at %L",
10309 : code->op == EXEC_OMP_TARGET_DATA
10310 : ? " DATA" : "", &n->where);
10311 2 : break;
10312 : }
10313 : break;
10314 697 : case EXEC_OMP_TARGET_ENTER_DATA:
10315 697 : switch (n->u.map.op)
10316 : {
10317 : case OMP_MAP_TO:
10318 : case OMP_MAP_ALWAYS_TO:
10319 : case OMP_MAP_PRESENT_TO:
10320 : case OMP_MAP_ALWAYS_PRESENT_TO:
10321 : case OMP_MAP_ALLOC:
10322 : case OMP_MAP_PRESENT_ALLOC:
10323 : break;
10324 178 : case OMP_MAP_TOFROM:
10325 178 : n->u.map.op = OMP_MAP_TO;
10326 178 : break;
10327 3 : case OMP_MAP_ALWAYS_TOFROM:
10328 3 : n->u.map.op = OMP_MAP_ALWAYS_TO;
10329 3 : break;
10330 2 : case OMP_MAP_PRESENT_TOFROM:
10331 2 : n->u.map.op = OMP_MAP_PRESENT_TO;
10332 2 : break;
10333 2 : case OMP_MAP_ALWAYS_PRESENT_TOFROM:
10334 2 : n->u.map.op = OMP_MAP_ALWAYS_PRESENT_TO;
10335 2 : break;
10336 2 : default:
10337 2 : gfc_error ("TARGET ENTER DATA with map-type other "
10338 : "than TO, TOFROM or ALLOC on MAP clause "
10339 : "at %L", &n->where);
10340 2 : break;
10341 : }
10342 : break;
10343 578 : case EXEC_OMP_TARGET_EXIT_DATA:
10344 578 : switch (n->u.map.op)
10345 : {
10346 : case OMP_MAP_FROM:
10347 : case OMP_MAP_ALWAYS_FROM:
10348 : case OMP_MAP_PRESENT_FROM:
10349 : case OMP_MAP_ALWAYS_PRESENT_FROM:
10350 : case OMP_MAP_RELEASE:
10351 : case OMP_MAP_DELETE:
10352 : break;
10353 132 : case OMP_MAP_TOFROM:
10354 132 : n->u.map.op = OMP_MAP_FROM;
10355 132 : break;
10356 1 : case OMP_MAP_ALWAYS_TOFROM:
10357 1 : n->u.map.op = OMP_MAP_ALWAYS_FROM;
10358 1 : break;
10359 0 : case OMP_MAP_PRESENT_TOFROM:
10360 0 : n->u.map.op = OMP_MAP_PRESENT_FROM;
10361 0 : break;
10362 0 : case OMP_MAP_ALWAYS_PRESENT_TOFROM:
10363 0 : n->u.map.op = OMP_MAP_ALWAYS_PRESENT_FROM;
10364 0 : break;
10365 2 : default:
10366 2 : gfc_error ("TARGET EXIT DATA with map-type other "
10367 : "than FROM, TOFROM, RELEASE, or DELETE on "
10368 : "MAP clause at %L", &n->where);
10369 2 : break;
10370 : }
10371 : break;
10372 : default:
10373 : break;
10374 : }
10375 19710 : if (list == OMP_LIST_MAP || list == OMP_LIST_TO || list == OMP_LIST_FROM)
10376 : {
10377 18844 : gfc_typespec *ts = n->expr ? &n->expr->ts : &n->sym->ts;
10378 :
10379 18844 : if (ts->type == BT_DERIVED || ts->type == BT_CLASS)
10380 : {
10381 9 : const char *mapper_id = (n->u3.udm
10382 999 : ? n->u3.udm->requested_mapper_id : "");
10383 999 : gfc_omp_udm *udm = gfc_find_omp_udm (gfc_current_ns, mapper_id, ts);
10384 999 : if (mapper_id[0] != '\0' && !udm)
10385 1 : gfc_error ("User-defined mapper %qs not found at %L",
10386 : mapper_id, &n->where);
10387 995 : else if (udm)
10388 : {
10389 26 : if (!n->u3.udm)
10390 : {
10391 18 : gcc_assert (mapper_id[0] == '\0');
10392 18 : n->u3.udm = gfc_get_omp_namelist_udm ();
10393 18 : n->u3.udm->requested_mapper_id = mapper_id;
10394 : }
10395 26 : n->u3.udm->resolved_udm = udm;
10396 : }
10397 : }
10398 : }
10399 :
10400 19710 : if (list != OMP_LIST_DEPEND)
10401 : {
10402 18980 : n->sym->attr.referenced = 1;
10403 18980 : if (n->sym->attr.threadprivate)
10404 1 : gfc_error ("THREADPRIVATE object %qs in %s clause at %L",
10405 : n->sym->name, name, &n->where);
10406 18980 : if (n->sym->attr.cray_pointee)
10407 14 : gfc_error ("Cray pointee %qs in %s clause at %L",
10408 : n->sym->name, name, &n->where);
10409 : }
10410 : }
10411 :
10412 : /* OpenMP directive resolving routines. */
10413 :
10414 : static void
10415 33042 : resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
10416 : gfc_namespace *ns, bool openacc = false)
10417 : {
10418 33042 : gfc_omp_namelist *n, *last;
10419 33042 : gfc_expr_list *el;
10420 33042 : enum gfc_omp_list_type list;
10421 33042 : int ifc;
10422 33042 : bool if_without_mod = false;
10423 33042 : gfc_omp_linear_op linear_op = OMP_LINEAR_DEFAULT;
10424 33042 : static const char *clause_names[]
10425 : = { "PRIVATE", "FIRSTPRIVATE", "LASTPRIVATE", "COPYPRIVATE", "SHARED",
10426 : "COPYIN", "UNIFORM", "AFFINITY", "ALIGNED", "LINEAR", "DEPEND", "MAP",
10427 : "TO", "FROM", "INCLUSIVE", "EXCLUSIVE",
10428 : "REDUCTION", "REDUCTION" /*inscan*/, "REDUCTION" /*task*/,
10429 : "IN_REDUCTION", "TASK_REDUCTION",
10430 : "DEVICE_RESIDENT", "LINK", "LOCAL", "USE_DEVICE",
10431 : "CACHE", "IS_DEVICE_PTR", "USE_DEVICE_PTR", "USE_DEVICE_ADDR",
10432 : "NONTEMPORAL", "ALLOCATE", "HAS_DEVICE_ADDR", "ENTER",
10433 : "USES_ALLOCATORS", "INIT", "USE", "DESTROY", "INTEROP", "ADJUST_ARGS" };
10434 33042 : STATIC_ASSERT (ARRAY_SIZE (clause_names) == OMP_LIST_NUM);
10435 :
10436 33042 : if (omp_clauses == NULL)
10437 : return;
10438 :
10439 33042 : if (ns == NULL)
10440 32598 : ns = gfc_current_ns;
10441 :
10442 33042 : check_omp_clauses_dupl_syms (code, omp_clauses, openacc);
10443 :
10444 33042 : if (omp_clauses->orderedc && omp_clauses->orderedc < omp_clauses->collapse)
10445 0 : gfc_error ("ORDERED clause parameter is less than COLLAPSE at %L",
10446 : &code->loc);
10447 33042 : if (omp_clauses->order_concurrent && omp_clauses->ordered)
10448 4 : gfc_error ("ORDER clause must not be used together with ORDERED at %L",
10449 : &code->loc);
10450 33042 : if (omp_clauses->if_expr)
10451 : {
10452 1299 : gfc_expr *expr = omp_clauses->if_expr;
10453 1299 : if (!gfc_resolve_expr (expr)
10454 1299 : || expr->ts.type != BT_LOGICAL || expr->rank != 0)
10455 16 : gfc_error ("IF clause at %L requires a scalar LOGICAL expression",
10456 : &expr->where);
10457 : if_without_mod = true;
10458 : }
10459 363462 : for (ifc = 0; ifc < OMP_IF_LAST; ifc++)
10460 330420 : if (omp_clauses->if_exprs[ifc])
10461 : {
10462 137 : gfc_expr *expr = omp_clauses->if_exprs[ifc];
10463 137 : bool ok = true;
10464 137 : if (!gfc_resolve_expr (expr)
10465 137 : || expr->ts.type != BT_LOGICAL || expr->rank != 0)
10466 0 : gfc_error ("IF clause at %L requires a scalar LOGICAL expression",
10467 : &expr->where);
10468 137 : else if (if_without_mod)
10469 : {
10470 1 : gfc_error ("IF clause without modifier at %L used together with "
10471 : "IF clauses with modifiers",
10472 1 : &omp_clauses->if_expr->where);
10473 1 : if_without_mod = false;
10474 : }
10475 : else
10476 136 : switch (code->op)
10477 : {
10478 13 : case EXEC_OMP_CANCEL:
10479 13 : ok = ifc == OMP_IF_CANCEL;
10480 13 : break;
10481 :
10482 16 : case EXEC_OMP_PARALLEL:
10483 16 : case EXEC_OMP_PARALLEL_DO:
10484 16 : case EXEC_OMP_PARALLEL_LOOP:
10485 16 : case EXEC_OMP_PARALLEL_MASKED:
10486 16 : case EXEC_OMP_PARALLEL_MASTER:
10487 16 : case EXEC_OMP_PARALLEL_SECTIONS:
10488 16 : case EXEC_OMP_PARALLEL_WORKSHARE:
10489 16 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
10490 16 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
10491 16 : ok = ifc == OMP_IF_PARALLEL;
10492 16 : break;
10493 :
10494 28 : case EXEC_OMP_PARALLEL_DO_SIMD:
10495 28 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
10496 28 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
10497 28 : ok = ifc == OMP_IF_PARALLEL || ifc == OMP_IF_SIMD;
10498 28 : break;
10499 :
10500 8 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
10501 8 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
10502 8 : ok = ifc == OMP_IF_PARALLEL || ifc == OMP_IF_TASKLOOP;
10503 8 : break;
10504 :
10505 12 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
10506 12 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
10507 12 : ok = (ifc == OMP_IF_PARALLEL
10508 12 : || ifc == OMP_IF_TASKLOOP
10509 : || ifc == OMP_IF_SIMD);
10510 : break;
10511 :
10512 0 : case EXEC_OMP_SIMD:
10513 0 : case EXEC_OMP_DO_SIMD:
10514 0 : case EXEC_OMP_DISTRIBUTE_SIMD:
10515 0 : case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
10516 0 : ok = ifc == OMP_IF_SIMD;
10517 0 : break;
10518 :
10519 1 : case EXEC_OMP_TASK:
10520 1 : ok = ifc == OMP_IF_TASK;
10521 1 : break;
10522 :
10523 5 : case EXEC_OMP_TASKLOOP:
10524 5 : case EXEC_OMP_MASKED_TASKLOOP:
10525 5 : case EXEC_OMP_MASTER_TASKLOOP:
10526 5 : ok = ifc == OMP_IF_TASKLOOP;
10527 5 : break;
10528 :
10529 20 : case EXEC_OMP_TASKLOOP_SIMD:
10530 20 : case EXEC_OMP_MASKED_TASKLOOP_SIMD:
10531 20 : case EXEC_OMP_MASTER_TASKLOOP_SIMD:
10532 20 : ok = ifc == OMP_IF_TASKLOOP || ifc == OMP_IF_SIMD;
10533 20 : break;
10534 :
10535 5 : case EXEC_OMP_TARGET:
10536 5 : case EXEC_OMP_TARGET_TEAMS:
10537 5 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
10538 5 : case EXEC_OMP_TARGET_TEAMS_LOOP:
10539 5 : ok = ifc == OMP_IF_TARGET;
10540 5 : break;
10541 :
10542 4 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
10543 4 : case EXEC_OMP_TARGET_SIMD:
10544 4 : ok = ifc == OMP_IF_TARGET || ifc == OMP_IF_SIMD;
10545 4 : break;
10546 :
10547 1 : case EXEC_OMP_TARGET_DATA:
10548 1 : ok = ifc == OMP_IF_TARGET_DATA;
10549 1 : break;
10550 :
10551 1 : case EXEC_OMP_TARGET_UPDATE:
10552 1 : ok = ifc == OMP_IF_TARGET_UPDATE;
10553 1 : break;
10554 :
10555 1 : case EXEC_OMP_TARGET_ENTER_DATA:
10556 1 : ok = ifc == OMP_IF_TARGET_ENTER_DATA;
10557 1 : break;
10558 :
10559 1 : case EXEC_OMP_TARGET_EXIT_DATA:
10560 1 : ok = ifc == OMP_IF_TARGET_EXIT_DATA;
10561 1 : break;
10562 :
10563 10 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
10564 10 : case EXEC_OMP_TARGET_PARALLEL:
10565 10 : case EXEC_OMP_TARGET_PARALLEL_DO:
10566 10 : case EXEC_OMP_TARGET_PARALLEL_LOOP:
10567 10 : ok = ifc == OMP_IF_TARGET || ifc == OMP_IF_PARALLEL;
10568 10 : break;
10569 :
10570 10 : case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
10571 10 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
10572 10 : ok = (ifc == OMP_IF_TARGET
10573 10 : || ifc == OMP_IF_PARALLEL
10574 : || ifc == OMP_IF_SIMD);
10575 : break;
10576 :
10577 : default:
10578 : ok = false;
10579 : break;
10580 : }
10581 115 : if (!ok)
10582 : {
10583 2 : static const char *ifs[] = {
10584 : "CANCEL",
10585 : "PARALLEL",
10586 : "SIMD",
10587 : "TASK",
10588 : "TASKLOOP",
10589 : "TARGET",
10590 : "TARGET DATA",
10591 : "TARGET UPDATE",
10592 : "TARGET ENTER DATA",
10593 : "TARGET EXIT DATA"
10594 : };
10595 2 : gfc_error ("IF clause modifier %s at %L not appropriate for "
10596 : "the current OpenMP construct", ifs[ifc], &expr->where);
10597 : }
10598 : }
10599 :
10600 33042 : if (omp_clauses->self_expr)
10601 : {
10602 177 : gfc_expr *expr = omp_clauses->self_expr;
10603 177 : if (!gfc_resolve_expr (expr)
10604 177 : || expr->ts.type != BT_LOGICAL || expr->rank != 0)
10605 6 : gfc_error ("SELF clause at %L requires a scalar LOGICAL expression",
10606 : &expr->where);
10607 : }
10608 :
10609 33042 : if (omp_clauses->final_expr)
10610 : {
10611 64 : gfc_expr *expr = omp_clauses->final_expr;
10612 64 : if (!gfc_resolve_expr (expr)
10613 64 : || expr->ts.type != BT_LOGICAL || expr->rank != 0)
10614 0 : gfc_error ("FINAL clause at %L requires a scalar LOGICAL expression",
10615 : &expr->where);
10616 : }
10617 33042 : if (omp_clauses->novariants)
10618 : {
10619 9 : gfc_expr *expr = omp_clauses->novariants;
10620 18 : if (!gfc_resolve_expr (expr) || expr->ts.type != BT_LOGICAL
10621 17 : || expr->rank != 0)
10622 1 : gfc_error (
10623 : "NOVARIANTS clause at %L requires a scalar LOGICAL expression",
10624 : &expr->where);
10625 33042 : if_without_mod = true;
10626 : }
10627 33042 : if (omp_clauses->nocontext)
10628 : {
10629 12 : gfc_expr *expr = omp_clauses->nocontext;
10630 24 : if (!gfc_resolve_expr (expr) || expr->ts.type != BT_LOGICAL
10631 23 : || expr->rank != 0)
10632 1 : gfc_error (
10633 : "NOCONTEXT clause at %L requires a scalar LOGICAL expression",
10634 : &expr->where);
10635 33042 : if_without_mod = true;
10636 : }
10637 :
10638 34058 : for (el = omp_clauses->num_threads_list; el; el = el->next)
10639 1016 : resolve_positive_int_expr (el->expr, "NUM_THREADS");
10640 :
10641 33042 : if (omp_clauses->dyn_groupprivate)
10642 10 : resolve_nonnegative_int_expr (omp_clauses->dyn_groupprivate,
10643 : "DYN_GROUPPRIVATE");
10644 33042 : if (omp_clauses->chunk_size)
10645 : {
10646 510 : gfc_expr *expr = omp_clauses->chunk_size;
10647 510 : if (!gfc_resolve_expr (expr)
10648 510 : || expr->ts.type != BT_INTEGER || expr->rank != 0)
10649 0 : gfc_error ("SCHEDULE clause's chunk_size at %L requires "
10650 : "a scalar INTEGER expression", &expr->where);
10651 510 : else if (expr->expr_type == EXPR_CONSTANT
10652 : && expr->ts.type == BT_INTEGER
10653 485 : && mpz_sgn (expr->value.integer) <= 0)
10654 2 : gfc_warning (OPT_Wopenmp, "INTEGER expression of SCHEDULE clause's "
10655 : "chunk_size at %L must be positive", &expr->where);
10656 : }
10657 33042 : if (omp_clauses->sched_kind != OMP_SCHED_NONE
10658 891 : && omp_clauses->sched_nonmonotonic)
10659 : {
10660 34 : if (omp_clauses->sched_monotonic)
10661 2 : gfc_error ("Both MONOTONIC and NONMONOTONIC schedule modifiers "
10662 : "specified at %L", &code->loc);
10663 32 : else if (omp_clauses->ordered)
10664 4 : gfc_error ("NONMONOTONIC schedule modifier specified with ORDERED "
10665 : "clause at %L", &code->loc);
10666 : }
10667 :
10668 33042 : if (omp_clauses->depobj
10669 33042 : && (!gfc_resolve_expr (omp_clauses->depobj)
10670 115 : || omp_clauses->depobj->ts.type != BT_INTEGER
10671 114 : || omp_clauses->depobj->ts.kind != 2 * gfc_index_integer_kind
10672 113 : || omp_clauses->depobj->rank != 0))
10673 4 : gfc_error ("DEPOBJ in DEPOBJ construct at %L shall be a scalar integer "
10674 4 : "of OMP_DEPEND_KIND kind", &omp_clauses->depobj->where);
10675 :
10676 : /* Check that list items are variables. */
10677 1321680 : for (list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
10678 1288638 : list = gfc_omp_list_type (list + 1))
10679 1334473 : for (n = omp_clauses->lists[list]; n; n = n->next)
10680 : {
10681 45835 : if (!n->sym) /* omp_all_memory. */
10682 47 : continue;
10683 45788 : if (n->sym->attr.flavor == FL_VARIABLE
10684 277 : || n->sym->attr.proc_pointer
10685 236 : || (!code
10686 0 : && !ns->omp_udm_ns
10687 0 : && (!n->sym->attr.dummy || n->sym->ns != ns)))
10688 : {
10689 45552 : if (!code
10690 302 : && !ns->omp_udm_ns
10691 264 : && (!n->sym->attr.dummy || n->sym->ns != ns))
10692 0 : gfc_error ("Variable %qs is not a dummy argument at %L",
10693 : n->sym->name, &n->where);
10694 45552 : continue;
10695 : }
10696 236 : if (n->sym->attr.flavor == FL_PROCEDURE
10697 153 : && n->sym->result == n->sym
10698 138 : && n->sym->attr.function)
10699 : {
10700 138 : if (ns->proc_name == n->sym
10701 44 : || (ns->parent && ns->parent->proc_name == n->sym))
10702 101 : continue;
10703 37 : if (ns->proc_name->attr.entry_master)
10704 : {
10705 32 : gfc_entry_list *el = ns->entries;
10706 51 : for (; el; el = el->next)
10707 51 : if (el->sym == n->sym)
10708 : break;
10709 32 : if (el)
10710 32 : continue;
10711 : }
10712 5 : if (ns->parent
10713 3 : && ns->parent->proc_name->attr.entry_master)
10714 : {
10715 2 : gfc_entry_list *el = ns->parent->entries;
10716 3 : for (; el; el = el->next)
10717 3 : if (el->sym == n->sym)
10718 : break;
10719 2 : if (el)
10720 2 : continue;
10721 : }
10722 : }
10723 101 : if (list == OMP_LIST_MAP
10724 18 : && n->sym->attr.flavor == FL_PARAMETER)
10725 : {
10726 : /* OpenACC since 3.4 permits for Fortran named constants, but
10727 : permits removing then as optimization is not needed and such
10728 : ignore them. Likewise below for FIRSTPRIVATE. */
10729 12 : if (openacc)
10730 10 : gfc_warning (OPT_Wsurprising, "Clause for object %qs at %L is "
10731 : "ignored as parameters need not be copied",
10732 : n->sym->name, &n->where);
10733 : else
10734 2 : gfc_error ("Object %qs is not a variable at %L; parameters"
10735 : " cannot be and need not be mapped", n->sym->name,
10736 : &n->where);
10737 : }
10738 89 : else if (openacc && n->sym->attr.flavor == FL_PARAMETER)
10739 9 : gfc_warning (OPT_Wsurprising, "Clause for object %qs at %L is ignored"
10740 : " as it is a parameter", n->sym->name, &n->where);
10741 80 : else if (list != OMP_LIST_USES_ALLOCATORS)
10742 30 : gfc_error ("Object %qs is not a variable at %L", n->sym->name,
10743 : &n->where);
10744 : }
10745 :
10746 33042 : if (omp_clauses->lists[OMP_LIST_REDUCTION_INSCAN])
10747 : {
10748 69 : locus *loc = &omp_clauses->lists[OMP_LIST_REDUCTION_INSCAN]->where;
10749 69 : if (code->op != EXEC_OMP_DO
10750 : && code->op != EXEC_OMP_SIMD
10751 : && code->op != EXEC_OMP_DO_SIMD
10752 : && code->op != EXEC_OMP_PARALLEL_DO
10753 : && code->op != EXEC_OMP_PARALLEL_DO_SIMD)
10754 23 : gfc_error ("%<inscan%> REDUCTION clause on construct other than DO, "
10755 : "SIMD, DO SIMD, PARALLEL DO, PARALLEL DO SIMD at %L",
10756 : loc);
10757 69 : if (omp_clauses->ordered)
10758 2 : gfc_error ("ORDERED clause specified together with %<inscan%> "
10759 : "REDUCTION clause at %L", loc);
10760 69 : if (omp_clauses->sched_kind != OMP_SCHED_NONE)
10761 3 : gfc_error ("SCHEDULE clause specified together with %<inscan%> "
10762 : "REDUCTION clause at %L", loc);
10763 : }
10764 :
10765 33042 : if (code
10766 32801 : && code->op == EXEC_OMP_INTEROP
10767 63 : && omp_clauses->lists[OMP_LIST_DEPEND])
10768 : {
10769 12 : if (!omp_clauses->lists[OMP_LIST_INIT]
10770 5 : && !omp_clauses->lists[OMP_LIST_USE]
10771 1 : && !omp_clauses->lists[OMP_LIST_DESTROY])
10772 : {
10773 1 : gfc_error ("DEPEND clause at %L requires action clause with "
10774 : "%<targetsync%> interop-type",
10775 : &omp_clauses->lists[OMP_LIST_DEPEND]->where);
10776 : }
10777 22 : for (n = omp_clauses->lists[OMP_LIST_INIT]; n; n = n->next)
10778 12 : if (!n->u.init.targetsync)
10779 : {
10780 2 : gfc_error ("DEPEND clause at %L requires %<targetsync%> "
10781 : "interop-type, lacking it for %qs at %L",
10782 2 : &omp_clauses->lists[OMP_LIST_DEPEND]->where,
10783 2 : n->sym->name, &n->where);
10784 2 : break;
10785 : }
10786 : }
10787 32801 : if (code && (code->op == EXEC_OMP_INTEROP || code->op == EXEC_OMP_DISPATCH))
10788 1085 : for (list = OMP_LIST_INIT; list <= OMP_LIST_INTEROP;
10789 868 : list = gfc_omp_list_type (list + 1))
10790 1123 : for (n = omp_clauses->lists[list]; n; n = n->next)
10791 : {
10792 255 : if (n->sym->ts.type != BT_INTEGER
10793 252 : || n->sym->ts.kind != gfc_index_integer_kind
10794 248 : || n->sym->attr.dimension
10795 243 : || n->sym->attr.flavor != FL_VARIABLE)
10796 16 : gfc_error ("%qs at %L in %qs clause must be a scalar integer "
10797 : "variable of %<omp_interop_kind%> kind", n->sym->name,
10798 : &n->where, clause_names[list]);
10799 255 : if (list != OMP_LIST_USE && list != OMP_LIST_INTEROP
10800 109 : && n->sym->attr.intent == INTENT_IN)
10801 2 : gfc_error ("%qs at %L in %qs clause must be definable",
10802 : n->sym->name, &n->where, clause_names[list]);
10803 : }
10804 :
10805 33042 : resolve_omp_allocate_clauses (code, omp_clauses, ns);
10806 :
10807 33042 : bool has_inscan = false, has_notinscan = false;
10808 1321680 : for (enum gfc_omp_list_type list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
10809 1288638 : list = gfc_omp_list_type (list + 1))
10810 1288638 : if ((n = omp_clauses->lists[list]) != NULL)
10811 : {
10812 29299 : const char *name = clause_names[list];
10813 :
10814 29299 : switch (list)
10815 : {
10816 : case OMP_LIST_COPYIN:
10817 267 : for (; n != NULL; n = n->next)
10818 : {
10819 170 : if (!n->sym->attr.threadprivate)
10820 0 : gfc_error ("Non-THREADPRIVATE object %qs in COPYIN clause"
10821 : " at %L", n->sym->name, &n->where);
10822 : }
10823 : break;
10824 83 : case OMP_LIST_COPYPRIVATE:
10825 83 : if (omp_clauses->nowait)
10826 6 : gfc_error ("NOWAIT clause must not be used with COPYPRIVATE "
10827 : "clause at %L", &n->where);
10828 376 : for (; n != NULL; n = n->next)
10829 : {
10830 293 : if (n->sym->as && n->sym->as->type == AS_ASSUMED_SIZE)
10831 0 : gfc_error ("Assumed size array %qs in COPYPRIVATE clause "
10832 : "at %L", n->sym->name, &n->where);
10833 293 : if (n->sym->attr.pointer && n->sym->attr.intent == INTENT_IN)
10834 1 : gfc_error ("INTENT(IN) POINTER %qs in COPYPRIVATE clause "
10835 : "at %L", n->sym->name, &n->where);
10836 : }
10837 : break;
10838 : case OMP_LIST_SHARED:
10839 2604 : for (; n != NULL; n = n->next)
10840 : {
10841 1642 : if (n->sym->attr.threadprivate)
10842 0 : gfc_error ("THREADPRIVATE object %qs in SHARED clause at "
10843 : "%L", n->sym->name, &n->where);
10844 1642 : if (n->sym->attr.cray_pointee)
10845 1 : gfc_error ("Cray pointee %qs in SHARED clause at %L",
10846 : n->sym->name, &n->where);
10847 1642 : if (n->sym->attr.associate_var)
10848 8 : gfc_error ("Associate name %qs in SHARED clause at %L",
10849 8 : n->sym->attr.select_type_temporary
10850 4 : ? n->sym->assoc->target->symtree->n.sym->name
10851 : : n->sym->name, &n->where);
10852 1642 : if (omp_clauses->detach
10853 1 : && n->sym == omp_clauses->detach->symtree->n.sym)
10854 1 : gfc_error ("DETACH event handle %qs in SHARED clause at %L",
10855 : n->sym->name, &n->where);
10856 : }
10857 : break;
10858 : case OMP_LIST_ALIGNED:
10859 256 : for (; n != NULL; n = n->next)
10860 : {
10861 150 : if (!n->sym->attr.pointer
10862 45 : && !n->sym->attr.allocatable
10863 30 : && !n->sym->attr.cray_pointer
10864 18 : && (n->sym->ts.type != BT_DERIVED
10865 18 : || (n->sym->ts.u.derived->from_intmod
10866 : != INTMOD_ISO_C_BINDING)
10867 18 : || (n->sym->ts.u.derived->intmod_sym_id
10868 : != ISOCBINDING_PTR)))
10869 0 : gfc_error ("%qs in ALIGNED clause must be POINTER, "
10870 : "ALLOCATABLE, Cray pointer or C_PTR at %L",
10871 : n->sym->name, &n->where);
10872 150 : else if (n->expr)
10873 : {
10874 147 : if (!gfc_resolve_expr (n->expr)
10875 147 : || n->expr->ts.type != BT_INTEGER
10876 146 : || n->expr->rank != 0
10877 146 : || n->expr->expr_type != EXPR_CONSTANT
10878 292 : || mpz_sgn (n->expr->value.integer) <= 0)
10879 4 : gfc_error ("%qs in ALIGNED clause at %L requires a scalar"
10880 : " positive constant integer alignment "
10881 4 : "expression", n->sym->name, &n->where);
10882 : }
10883 : }
10884 : break;
10885 : case OMP_LIST_AFFINITY:
10886 : case OMP_LIST_DEPEND:
10887 : case OMP_LIST_MAP:
10888 : case OMP_LIST_TO:
10889 : case OMP_LIST_FROM:
10890 : case OMP_LIST_CACHE:
10891 33196 : for (; n != NULL; n = n->next)
10892 20943 : resolve_omp_clauses_aff_dep_map_cache (code, n, name, list,
10893 : omp_clauses, openacc);
10894 : break;
10895 : case OMP_LIST_IS_DEVICE_PTR:
10896 : last = NULL;
10897 377 : for (n = omp_clauses->lists[list]; n != NULL; )
10898 : {
10899 257 : if ((n->sym->ts.type != BT_DERIVED
10900 71 : || !n->sym->ts.u.derived->ts.is_iso_c
10901 71 : || (n->sym->ts.u.derived->intmod_sym_id
10902 : != ISOCBINDING_PTR))
10903 187 : && code->op == EXEC_OMP_DISPATCH)
10904 : /* Non-TARGET (i.e. DISPATCH) requires a C_PTR. */
10905 3 : gfc_error ("List item %qs in %s clause at %L must be of "
10906 : "TYPE(C_PTR)", n->sym->name, name, &n->where);
10907 254 : else if (n->sym->ts.type != BT_DERIVED
10908 70 : || !n->sym->ts.u.derived->ts.is_iso_c
10909 70 : || (n->sym->ts.u.derived->intmod_sym_id
10910 : != ISOCBINDING_PTR))
10911 : {
10912 : /* For TARGET, non-C_PTR are deprecated and handled as
10913 : has_device_addr. */
10914 184 : gfc_warning (OPT_Wdeprecated_openmp,
10915 : "Non-C_PTR type argument at %L is deprecated, "
10916 : "use HAS_DEVICE_ADDR", &n->where);
10917 184 : gfc_omp_namelist *n2 = n;
10918 184 : n = n->next;
10919 184 : if (last)
10920 0 : last->next = n;
10921 : else
10922 184 : omp_clauses->lists[list] = n;
10923 184 : n2->next = omp_clauses->lists[OMP_LIST_HAS_DEVICE_ADDR];
10924 184 : omp_clauses->lists[OMP_LIST_HAS_DEVICE_ADDR] = n2;
10925 184 : continue;
10926 184 : }
10927 73 : last = n;
10928 73 : n = n->next;
10929 : }
10930 : break;
10931 : case OMP_LIST_HAS_DEVICE_ADDR:
10932 : case OMP_LIST_USE_DEVICE_ADDR:
10933 : break;
10934 : case OMP_LIST_USE_DEVICE_PTR:
10935 : /* Non-C_PTR are deprecated and handled as use_device_ADDR. */
10936 : last = NULL;
10937 475 : for (n = omp_clauses->lists[list]; n != NULL; )
10938 : {
10939 312 : gfc_omp_namelist *n2 = n;
10940 312 : if (n->sym->ts.type != BT_DERIVED
10941 18 : || !n->sym->ts.u.derived->ts.is_iso_c)
10942 : {
10943 294 : gfc_warning (OPT_Wdeprecated_openmp,
10944 : "Non-C_PTR type argument at %L is "
10945 : "deprecated, use USE_DEVICE_ADDR", &n->where);
10946 294 : n = n->next;
10947 294 : if (last)
10948 0 : last->next = n;
10949 : else
10950 294 : omp_clauses->lists[list] = n;
10951 294 : n2->next = omp_clauses->lists[OMP_LIST_USE_DEVICE_ADDR];
10952 294 : omp_clauses->lists[OMP_LIST_USE_DEVICE_ADDR] = n2;
10953 294 : continue;
10954 : }
10955 18 : last = n;
10956 18 : n = n->next;
10957 : }
10958 : break;
10959 65 : case OMP_LIST_USES_ALLOCATORS:
10960 65 : {
10961 65 : if (n != NULL
10962 65 : && n->u.memspace_sym
10963 20 : && (n->u.memspace_sym->attr.flavor != FL_PARAMETER
10964 18 : || n->u.memspace_sym->ts.type != BT_INTEGER
10965 18 : || n->u.memspace_sym->ts.kind != gfc_c_intptr_kind
10966 18 : || n->u.memspace_sym->attr.dimension
10967 18 : || (!startswith (n->u.memspace_sym->name, "omp_")
10968 0 : && !startswith (n->u.memspace_sym->name, "ompx_"))
10969 18 : || !endswith (n->u.memspace_sym->name, "_mem_space")))
10970 3 : gfc_error ("Memspace %qs at %L in USES_ALLOCATORS must be "
10971 : "a predefined memory space",
10972 : n->u.memspace_sym->name, &n->where);
10973 180 : for (; n != NULL; n = n->next)
10974 : {
10975 122 : if (n->sym->ts.type != BT_INTEGER
10976 121 : || n->sym->ts.kind != gfc_c_intptr_kind
10977 120 : || n->sym->attr.dimension)
10978 3 : gfc_error ("Allocator %qs at %L in USES_ALLOCATORS must "
10979 : "be a scalar integer of kind "
10980 : "%<omp_allocator_handle_kind%>", n->sym->name,
10981 : &n->where);
10982 119 : else if (n->sym->attr.flavor != FL_VARIABLE
10983 50 : && strcmp (n->sym->name, "omp_null_allocator") != 0
10984 165 : && ((!startswith (n->sym->name, "omp_")
10985 1 : && !startswith (n->sym->name, "ompx_"))
10986 45 : || !endswith (n->sym->name, "_mem_alloc")))
10987 2 : gfc_error ("Allocator %qs at %L in USES_ALLOCATORS must "
10988 : "either a variable or a predefined allocator",
10989 : n->sym->name, &n->where);
10990 117 : else if ((n->u.memspace_sym || n->u2.traits_sym)
10991 61 : && n->sym->attr.flavor != FL_VARIABLE)
10992 3 : gfc_error ("A memory space or traits array may not be "
10993 : "specified for predefined allocator %qs at %L",
10994 : n->sym->name, &n->where);
10995 122 : if (n->u2.traits_sym
10996 50 : && (n->u2.traits_sym->attr.flavor != FL_PARAMETER
10997 47 : || !n->u2.traits_sym->attr.dimension
10998 45 : || n->u2.traits_sym->as->rank != 1
10999 45 : || n->u2.traits_sym->ts.type != BT_DERIVED
11000 43 : || strcmp (n->u2.traits_sym->ts.u.derived->name,
11001 : "omp_alloctrait") != 0))
11002 : {
11003 7 : gfc_error ("Traits array %qs in USES_ALLOCATORS %L must "
11004 : "be a one-dimensional named constant array of "
11005 : "type %<omp_alloctrait%>",
11006 : n->u2.traits_sym->name, &n->where);
11007 7 : break;
11008 : }
11009 : }
11010 : break;
11011 : }
11012 : default:
11013 34776 : for (; n != NULL; n = n->next)
11014 : {
11015 20380 : if (n->sym == NULL)
11016 : {
11017 26 : gcc_assert (code->op == EXEC_OMP_ALLOCATORS
11018 : || code->op == EXEC_OMP_ALLOCATE);
11019 26 : continue;
11020 : }
11021 20354 : bool bad = false;
11022 20354 : bool is_reduction = (list == OMP_LIST_REDUCTION
11023 : || list == OMP_LIST_REDUCTION_INSCAN
11024 : || list == OMP_LIST_REDUCTION_TASK
11025 : || list == OMP_LIST_IN_REDUCTION
11026 20354 : || list == OMP_LIST_TASK_REDUCTION);
11027 20354 : if (list == OMP_LIST_REDUCTION_INSCAN)
11028 : has_inscan = true;
11029 20282 : else if (is_reduction)
11030 4737 : has_notinscan = true;
11031 20354 : if (has_inscan && has_notinscan && is_reduction)
11032 : {
11033 3 : gfc_error ("%<inscan%> and non-%<inscan%> %<reduction%> "
11034 : "clauses on the same construct at %L",
11035 : &n->where);
11036 3 : break;
11037 : }
11038 20351 : if (n->sym->attr.threadprivate)
11039 1 : gfc_error ("THREADPRIVATE object %qs in %s clause at %L",
11040 : n->sym->name, name, &n->where);
11041 20351 : if (n->sym->attr.cray_pointee)
11042 14 : gfc_error ("Cray pointee %qs in %s clause at %L",
11043 : n->sym->name, name, &n->where);
11044 20351 : if (n->sym->attr.associate_var)
11045 22 : gfc_error ("Associate name %qs in %s clause at %L",
11046 22 : n->sym->attr.select_type_temporary
11047 4 : ? n->sym->assoc->target->symtree->n.sym->name
11048 : : n->sym->name, name, &n->where);
11049 20351 : if (list != OMP_LIST_PRIVATE && is_reduction)
11050 : {
11051 4806 : if (n->sym->attr.proc_pointer)
11052 1 : gfc_error ("Procedure pointer %qs in %s clause at %L",
11053 : n->sym->name, name, &n->where);
11054 4806 : if (n->sym->attr.pointer)
11055 3 : gfc_error ("POINTER object %qs in %s clause at %L",
11056 : n->sym->name, name, &n->where);
11057 4806 : if (n->sym->attr.cray_pointer)
11058 5 : gfc_error ("Cray pointer %qs in %s clause at %L",
11059 : n->sym->name, name, &n->where);
11060 : }
11061 20351 : if (code
11062 20351 : && (oacc_is_loop (code)
11063 : || code->op == EXEC_OACC_PARALLEL
11064 : || code->op == EXEC_OACC_SERIAL))
11065 8741 : check_array_not_assumed (n->sym, n->where, name);
11066 11610 : else if (list != OMP_LIST_UNIFORM
11067 11493 : && n->sym->as && n->sym->as->type == AS_ASSUMED_SIZE)
11068 2 : gfc_error ("Assumed size array %qs in %s clause at %L",
11069 : n->sym->name, name, &n->where);
11070 20351 : if (n->sym->attr.in_namelist && !is_reduction)
11071 0 : gfc_error ("Variable %qs in %s clause is used in "
11072 : "NAMELIST statement at %L",
11073 : n->sym->name, name, &n->where);
11074 20351 : if (n->sym->attr.pointer && n->sym->attr.intent == INTENT_IN)
11075 3 : switch (list)
11076 : {
11077 3 : case OMP_LIST_PRIVATE:
11078 3 : case OMP_LIST_LASTPRIVATE:
11079 3 : case OMP_LIST_LINEAR:
11080 : /* case OMP_LIST_REDUCTION: */
11081 3 : gfc_error ("INTENT(IN) POINTER %qs in %s clause at %L",
11082 : n->sym->name, name, &n->where);
11083 3 : break;
11084 : default:
11085 : break;
11086 : }
11087 20351 : if (omp_clauses->detach
11088 3 : && (list == OMP_LIST_PRIVATE
11089 : || list == OMP_LIST_FIRSTPRIVATE
11090 : || list == OMP_LIST_LASTPRIVATE)
11091 3 : && n->sym == omp_clauses->detach->symtree->n.sym)
11092 1 : gfc_error ("DETACH event handle %qs in %s clause at %L",
11093 : n->sym->name, name, &n->where);
11094 :
11095 20351 : if (!openacc
11096 20351 : && (list == OMP_LIST_PRIVATE
11097 20351 : || list == OMP_LIST_FIRSTPRIVATE)
11098 4704 : && ((n->sym->ts.type == BT_DERIVED
11099 158 : && n->sym->ts.u.derived->attr.alloc_comp)
11100 4594 : || n->sym->ts.type == BT_CLASS))
11101 170 : switch (code->op)
11102 : {
11103 8 : case EXEC_OMP_TARGET:
11104 8 : case EXEC_OMP_TARGET_PARALLEL:
11105 8 : case EXEC_OMP_TARGET_PARALLEL_DO:
11106 8 : case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
11107 8 : case EXEC_OMP_TARGET_PARALLEL_LOOP:
11108 8 : case EXEC_OMP_TARGET_SIMD:
11109 8 : case EXEC_OMP_TARGET_TEAMS:
11110 8 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
11111 8 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
11112 8 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
11113 8 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
11114 8 : case EXEC_OMP_TARGET_TEAMS_LOOP:
11115 8 : if (n->sym->ts.type == BT_DERIVED
11116 2 : && n->sym->ts.u.derived->attr.alloc_comp)
11117 3 : gfc_error ("Sorry, list item %qs at %L with allocatable"
11118 : " components is not yet supported in %s "
11119 : "clause", n->sym->name, &n->where,
11120 : list == OMP_LIST_PRIVATE ? "PRIVATE"
11121 : : "FIRSTPRIVATE");
11122 : else
11123 9 : gfc_error ("Polymorphic list item %qs at %L in %s "
11124 : "clause has unspecified behavior and "
11125 : "unsupported", n->sym->name, &n->where,
11126 : list == OMP_LIST_PRIVATE ? "PRIVATE"
11127 : : "FIRSTPRIVATE");
11128 : break;
11129 : default:
11130 : break;
11131 : }
11132 :
11133 20351 : switch (list)
11134 : {
11135 104 : case OMP_LIST_REDUCTION_TASK:
11136 104 : if (code
11137 104 : && (code->op == EXEC_OMP_LOOP
11138 : || code->op == EXEC_OMP_TASKLOOP
11139 : || code->op == EXEC_OMP_TASKLOOP_SIMD
11140 : || code->op == EXEC_OMP_MASKED_TASKLOOP
11141 : || code->op == EXEC_OMP_MASKED_TASKLOOP_SIMD
11142 : || code->op == EXEC_OMP_MASTER_TASKLOOP
11143 : || code->op == EXEC_OMP_MASTER_TASKLOOP_SIMD
11144 : || code->op == EXEC_OMP_PARALLEL_LOOP
11145 : || code->op == EXEC_OMP_PARALLEL_MASKED_TASKLOOP
11146 : || code->op == EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD
11147 : || code->op == EXEC_OMP_PARALLEL_MASTER_TASKLOOP
11148 : || code->op == EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD
11149 : || code->op == EXEC_OMP_TARGET_PARALLEL_LOOP
11150 : || code->op == EXEC_OMP_TARGET_TEAMS_LOOP
11151 : || code->op == EXEC_OMP_TEAMS
11152 : || code->op == EXEC_OMP_TEAMS_DISTRIBUTE
11153 : || code->op == EXEC_OMP_TEAMS_LOOP))
11154 : {
11155 17 : gfc_error ("Only DEFAULT permitted as reduction-"
11156 : "modifier in REDUCTION clause at %L",
11157 : &n->where);
11158 17 : break;
11159 : }
11160 4789 : gcc_fallthrough ();
11161 4789 : case OMP_LIST_REDUCTION:
11162 4789 : case OMP_LIST_IN_REDUCTION:
11163 4789 : case OMP_LIST_TASK_REDUCTION:
11164 4789 : case OMP_LIST_REDUCTION_INSCAN:
11165 4789 : switch (n->u.reduction_op)
11166 : {
11167 2655 : case OMP_REDUCTION_PLUS:
11168 2655 : case OMP_REDUCTION_TIMES:
11169 2655 : case OMP_REDUCTION_MINUS:
11170 2655 : if (!gfc_numeric_ts (&n->sym->ts))
11171 : bad = true;
11172 : break;
11173 1112 : case OMP_REDUCTION_AND:
11174 1112 : case OMP_REDUCTION_OR:
11175 1112 : case OMP_REDUCTION_EQV:
11176 1112 : case OMP_REDUCTION_NEQV:
11177 1112 : if (n->sym->ts.type != BT_LOGICAL)
11178 : bad = true;
11179 : break;
11180 480 : case OMP_REDUCTION_MAX:
11181 480 : case OMP_REDUCTION_MIN:
11182 480 : if (n->sym->ts.type != BT_INTEGER
11183 212 : && n->sym->ts.type != BT_REAL)
11184 : bad = true;
11185 : break;
11186 192 : case OMP_REDUCTION_IAND:
11187 192 : case OMP_REDUCTION_IOR:
11188 192 : case OMP_REDUCTION_IEOR:
11189 192 : if (n->sym->ts.type != BT_INTEGER)
11190 : bad = true;
11191 : break;
11192 : case OMP_REDUCTION_USER:
11193 : bad = true;
11194 : break;
11195 : default:
11196 : break;
11197 : }
11198 : if (!bad)
11199 4215 : n->u2.udr = NULL;
11200 : else
11201 : {
11202 574 : const char *udr_name = NULL;
11203 574 : if (n->u2.udr)
11204 : {
11205 470 : udr_name = n->u2.udr->udr->name;
11206 470 : n->u2.udr->udr
11207 940 : = gfc_find_omp_udr (NULL, udr_name,
11208 470 : &n->sym->ts);
11209 470 : if (n->u2.udr->udr == NULL)
11210 : {
11211 0 : free (n->u2.udr);
11212 0 : n->u2.udr = NULL;
11213 : }
11214 : }
11215 574 : if (n->u2.udr == NULL)
11216 : {
11217 104 : if (udr_name == NULL)
11218 104 : switch (n->u.reduction_op)
11219 : {
11220 50 : case OMP_REDUCTION_PLUS:
11221 50 : case OMP_REDUCTION_TIMES:
11222 50 : case OMP_REDUCTION_MINUS:
11223 50 : case OMP_REDUCTION_AND:
11224 50 : case OMP_REDUCTION_OR:
11225 50 : case OMP_REDUCTION_EQV:
11226 50 : case OMP_REDUCTION_NEQV:
11227 50 : udr_name = gfc_op2string ((gfc_intrinsic_op)
11228 : n->u.reduction_op);
11229 50 : break;
11230 : case OMP_REDUCTION_MAX:
11231 : udr_name = "max";
11232 : break;
11233 9 : case OMP_REDUCTION_MIN:
11234 9 : udr_name = "min";
11235 9 : break;
11236 12 : case OMP_REDUCTION_IAND:
11237 12 : udr_name = "iand";
11238 12 : break;
11239 12 : case OMP_REDUCTION_IOR:
11240 12 : udr_name = "ior";
11241 12 : break;
11242 9 : case OMP_REDUCTION_IEOR:
11243 9 : udr_name = "ieor";
11244 9 : break;
11245 0 : default:
11246 0 : gcc_unreachable ();
11247 : }
11248 104 : gfc_error ("!$OMP DECLARE REDUCTION %s not found "
11249 : "for type %s at %L", udr_name,
11250 104 : gfc_typename (&n->sym->ts), &n->where);
11251 : }
11252 : else
11253 : {
11254 470 : gfc_omp_udr *udr = n->u2.udr->udr;
11255 470 : n->u.reduction_op = OMP_REDUCTION_USER;
11256 470 : n->u2.udr->combiner
11257 940 : = resolve_omp_udr_clause (n, udr->combiner_ns,
11258 470 : udr->omp_out,
11259 470 : udr->omp_in);
11260 470 : if (udr->initializer_ns)
11261 331 : n->u2.udr->initializer
11262 331 : = resolve_omp_udr_clause (n,
11263 : udr->initializer_ns,
11264 331 : udr->omp_priv,
11265 331 : udr->omp_orig);
11266 : }
11267 : }
11268 : break;
11269 874 : case OMP_LIST_LINEAR:
11270 874 : if (code)
11271 : {
11272 727 : bool is_worksharing_for = false;
11273 727 : switch (code->op)
11274 : {
11275 54 : case EXEC_OMP_DO:
11276 54 : case EXEC_OMP_PARALLEL_DO:
11277 54 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
11278 54 : case EXEC_OMP_TARGET_PARALLEL_DO:
11279 54 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
11280 54 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
11281 54 : is_worksharing_for = true;
11282 54 : break;
11283 : default:
11284 : break;
11285 : }
11286 :
11287 54 : if (is_worksharing_for
11288 54 : && (n->sym->attr.dimension
11289 53 : || n->sym->attr.allocatable))
11290 : {
11291 1 : if (n->sym->attr.allocatable)
11292 0 : gfc_error ("Sorry, ALLOCATABLE object %qs in "
11293 : "LINEAR clause on worksharing-loop "
11294 : "construct at %L is not yet supported",
11295 : n->sym->name, &n->where);
11296 : else
11297 1 : gfc_error ("Sorry, array %qs in LINEAR clause "
11298 : "on worksharing-loop construct at %L "
11299 : "is not yet supported",
11300 : n->sym->name, &n->where);
11301 : break;
11302 : }
11303 : }
11304 :
11305 726 : if (code
11306 726 : && n->u.linear.op != OMP_LINEAR_DEFAULT
11307 23 : && n->u.linear.op != linear_op)
11308 : {
11309 23 : if (n->u.linear.old_modifier)
11310 : {
11311 9 : gfc_error ("LINEAR clause modifier used on DO or "
11312 : "SIMD construct at %L", &n->where);
11313 9 : linear_op = n->u.linear.op;
11314 : }
11315 14 : else if (n->u.linear.op != OMP_LINEAR_VAL)
11316 : {
11317 6 : gfc_error ("LINEAR clause modifier other than VAL "
11318 : "used on DO or SIMD construct at %L",
11319 : &n->where);
11320 6 : linear_op = n->u.linear.op;
11321 : }
11322 : }
11323 850 : else if (n->u.linear.op != OMP_LINEAR_REF
11324 800 : && n->sym->ts.type != BT_INTEGER)
11325 1 : gfc_error ("LINEAR variable %qs must be INTEGER "
11326 : "at %L", n->sym->name, &n->where);
11327 849 : else if ((n->u.linear.op == OMP_LINEAR_REF
11328 799 : || n->u.linear.op == OMP_LINEAR_UVAL)
11329 61 : && n->sym->attr.value)
11330 0 : gfc_error ("LINEAR dummy argument %qs with VALUE "
11331 : "attribute with %s modifier at %L",
11332 : n->sym->name,
11333 : n->u.linear.op == OMP_LINEAR_REF
11334 : ? "REF" : "UVAL", &n->where);
11335 849 : else if (n->expr)
11336 : {
11337 830 : gfc_expr *expr = n->expr;
11338 830 : if (!gfc_resolve_expr (expr)
11339 830 : || expr->ts.type != BT_INTEGER
11340 1660 : || expr->rank != 0)
11341 0 : gfc_error ("%qs in LINEAR clause at %L requires "
11342 : "a scalar integer linear-step expression",
11343 0 : n->sym->name, &n->where);
11344 830 : else if (!code && expr->expr_type != EXPR_CONSTANT)
11345 : {
11346 11 : if (expr->expr_type == EXPR_VARIABLE
11347 7 : && expr->symtree->n.sym->attr.dummy
11348 6 : && expr->symtree->n.sym->ns == ns)
11349 : {
11350 6 : gfc_omp_namelist *n2;
11351 6 : for (n2 = omp_clauses->lists[OMP_LIST_UNIFORM];
11352 6 : n2; n2 = n2->next)
11353 6 : if (n2->sym == expr->symtree->n.sym)
11354 : break;
11355 6 : if (n2)
11356 : break;
11357 : }
11358 5 : gfc_error ("%qs in LINEAR clause at %L requires "
11359 : "a constant integer linear-step "
11360 : "expression or dummy argument "
11361 : "specified in UNIFORM clause",
11362 5 : n->sym->name, &n->where);
11363 : }
11364 : }
11365 : break;
11366 : /* Workaround for PR middle-end/26316, nothing really needs
11367 : to be done here for OMP_LIST_PRIVATE. */
11368 9394 : case OMP_LIST_PRIVATE:
11369 9394 : gcc_assert (code && code->op != EXEC_NOP);
11370 : break;
11371 98 : case OMP_LIST_USE_DEVICE:
11372 98 : if (n->sym->attr.allocatable
11373 98 : || (n->sym->ts.type == BT_CLASS && CLASS_DATA (n->sym)
11374 0 : && CLASS_DATA (n->sym)->attr.allocatable))
11375 0 : gfc_error ("ALLOCATABLE object %qs in %s clause at %L",
11376 : n->sym->name, name, &n->where);
11377 98 : if (n->sym->ts.type == BT_CLASS
11378 0 : && CLASS_DATA (n->sym)
11379 0 : && CLASS_DATA (n->sym)->attr.class_pointer)
11380 0 : gfc_error ("POINTER object %qs of polymorphic type in "
11381 : "%s clause at %L", n->sym->name, name,
11382 : &n->where);
11383 98 : if (n->sym->attr.cray_pointer)
11384 2 : gfc_error ("Cray pointer object %qs in %s clause at %L",
11385 : n->sym->name, name, &n->where);
11386 96 : else if (n->sym->attr.cray_pointee)
11387 2 : gfc_error ("Cray pointee object %qs in %s clause at %L",
11388 : n->sym->name, name, &n->where);
11389 94 : else if (n->sym->attr.flavor == FL_VARIABLE
11390 93 : && !n->sym->as
11391 54 : && !n->sym->attr.pointer)
11392 13 : gfc_error ("%s clause variable %qs at %L is neither "
11393 : "a POINTER nor an array", name,
11394 : n->sym->name, &n->where);
11395 : /* FALLTHRU */
11396 98 : case OMP_LIST_DEVICE_RESIDENT:
11397 98 : check_symbol_not_pointer (n->sym, n->where, name);
11398 98 : check_array_not_assumed (n->sym, n->where, name);
11399 98 : break;
11400 : default:
11401 : break;
11402 : }
11403 : }
11404 : break;
11405 : }
11406 : }
11407 : /* OpenMP 5.1: use_device_ptr acts like use_device_addr, except for
11408 : type(c_ptr). */
11409 33042 : if (omp_clauses->lists[OMP_LIST_USE_DEVICE_PTR])
11410 : {
11411 9 : gfc_omp_namelist *n_prev, *n_next, *n_addr;
11412 9 : n_addr = omp_clauses->lists[OMP_LIST_USE_DEVICE_ADDR];
11413 28 : for (; n_addr && n_addr->next; n_addr = n_addr->next)
11414 : ;
11415 : n_prev = NULL;
11416 : n = omp_clauses->lists[OMP_LIST_USE_DEVICE_PTR];
11417 27 : while (n)
11418 : {
11419 18 : n_next = n->next;
11420 18 : if (n->sym->ts.type != BT_DERIVED
11421 18 : || n->sym->ts.u.derived->ts.f90_type != BT_VOID)
11422 : {
11423 0 : n->next = NULL;
11424 0 : if (n_addr)
11425 0 : n_addr->next = n;
11426 : else
11427 0 : omp_clauses->lists[OMP_LIST_USE_DEVICE_ADDR] = n;
11428 0 : n_addr = n;
11429 0 : if (n_prev)
11430 0 : n_prev->next = n_next;
11431 : else
11432 0 : omp_clauses->lists[OMP_LIST_USE_DEVICE_PTR] = n_next;
11433 : }
11434 : else
11435 : n_prev = n;
11436 : n = n_next;
11437 : }
11438 : }
11439 33042 : if (omp_clauses->safelen_expr)
11440 93 : resolve_positive_int_expr (omp_clauses->safelen_expr, "SAFELEN");
11441 33042 : if (omp_clauses->simdlen_expr)
11442 123 : resolve_positive_int_expr (omp_clauses->simdlen_expr, "SIMDLEN");
11443 33236 : for (el = omp_clauses->num_teams_list; el; el = el->next)
11444 194 : resolve_positive_int_expr (el->expr, "NUM_TEAMS");
11445 33042 : if (omp_clauses->num_teams_list
11446 153 : && omp_clauses->num_teams_list->next
11447 34 : && !omp_clauses->num_teams_dims
11448 27 : && omp_clauses->num_teams_list->expr->expr_type == EXPR_CONSTANT
11449 13 : && omp_clauses->num_teams_list->next->expr->expr_type == EXPR_CONSTANT
11450 13 : && mpz_cmp (omp_clauses->num_teams_list->expr->value.integer,
11451 13 : omp_clauses->num_teams_list->next->expr->value.integer) > 0)
11452 2 : gfc_warning (OPT_Wopenmp, "NUM_TEAMS lower bound at %L larger than upper "
11453 : "bound at %L", &omp_clauses->num_teams_list->expr->where,
11454 : &omp_clauses->num_teams_list->next->expr->where);
11455 33042 : if (omp_clauses->device)
11456 333 : resolve_scalar_int_expr (omp_clauses->device, "DEVICE");
11457 33042 : if (omp_clauses->filter)
11458 42 : resolve_nonnegative_int_expr (omp_clauses->filter, "FILTER");
11459 33042 : if (omp_clauses->hint)
11460 : {
11461 42 : resolve_scalar_int_expr (omp_clauses->hint, "HINT");
11462 42 : if (omp_clauses->hint->ts.type != BT_INTEGER
11463 40 : || omp_clauses->hint->expr_type != EXPR_CONSTANT
11464 38 : || mpz_sgn (omp_clauses->hint->value.integer) < 0)
11465 5 : gfc_error ("Value of HINT clause at %L shall be a valid "
11466 : "constant hint expression", &omp_clauses->hint->where);
11467 : }
11468 33042 : if (omp_clauses->priority)
11469 34 : resolve_nonnegative_int_expr (omp_clauses->priority, "PRIORITY");
11470 33042 : if (omp_clauses->dist_chunk_size)
11471 : {
11472 83 : gfc_expr *expr = omp_clauses->dist_chunk_size;
11473 83 : if (!gfc_resolve_expr (expr)
11474 83 : || expr->ts.type != BT_INTEGER || expr->rank != 0)
11475 0 : gfc_error ("DIST_SCHEDULE clause's chunk_size at %L requires "
11476 : "a scalar INTEGER expression", &expr->where);
11477 : }
11478 33164 : for (el = omp_clauses->thread_limit_list; el; el = el->next)
11479 122 : resolve_positive_int_expr (el->expr, "THREAD_LIMIT");
11480 33042 : if (omp_clauses->grainsize)
11481 34 : resolve_positive_int_expr (omp_clauses->grainsize, "GRAINSIZE");
11482 33042 : if (omp_clauses->num_tasks)
11483 26 : resolve_positive_int_expr (omp_clauses->num_tasks, "NUM_TASKS");
11484 33042 : if (omp_clauses->grainsize && omp_clauses->num_tasks)
11485 1 : gfc_error ("%<GRAINSIZE%> clause at %L must not be used together with "
11486 : "%<NUM_TASKS%> clause", &omp_clauses->grainsize->where);
11487 33042 : if (omp_clauses->lists[OMP_LIST_REDUCTION] && omp_clauses->nogroup)
11488 1 : gfc_error ("%<REDUCTION%> clause at %L must not be used together with "
11489 : "%<NOGROUP%> clause",
11490 : &omp_clauses->lists[OMP_LIST_REDUCTION]->where);
11491 33042 : if (omp_clauses->full && omp_clauses->partial)
11492 0 : gfc_error ("%<FULL%> clause at %C must not be used together with "
11493 : "%<PARTIAL%> clause");
11494 33042 : if (omp_clauses->async)
11495 610 : if (omp_clauses->async_expr)
11496 610 : resolve_scalar_int_expr (omp_clauses->async_expr, "ASYNC");
11497 33042 : if (omp_clauses->device_num_expr)
11498 105 : resolve_scalar_int_expr (omp_clauses->device_num_expr, "DEVICE_NUM");
11499 33042 : if (code && code->op == EXEC_OACC_SET
11500 121 : && !omp_clauses->device_num_expr
11501 52 : && !omp_clauses->oacc_device_type_present)
11502 2 : gfc_error ("At least one of the clauses %<DEVICE_TYPE%> and %<DEVICE_NUM%> "
11503 : "should be present in %<SET%> directive at %L", &code->loc);
11504 33042 : if (omp_clauses->num_gangs_expr)
11505 682 : resolve_positive_int_expr (omp_clauses->num_gangs_expr, "NUM_GANGS");
11506 33042 : if (omp_clauses->num_workers_expr)
11507 599 : resolve_positive_int_expr (omp_clauses->num_workers_expr, "NUM_WORKERS");
11508 33042 : if (omp_clauses->vector_length_expr)
11509 569 : resolve_positive_int_expr (omp_clauses->vector_length_expr,
11510 : "VECTOR_LENGTH");
11511 33042 : if (omp_clauses->gang_num_expr)
11512 114 : resolve_positive_int_expr (omp_clauses->gang_num_expr, "GANG");
11513 33042 : if (omp_clauses->gang_static_expr)
11514 94 : resolve_positive_int_expr (omp_clauses->gang_static_expr, "GANG");
11515 33042 : if (omp_clauses->worker_expr)
11516 101 : resolve_positive_int_expr (omp_clauses->worker_expr, "WORKER");
11517 33042 : if (omp_clauses->vector_expr)
11518 132 : resolve_positive_int_expr (omp_clauses->vector_expr, "VECTOR");
11519 33381 : for (el = omp_clauses->wait_list; el; el = el->next)
11520 339 : resolve_scalar_int_expr (el->expr, "WAIT");
11521 33042 : if (omp_clauses->collapse && omp_clauses->tile_list)
11522 4 : gfc_error ("Incompatible use of TILE and COLLAPSE at %L", &code->loc);
11523 33042 : if (omp_clauses->message)
11524 : {
11525 56 : gfc_expr *expr = omp_clauses->message;
11526 56 : if (!gfc_resolve_expr (expr)
11527 56 : || expr->ts.kind != gfc_default_character_kind
11528 109 : || expr->ts.type != BT_CHARACTER || expr->rank != 0)
11529 4 : gfc_error ("MESSAGE clause at %L requires a scalar default-kind "
11530 : "CHARACTER expression", &expr->where);
11531 : }
11532 33042 : if (!openacc
11533 33042 : && code
11534 19806 : && omp_clauses->lists[OMP_LIST_MAP] == NULL
11535 16019 : && omp_clauses->lists[OMP_LIST_USE_DEVICE_PTR] == NULL
11536 16016 : && omp_clauses->lists[OMP_LIST_USE_DEVICE_ADDR] == NULL)
11537 : {
11538 15993 : const char *p = NULL;
11539 15993 : switch (code->op)
11540 : {
11541 1 : case EXEC_OMP_TARGET_ENTER_DATA: p = "TARGET ENTER DATA"; break;
11542 1 : case EXEC_OMP_TARGET_EXIT_DATA: p = "TARGET EXIT DATA"; break;
11543 : default: break;
11544 : }
11545 15993 : if (code->op == EXEC_OMP_TARGET_DATA)
11546 1 : gfc_error ("TARGET DATA must contain at least one MAP, USE_DEVICE_PTR, "
11547 : "or USE_DEVICE_ADDR clause at %L", &code->loc);
11548 15992 : else if (p)
11549 2 : gfc_error ("%s must contain at least one MAP clause at %L",
11550 : p, &code->loc);
11551 : }
11552 33042 : if (omp_clauses->sizes_list)
11553 : {
11554 : gfc_expr_list *el;
11555 572 : for (el = omp_clauses->sizes_list; el; el = el->next)
11556 : {
11557 377 : resolve_scalar_int_expr (el->expr, "SIZES");
11558 377 : if (el->expr->expr_type != EXPR_CONSTANT)
11559 1 : gfc_error ("SIZES requires constant expression at %L",
11560 : &el->expr->where);
11561 376 : else if (el->expr->expr_type == EXPR_CONSTANT
11562 376 : && el->expr->ts.type == BT_INTEGER
11563 376 : && mpz_sgn (el->expr->value.integer) <= 0)
11564 2 : gfc_error ("INTEGER expression of %s clause at %L must be "
11565 : "positive", "SIZES", &el->expr->where);
11566 : }
11567 : }
11568 :
11569 33042 : if (!openacc && omp_clauses->detach)
11570 : {
11571 125 : if (!gfc_resolve_expr (omp_clauses->detach)
11572 125 : || omp_clauses->detach->ts.type != BT_INTEGER
11573 124 : || omp_clauses->detach->ts.kind != gfc_c_intptr_kind
11574 248 : || omp_clauses->detach->rank != 0)
11575 3 : gfc_error ("%qs at %L should be a scalar of type "
11576 : "integer(kind=omp_event_handle_kind)",
11577 3 : omp_clauses->detach->symtree->n.sym->name,
11578 3 : &omp_clauses->detach->where);
11579 122 : else if (omp_clauses->detach->symtree->n.sym->attr.dimension > 0)
11580 1 : gfc_error ("The event handle at %L must not be an array element",
11581 : &omp_clauses->detach->where);
11582 121 : else if (omp_clauses->detach->symtree->n.sym->ts.type == BT_DERIVED
11583 120 : || omp_clauses->detach->symtree->n.sym->ts.type == BT_CLASS)
11584 1 : gfc_error ("The event handle at %L must not be part of "
11585 : "a derived type or class", &omp_clauses->detach->where);
11586 :
11587 125 : if (omp_clauses->mergeable)
11588 2 : gfc_error ("%<DETACH%> clause at %L must not be used together with "
11589 2 : "%<MERGEABLE%> clause", &omp_clauses->detach->where);
11590 : }
11591 :
11592 12995 : if (openacc
11593 12995 : && code->op == EXEC_OACC_HOST_DATA
11594 60 : && omp_clauses->lists[OMP_LIST_USE_DEVICE] == NULL)
11595 1 : gfc_error ("%<host_data%> construct at %L requires %<use_device%> clause",
11596 : &code->loc);
11597 :
11598 33042 : if (omp_clauses->assume)
11599 16 : gfc_resolve_omp_assumptions (omp_clauses->assume);
11600 : }
11601 :
11602 :
11603 : /* Return true if SYM is ever referenced in EXPR except in the SE node. */
11604 :
11605 : static bool
11606 4991 : expr_references_sym (gfc_expr *e, gfc_symbol *s, gfc_expr *se)
11607 : {
11608 6617 : gfc_actual_arglist *arg;
11609 6617 : if (e == NULL || e == se)
11610 : return false;
11611 5366 : switch (e->expr_type)
11612 : {
11613 3120 : case EXPR_CONSTANT:
11614 3120 : case EXPR_NULL:
11615 3120 : case EXPR_VARIABLE:
11616 3120 : case EXPR_STRUCTURE:
11617 3120 : case EXPR_ARRAY:
11618 3120 : if (e->symtree != NULL
11619 1152 : && e->symtree->n.sym == s)
11620 : return true;
11621 : return false;
11622 0 : case EXPR_SUBSTRING:
11623 0 : if (e->ref != NULL
11624 0 : && (expr_references_sym (e->ref->u.ss.start, s, se)
11625 0 : || expr_references_sym (e->ref->u.ss.end, s, se)))
11626 0 : return true;
11627 : return false;
11628 1735 : case EXPR_OP:
11629 1735 : if (expr_references_sym (e->value.op.op2, s, se))
11630 : return true;
11631 1626 : return expr_references_sym (e->value.op.op1, s, se);
11632 511 : case EXPR_FUNCTION:
11633 896 : for (arg = e->value.function.actual; arg; arg = arg->next)
11634 586 : if (expr_references_sym (arg->expr, s, se))
11635 : return true;
11636 : return false;
11637 0 : default:
11638 0 : gcc_unreachable ();
11639 : }
11640 : }
11641 :
11642 :
11643 : /* If EXPR is a conversion function that widens the type
11644 : if WIDENING is true or narrows the type if NARROW is true,
11645 : return the inner expression, otherwise return NULL. */
11646 :
11647 : static gfc_expr *
11648 5911 : is_conversion (gfc_expr *expr, bool narrowing, bool widening)
11649 : {
11650 5911 : gfc_typespec *ts1, *ts2;
11651 :
11652 5911 : if (expr->expr_type != EXPR_FUNCTION
11653 917 : || expr->value.function.isym == NULL
11654 894 : || expr->value.function.esym != NULL
11655 894 : || expr->value.function.isym->id != GFC_ISYM_CONVERSION
11656 388 : || (!narrowing && !widening))
11657 : return NULL;
11658 :
11659 388 : if (narrowing && widening)
11660 267 : return expr->value.function.actual->expr;
11661 :
11662 121 : if (widening)
11663 : {
11664 121 : ts1 = &expr->ts;
11665 121 : ts2 = &expr->value.function.actual->expr->ts;
11666 : }
11667 : else
11668 : {
11669 0 : ts1 = &expr->value.function.actual->expr->ts;
11670 0 : ts2 = &expr->ts;
11671 : }
11672 :
11673 121 : if (ts1->type > ts2->type
11674 49 : || (ts1->type == ts2->type && ts1->kind > ts2->kind))
11675 121 : return expr->value.function.actual->expr;
11676 :
11677 : return NULL;
11678 : }
11679 :
11680 : static bool
11681 6855 : is_scalar_intrinsic_expr (gfc_expr *expr, bool must_be_var, bool conv_ok)
11682 : {
11683 6855 : if (must_be_var
11684 4020 : && (expr->expr_type != EXPR_VARIABLE || !expr->symtree))
11685 : {
11686 37 : if (!conv_ok)
11687 : return false;
11688 37 : gfc_expr *conv = is_conversion (expr, true, true);
11689 37 : if (!conv)
11690 : return false;
11691 36 : if (conv->expr_type != EXPR_VARIABLE || !conv->symtree)
11692 : return false;
11693 : }
11694 6852 : return (expr->rank == 0
11695 6848 : && !gfc_is_coindexed (expr)
11696 13700 : && (expr->ts.type == BT_INTEGER
11697 : || expr->ts.type == BT_REAL
11698 : || expr->ts.type == BT_COMPLEX
11699 : || expr->ts.type == BT_LOGICAL));
11700 : }
11701 :
11702 : static void
11703 2697 : resolve_omp_atomic (gfc_code *code)
11704 : {
11705 2697 : gfc_code *atomic_code = code->block;
11706 2697 : gfc_symbol *var;
11707 2697 : gfc_expr *stmt_expr2, *capt_expr2;
11708 2697 : gfc_omp_atomic_op aop
11709 2697 : = (gfc_omp_atomic_op) (atomic_code->ext.omp_clauses->atomic_op
11710 : & GFC_OMP_ATOMIC_MASK);
11711 2697 : gfc_code *stmt = NULL, *capture_stmt = NULL, *tailing_stmt = NULL;
11712 2697 : gfc_expr *comp_cond = NULL;
11713 2697 : locus *loc = NULL;
11714 :
11715 2697 : code = code->block->next;
11716 : /* resolve_blocks asserts this is initially EXEC_ASSIGN or EXEC_IF
11717 : If it changed to EXEC_NOP, assume an error has been emitted already. */
11718 2697 : if (code->op == EXEC_NOP)
11719 : return;
11720 :
11721 2696 : if (atomic_code->ext.omp_clauses->compare
11722 156 : && atomic_code->ext.omp_clauses->capture)
11723 : {
11724 : /* Must be either "if (x == e) then; x = d; else; v = x; end if"
11725 : or "v = expr" followed/preceded by
11726 : "if (x == e) then; x = d; end if" or "if (x == e) x = d". */
11727 103 : gfc_code *next = code;
11728 103 : if (code->op == EXEC_ASSIGN)
11729 : {
11730 19 : capture_stmt = code;
11731 19 : next = code->next;
11732 : }
11733 103 : if (next->op == EXEC_IF
11734 103 : && next->block
11735 103 : && next->block->op == EXEC_IF
11736 103 : && next->block->next
11737 102 : && next->block->next->op == EXEC_ASSIGN)
11738 : {
11739 102 : comp_cond = next->block->expr1;
11740 102 : stmt = next->block->next;
11741 102 : if (stmt->next)
11742 : {
11743 0 : loc = &stmt->loc;
11744 0 : goto unexpected;
11745 : }
11746 : }
11747 1 : else if (capture_stmt)
11748 : {
11749 0 : gfc_error ("Expected IF at %L in atomic compare capture",
11750 : &next->loc);
11751 0 : return;
11752 : }
11753 103 : if (stmt && !capture_stmt && next->block->block)
11754 : {
11755 64 : if (next->block->block->expr1)
11756 : {
11757 0 : gfc_error ("Expected ELSE at %L in atomic compare capture",
11758 : &next->block->block->expr1->where);
11759 0 : return;
11760 : }
11761 64 : if (!code->block->block->next
11762 64 : || code->block->block->next->op != EXEC_ASSIGN)
11763 : {
11764 0 : loc = (code->block->block->next ? &code->block->block->next->loc
11765 : : &code->block->block->loc);
11766 0 : goto unexpected;
11767 : }
11768 64 : capture_stmt = code->block->block->next;
11769 64 : if (capture_stmt->next)
11770 : {
11771 0 : loc = &capture_stmt->next->loc;
11772 0 : goto unexpected;
11773 : }
11774 : }
11775 103 : if (stmt && !capture_stmt && next->next->op == EXEC_ASSIGN)
11776 : capture_stmt = next->next;
11777 84 : else if (!capture_stmt)
11778 : {
11779 1 : loc = &code->loc;
11780 1 : goto unexpected;
11781 : }
11782 : }
11783 2593 : else if (atomic_code->ext.omp_clauses->compare)
11784 : {
11785 : /* Must be: "if (x == e) then; x = d; end if" or "if (x == e) x = d". */
11786 53 : if (code->op == EXEC_IF
11787 53 : && code->block
11788 53 : && code->block->op == EXEC_IF
11789 53 : && code->block->next
11790 51 : && code->block->next->op == EXEC_ASSIGN)
11791 : {
11792 51 : comp_cond = code->block->expr1;
11793 51 : stmt = code->block->next;
11794 51 : if (stmt->next || code->block->block)
11795 : {
11796 0 : loc = stmt->next ? &stmt->next->loc : &code->block->block->loc;
11797 0 : goto unexpected;
11798 : }
11799 : }
11800 : else
11801 : {
11802 2 : loc = &code->loc;
11803 2 : goto unexpected;
11804 : }
11805 : }
11806 2540 : else if (atomic_code->ext.omp_clauses->capture)
11807 : {
11808 : /* Must be: "v = x" followed/preceded by "x = ...". */
11809 489 : if (code->op != EXEC_ASSIGN)
11810 0 : goto unexpected;
11811 489 : if (code->next->op != EXEC_ASSIGN)
11812 : {
11813 0 : loc = &code->next->loc;
11814 0 : goto unexpected;
11815 : }
11816 489 : gfc_expr *expr2, *expr2_next;
11817 489 : expr2 = is_conversion (code->expr2, true, true);
11818 489 : if (expr2 == NULL)
11819 447 : expr2 = code->expr2;
11820 489 : expr2_next = is_conversion (code->next->expr2, true, true);
11821 489 : if (expr2_next == NULL)
11822 478 : expr2_next = code->next->expr2;
11823 489 : if (code->expr1->expr_type == EXPR_VARIABLE
11824 489 : && code->next->expr1->expr_type == EXPR_VARIABLE
11825 489 : && expr2->expr_type == EXPR_VARIABLE
11826 243 : && expr2_next->expr_type == EXPR_VARIABLE)
11827 : {
11828 1 : if (code->expr1->symtree->n.sym == expr2_next->symtree->n.sym)
11829 : {
11830 : stmt = code;
11831 : capture_stmt = code->next;
11832 : }
11833 : else
11834 : {
11835 489 : capture_stmt = code;
11836 489 : stmt = code->next;
11837 : }
11838 : }
11839 488 : else if (expr2->expr_type == EXPR_VARIABLE)
11840 : {
11841 : capture_stmt = code;
11842 : stmt = code->next;
11843 : }
11844 : else
11845 : {
11846 247 : stmt = code;
11847 247 : capture_stmt = code->next;
11848 : }
11849 : /* Shall be NULL but can happen for invalid code. */
11850 489 : tailing_stmt = code->next->next;
11851 : }
11852 : else
11853 : {
11854 : /* x = ... */
11855 2051 : stmt = code;
11856 2051 : if (!atomic_code->ext.omp_clauses->compare && stmt->op != EXEC_ASSIGN)
11857 1 : goto unexpected;
11858 : /* Shall be NULL but can happen for invalid code. */
11859 2050 : tailing_stmt = code->next;
11860 : }
11861 :
11862 2692 : if (comp_cond)
11863 : {
11864 153 : if (comp_cond->expr_type != EXPR_OP
11865 153 : || (comp_cond->value.op.op != INTRINSIC_EQ
11866 : && comp_cond->value.op.op != INTRINSIC_EQ_OS
11867 : && comp_cond->value.op.op != INTRINSIC_EQV))
11868 : {
11869 0 : gfc_error ("Expected %<==%>, %<.EQ.%> or %<.EQV.%> atomic comparison "
11870 : "expression at %L", &comp_cond->where);
11871 0 : return;
11872 : }
11873 153 : if (!is_scalar_intrinsic_expr (comp_cond->value.op.op1, true, true))
11874 : {
11875 1 : gfc_error ("Expected scalar intrinsic variable at %L in atomic "
11876 1 : "comparison", &comp_cond->value.op.op1->where);
11877 1 : return;
11878 : }
11879 152 : if (!gfc_resolve_expr (comp_cond->value.op.op2))
11880 : return;
11881 152 : if (!is_scalar_intrinsic_expr (comp_cond->value.op.op2, false, false))
11882 : {
11883 0 : gfc_error ("Expected scalar intrinsic expression at %L in atomic "
11884 0 : "comparison", &comp_cond->value.op.op1->where);
11885 0 : return;
11886 : }
11887 : }
11888 :
11889 2691 : if (!is_scalar_intrinsic_expr (stmt->expr1, true, false))
11890 : {
11891 4 : gfc_error ("!$OMP ATOMIC statement must set a scalar variable of "
11892 4 : "intrinsic type at %L", &stmt->expr1->where);
11893 4 : return;
11894 : }
11895 :
11896 2687 : if (!gfc_resolve_expr (stmt->expr2))
11897 : return;
11898 2683 : if (!is_scalar_intrinsic_expr (stmt->expr2, false, false))
11899 : {
11900 0 : gfc_error ("!$OMP ATOMIC statement must assign an expression of "
11901 0 : "intrinsic type at %L", &stmt->expr2->where);
11902 0 : return;
11903 : }
11904 :
11905 2683 : if (gfc_expr_attr (stmt->expr1).allocatable)
11906 : {
11907 0 : gfc_error ("!$OMP ATOMIC with ALLOCATABLE variable at %L",
11908 0 : &stmt->expr1->where);
11909 0 : return;
11910 : }
11911 :
11912 : /* Should be diagnosed above already. */
11913 2683 : gcc_assert (tailing_stmt == NULL);
11914 :
11915 2683 : var = stmt->expr1->symtree->n.sym;
11916 2683 : stmt_expr2 = is_conversion (stmt->expr2, true, true);
11917 2683 : if (stmt_expr2 == NULL)
11918 2527 : stmt_expr2 = stmt->expr2;
11919 :
11920 2683 : switch (aop)
11921 : {
11922 503 : case GFC_OMP_ATOMIC_READ:
11923 503 : if (stmt_expr2->expr_type != EXPR_VARIABLE)
11924 0 : gfc_error ("!$OMP ATOMIC READ statement must read from a scalar "
11925 : "variable of intrinsic type at %L", &stmt_expr2->where);
11926 : return;
11927 421 : case GFC_OMP_ATOMIC_WRITE:
11928 421 : if (expr_references_sym (stmt_expr2, var, NULL))
11929 0 : gfc_error ("expr in !$OMP ATOMIC WRITE assignment var = expr "
11930 : "must be scalar and cannot reference var at %L",
11931 : &stmt_expr2->where);
11932 : return;
11933 1759 : default:
11934 1759 : break;
11935 : }
11936 :
11937 1759 : if (atomic_code->ext.omp_clauses->capture)
11938 : {
11939 588 : if (!is_scalar_intrinsic_expr (capture_stmt->expr1, true, false))
11940 : {
11941 0 : gfc_error ("!$OMP ATOMIC capture-statement must set a scalar "
11942 : "variable of intrinsic type at %L",
11943 0 : &capture_stmt->expr1->where);
11944 0 : return;
11945 : }
11946 :
11947 588 : if (!is_scalar_intrinsic_expr (capture_stmt->expr2, true, true))
11948 : {
11949 2 : gfc_error ("!$OMP ATOMIC capture-statement requires a scalar variable"
11950 2 : " of intrinsic type at %L", &capture_stmt->expr2->where);
11951 2 : return;
11952 : }
11953 586 : capt_expr2 = is_conversion (capture_stmt->expr2, true, true);
11954 586 : if (capt_expr2 == NULL)
11955 564 : capt_expr2 = capture_stmt->expr2;
11956 :
11957 586 : if (capt_expr2->symtree->n.sym != var)
11958 : {
11959 1 : gfc_error ("!$OMP ATOMIC CAPTURE capture statement reads from "
11960 : "different variable than update statement writes "
11961 : "into at %L", &capture_stmt->expr2->where);
11962 1 : return;
11963 : }
11964 : }
11965 :
11966 1756 : if (atomic_code->ext.omp_clauses->compare)
11967 : {
11968 149 : gfc_expr *var_expr;
11969 149 : if (comp_cond->value.op.op1->expr_type == EXPR_VARIABLE)
11970 : var_expr = comp_cond->value.op.op1;
11971 : else
11972 12 : var_expr = comp_cond->value.op.op1->value.function.actual->expr;
11973 149 : if (var_expr->symtree->n.sym != var)
11974 : {
11975 2 : gfc_error ("For !$OMP ATOMIC COMPARE, the first operand in comparison"
11976 : " at %L must be the variable %qs that the update statement"
11977 : " writes into at %L", &var_expr->where, var->name,
11978 2 : &stmt->expr1->where);
11979 2 : return;
11980 : }
11981 147 : if (stmt_expr2->rank != 0 || expr_references_sym (stmt_expr2, var, NULL))
11982 : {
11983 1 : gfc_error ("expr in !$OMP ATOMIC COMPARE assignment var = expr "
11984 : "must be scalar and cannot reference var at %L",
11985 : &stmt_expr2->where);
11986 1 : return;
11987 : }
11988 : }
11989 1607 : else if (atomic_code->ext.omp_clauses->capture
11990 1607 : && !expr_references_sym (stmt_expr2, var, NULL))
11991 22 : atomic_code->ext.omp_clauses->atomic_op
11992 22 : = (gfc_omp_atomic_op) (atomic_code->ext.omp_clauses->atomic_op
11993 : | GFC_OMP_ATOMIC_SWAP);
11994 1585 : else if (stmt_expr2->expr_type == EXPR_OP)
11995 : {
11996 1229 : gfc_expr *v = NULL, *e, *c;
11997 1229 : gfc_intrinsic_op op = stmt_expr2->value.op.op;
11998 1229 : gfc_intrinsic_op alt_op = INTRINSIC_NONE;
11999 :
12000 1229 : if (atomic_code->ext.omp_clauses->fail != OMP_MEMORDER_UNSET)
12001 3 : gfc_error ("!$OMP ATOMIC UPDATE at %L with FAIL clause requires either"
12002 : " the COMPARE clause or using the intrinsic MIN/MAX "
12003 : "procedure", &atomic_code->loc);
12004 1229 : switch (op)
12005 : {
12006 742 : case INTRINSIC_PLUS:
12007 742 : alt_op = INTRINSIC_MINUS;
12008 742 : break;
12009 94 : case INTRINSIC_TIMES:
12010 94 : alt_op = INTRINSIC_DIVIDE;
12011 94 : break;
12012 120 : case INTRINSIC_MINUS:
12013 120 : alt_op = INTRINSIC_PLUS;
12014 120 : break;
12015 94 : case INTRINSIC_DIVIDE:
12016 94 : alt_op = INTRINSIC_TIMES;
12017 94 : break;
12018 : case INTRINSIC_AND:
12019 : case INTRINSIC_OR:
12020 : break;
12021 43 : case INTRINSIC_EQV:
12022 43 : alt_op = INTRINSIC_NEQV;
12023 43 : break;
12024 43 : case INTRINSIC_NEQV:
12025 43 : alt_op = INTRINSIC_EQV;
12026 43 : break;
12027 1 : default:
12028 1 : gfc_error ("!$OMP ATOMIC assignment operator must be binary "
12029 : "+, *, -, /, .AND., .OR., .EQV. or .NEQV. at %L",
12030 : &stmt_expr2->where);
12031 1 : return;
12032 : }
12033 :
12034 : /* Check for var = var op expr resp. var = expr op var where
12035 : expr doesn't reference var and var op expr is mathematically
12036 : equivalent to var op (expr) resp. expr op var equivalent to
12037 : (expr) op var. We rely here on the fact that the matcher
12038 : for x op1 y op2 z where op1 and op2 have equal precedence
12039 : returns (x op1 y) op2 z. */
12040 1228 : e = stmt_expr2->value.op.op2;
12041 1228 : if (e->expr_type == EXPR_VARIABLE
12042 288 : && e->symtree != NULL
12043 288 : && e->symtree->n.sym == var)
12044 : v = e;
12045 999 : else if ((c = is_conversion (e, false, true)) != NULL
12046 48 : && c->expr_type == EXPR_VARIABLE
12047 48 : && c->symtree != NULL
12048 1047 : && c->symtree->n.sym == var)
12049 : v = c;
12050 : else
12051 : {
12052 951 : gfc_expr **p = NULL, **q;
12053 1049 : for (q = &stmt_expr2->value.op.op1; (e = *q) != NULL; )
12054 1049 : if (e->expr_type == EXPR_VARIABLE
12055 948 : && e->symtree != NULL
12056 948 : && e->symtree->n.sym == var)
12057 : {
12058 : v = e;
12059 : break;
12060 : }
12061 101 : else if ((c = is_conversion (e, false, true)) != NULL)
12062 60 : q = &e->value.function.actual->expr;
12063 41 : else if (e->expr_type != EXPR_OP
12064 41 : || (e->value.op.op != op
12065 15 : && e->value.op.op != alt_op)
12066 38 : || e->rank != 0)
12067 : break;
12068 : else
12069 : {
12070 38 : p = q;
12071 38 : q = &e->value.op.op1;
12072 : }
12073 :
12074 951 : if (v == NULL)
12075 : {
12076 3 : gfc_error ("!$OMP ATOMIC assignment must be var = var op expr "
12077 : "or var = expr op var at %L", &stmt_expr2->where);
12078 3 : return;
12079 : }
12080 :
12081 948 : if (p != NULL)
12082 : {
12083 38 : e = *p;
12084 38 : switch (e->value.op.op)
12085 : {
12086 8 : case INTRINSIC_MINUS:
12087 8 : case INTRINSIC_DIVIDE:
12088 8 : case INTRINSIC_EQV:
12089 8 : case INTRINSIC_NEQV:
12090 8 : gfc_error ("!$OMP ATOMIC var = var op expr not "
12091 : "mathematically equivalent to var = var op "
12092 : "(expr) at %L", &stmt_expr2->where);
12093 8 : break;
12094 : default:
12095 : break;
12096 : }
12097 :
12098 : /* Canonicalize into var = var op (expr). */
12099 38 : *p = e->value.op.op2;
12100 38 : e->value.op.op2 = stmt_expr2;
12101 38 : e->ts = stmt_expr2->ts;
12102 38 : if (stmt->expr2 == stmt_expr2)
12103 26 : stmt->expr2 = stmt_expr2 = e;
12104 : else
12105 12 : stmt->expr2->value.function.actual->expr = stmt_expr2 = e;
12106 :
12107 38 : if (!gfc_compare_types (&stmt_expr2->value.op.op1->ts,
12108 : &stmt_expr2->ts))
12109 : {
12110 24 : for (p = &stmt_expr2->value.op.op1; *p != v;
12111 12 : p = &(*p)->value.function.actual->expr)
12112 : ;
12113 12 : *p = NULL;
12114 12 : gfc_free_expr (stmt_expr2->value.op.op1);
12115 12 : stmt_expr2->value.op.op1 = v;
12116 12 : gfc_convert_type (v, &stmt_expr2->ts, 2);
12117 : }
12118 : }
12119 : }
12120 :
12121 1225 : if (e->rank != 0 || expr_references_sym (stmt->expr2, var, v))
12122 : {
12123 1 : gfc_error ("expr in !$OMP ATOMIC assignment var = var op expr "
12124 : "must be scalar and cannot reference var at %L",
12125 : &stmt_expr2->where);
12126 1 : return;
12127 : }
12128 : }
12129 356 : else if (stmt_expr2->expr_type == EXPR_FUNCTION
12130 355 : && stmt_expr2->value.function.isym != NULL
12131 355 : && stmt_expr2->value.function.esym == NULL
12132 355 : && stmt_expr2->value.function.actual != NULL
12133 355 : && stmt_expr2->value.function.actual->next != NULL)
12134 : {
12135 355 : gfc_actual_arglist *arg, *var_arg;
12136 :
12137 355 : switch (stmt_expr2->value.function.isym->id)
12138 : {
12139 : case GFC_ISYM_MIN:
12140 : case GFC_ISYM_MAX:
12141 : break;
12142 147 : case GFC_ISYM_IAND:
12143 147 : case GFC_ISYM_IOR:
12144 147 : case GFC_ISYM_IEOR:
12145 147 : if (stmt_expr2->value.function.actual->next->next != NULL)
12146 : {
12147 0 : gfc_error ("!$OMP ATOMIC assignment intrinsic IAND, IOR "
12148 : "or IEOR must have two arguments at %L",
12149 : &stmt_expr2->where);
12150 0 : return;
12151 : }
12152 : break;
12153 1 : default:
12154 1 : gfc_error ("!$OMP ATOMIC assignment intrinsic must be "
12155 : "MIN, MAX, IAND, IOR or IEOR at %L",
12156 : &stmt_expr2->where);
12157 1 : return;
12158 : }
12159 :
12160 : var_arg = NULL;
12161 1088 : for (arg = stmt_expr2->value.function.actual; arg; arg = arg->next)
12162 : {
12163 741 : gfc_expr *e = NULL;
12164 741 : if (arg == stmt_expr2->value.function.actual
12165 387 : || (var_arg == NULL && arg->next == NULL))
12166 : {
12167 527 : e = is_conversion (arg->expr, false, true);
12168 527 : if (!e)
12169 514 : e = arg->expr;
12170 527 : if (e->expr_type == EXPR_VARIABLE
12171 453 : && e->symtree != NULL
12172 453 : && e->symtree->n.sym == var)
12173 741 : var_arg = arg;
12174 : }
12175 741 : if ((!var_arg || !e) && expr_references_sym (arg->expr, var, NULL))
12176 : {
12177 7 : gfc_error ("!$OMP ATOMIC intrinsic arguments except one must "
12178 : "not reference %qs at %L",
12179 : var->name, &arg->expr->where);
12180 7 : return;
12181 : }
12182 734 : if (arg->expr->rank != 0)
12183 : {
12184 0 : gfc_error ("!$OMP ATOMIC intrinsic arguments must be scalar "
12185 : "at %L", &arg->expr->where);
12186 0 : return;
12187 : }
12188 : }
12189 :
12190 347 : if (var_arg == NULL)
12191 : {
12192 1 : gfc_error ("First or last !$OMP ATOMIC intrinsic argument must "
12193 : "be %qs at %L", var->name, &stmt_expr2->where);
12194 1 : return;
12195 : }
12196 :
12197 346 : if (var_arg != stmt_expr2->value.function.actual)
12198 : {
12199 : /* Canonicalize, so that var comes first. */
12200 172 : gcc_assert (var_arg->next == NULL);
12201 : for (arg = stmt_expr2->value.function.actual;
12202 185 : arg->next != var_arg; arg = arg->next)
12203 : ;
12204 172 : var_arg->next = stmt_expr2->value.function.actual;
12205 172 : stmt_expr2->value.function.actual = var_arg;
12206 172 : arg->next = NULL;
12207 : }
12208 : }
12209 : else
12210 1 : gfc_error ("!$OMP ATOMIC assignment must have an operator or "
12211 : "intrinsic on right hand side at %L", &stmt_expr2->where);
12212 : return;
12213 :
12214 4 : unexpected:
12215 4 : gfc_error ("unexpected !$OMP ATOMIC expression at %L",
12216 : loc ? loc : &code->loc);
12217 4 : return;
12218 : }
12219 :
12220 :
12221 : static struct fortran_omp_context
12222 : {
12223 : gfc_code *code;
12224 : hash_set<gfc_symbol *> *sharing_clauses;
12225 : hash_set<gfc_symbol *> *private_iterators;
12226 : struct fortran_omp_context *previous;
12227 : bool is_openmp;
12228 : } *omp_current_ctx;
12229 : static gfc_code *omp_current_do_code;
12230 : static int omp_current_do_collapse;
12231 :
12232 : /* Forward declaration for mutually recursive functions. */
12233 : static gfc_code *
12234 : find_nested_loop_in_block (gfc_code *block);
12235 :
12236 : /* Return the first nested DO loop in CHAIN, or NULL if there
12237 : isn't one. Does no error checking on intervening code. */
12238 :
12239 : static gfc_code *
12240 27482 : find_nested_loop_in_chain (gfc_code *chain)
12241 : {
12242 27482 : gfc_code *code;
12243 :
12244 27482 : if (!chain)
12245 : return NULL;
12246 :
12247 31643 : for (code = chain; code; code = code->next)
12248 31222 : switch (code->op)
12249 : {
12250 : case EXEC_DO:
12251 : case EXEC_OMP_TILE:
12252 : case EXEC_OMP_UNROLL:
12253 : return code;
12254 621 : case EXEC_BLOCK:
12255 621 : if (gfc_code *c = find_nested_loop_in_block (code))
12256 : return c;
12257 : break;
12258 : default:
12259 : break;
12260 : }
12261 : return NULL;
12262 : }
12263 :
12264 : /* Return the first nested DO loop in BLOCK, or NULL if there
12265 : isn't one. Does no error checking on intervening code. */
12266 : static gfc_code *
12267 939 : find_nested_loop_in_block (gfc_code *block)
12268 : {
12269 939 : gfc_namespace *ns;
12270 939 : gcc_assert (block->op == EXEC_BLOCK);
12271 939 : ns = block->ext.block.ns;
12272 939 : gcc_assert (ns);
12273 939 : return find_nested_loop_in_chain (ns->code);
12274 : }
12275 :
12276 : void
12277 5432 : gfc_resolve_omp_do_blocks (gfc_code *code, gfc_namespace *ns)
12278 : {
12279 5432 : if (code->block->next && code->block->next->op == EXEC_DO)
12280 : {
12281 5079 : int i;
12282 :
12283 5079 : omp_current_do_code = code->block->next;
12284 5079 : if (code->ext.omp_clauses->orderedc)
12285 142 : omp_current_do_collapse = code->ext.omp_clauses->orderedc;
12286 4937 : else if (code->ext.omp_clauses->collapse)
12287 1121 : omp_current_do_collapse = code->ext.omp_clauses->collapse;
12288 3816 : else if (code->ext.omp_clauses->sizes_list)
12289 175 : omp_current_do_collapse
12290 175 : = gfc_expr_list_len (code->ext.omp_clauses->sizes_list);
12291 : else
12292 3641 : omp_current_do_collapse = 1;
12293 5079 : if (code->ext.omp_clauses->lists[OMP_LIST_REDUCTION_INSCAN])
12294 : {
12295 : /* Checking that there is a matching EXEC_OMP_SCAN in the
12296 : innermost body cannot be deferred to resolve_omp_do because
12297 : we process directives nested in the loop before we get
12298 : there. */
12299 60 : locus *loc
12300 : = &code->ext.omp_clauses->lists[OMP_LIST_REDUCTION_INSCAN]->where;
12301 60 : gfc_code *c;
12302 :
12303 80 : for (i = 1, c = omp_current_do_code;
12304 80 : i < omp_current_do_collapse; i++)
12305 : {
12306 22 : c = find_nested_loop_in_chain (c->block->next);
12307 22 : if (!c || c->op != EXEC_DO || c->block == NULL)
12308 : break;
12309 : }
12310 :
12311 : /* Skip this if we don't have enough nested loops. That
12312 : problem will be diagnosed elsewhere. */
12313 60 : if (c && c->op == EXEC_DO)
12314 : {
12315 58 : gfc_code *block = c->block ? c->block->next : NULL;
12316 58 : if (block && block->op != EXEC_OMP_SCAN)
12317 54 : while (block && block->next
12318 54 : && block->next->op != EXEC_OMP_SCAN)
12319 : block = block->next;
12320 43 : if (!block
12321 46 : || (block->op != EXEC_OMP_SCAN
12322 43 : && (!block->next || block->next->op != EXEC_OMP_SCAN)))
12323 19 : gfc_error ("With INSCAN at %L, expected loop body with "
12324 : "!$OMP SCAN between two "
12325 : "structured block sequences", loc);
12326 : else
12327 : {
12328 39 : if (block->op == EXEC_OMP_SCAN)
12329 3 : gfc_warning (OPT_Wopenmp,
12330 : "!$OMP SCAN at %L with zero executable "
12331 : "statements in preceding structured block "
12332 : "sequence", &block->loc);
12333 39 : if ((block->op == EXEC_OMP_SCAN && !block->next)
12334 38 : || (block->next && block->next->op == EXEC_OMP_SCAN
12335 36 : && !block->next->next))
12336 3 : gfc_warning (OPT_Wopenmp,
12337 : "!$OMP SCAN at %L with zero executable "
12338 : "statements in succeeding structured block "
12339 : "sequence", block->op == EXEC_OMP_SCAN
12340 1 : ? &block->loc : &block->next->loc);
12341 : }
12342 58 : if (block && block->op != EXEC_OMP_SCAN)
12343 43 : block = block->next;
12344 46 : if (block && block->op == EXEC_OMP_SCAN)
12345 : /* Mark 'omp scan' as checked; flag will be unset later. */
12346 39 : block->ext.omp_clauses->if_present = true;
12347 : }
12348 : }
12349 : }
12350 5432 : gfc_resolve_blocks (code->block, ns);
12351 5432 : omp_current_do_collapse = 0;
12352 5432 : omp_current_do_code = NULL;
12353 5432 : }
12354 :
12355 :
12356 : void
12357 6103 : gfc_resolve_omp_parallel_blocks (gfc_code *code, gfc_namespace *ns)
12358 : {
12359 6103 : struct fortran_omp_context ctx;
12360 6103 : gfc_omp_clauses *omp_clauses = code->ext.omp_clauses;
12361 6103 : gfc_omp_namelist *n;
12362 :
12363 6103 : ctx.code = code;
12364 6103 : ctx.sharing_clauses = new hash_set<gfc_symbol *>;
12365 6103 : ctx.private_iterators = new hash_set<gfc_symbol *>;
12366 6103 : ctx.previous = omp_current_ctx;
12367 6103 : ctx.is_openmp = true;
12368 6103 : omp_current_ctx = &ctx;
12369 :
12370 244120 : for (enum gfc_omp_list_type list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
12371 238017 : list = gfc_omp_list_type (list + 1))
12372 238017 : switch (list)
12373 : {
12374 61030 : case OMP_LIST_SHARED:
12375 61030 : case OMP_LIST_PRIVATE:
12376 61030 : case OMP_LIST_FIRSTPRIVATE:
12377 61030 : case OMP_LIST_LASTPRIVATE:
12378 61030 : case OMP_LIST_REDUCTION:
12379 61030 : case OMP_LIST_REDUCTION_INSCAN:
12380 61030 : case OMP_LIST_REDUCTION_TASK:
12381 61030 : case OMP_LIST_IN_REDUCTION:
12382 61030 : case OMP_LIST_TASK_REDUCTION:
12383 61030 : case OMP_LIST_LINEAR:
12384 70021 : for (n = omp_clauses->lists[list]; n; n = n->next)
12385 8991 : ctx.sharing_clauses->add (n->sym);
12386 : break;
12387 : default:
12388 : break;
12389 : }
12390 :
12391 6103 : switch (code->op)
12392 : {
12393 2368 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
12394 2368 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
12395 2368 : case EXEC_OMP_MASKED_TASKLOOP:
12396 2368 : case EXEC_OMP_MASKED_TASKLOOP_SIMD:
12397 2368 : case EXEC_OMP_MASTER_TASKLOOP:
12398 2368 : case EXEC_OMP_MASTER_TASKLOOP_SIMD:
12399 2368 : case EXEC_OMP_PARALLEL_DO:
12400 2368 : case EXEC_OMP_PARALLEL_DO_SIMD:
12401 2368 : case EXEC_OMP_PARALLEL_LOOP:
12402 2368 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
12403 2368 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
12404 2368 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
12405 2368 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
12406 2368 : case EXEC_OMP_TARGET_PARALLEL_DO:
12407 2368 : case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
12408 2368 : case EXEC_OMP_TARGET_PARALLEL_LOOP:
12409 2368 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
12410 2368 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
12411 2368 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
12412 2368 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
12413 2368 : case EXEC_OMP_TARGET_TEAMS_LOOP:
12414 2368 : case EXEC_OMP_TASKLOOP:
12415 2368 : case EXEC_OMP_TASKLOOP_SIMD:
12416 2368 : case EXEC_OMP_TEAMS_DISTRIBUTE:
12417 2368 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
12418 2368 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
12419 2368 : case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
12420 2368 : case EXEC_OMP_TEAMS_LOOP:
12421 2368 : gfc_resolve_omp_do_blocks (code, ns);
12422 2368 : break;
12423 3735 : default:
12424 3735 : gfc_resolve_blocks (code->block, ns);
12425 : }
12426 :
12427 6103 : omp_current_ctx = ctx.previous;
12428 12206 : delete ctx.sharing_clauses;
12429 12206 : delete ctx.private_iterators;
12430 6103 : }
12431 :
12432 :
12433 : /* Save and clear openmp.cc private state. */
12434 :
12435 : void
12436 301727 : gfc_omp_save_and_clear_state (struct gfc_omp_saved_state *state)
12437 : {
12438 301727 : state->ptrs[0] = omp_current_ctx;
12439 301727 : state->ptrs[1] = omp_current_do_code;
12440 301727 : state->ints[0] = omp_current_do_collapse;
12441 301727 : omp_current_ctx = NULL;
12442 301727 : omp_current_do_code = NULL;
12443 301727 : omp_current_do_collapse = 0;
12444 301727 : }
12445 :
12446 :
12447 : /* Restore openmp.cc private state from the saved state. */
12448 :
12449 : void
12450 301726 : gfc_omp_restore_state (struct gfc_omp_saved_state *state)
12451 : {
12452 301726 : omp_current_ctx = (struct fortran_omp_context *) state->ptrs[0];
12453 301726 : omp_current_do_code = (gfc_code *) state->ptrs[1];
12454 301726 : omp_current_do_collapse = state->ints[0];
12455 301726 : }
12456 :
12457 :
12458 : /* Note a DO iterator variable. This is special in !$omp parallel
12459 : construct, where they are predetermined private. */
12460 :
12461 : void
12462 33170 : gfc_resolve_do_iterator (gfc_code *code, gfc_symbol *sym, bool add_clause)
12463 : {
12464 33170 : if (omp_current_ctx == NULL)
12465 : return;
12466 :
12467 13113 : int i = omp_current_do_collapse;
12468 13113 : gfc_code *c = omp_current_do_code;
12469 :
12470 13113 : if (sym->attr.threadprivate)
12471 : return;
12472 :
12473 : /* !$omp do and !$omp parallel do iteration variable is predetermined
12474 : private just in the !$omp do resp. !$omp parallel do construct,
12475 : with no implications for the outer parallel constructs. */
12476 :
12477 17948 : while (i-- >= 1 && c)
12478 : {
12479 9502 : if (code == c)
12480 : return;
12481 4835 : c = find_nested_loop_in_chain (c->block->next);
12482 4835 : if (c && (c->op == EXEC_OMP_TILE || c->op == EXEC_OMP_UNROLL))
12483 : return;
12484 : }
12485 :
12486 : /* An openacc context may represent a data clause. Abort if so. */
12487 8446 : if (!omp_current_ctx->is_openmp && !oacc_is_loop (omp_current_ctx->code))
12488 : return;
12489 :
12490 7468 : if (omp_current_ctx->sharing_clauses->contains (sym))
12491 : return;
12492 :
12493 6466 : if (! omp_current_ctx->private_iterators->add (sym) && add_clause)
12494 : {
12495 6276 : gfc_omp_clauses *omp_clauses = omp_current_ctx->code->ext.omp_clauses;
12496 6276 : gfc_omp_namelist *p;
12497 :
12498 6276 : p = gfc_get_omp_namelist ();
12499 6276 : p->sym = sym;
12500 6276 : p->where = omp_current_ctx->code->loc;
12501 6276 : p->next = omp_clauses->lists[OMP_LIST_PRIVATE];
12502 6276 : omp_clauses->lists[OMP_LIST_PRIVATE] = p;
12503 : }
12504 : }
12505 :
12506 : static void
12507 775 : handle_local_var (gfc_symbol *sym)
12508 : {
12509 775 : if (sym->attr.flavor != FL_VARIABLE
12510 180 : || sym->as != NULL
12511 139 : || (sym->ts.type != BT_INTEGER && sym->ts.type != BT_REAL))
12512 : return;
12513 72 : gfc_resolve_do_iterator (sym->ns->code, sym, false);
12514 : }
12515 :
12516 : void
12517 348691 : gfc_resolve_omp_local_vars (gfc_namespace *ns)
12518 : {
12519 348691 : if (omp_current_ctx)
12520 469 : gfc_traverse_ns (ns, handle_local_var);
12521 348691 : }
12522 :
12523 :
12524 : /* Error checking on intervening code uses a code walker. */
12525 :
12526 : struct icode_error_state
12527 : {
12528 : const char *name;
12529 : bool errorp;
12530 : gfc_code *nested;
12531 : gfc_code *next;
12532 : };
12533 :
12534 : static int
12535 944 : icode_code_error_callback (gfc_code **codep,
12536 : int *walk_subtrees ATTRIBUTE_UNUSED, void *opaque)
12537 : {
12538 944 : gfc_code *code = *codep;
12539 944 : icode_error_state *state = (icode_error_state *)opaque;
12540 :
12541 : /* gfc_code_walker walks down CODE's next chain as well as
12542 : walking things that are actually nested in CODE. We need to
12543 : special-case traversal of outer blocks, so stop immediately if we
12544 : are heading down such a next chain. */
12545 944 : if (code == state->next)
12546 : return 1;
12547 :
12548 647 : switch (code->op)
12549 : {
12550 1 : case EXEC_DO:
12551 1 : case EXEC_DO_WHILE:
12552 1 : case EXEC_DO_CONCURRENT:
12553 1 : gfc_error ("%s cannot contain loop in intervening code at %L",
12554 : state->name, &code->loc);
12555 1 : state->errorp = true;
12556 1 : break;
12557 0 : case EXEC_CYCLE:
12558 0 : case EXEC_EXIT:
12559 : /* Errors have already been diagnosed in match_exit_cycle. */
12560 0 : state->errorp = true;
12561 0 : break;
12562 : case EXEC_OMP_ASSUME:
12563 : case EXEC_OMP_METADIRECTIVE:
12564 : /* Per OpenMP 6.0, some non-executable directives are allowed in
12565 : intervening code. */
12566 : break;
12567 477 : case EXEC_CALL:
12568 : /* Per OpenMP 5.2, the "omp_" prefix is reserved, so we don't have to
12569 : consider the possibility that some locally-bound definition
12570 : overrides the runtime routine. */
12571 477 : if (code->resolved_sym
12572 477 : && omp_runtime_api_procname (code->resolved_sym->name))
12573 : {
12574 1 : gfc_error ("%s cannot contain OpenMP API call in intervening code "
12575 : "at %L",
12576 : state->name, &code->loc);
12577 1 : state->errorp = true;
12578 : }
12579 : break;
12580 168 : default:
12581 168 : if (code->op >= EXEC_OMP_FIRST_OPENMP_EXEC
12582 168 : && code->op <= EXEC_OMP_LAST_OPENMP_EXEC)
12583 : {
12584 2 : gfc_error ("%s cannot contain OpenMP directive in intervening code "
12585 : "at %L",
12586 : state->name, &code->loc);
12587 2 : state->errorp = true;
12588 : }
12589 : }
12590 : return 0;
12591 : }
12592 :
12593 : static int
12594 1081 : icode_expr_error_callback (gfc_expr **expr,
12595 : int *walk_subtrees ATTRIBUTE_UNUSED, void *opaque)
12596 : {
12597 1081 : icode_error_state *state = (icode_error_state *)opaque;
12598 :
12599 1081 : switch ((*expr)->expr_type)
12600 : {
12601 : /* As for EXPR_CALL with "omp_"-prefixed symbols. */
12602 2 : case EXPR_FUNCTION:
12603 2 : {
12604 2 : gfc_symbol *sym = (*expr)->value.function.esym;
12605 2 : if (sym && omp_runtime_api_procname (sym->name))
12606 : {
12607 1 : gfc_error ("%s cannot contain OpenMP API call in intervening code "
12608 : "at %L",
12609 1 : state->name, &((*expr)->where));
12610 1 : state->errorp = true;
12611 : }
12612 : }
12613 :
12614 : break;
12615 : default:
12616 : break;
12617 : }
12618 :
12619 : /* FIXME: The description of canonical loop form in the OpenMP standard
12620 : also says "array expressions" are not permitted in intervening code.
12621 : That term is not defined in either the OpenMP spec or the Fortran
12622 : standard, although the latter uses it informally to refer to any
12623 : expression that is not scalar-valued. It is also apparently not the
12624 : thing GCC internally calls EXPR_ARRAY. It seems the intent of the
12625 : OpenMP restriction is to disallow elemental operations/intrinsics
12626 : (including things that are not expressions, like assignment
12627 : statements) that generate implicit loops over array operands
12628 : (even if the result is a scalar), but even if the spec said
12629 : that there is no list of all the cases that would be forbidden.
12630 : This is OpenMP issue 3326. */
12631 :
12632 1081 : return 0;
12633 : }
12634 :
12635 : static void
12636 267 : diagnose_intervening_code_errors_1 (gfc_code *chain,
12637 : struct icode_error_state *state)
12638 : {
12639 267 : gfc_code *code;
12640 1080 : for (code = chain; code; code = code->next)
12641 : {
12642 813 : if (code == state->nested)
12643 : /* Do not walk the nested loop or its body, we are only
12644 : interested in intervening code. */
12645 : ;
12646 636 : else if (code->op == EXEC_BLOCK
12647 636 : && find_nested_loop_in_block (code) == state->nested)
12648 : /* This block contains the nested loop, recurse on its
12649 : statements. */
12650 : {
12651 90 : gfc_namespace* ns = code->ext.block.ns;
12652 90 : diagnose_intervening_code_errors_1 (ns->code, state);
12653 : }
12654 : else
12655 : /* Treat the whole statement as a unit. */
12656 : {
12657 546 : gfc_code *temp = state->next;
12658 546 : state->next = code->next;
12659 546 : gfc_code_walker (&code, icode_code_error_callback,
12660 : icode_expr_error_callback, state);
12661 546 : state->next = temp;
12662 : }
12663 : }
12664 267 : }
12665 :
12666 : /* Diagnose intervening code errors in BLOCK with nested loop NESTED.
12667 : NAME is the user-friendly name of the OMP directive, used for error
12668 : messages. Returns true if any error was found. */
12669 : static bool
12670 177 : diagnose_intervening_code_errors (gfc_code *chain, const char *name,
12671 : gfc_code *nested)
12672 : {
12673 177 : struct icode_error_state state;
12674 177 : state.name = name;
12675 177 : state.errorp = false;
12676 177 : state.nested = nested;
12677 177 : state.next = NULL;
12678 0 : diagnose_intervening_code_errors_1 (chain, &state);
12679 177 : return state.errorp;
12680 : }
12681 :
12682 : /* Helper function for restructure_intervening_code: wrap CHAIN in
12683 : a marker to indicate that it is a structured block sequence. That
12684 : information will be used later on (in omp-low.cc) for error checking. */
12685 : static gfc_code *
12686 461 : make_structured_block (gfc_code *chain)
12687 : {
12688 461 : gcc_assert (chain);
12689 461 : gfc_namespace *ns = gfc_build_block_ns (gfc_current_ns);
12690 461 : gfc_code *result = gfc_get_code (EXEC_BLOCK);
12691 461 : result->op = EXEC_BLOCK;
12692 461 : result->ext.block.ns = ns;
12693 461 : result->ext.block.assoc = NULL;
12694 461 : result->loc = chain->loc;
12695 461 : ns->omp_structured_block = 1;
12696 461 : ns->code = chain;
12697 461 : return result;
12698 : }
12699 :
12700 : /* Push intervening code surrounding a loop, including nested scopes,
12701 : into the body of the loop. CHAINP is the pointer to the head of
12702 : the next-chain to scan, OUTER_LOOP is the EXEC_DO for the next outer
12703 : loop level, and COLLAPSE is the number of nested loops we need to
12704 : process.
12705 : Note that CHAINP may point at outer_loop->block->next when we
12706 : are scanning the body of a loop, but if there is an intervening block
12707 : CHAINP points into the block's chain rather than its enclosing outer
12708 : loop. This is why OUTER_LOOP is passed separately. */
12709 : static gfc_code *
12710 7182 : restructure_intervening_code (gfc_code **chainp, gfc_code *outer_loop,
12711 : int count)
12712 : {
12713 7182 : gfc_code *code;
12714 7182 : gfc_code *head = *chainp;
12715 7182 : gfc_code *tail = NULL;
12716 7182 : gfc_code *innermost_loop = NULL;
12717 :
12718 7446 : for (code = *chainp; code; code = code->next, chainp = &(*chainp)->next)
12719 : {
12720 7446 : if (code->op == EXEC_DO)
12721 : {
12722 : /* Cut CODE free from its chain, leaving the ends dangling. */
12723 7098 : *chainp = NULL;
12724 7098 : tail = code->next;
12725 7098 : code->next = NULL;
12726 :
12727 7098 : if (count == 1)
12728 : innermost_loop = code;
12729 : else
12730 2090 : innermost_loop
12731 2090 : = restructure_intervening_code (&code->block->next,
12732 : code, count - 1);
12733 : break;
12734 : }
12735 348 : else if (code->op == EXEC_BLOCK
12736 348 : && find_nested_loop_in_block (code))
12737 : {
12738 84 : gfc_namespace *ns = code->ext.block.ns;
12739 :
12740 : /* Cut CODE free from its chain, leaving the ends dangling. */
12741 84 : *chainp = NULL;
12742 84 : tail = code->next;
12743 84 : code->next = NULL;
12744 :
12745 84 : innermost_loop
12746 84 : = restructure_intervening_code (&ns->code, outer_loop,
12747 : count);
12748 :
12749 : /* At this point we have already pulled out the nested loop and
12750 : pointed outer_loop at it, and moved the intervening code that
12751 : was previously in the block into the body of innermost_loop.
12752 : Now we want to move the BLOCK itself so it wraps the entire
12753 : current body of innermost_loop. */
12754 84 : ns->code = innermost_loop->block->next;
12755 84 : innermost_loop->block->next = code;
12756 84 : break;
12757 : }
12758 : }
12759 :
12760 2174 : gcc_assert (innermost_loop);
12761 :
12762 : /* Now we have split the intervening code into two parts:
12763 : head is the start of the part before the loop/block, terminating
12764 : at *chainp, and tail is the part after it. Mark each part as
12765 : a structured block sequence, and splice the two parts around the
12766 : existing body of the innermost loop. */
12767 7182 : if (head != code)
12768 : {
12769 222 : gfc_code *block = make_structured_block (head);
12770 222 : if (innermost_loop->block->next)
12771 221 : gfc_append_code (block, innermost_loop->block->next);
12772 222 : innermost_loop->block->next = block;
12773 : }
12774 7182 : if (tail)
12775 : {
12776 239 : gfc_code *block = make_structured_block (tail);
12777 239 : if (innermost_loop->block->next)
12778 237 : gfc_append_code (innermost_loop->block->next, block);
12779 : else
12780 2 : innermost_loop->block->next = block;
12781 : }
12782 :
12783 : /* For loops, finally splice CODE into OUTER_LOOP. We already handled
12784 : relinking EXEC_BLOCK above. */
12785 7182 : if (code->op == EXEC_DO && outer_loop)
12786 7098 : outer_loop->block->next = code;
12787 :
12788 7182 : return innermost_loop;
12789 : }
12790 :
12791 : /* CODE is an OMP loop construct. Return true if VAR matches an iteration
12792 : variable outer to level DEPTH. */
12793 : static bool
12794 8095 : is_outer_iteration_variable (gfc_code *code, int depth, gfc_symbol *var)
12795 : {
12796 8095 : int i;
12797 8095 : gfc_code *do_code = code;
12798 :
12799 12622 : for (i = 1; i < depth; i++)
12800 : {
12801 5028 : do_code = find_nested_loop_in_chain (do_code->block->next);
12802 5028 : gcc_assert (do_code);
12803 5028 : if (do_code->op == EXEC_OMP_TILE || do_code->op == EXEC_OMP_UNROLL)
12804 : {
12805 51 : --i;
12806 51 : continue;
12807 : }
12808 4977 : gfc_symbol *ivar = do_code->ext.iterator->var->symtree->n.sym;
12809 4977 : if (var == ivar)
12810 : return true;
12811 : }
12812 : return false;
12813 : }
12814 :
12815 : /* Forward declaration for recursive functions. */
12816 : static gfc_code *
12817 : check_nested_loop_in_block (gfc_code *block, gfc_expr *expr, gfc_symbol *sym,
12818 : bool *bad);
12819 :
12820 : /* Like find_nested_loop_in_chain, but additionally check that EXPR
12821 : does not reference any variables bound in intervening EXEC_BLOCKs
12822 : and that SYM is not bound in such intervening blocks. Either EXPR or SYM
12823 : may be null. Sets *BAD to true if either test fails. */
12824 : static gfc_code *
12825 48213 : check_nested_loop_in_chain (gfc_code *chain, gfc_expr *expr, gfc_symbol *sym,
12826 : bool *bad)
12827 : {
12828 51817 : for (gfc_code *code = chain; code; code = code->next)
12829 : {
12830 51529 : if (code->op == EXEC_DO)
12831 : return code;
12832 4123 : else if (code->op == EXEC_OMP_TILE || code->op == EXEC_OMP_UNROLL)
12833 1682 : return check_nested_loop_in_chain (code->block->next, expr, sym, bad);
12834 2441 : else if (code->op == EXEC_BLOCK)
12835 : {
12836 807 : gfc_code *c = check_nested_loop_in_block (code, expr, sym, bad);
12837 807 : if (c)
12838 : return c;
12839 : }
12840 : }
12841 : return NULL;
12842 : }
12843 :
12844 : /* Code walker for block symtrees. It doesn't take any kind of state
12845 : argument, so use a static variable. */
12846 : static struct check_nested_loop_in_block_state_t {
12847 : gfc_expr *expr;
12848 : gfc_symbol *sym;
12849 : bool *bad;
12850 : } check_nested_loop_in_block_state;
12851 :
12852 : static void
12853 766 : check_nested_loop_in_block_symbol (gfc_symbol *sym)
12854 : {
12855 766 : if (sym == check_nested_loop_in_block_state.sym
12856 766 : || (check_nested_loop_in_block_state.expr
12857 567 : && gfc_find_sym_in_expr (sym,
12858 : check_nested_loop_in_block_state.expr)))
12859 5 : *check_nested_loop_in_block_state.bad = true;
12860 766 : }
12861 :
12862 : /* Return the first nested DO loop in BLOCK, or NULL if there
12863 : isn't one. Set *BAD to true if EXPR references any variables in BLOCK, or
12864 : SYM is bound in BLOCK. Either EXPR or SYM may be null. */
12865 : static gfc_code *
12866 807 : check_nested_loop_in_block (gfc_code *block, gfc_expr *expr,
12867 : gfc_symbol *sym, bool *bad)
12868 : {
12869 807 : gfc_namespace *ns;
12870 807 : gcc_assert (block->op == EXEC_BLOCK);
12871 807 : ns = block->ext.block.ns;
12872 807 : gcc_assert (ns);
12873 :
12874 : /* Skip the check if this block doesn't contain the nested loop, or
12875 : if we already know it's bad. */
12876 807 : gfc_code *result = check_nested_loop_in_chain (ns->code, expr, sym, bad);
12877 807 : if (result && !*bad)
12878 : {
12879 519 : check_nested_loop_in_block_state.expr = expr;
12880 519 : check_nested_loop_in_block_state.sym = sym;
12881 519 : check_nested_loop_in_block_state.bad = bad;
12882 519 : gfc_traverse_ns (ns, check_nested_loop_in_block_symbol);
12883 519 : check_nested_loop_in_block_state.expr = NULL;
12884 519 : check_nested_loop_in_block_state.sym = NULL;
12885 519 : check_nested_loop_in_block_state.bad = NULL;
12886 : }
12887 807 : return result;
12888 : }
12889 :
12890 : /* CODE is an OMP loop construct. Return true if EXPR references
12891 : any variables bound in intervening code, to level DEPTH. */
12892 : static bool
12893 22753 : expr_uses_intervening_var (gfc_code *code, int depth, gfc_expr *expr)
12894 : {
12895 22753 : int i;
12896 22753 : gfc_code *do_code = code;
12897 :
12898 58285 : for (i = 0; i < depth; i++)
12899 : {
12900 35535 : bool bad = false;
12901 35535 : do_code = check_nested_loop_in_chain (do_code->block->next,
12902 : expr, NULL, &bad);
12903 35535 : if (bad)
12904 3 : return true;
12905 : }
12906 : return false;
12907 : }
12908 :
12909 : /* CODE is an OMP loop construct. Return true if SYM is bound in
12910 : intervening code, to level DEPTH. */
12911 : static bool
12912 7594 : is_intervening_var (gfc_code *code, int depth, gfc_symbol *sym)
12913 : {
12914 7594 : int i;
12915 7594 : gfc_code *do_code = code;
12916 :
12917 19463 : for (i = 0; i < depth; i++)
12918 : {
12919 11871 : bool bad = false;
12920 11871 : do_code = check_nested_loop_in_chain (do_code->block->next,
12921 : NULL, sym, &bad);
12922 11871 : if (bad)
12923 2 : return true;
12924 : }
12925 : return false;
12926 : }
12927 :
12928 : /* CODE is an OMP loop construct. Return true if EXPR does not reference
12929 : any iteration variables outer to level DEPTH. */
12930 : static bool
12931 23832 : expr_is_invariant (gfc_code *code, int depth, gfc_expr *expr)
12932 : {
12933 23832 : int i;
12934 23832 : gfc_code *do_code = code;
12935 :
12936 37154 : for (i = 1; i < depth; i++)
12937 : {
12938 14388 : do_code = find_nested_loop_in_chain (do_code->block->next);
12939 14388 : gcc_assert (do_code);
12940 14388 : if (do_code->op == EXEC_OMP_TILE || do_code->op == EXEC_OMP_UNROLL)
12941 : {
12942 136 : --i;
12943 136 : continue;
12944 : }
12945 14252 : gfc_symbol *ivar = do_code->ext.iterator->var->symtree->n.sym;
12946 14252 : if (gfc_find_sym_in_expr (ivar, expr))
12947 : return false;
12948 : }
12949 : return true;
12950 : }
12951 :
12952 : /* CODE is an OMP loop construct. Return true if EXPR matches one of the
12953 : canonical forms for a bound expression. It may include references to
12954 : an iteration variable outer to level DEPTH; set OUTER_VARP if so. */
12955 : static bool
12956 15179 : bound_expr_is_canonical (gfc_code *code, int depth, gfc_expr *expr,
12957 : gfc_symbol **outer_varp)
12958 : {
12959 15179 : gfc_expr *expr2 = NULL;
12960 :
12961 : /* Rectangular case. */
12962 15179 : if (depth == 0 || expr_is_invariant (code, depth, expr))
12963 14611 : return true;
12964 :
12965 : /* Any simple variable that didn't pass expr_is_invariant must be
12966 : an outer_var. */
12967 568 : if (expr->expr_type == EXPR_VARIABLE && expr->rank == 0)
12968 : {
12969 63 : *outer_varp = expr->symtree->n.sym;
12970 63 : return true;
12971 : }
12972 :
12973 : /* All other permitted forms are binary operators. */
12974 505 : if (expr->expr_type != EXPR_OP)
12975 : return false;
12976 :
12977 : /* Check for plus/minus a loop invariant expr. */
12978 503 : if (expr->value.op.op == INTRINSIC_PLUS
12979 503 : || expr->value.op.op == INTRINSIC_MINUS)
12980 : {
12981 483 : if (expr_is_invariant (code, depth, expr->value.op.op1))
12982 48 : expr2 = expr->value.op.op2;
12983 435 : else if (expr_is_invariant (code, depth, expr->value.op.op2))
12984 434 : expr2 = expr->value.op.op1;
12985 : else
12986 : return false;
12987 : }
12988 : else
12989 : expr2 = expr;
12990 :
12991 : /* Check for a product with a loop-invariant expr. */
12992 502 : if (expr2->expr_type == EXPR_OP
12993 96 : && expr2->value.op.op == INTRINSIC_TIMES)
12994 : {
12995 96 : if (expr_is_invariant (code, depth, expr2->value.op.op1))
12996 40 : expr2 = expr2->value.op.op2;
12997 56 : else if (expr_is_invariant (code, depth, expr2->value.op.op2))
12998 53 : expr2 = expr2->value.op.op1;
12999 : else
13000 : return false;
13001 : }
13002 :
13003 : /* What's left must be a reference to an outer loop variable. */
13004 499 : if (expr2->expr_type == EXPR_VARIABLE
13005 499 : && expr2->rank == 0
13006 998 : && is_outer_iteration_variable (code, depth, expr2->symtree->n.sym))
13007 : {
13008 499 : *outer_varp = expr2->symtree->n.sym;
13009 499 : return true;
13010 : }
13011 :
13012 : return false;
13013 : }
13014 :
13015 : static void
13016 5432 : resolve_omp_do (gfc_code *code)
13017 : {
13018 5432 : gfc_code *do_code, *next;
13019 5432 : int i, count, non_generated_count;
13020 5432 : gfc_omp_namelist *n;
13021 5432 : gfc_symbol *dovar;
13022 5432 : const char *name;
13023 5432 : bool is_simd = false;
13024 5432 : bool errorp = false;
13025 5432 : bool perfect_nesting_errorp = false;
13026 5432 : bool imperfect = false;
13027 :
13028 5432 : switch (code->op)
13029 : {
13030 : case EXEC_OMP_DISTRIBUTE: name = "!$OMP DISTRIBUTE"; break;
13031 49 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
13032 49 : name = "!$OMP DISTRIBUTE PARALLEL DO";
13033 49 : break;
13034 32 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
13035 32 : name = "!$OMP DISTRIBUTE PARALLEL DO SIMD";
13036 32 : is_simd = true;
13037 32 : break;
13038 50 : case EXEC_OMP_DISTRIBUTE_SIMD:
13039 50 : name = "!$OMP DISTRIBUTE SIMD";
13040 50 : is_simd = true;
13041 50 : break;
13042 1336 : case EXEC_OMP_DO: name = "!$OMP DO"; break;
13043 134 : case EXEC_OMP_DO_SIMD: name = "!$OMP DO SIMD"; is_simd = true; break;
13044 64 : case EXEC_OMP_LOOP: name = "!$OMP LOOP"; break;
13045 1220 : case EXEC_OMP_PARALLEL_DO: name = "!$OMP PARALLEL DO"; break;
13046 304 : case EXEC_OMP_PARALLEL_DO_SIMD:
13047 304 : name = "!$OMP PARALLEL DO SIMD";
13048 304 : is_simd = true;
13049 304 : break;
13050 46 : case EXEC_OMP_PARALLEL_LOOP: name = "!$OMP PARALLEL LOOP"; break;
13051 7 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
13052 7 : name = "!$OMP PARALLEL MASKED TASKLOOP";
13053 7 : break;
13054 10 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
13055 10 : name = "!$OMP PARALLEL MASKED TASKLOOP SIMD";
13056 10 : is_simd = true;
13057 10 : break;
13058 12 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
13059 12 : name = "!$OMP PARALLEL MASTER TASKLOOP";
13060 12 : break;
13061 18 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
13062 18 : name = "!$OMP PARALLEL MASTER TASKLOOP SIMD";
13063 18 : is_simd = true;
13064 18 : break;
13065 8 : case EXEC_OMP_MASKED_TASKLOOP: name = "!$OMP MASKED TASKLOOP"; break;
13066 14 : case EXEC_OMP_MASKED_TASKLOOP_SIMD:
13067 14 : name = "!$OMP MASKED TASKLOOP SIMD";
13068 14 : is_simd = true;
13069 14 : break;
13070 14 : case EXEC_OMP_MASTER_TASKLOOP: name = "!$OMP MASTER TASKLOOP"; break;
13071 19 : case EXEC_OMP_MASTER_TASKLOOP_SIMD:
13072 19 : name = "!$OMP MASTER TASKLOOP SIMD";
13073 19 : is_simd = true;
13074 19 : break;
13075 783 : case EXEC_OMP_SIMD: name = "!$OMP SIMD"; is_simd = true; break;
13076 88 : case EXEC_OMP_TARGET_PARALLEL_DO: name = "!$OMP TARGET PARALLEL DO"; break;
13077 20 : case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
13078 20 : name = "!$OMP TARGET PARALLEL DO SIMD";
13079 20 : is_simd = true;
13080 20 : break;
13081 16 : case EXEC_OMP_TARGET_PARALLEL_LOOP:
13082 16 : name = "!$OMP TARGET PARALLEL LOOP";
13083 16 : break;
13084 33 : case EXEC_OMP_TARGET_SIMD:
13085 33 : name = "!$OMP TARGET SIMD";
13086 33 : is_simd = true;
13087 33 : break;
13088 20 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
13089 20 : name = "!$OMP TARGET TEAMS DISTRIBUTE";
13090 20 : break;
13091 77 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
13092 77 : name = "!$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO";
13093 77 : break;
13094 38 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
13095 38 : name = "!$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD";
13096 38 : is_simd = true;
13097 38 : break;
13098 20 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
13099 20 : name = "!$OMP TARGET TEAMS DISTRIBUTE SIMD";
13100 20 : is_simd = true;
13101 20 : break;
13102 19 : case EXEC_OMP_TARGET_TEAMS_LOOP: name = "!$OMP TARGET TEAMS LOOP"; break;
13103 69 : case EXEC_OMP_TASKLOOP: name = "!$OMP TASKLOOP"; break;
13104 38 : case EXEC_OMP_TASKLOOP_SIMD:
13105 38 : name = "!$OMP TASKLOOP SIMD";
13106 38 : is_simd = true;
13107 38 : break;
13108 20 : case EXEC_OMP_TEAMS_DISTRIBUTE: name = "!$OMP TEAMS DISTRIBUTE"; break;
13109 39 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
13110 39 : name = "!$OMP TEAMS DISTRIBUTE PARALLEL DO";
13111 39 : break;
13112 61 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
13113 61 : name = "!$OMP TEAMS DISTRIBUTE PARALLEL DO SIMD";
13114 61 : is_simd = true;
13115 61 : break;
13116 42 : case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
13117 42 : name = "!$OMP TEAMS DISTRIBUTE SIMD";
13118 42 : is_simd = true;
13119 42 : break;
13120 48 : case EXEC_OMP_TEAMS_LOOP: name = "!$OMP TEAMS LOOP"; break;
13121 195 : case EXEC_OMP_TILE: name = "!$OMP TILE"; break;
13122 415 : case EXEC_OMP_UNROLL: name = "!$OMP UNROLL"; break;
13123 0 : default: gcc_unreachable ();
13124 : }
13125 :
13126 5432 : if (code->ext.omp_clauses)
13127 5432 : resolve_omp_clauses (code, code->ext.omp_clauses, NULL);
13128 :
13129 5432 : if (code->op == EXEC_OMP_TILE && code->ext.omp_clauses->sizes_list == NULL)
13130 0 : gfc_error ("SIZES clause is required on !$OMP TILE construct at %L",
13131 : &code->loc);
13132 :
13133 5432 : do_code = code->block->next;
13134 5432 : if (code->ext.omp_clauses->orderedc)
13135 : count = code->ext.omp_clauses->orderedc;
13136 5288 : else if (code->ext.omp_clauses->sizes_list)
13137 195 : count = gfc_expr_list_len (code->ext.omp_clauses->sizes_list);
13138 : else
13139 : {
13140 5093 : count = code->ext.omp_clauses->collapse;
13141 5093 : if (count <= 0)
13142 : count = 1;
13143 : }
13144 :
13145 5432 : non_generated_count = count;
13146 : /* While the spec defines the loop nest depth independently of the COLLAPSE
13147 : clause, in practice the middle end only pays attention to the COLLAPSE
13148 : depth and treats any further inner loops as the final-loop-body. So
13149 : here we also check canonical loop nest form only for the number of
13150 : outer loops specified by the COLLAPSE clause too. */
13151 8072 : for (i = 1; i <= count; i++)
13152 : {
13153 8072 : gfc_symbol *start_var = NULL, *end_var = NULL;
13154 : /* Parse errors are not recoverable. */
13155 8072 : if (do_code->op == EXEC_DO_WHILE)
13156 : {
13157 6 : gfc_error ("%s cannot be a DO WHILE or DO without loop control "
13158 : "at %L", name, &do_code->loc);
13159 106 : goto fail;
13160 : }
13161 8066 : if (do_code->op == EXEC_DO_CONCURRENT)
13162 : {
13163 4 : gfc_error ("%s cannot be a DO CONCURRENT loop at %L", name,
13164 : &do_code->loc);
13165 4 : goto fail;
13166 : }
13167 8062 : if (do_code->op == EXEC_OMP_TILE || do_code->op == EXEC_OMP_UNROLL)
13168 : {
13169 466 : if (do_code->op == EXEC_OMP_UNROLL)
13170 : {
13171 308 : if (!do_code->ext.omp_clauses->partial)
13172 : {
13173 53 : gfc_error ("Generated loop of UNROLL construct at %L "
13174 : "without PARTIAL clause does not have "
13175 : "canonical form", &do_code->loc);
13176 53 : goto fail;
13177 : }
13178 255 : else if (i != count)
13179 : {
13180 5 : gfc_error ("UNROLL construct at %L with PARTIAL clause "
13181 : "generates just one loop with canonical form "
13182 : "but %d loops are needed",
13183 5 : &do_code->loc, count - i + 1);
13184 5 : goto fail;
13185 : }
13186 : }
13187 158 : else if (do_code->op == EXEC_OMP_TILE)
13188 : {
13189 158 : if (do_code->ext.omp_clauses->sizes_list == NULL)
13190 : /* This should have been diagnosed earlier already. */
13191 0 : return;
13192 158 : int l = gfc_expr_list_len (do_code->ext.omp_clauses->sizes_list);
13193 158 : if (count - i + 1 > l)
13194 : {
13195 14 : gfc_error ("TILE construct at %L generates %d loops "
13196 : "with canonical form but %d loops are needed",
13197 : &do_code->loc, l, count - i + 1);
13198 14 : goto fail;
13199 : }
13200 : }
13201 394 : if (do_code->ext.omp_clauses && do_code->ext.omp_clauses->erroneous)
13202 17 : goto fail;
13203 377 : if (imperfect && !perfect_nesting_errorp)
13204 : {
13205 4 : sorry_at (gfc_get_location (&do_code->loc),
13206 : "Imperfectly nested loop using generated loops");
13207 4 : errorp = true;
13208 : }
13209 377 : if (non_generated_count == count)
13210 329 : non_generated_count = i - 1;
13211 377 : --i;
13212 377 : do_code = do_code->block->next;
13213 377 : continue;
13214 377 : }
13215 7596 : gcc_assert (do_code->op == EXEC_DO);
13216 7596 : if (do_code->ext.iterator->var->ts.type != BT_INTEGER)
13217 : {
13218 3 : gfc_error ("%s iteration variable must be of type integer at %L",
13219 : name, &do_code->loc);
13220 3 : errorp = true;
13221 : }
13222 7596 : dovar = do_code->ext.iterator->var->symtree->n.sym;
13223 7596 : if (dovar->attr.threadprivate)
13224 : {
13225 0 : gfc_error ("%s iteration variable must not be THREADPRIVATE "
13226 : "at %L", name, &do_code->loc);
13227 0 : errorp = true;
13228 : }
13229 7596 : if (code->ext.omp_clauses)
13230 303840 : for (enum gfc_omp_list_type list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
13231 296244 : list = gfc_omp_list_type (list + 1))
13232 97578 : if (!is_simd || code->ext.omp_clauses->collapse > 1
13233 296244 : ? (list != OMP_LIST_PRIVATE && list != OMP_LIST_LASTPRIVATE
13234 255021 : && list != OMP_LIST_ALLOCATE)
13235 41223 : : (list != OMP_LIST_PRIVATE && list != OMP_LIST_LASTPRIVATE
13236 41223 : && list != OMP_LIST_ALLOCATE && list != OMP_LIST_LINEAR))
13237 276784 : for (n = code->ext.omp_clauses->lists[list]; n; n = n->next)
13238 4385 : if (dovar == n->sym)
13239 : {
13240 5 : if (!is_simd || code->ext.omp_clauses->collapse > 1)
13241 4 : gfc_error ("%s iteration variable present on clause "
13242 : "other than PRIVATE, LASTPRIVATE or "
13243 : "ALLOCATE at %L", name, &do_code->loc);
13244 : else
13245 1 : gfc_error ("%s iteration variable present on clause "
13246 : "other than PRIVATE, LASTPRIVATE, ALLOCATE or "
13247 : "LINEAR at %L", name, &do_code->loc);
13248 : errorp = true;
13249 : }
13250 7596 : if (is_outer_iteration_variable (code, i, dovar))
13251 : {
13252 2 : gfc_error ("%s iteration variable used in more than one loop at %L",
13253 : name, &do_code->loc);
13254 2 : errorp = true;
13255 : }
13256 7594 : else if (is_intervening_var (code, i, dovar))
13257 : {
13258 2 : gfc_error ("%s iteration variable at %L is bound in "
13259 : "intervening code",
13260 : name, &do_code->loc);
13261 2 : errorp = true;
13262 : }
13263 7592 : else if (!bound_expr_is_canonical (code, i,
13264 7592 : do_code->ext.iterator->start,
13265 : &start_var))
13266 : {
13267 4 : gfc_error ("%s loop start expression not in canonical form at %L",
13268 : name, &do_code->loc);
13269 4 : errorp = true;
13270 : }
13271 7588 : else if (expr_uses_intervening_var (code, i,
13272 7588 : do_code->ext.iterator->start))
13273 : {
13274 1 : gfc_error ("%s loop start expression at %L uses variable bound in "
13275 : "intervening code",
13276 : name, &do_code->loc);
13277 1 : errorp = true;
13278 : }
13279 7587 : else if (!bound_expr_is_canonical (code, i,
13280 7587 : do_code->ext.iterator->end,
13281 : &end_var))
13282 : {
13283 2 : gfc_error ("%s loop end expression not in canonical form at %L",
13284 : name, &do_code->loc);
13285 2 : errorp = true;
13286 : }
13287 7585 : else if (expr_uses_intervening_var (code, i,
13288 7585 : do_code->ext.iterator->end))
13289 : {
13290 1 : gfc_error ("%s loop end expression at %L uses variable bound in "
13291 : "intervening code",
13292 : name, &do_code->loc);
13293 1 : errorp = true;
13294 : }
13295 7584 : else if (start_var && end_var && start_var != end_var)
13296 : {
13297 1 : gfc_error ("%s loop bounds reference different "
13298 : "iteration variables at %L", name, &do_code->loc);
13299 1 : errorp = true;
13300 : }
13301 7583 : else if (!expr_is_invariant (code, i, do_code->ext.iterator->step))
13302 : {
13303 3 : gfc_error ("%s loop increment not in canonical form at %L",
13304 : name, &do_code->loc);
13305 3 : errorp = true;
13306 : }
13307 7580 : else if (expr_uses_intervening_var (code, i,
13308 7580 : do_code->ext.iterator->step))
13309 : {
13310 1 : gfc_error ("%s loop increment expression at %L uses variable "
13311 : "bound in intervening code",
13312 : name, &do_code->loc);
13313 1 : errorp = true;
13314 : }
13315 7596 : if (start_var || end_var)
13316 : {
13317 528 : code->ext.omp_clauses->non_rectangular = 1;
13318 528 : if (i > non_generated_count)
13319 : {
13320 3 : sorry_at (gfc_get_location (&do_code->loc),
13321 : "Non-rectangular loops from generated loops "
13322 : "unsupported");
13323 3 : errorp = true;
13324 : }
13325 : }
13326 :
13327 : /* Only parse loop body into nested loop and intervening code if
13328 : there are supposed to be more loops in the nest to collapse. */
13329 7596 : if (i == count)
13330 : break;
13331 :
13332 2270 : next = find_nested_loop_in_chain (do_code->block->next);
13333 :
13334 2270 : if (!next)
13335 : {
13336 : /* Parse error, can't recover from this. */
13337 7 : gfc_error ("not enough DO loops for collapsed %s (level %d) at %L",
13338 : name, i, &code->loc);
13339 7 : goto fail;
13340 : }
13341 2263 : else if (next != do_code->block->next
13342 2103 : || (next->next && next->next->op != EXEC_CONTINUE))
13343 : /* Imperfectly nested loop found. */
13344 : {
13345 : /* Only diagnose violation of imperfect nesting constraints once. */
13346 177 : if (!perfect_nesting_errorp)
13347 : {
13348 176 : if (code->ext.omp_clauses->orderedc)
13349 : {
13350 3 : gfc_error ("%s inner loops must be perfectly nested with "
13351 : "ORDERED clause at %L",
13352 : name, &code->loc);
13353 3 : perfect_nesting_errorp = true;
13354 : }
13355 173 : else if (code->ext.omp_clauses->lists[OMP_LIST_REDUCTION_INSCAN])
13356 : {
13357 2 : gfc_error ("%s inner loops must be perfectly nested with "
13358 : "REDUCTION INSCAN clause at %L",
13359 : name, &code->loc);
13360 2 : perfect_nesting_errorp = true;
13361 : }
13362 171 : else if (code->op == EXEC_OMP_TILE)
13363 : {
13364 8 : gfc_error ("%s inner loops must be perfectly nested at %L",
13365 : name, &code->loc);
13366 8 : perfect_nesting_errorp = true;
13367 : }
13368 13 : if (perfect_nesting_errorp)
13369 : errorp = true;
13370 : }
13371 177 : if (diagnose_intervening_code_errors (do_code->block->next,
13372 : name, next))
13373 5 : errorp = true;
13374 : imperfect = true;
13375 : }
13376 2263 : do_code = next;
13377 : }
13378 :
13379 : /* Give up now if we found any constraint violations. */
13380 5326 : if (errorp)
13381 : {
13382 48 : fail:
13383 154 : if (code->ext.omp_clauses)
13384 154 : code->ext.omp_clauses->erroneous = 1;
13385 154 : return;
13386 : }
13387 :
13388 5278 : if (non_generated_count)
13389 5008 : restructure_intervening_code (&code->block->next, code,
13390 : non_generated_count);
13391 : }
13392 :
13393 : /* Resolve the context selector. In particular, SKIP_P is set to true,
13394 : the context can never be matched. */
13395 :
13396 : static void
13397 764 : gfc_resolve_omp_context_selector (gfc_omp_set_selector *oss,
13398 : bool is_metadirective, bool *skip_p)
13399 : {
13400 764 : if (skip_p)
13401 310 : *skip_p = false;
13402 1453 : for (gfc_omp_set_selector *set_selector = oss; set_selector;
13403 689 : set_selector = set_selector->next)
13404 1485 : for (gfc_omp_selector *os = set_selector->trait_selectors; os; os = os->next)
13405 : {
13406 814 : if (os->score)
13407 : {
13408 52 : if (!gfc_resolve_expr (os->score)
13409 52 : || os->score->ts.type != BT_INTEGER
13410 104 : || os->score->rank != 0)
13411 : {
13412 0 : gfc_error ("%<score%> argument must be constant integer "
13413 0 : "expression at %L", &os->score->where);
13414 0 : gfc_free_expr (os->score);
13415 0 : os->score = nullptr;
13416 : }
13417 52 : else if (os->score->expr_type == EXPR_CONSTANT
13418 52 : && mpz_sgn (os->score->value.integer) < 0)
13419 : {
13420 1 : gfc_error ("%<score%> argument must be non-negative at %L",
13421 : &os->score->where);
13422 1 : gfc_free_expr (os->score);
13423 1 : os->score = nullptr;
13424 : }
13425 : }
13426 :
13427 814 : if (os->code == OMP_TRAIT_INVALID)
13428 : break;
13429 796 : enum omp_tp_type property_kind = omp_ts_map[os->code].tp_type;
13430 796 : gfc_omp_trait_property *otp = os->properties;
13431 :
13432 796 : if (!otp)
13433 409 : continue;
13434 387 : switch (property_kind)
13435 : {
13436 139 : case OMP_TRAIT_PROPERTY_DEV_NUM_EXPR:
13437 139 : case OMP_TRAIT_PROPERTY_BOOL_EXPR:
13438 139 : if (!gfc_resolve_expr (otp->expr)
13439 138 : || (property_kind == OMP_TRAIT_PROPERTY_BOOL_EXPR
13440 124 : && otp->expr->ts.type != BT_LOGICAL)
13441 137 : || (property_kind == OMP_TRAIT_PROPERTY_DEV_NUM_EXPR
13442 14 : && otp->expr->ts.type != BT_INTEGER)
13443 137 : || otp->expr->rank != 0
13444 276 : || (!is_metadirective && otp->expr->expr_type != EXPR_CONSTANT))
13445 : {
13446 3 : if (is_metadirective)
13447 : {
13448 0 : if (property_kind == OMP_TRAIT_PROPERTY_BOOL_EXPR)
13449 0 : gfc_error ("property must be a "
13450 : "logical expression at %L",
13451 0 : &otp->expr->where);
13452 : else
13453 0 : gfc_error ("property must be an "
13454 : "integer expression at %L",
13455 0 : &otp->expr->where);
13456 : }
13457 : else
13458 : {
13459 3 : if (property_kind == OMP_TRAIT_PROPERTY_BOOL_EXPR)
13460 2 : gfc_error ("property must be a constant "
13461 : "logical expression at %L",
13462 2 : &otp->expr->where);
13463 : else
13464 1 : gfc_error ("property must be a constant "
13465 : "integer expression at %L",
13466 1 : &otp->expr->where);
13467 : }
13468 : /* Prevent later ICEs. */
13469 3 : gfc_expr *e;
13470 3 : if (property_kind == OMP_TRAIT_PROPERTY_BOOL_EXPR)
13471 2 : e = gfc_get_logical_expr (gfc_default_logical_kind,
13472 2 : &otp->expr->where, true);
13473 : else
13474 1 : e = gfc_get_int_expr (gfc_default_integer_kind,
13475 1 : &otp->expr->where, 0);
13476 3 : gfc_free_expr (otp->expr);
13477 3 : otp->expr = e;
13478 3 : continue;
13479 3 : }
13480 : /* Device number must be conforming, which includes
13481 : omp_initial_device (-1), omp_invalid_device (-4),
13482 : and omp_default_device (-5). */
13483 136 : if (property_kind == OMP_TRAIT_PROPERTY_DEV_NUM_EXPR
13484 14 : && otp->expr->expr_type == EXPR_CONSTANT
13485 5 : && mpz_sgn (otp->expr->value.integer) < 0
13486 3 : && mpz_cmp_si (otp->expr->value.integer, -1) != 0
13487 2 : && mpz_cmp_si (otp->expr->value.integer, -4) != 0
13488 1 : && mpz_cmp_si (otp->expr->value.integer, -5) != 0)
13489 1 : gfc_error ("property must be a conforming device number at %L",
13490 : &otp->expr->where);
13491 : break;
13492 : default:
13493 : break;
13494 : }
13495 : /* This only handles one specific case: User condition.
13496 : FIXME: Handle more cases by calling omp_context_selector_matches;
13497 : unfortunately, we cannot generate the tree here as, e.g., PARM_DECL
13498 : backend decl are not available at this stage - but might be used in,
13499 : e.g. user conditions. See PR122361. */
13500 384 : if (skip_p && otp
13501 138 : && os->code == OMP_TRAIT_USER_CONDITION
13502 81 : && otp->expr->expr_type == EXPR_CONSTANT
13503 14 : && otp->expr->value.logical == false)
13504 12 : *skip_p = true;
13505 : }
13506 764 : }
13507 :
13508 :
13509 : static void
13510 138 : resolve_omp_metadirective (gfc_code *code, gfc_namespace *ns)
13511 : {
13512 138 : gfc_omp_variant *variant = code->ext.omp_variants;
13513 138 : gfc_omp_variant *prev_variant = variant;
13514 :
13515 448 : while (variant)
13516 : {
13517 310 : bool skip;
13518 310 : gfc_resolve_omp_context_selector (variant->selectors, true, &skip);
13519 310 : gfc_code *variant_code = variant->code;
13520 310 : gfc_resolve_code (variant_code, ns);
13521 310 : if (skip)
13522 : {
13523 : /* The following should only be true if an error occurred
13524 : as the 'otherwise' clause should always match. */
13525 12 : if (variant == code->ext.omp_variants && !variant->next)
13526 : break;
13527 12 : gfc_omp_variant *tmp = variant;
13528 12 : if (variant == code->ext.omp_variants)
13529 11 : variant = prev_variant = code->ext.omp_variants = variant->next;
13530 : else
13531 1 : variant = prev_variant->next = variant->next;
13532 12 : gfc_free_omp_set_selector_list (tmp->selectors);
13533 12 : free (tmp);
13534 : }
13535 : else
13536 : {
13537 298 : prev_variant = variant;
13538 298 : variant = variant->next;
13539 : }
13540 : }
13541 : /* Replace metadirective by its body if only 'nothing' remains. */
13542 138 : if (!code->ext.omp_variants->next && code->ext.omp_variants->stmt == ST_NONE)
13543 : {
13544 11 : gfc_code *next = code->next;
13545 11 : gfc_code *inner = code->ext.omp_variants->code;
13546 11 : gfc_free_omp_set_selector_list (code->ext.omp_variants->selectors);
13547 11 : free (code->ext.omp_variants);
13548 11 : *code = *inner;
13549 11 : free (inner);
13550 11 : while (code->next)
13551 : code = code->next;
13552 11 : code->next = next;
13553 : }
13554 138 : }
13555 :
13556 :
13557 : static gfc_statement
13558 63 : omp_code_to_statement (gfc_code *code)
13559 : {
13560 63 : switch (code->op)
13561 : {
13562 : case EXEC_OMP_PARALLEL:
13563 : return ST_OMP_PARALLEL;
13564 0 : case EXEC_OMP_PARALLEL_MASKED:
13565 0 : return ST_OMP_PARALLEL_MASKED;
13566 0 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
13567 0 : return ST_OMP_PARALLEL_MASKED_TASKLOOP;
13568 0 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
13569 0 : return ST_OMP_PARALLEL_MASKED_TASKLOOP_SIMD;
13570 0 : case EXEC_OMP_PARALLEL_MASTER:
13571 0 : return ST_OMP_PARALLEL_MASTER;
13572 0 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
13573 0 : return ST_OMP_PARALLEL_MASTER_TASKLOOP;
13574 0 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
13575 0 : return ST_OMP_PARALLEL_MASTER_TASKLOOP_SIMD;
13576 1 : case EXEC_OMP_PARALLEL_SECTIONS:
13577 1 : return ST_OMP_PARALLEL_SECTIONS;
13578 1 : case EXEC_OMP_SECTIONS:
13579 1 : return ST_OMP_SECTIONS;
13580 1 : case EXEC_OMP_ORDERED:
13581 1 : return ST_OMP_ORDERED;
13582 1 : case EXEC_OMP_CRITICAL:
13583 1 : return ST_OMP_CRITICAL;
13584 0 : case EXEC_OMP_MASKED:
13585 0 : return ST_OMP_MASKED;
13586 0 : case EXEC_OMP_MASKED_TASKLOOP:
13587 0 : return ST_OMP_MASKED_TASKLOOP;
13588 0 : case EXEC_OMP_MASKED_TASKLOOP_SIMD:
13589 0 : return ST_OMP_MASKED_TASKLOOP_SIMD;
13590 1 : case EXEC_OMP_MASTER:
13591 1 : return ST_OMP_MASTER;
13592 0 : case EXEC_OMP_MASTER_TASKLOOP:
13593 0 : return ST_OMP_MASTER_TASKLOOP;
13594 0 : case EXEC_OMP_MASTER_TASKLOOP_SIMD:
13595 0 : return ST_OMP_MASTER_TASKLOOP_SIMD;
13596 1 : case EXEC_OMP_SINGLE:
13597 1 : return ST_OMP_SINGLE;
13598 1 : case EXEC_OMP_TASK:
13599 1 : return ST_OMP_TASK;
13600 1 : case EXEC_OMP_WORKSHARE:
13601 1 : return ST_OMP_WORKSHARE;
13602 1 : case EXEC_OMP_PARALLEL_WORKSHARE:
13603 1 : return ST_OMP_PARALLEL_WORKSHARE;
13604 3 : case EXEC_OMP_DO:
13605 3 : return ST_OMP_DO;
13606 0 : case EXEC_OMP_LOOP:
13607 0 : return ST_OMP_LOOP;
13608 0 : case EXEC_OMP_ALLOCATE:
13609 0 : return ST_OMP_ALLOCATE_EXEC;
13610 0 : case EXEC_OMP_ALLOCATORS:
13611 0 : return ST_OMP_ALLOCATORS;
13612 0 : case EXEC_OMP_ASSUME:
13613 0 : return ST_OMP_ASSUME;
13614 1 : case EXEC_OMP_ATOMIC:
13615 1 : return ST_OMP_ATOMIC;
13616 1 : case EXEC_OMP_BARRIER:
13617 1 : return ST_OMP_BARRIER;
13618 1 : case EXEC_OMP_CANCEL:
13619 1 : return ST_OMP_CANCEL;
13620 1 : case EXEC_OMP_CANCELLATION_POINT:
13621 1 : return ST_OMP_CANCELLATION_POINT;
13622 0 : case EXEC_OMP_ERROR:
13623 0 : return ST_OMP_ERROR;
13624 1 : case EXEC_OMP_FLUSH:
13625 1 : return ST_OMP_FLUSH;
13626 0 : case EXEC_OMP_INTEROP:
13627 0 : return ST_OMP_INTEROP;
13628 1 : case EXEC_OMP_DISTRIBUTE:
13629 1 : return ST_OMP_DISTRIBUTE;
13630 1 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
13631 1 : return ST_OMP_DISTRIBUTE_PARALLEL_DO;
13632 1 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
13633 1 : return ST_OMP_DISTRIBUTE_PARALLEL_DO_SIMD;
13634 1 : case EXEC_OMP_DISTRIBUTE_SIMD:
13635 1 : return ST_OMP_DISTRIBUTE_SIMD;
13636 1 : case EXEC_OMP_DO_SIMD:
13637 1 : return ST_OMP_DO_SIMD;
13638 0 : case EXEC_OMP_SCAN:
13639 0 : return ST_OMP_SCAN;
13640 0 : case EXEC_OMP_SCOPE:
13641 0 : return ST_OMP_SCOPE;
13642 1 : case EXEC_OMP_SIMD:
13643 1 : return ST_OMP_SIMD;
13644 1 : case EXEC_OMP_TARGET:
13645 1 : return ST_OMP_TARGET;
13646 1 : case EXEC_OMP_TARGET_DATA:
13647 1 : return ST_OMP_TARGET_DATA;
13648 1 : case EXEC_OMP_TARGET_ENTER_DATA:
13649 1 : return ST_OMP_TARGET_ENTER_DATA;
13650 1 : case EXEC_OMP_TARGET_EXIT_DATA:
13651 1 : return ST_OMP_TARGET_EXIT_DATA;
13652 1 : case EXEC_OMP_TARGET_PARALLEL:
13653 1 : return ST_OMP_TARGET_PARALLEL;
13654 1 : case EXEC_OMP_TARGET_PARALLEL_DO:
13655 1 : return ST_OMP_TARGET_PARALLEL_DO;
13656 1 : case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
13657 1 : return ST_OMP_TARGET_PARALLEL_DO_SIMD;
13658 0 : case EXEC_OMP_TARGET_PARALLEL_LOOP:
13659 0 : return ST_OMP_TARGET_PARALLEL_LOOP;
13660 1 : case EXEC_OMP_TARGET_SIMD:
13661 1 : return ST_OMP_TARGET_SIMD;
13662 1 : case EXEC_OMP_TARGET_TEAMS:
13663 1 : return ST_OMP_TARGET_TEAMS;
13664 1 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
13665 1 : return ST_OMP_TARGET_TEAMS_DISTRIBUTE;
13666 1 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
13667 1 : return ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO;
13668 1 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
13669 1 : return ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD;
13670 1 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
13671 1 : return ST_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD;
13672 0 : case EXEC_OMP_TARGET_TEAMS_LOOP:
13673 0 : return ST_OMP_TARGET_TEAMS_LOOP;
13674 1 : case EXEC_OMP_TARGET_UPDATE:
13675 1 : return ST_OMP_TARGET_UPDATE;
13676 1 : case EXEC_OMP_TASKGROUP:
13677 1 : return ST_OMP_TASKGROUP;
13678 1 : case EXEC_OMP_TASKLOOP:
13679 1 : return ST_OMP_TASKLOOP;
13680 1 : case EXEC_OMP_TASKLOOP_SIMD:
13681 1 : return ST_OMP_TASKLOOP_SIMD;
13682 1 : case EXEC_OMP_TASKWAIT:
13683 1 : return ST_OMP_TASKWAIT;
13684 1 : case EXEC_OMP_TASKYIELD:
13685 1 : return ST_OMP_TASKYIELD;
13686 1 : case EXEC_OMP_TEAMS:
13687 1 : return ST_OMP_TEAMS;
13688 1 : case EXEC_OMP_TEAMS_DISTRIBUTE:
13689 1 : return ST_OMP_TEAMS_DISTRIBUTE;
13690 1 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
13691 1 : return ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO;
13692 1 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
13693 1 : return ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD;
13694 1 : case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
13695 1 : return ST_OMP_TEAMS_DISTRIBUTE_SIMD;
13696 0 : case EXEC_OMP_TEAMS_LOOP:
13697 0 : return ST_OMP_TEAMS_LOOP;
13698 6 : case EXEC_OMP_PARALLEL_DO:
13699 6 : return ST_OMP_PARALLEL_DO;
13700 1 : case EXEC_OMP_PARALLEL_DO_SIMD:
13701 1 : return ST_OMP_PARALLEL_DO_SIMD;
13702 0 : case EXEC_OMP_PARALLEL_LOOP:
13703 0 : return ST_OMP_PARALLEL_LOOP;
13704 1 : case EXEC_OMP_DEPOBJ:
13705 1 : return ST_OMP_DEPOBJ;
13706 0 : case EXEC_OMP_TILE:
13707 0 : return ST_OMP_TILE;
13708 0 : case EXEC_OMP_UNROLL:
13709 0 : return ST_OMP_UNROLL;
13710 0 : case EXEC_OMP_DISPATCH:
13711 0 : return ST_OMP_DISPATCH;
13712 0 : default:
13713 0 : gcc_unreachable ();
13714 : }
13715 : }
13716 :
13717 : static gfc_statement
13718 63 : oacc_code_to_statement (gfc_code *code)
13719 : {
13720 63 : switch (code->op)
13721 : {
13722 : case EXEC_OACC_PARALLEL:
13723 : return ST_OACC_PARALLEL;
13724 : case EXEC_OACC_KERNELS:
13725 : return ST_OACC_KERNELS;
13726 : case EXEC_OACC_SERIAL:
13727 : return ST_OACC_SERIAL;
13728 : case EXEC_OACC_DATA:
13729 : return ST_OACC_DATA;
13730 : case EXEC_OACC_HOST_DATA:
13731 : return ST_OACC_HOST_DATA;
13732 : case EXEC_OACC_PARALLEL_LOOP:
13733 : return ST_OACC_PARALLEL_LOOP;
13734 : case EXEC_OACC_KERNELS_LOOP:
13735 : return ST_OACC_KERNELS_LOOP;
13736 : case EXEC_OACC_SERIAL_LOOP:
13737 : return ST_OACC_SERIAL_LOOP;
13738 : case EXEC_OACC_LOOP:
13739 : return ST_OACC_LOOP;
13740 : case EXEC_OACC_ATOMIC:
13741 : return ST_OACC_ATOMIC;
13742 : case EXEC_OACC_ROUTINE:
13743 : return ST_OACC_ROUTINE;
13744 : case EXEC_OACC_UPDATE:
13745 : return ST_OACC_UPDATE;
13746 : case EXEC_OACC_WAIT:
13747 : return ST_OACC_WAIT;
13748 : case EXEC_OACC_CACHE:
13749 : return ST_OACC_CACHE;
13750 : case EXEC_OACC_ENTER_DATA:
13751 : return ST_OACC_ENTER_DATA;
13752 : case EXEC_OACC_EXIT_DATA:
13753 : return ST_OACC_EXIT_DATA;
13754 : case EXEC_OACC_DECLARE:
13755 : return ST_OACC_DECLARE;
13756 : case EXEC_OACC_INIT:
13757 : return ST_OACC_INIT;
13758 : case EXEC_OACC_SHUTDOWN:
13759 : return ST_OACC_SHUTDOWN;
13760 : case EXEC_OACC_SET:
13761 : return ST_OACC_SET;
13762 0 : default:
13763 0 : gcc_unreachable ();
13764 : }
13765 : }
13766 :
13767 : static void
13768 13538 : resolve_oacc_directive_inside_omp_region (gfc_code *code)
13769 : {
13770 13538 : if (omp_current_ctx != NULL && omp_current_ctx->is_openmp)
13771 : {
13772 11 : gfc_statement st = omp_code_to_statement (omp_current_ctx->code);
13773 11 : gfc_statement oacc_st = oacc_code_to_statement (code);
13774 11 : gfc_error ("The %s directive cannot be specified within "
13775 : "a %s region at %L", gfc_ascii_statement (oacc_st),
13776 : gfc_ascii_statement (st), &code->loc);
13777 : }
13778 13538 : }
13779 :
13780 : static void
13781 21246 : resolve_omp_directive_inside_oacc_region (gfc_code *code)
13782 : {
13783 21246 : if (omp_current_ctx != NULL && !omp_current_ctx->is_openmp)
13784 : {
13785 52 : gfc_statement st = oacc_code_to_statement (omp_current_ctx->code);
13786 52 : gfc_statement omp_st = omp_code_to_statement (code);
13787 52 : gfc_error ("The %s directive cannot be specified within "
13788 : "a %s region at %L", gfc_ascii_statement (omp_st),
13789 : gfc_ascii_statement (st), &code->loc);
13790 : }
13791 21246 : }
13792 :
13793 :
13794 : static void
13795 5272 : resolve_oacc_nested_loops (gfc_code *code, gfc_code* do_code, int collapse,
13796 : const char *clause)
13797 : {
13798 5272 : gfc_symbol *dovar;
13799 5272 : gfc_code *c;
13800 5272 : int i;
13801 :
13802 5792 : for (i = 1; i <= collapse; i++)
13803 : {
13804 5792 : if (do_code->op == EXEC_DO_WHILE)
13805 : {
13806 10 : gfc_error ("!$ACC LOOP cannot be a DO WHILE or DO without loop control "
13807 : "at %L", &do_code->loc);
13808 10 : break;
13809 : }
13810 5782 : if (do_code->op == EXEC_DO_CONCURRENT)
13811 : {
13812 3 : gfc_error ("!$ACC LOOP cannot be a DO CONCURRENT loop at %L",
13813 : &do_code->loc);
13814 3 : break;
13815 : }
13816 5779 : gcc_assert (do_code->op == EXEC_DO);
13817 5779 : if (do_code->ext.iterator->var->ts.type != BT_INTEGER)
13818 6 : gfc_error ("!$ACC LOOP iteration variable must be of type integer at %L",
13819 : &do_code->loc);
13820 5779 : dovar = do_code->ext.iterator->var->symtree->n.sym;
13821 5779 : if (i > 1)
13822 : {
13823 518 : gfc_code *do_code2 = code->block->next;
13824 518 : int j;
13825 :
13826 1218 : for (j = 1; j < i; j++)
13827 : {
13828 710 : gfc_symbol *ivar = do_code2->ext.iterator->var->symtree->n.sym;
13829 710 : if (dovar == ivar
13830 710 : || gfc_find_sym_in_expr (ivar, do_code->ext.iterator->start)
13831 701 : || gfc_find_sym_in_expr (ivar, do_code->ext.iterator->end)
13832 1410 : || gfc_find_sym_in_expr (ivar, do_code->ext.iterator->step))
13833 : {
13834 10 : gfc_error ("!$ACC LOOP %s loops don't form rectangular "
13835 : "iteration space at %L", clause, &do_code->loc);
13836 10 : break;
13837 : }
13838 700 : do_code2 = do_code2->block->next;
13839 : }
13840 : }
13841 5779 : if (i == collapse)
13842 : break;
13843 577 : for (c = do_code->next; c; c = c->next)
13844 48 : if (c->op != EXEC_NOP && c->op != EXEC_CONTINUE)
13845 : {
13846 0 : gfc_error ("%s !$ACC LOOP loops not perfectly nested at %L",
13847 : clause, &c->loc);
13848 0 : break;
13849 : }
13850 529 : if (c)
13851 : break;
13852 529 : do_code = do_code->block;
13853 529 : if (do_code->op != EXEC_DO && do_code->op != EXEC_DO_WHILE
13854 0 : && do_code->op != EXEC_DO_CONCURRENT)
13855 : {
13856 0 : gfc_error ("not enough DO loops for %s !$ACC LOOP at %L",
13857 : clause, &code->loc);
13858 0 : break;
13859 : }
13860 529 : do_code = do_code->next;
13861 529 : if (do_code == NULL
13862 522 : || (do_code->op != EXEC_DO && do_code->op != EXEC_DO_WHILE
13863 2 : && do_code->op != EXEC_DO_CONCURRENT))
13864 : {
13865 9 : gfc_error ("not enough DO loops for %s !$ACC LOOP at %L",
13866 : clause, &code->loc);
13867 9 : break;
13868 : }
13869 : }
13870 5272 : }
13871 :
13872 :
13873 : static void
13874 10119 : resolve_oacc_loop_blocks (gfc_code *code)
13875 : {
13876 10119 : if (!oacc_is_loop (code))
13877 : return;
13878 :
13879 5272 : if (code->ext.omp_clauses->tile_list && code->ext.omp_clauses->gang
13880 24 : && code->ext.omp_clauses->worker && code->ext.omp_clauses->vector)
13881 0 : gfc_error ("Tiled loop cannot be parallelized across gangs, workers and "
13882 : "vectors at the same time at %L", &code->loc);
13883 :
13884 5272 : if (code->ext.omp_clauses->tile_list)
13885 : {
13886 : gfc_expr_list *el;
13887 501 : for (el = code->ext.omp_clauses->tile_list; el; el = el->next)
13888 : {
13889 304 : if (el->expr == NULL)
13890 : {
13891 : /* NULL expressions are used to represent '*' arguments.
13892 : Convert those to a 0 expressions. */
13893 113 : el->expr = gfc_get_constant_expr (BT_INTEGER,
13894 : gfc_default_integer_kind,
13895 : &code->loc);
13896 113 : mpz_set_si (el->expr->value.integer, 0);
13897 : }
13898 : else
13899 : {
13900 191 : resolve_positive_int_expr (el->expr, "TILE");
13901 191 : if (el->expr->expr_type != EXPR_CONSTANT)
13902 14 : gfc_error ("TILE requires constant expression at %L",
13903 : &code->loc);
13904 : }
13905 : }
13906 : }
13907 : }
13908 :
13909 :
13910 : void
13911 10119 : gfc_resolve_oacc_blocks (gfc_code *code, gfc_namespace *ns)
13912 : {
13913 10119 : fortran_omp_context ctx;
13914 10119 : gfc_omp_clauses *omp_clauses = code->ext.omp_clauses;
13915 10119 : gfc_omp_namelist *n;
13916 :
13917 10119 : resolve_oacc_loop_blocks (code);
13918 :
13919 10119 : ctx.code = code;
13920 10119 : ctx.sharing_clauses = new hash_set<gfc_symbol *>;
13921 10119 : ctx.private_iterators = new hash_set<gfc_symbol *>;
13922 10119 : ctx.previous = omp_current_ctx;
13923 10119 : ctx.is_openmp = false;
13924 10119 : omp_current_ctx = &ctx;
13925 :
13926 404760 : for (enum gfc_omp_list_type list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
13927 394641 : list = gfc_omp_list_type (list + 1))
13928 394641 : switch (list)
13929 : {
13930 10119 : case OMP_LIST_PRIVATE:
13931 10710 : for (n = omp_clauses->lists[list]; n; n = n->next)
13932 591 : ctx.sharing_clauses->add (n->sym);
13933 : break;
13934 : default:
13935 : break;
13936 : }
13937 :
13938 10119 : gfc_resolve_blocks (code->block, ns);
13939 :
13940 10119 : omp_current_ctx = ctx.previous;
13941 20238 : delete ctx.sharing_clauses;
13942 20238 : delete ctx.private_iterators;
13943 10119 : }
13944 :
13945 :
13946 : static void
13947 5272 : resolve_oacc_loop (gfc_code *code)
13948 : {
13949 5272 : gfc_code *do_code;
13950 5272 : int collapse;
13951 :
13952 5272 : if (code->ext.omp_clauses)
13953 5272 : resolve_omp_clauses (code, code->ext.omp_clauses, NULL, true);
13954 :
13955 5272 : do_code = code->block->next;
13956 5272 : collapse = code->ext.omp_clauses->collapse;
13957 :
13958 : /* Both collapsed and tiled loops are lowered the same way, but are not
13959 : compatible. In gfc_trans_omp_do, the tile is prioritized. */
13960 5272 : if (code->ext.omp_clauses->tile_list)
13961 : {
13962 : int num = 0;
13963 : gfc_expr_list *el;
13964 501 : for (el = code->ext.omp_clauses->tile_list; el; el = el->next)
13965 304 : ++num;
13966 197 : resolve_oacc_nested_loops (code, code->block->next, num, "tiled");
13967 197 : return;
13968 : }
13969 :
13970 5075 : if (collapse <= 0)
13971 : collapse = 1;
13972 5075 : resolve_oacc_nested_loops (code, do_code, collapse, "collapsed");
13973 : }
13974 :
13975 : void
13976 348691 : gfc_resolve_oacc_declare (gfc_namespace *ns)
13977 : {
13978 348691 : enum gfc_omp_list_type list;
13979 348691 : gfc_omp_namelist *n;
13980 348691 : gfc_oacc_declare *oc;
13981 :
13982 348691 : if (ns->oacc_declare == NULL)
13983 : return;
13984 :
13985 290 : for (oc = ns->oacc_declare; oc; oc = oc->next)
13986 : {
13987 6480 : for (list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
13988 6318 : list = gfc_omp_list_type (list + 1))
13989 6574 : for (n = oc->clauses->lists[list]; n; n = n->next)
13990 : {
13991 256 : n->sym->mark = 0;
13992 256 : if (n->sym->attr.flavor != FL_VARIABLE
13993 16 : && (n->sym->attr.flavor != FL_PROCEDURE
13994 8 : || n->sym->result != n->sym))
13995 : {
13996 14 : if (n->sym->attr.flavor != FL_PARAMETER)
13997 : {
13998 8 : gfc_error ("Object %qs is not a variable at %L",
13999 : n->sym->name, &oc->loc);
14000 8 : continue;
14001 : }
14002 : /* Note that OpenACC 3.4 permits name constants, but the
14003 : implementation is permitted to ignore the clause;
14004 : as semantically, device_resident kind of makes sense
14005 : (and the wording with it is a bit odd), the warning
14006 : is suppressed. */
14007 6 : if (list != OMP_LIST_DEVICE_RESIDENT)
14008 5 : gfc_warning (OPT_Wsurprising, "Object %qs at %L is ignored as"
14009 : " parameters need not be copied", n->sym->name,
14010 : &oc->loc);
14011 : }
14012 :
14013 248 : if (n->expr && n->expr->ref->type == REF_ARRAY)
14014 : {
14015 1 : gfc_error ("Array sections: %qs not allowed in"
14016 1 : " !$ACC DECLARE at %L", n->sym->name, &oc->loc);
14017 1 : continue;
14018 : }
14019 : }
14020 :
14021 252 : for (n = oc->clauses->lists[OMP_LIST_DEVICE_RESIDENT]; n; n = n->next)
14022 90 : check_array_not_assumed (n->sym, oc->loc, "DEVICE_RESIDENT");
14023 : }
14024 :
14025 290 : for (oc = ns->oacc_declare; oc; oc = oc->next)
14026 : {
14027 6480 : for (list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
14028 6318 : list = gfc_omp_list_type (list + 1))
14029 6574 : for (n = oc->clauses->lists[list]; n; n = n->next)
14030 : {
14031 256 : if (n->sym->mark)
14032 : {
14033 9 : gfc_error ("Symbol %qs present on multiple clauses at %L",
14034 : n->sym->name, &oc->loc);
14035 9 : continue;
14036 : }
14037 : else
14038 247 : n->sym->mark = 1;
14039 : }
14040 : }
14041 :
14042 290 : for (oc = ns->oacc_declare; oc; oc = oc->next)
14043 : {
14044 6480 : for (list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
14045 6318 : list = gfc_omp_list_type (list + 1))
14046 6574 : for (n = oc->clauses->lists[list]; n; n = n->next)
14047 256 : n->sym->mark = 0;
14048 : }
14049 : }
14050 :
14051 :
14052 : void
14053 348691 : gfc_resolve_oacc_routines (gfc_namespace *ns)
14054 : {
14055 348691 : for (gfc_oacc_routine_name *orn = ns->oacc_routine_names;
14056 348791 : orn;
14057 100 : orn = orn->next)
14058 : {
14059 100 : gfc_symbol *sym = orn->sym;
14060 100 : if (!sym->attr.external
14061 29 : && !sym->attr.function
14062 27 : && !sym->attr.subroutine)
14063 : {
14064 7 : gfc_error ("NAME %qs does not refer to a subroutine or function"
14065 : " in !$ACC ROUTINE ( NAME ) at %L", sym->name, &orn->loc);
14066 7 : continue;
14067 : }
14068 93 : if (!gfc_add_omp_declare_target (&sym->attr, sym->name, &orn->loc))
14069 : {
14070 20 : gfc_error ("NAME %qs invalid"
14071 : " in !$ACC ROUTINE ( NAME ) at %L", sym->name, &orn->loc);
14072 20 : continue;
14073 : }
14074 : }
14075 348691 : }
14076 :
14077 :
14078 : void
14079 13538 : gfc_resolve_oacc_directive (gfc_code *code, gfc_namespace *ns ATTRIBUTE_UNUSED)
14080 : {
14081 13538 : resolve_oacc_directive_inside_omp_region (code);
14082 :
14083 13538 : switch (code->op)
14084 : {
14085 7723 : case EXEC_OACC_PARALLEL:
14086 7723 : case EXEC_OACC_KERNELS:
14087 7723 : case EXEC_OACC_SERIAL:
14088 7723 : case EXEC_OACC_DATA:
14089 7723 : case EXEC_OACC_HOST_DATA:
14090 7723 : case EXEC_OACC_UPDATE:
14091 7723 : case EXEC_OACC_ENTER_DATA:
14092 7723 : case EXEC_OACC_EXIT_DATA:
14093 7723 : case EXEC_OACC_WAIT:
14094 7723 : case EXEC_OACC_CACHE:
14095 7723 : case EXEC_OACC_INIT:
14096 7723 : case EXEC_OACC_SHUTDOWN:
14097 7723 : case EXEC_OACC_SET:
14098 7723 : resolve_omp_clauses (code, code->ext.omp_clauses, NULL, true);
14099 7723 : break;
14100 5272 : case EXEC_OACC_PARALLEL_LOOP:
14101 5272 : case EXEC_OACC_KERNELS_LOOP:
14102 5272 : case EXEC_OACC_SERIAL_LOOP:
14103 5272 : case EXEC_OACC_LOOP:
14104 5272 : resolve_oacc_loop (code);
14105 5272 : break;
14106 543 : case EXEC_OACC_ATOMIC:
14107 543 : resolve_omp_atomic (code);
14108 543 : break;
14109 : default:
14110 : break;
14111 : }
14112 13538 : }
14113 :
14114 :
14115 : static void
14116 2182 : resolve_omp_target (gfc_code *code)
14117 : {
14118 : #define GFC_IS_TEAMS_CONSTRUCT(op) \
14119 : (op == EXEC_OMP_TEAMS \
14120 : || op == EXEC_OMP_TEAMS_DISTRIBUTE \
14121 : || op == EXEC_OMP_TEAMS_DISTRIBUTE_SIMD \
14122 : || op == EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO \
14123 : || op == EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD \
14124 : || op == EXEC_OMP_TEAMS_LOOP)
14125 :
14126 2182 : if (!code->ext.omp_clauses->contains_teams_construct)
14127 : return;
14128 203 : gfc_code *c = code->block->next;
14129 203 : if (c->op == EXEC_BLOCK)
14130 30 : c = c->ext.block.ns->code;
14131 203 : if (code->ext.omp_clauses->target_first_st_is_teams_or_meta)
14132 : {
14133 192 : if (c->op == EXEC_OMP_METADIRECTIVE)
14134 : {
14135 15 : struct gfc_omp_variant *mc
14136 : = c->ext.omp_variants;
14137 : /* All mc->(next...->)code should be identical with regards
14138 : to the diagnostic below. */
14139 16 : do
14140 : {
14141 16 : if (mc->stmt != ST_NONE
14142 15 : && GFC_IS_TEAMS_CONSTRUCT (mc->code->op))
14143 : {
14144 14 : if (c->next == NULL && mc->code->next == NULL)
14145 : return;
14146 : c = mc->code;
14147 : break;
14148 : }
14149 2 : mc = mc->next;
14150 : }
14151 2 : while (mc);
14152 : }
14153 177 : else if (GFC_IS_TEAMS_CONSTRUCT (c->op) && c->next == NULL)
14154 : return;
14155 : }
14156 :
14157 31 : while (c && !GFC_IS_TEAMS_CONSTRUCT (c->op))
14158 8 : c = c->next;
14159 23 : if (c)
14160 19 : gfc_error ("!$OMP TARGET region at %L with a nested TEAMS at %L may not "
14161 : "contain any other statement, declaration or directive outside "
14162 : "of the single TEAMS construct", &c->loc, &code->loc);
14163 : else
14164 4 : gfc_error ("!$OMP TARGET region at %L with a nested TEAMS may not "
14165 : "contain any other statement, declaration or directive outside "
14166 : "of the single TEAMS construct", &code->loc);
14167 : #undef GFC_IS_TEAMS_CONSTRUCT
14168 : }
14169 :
14170 : static void
14171 154 : resolve_omp_dispatch (gfc_code *code)
14172 : {
14173 154 : gfc_code *next = code->block->next;
14174 154 : if (next == NULL)
14175 : return;
14176 :
14177 151 : gfc_exec_op op = next->op;
14178 151 : gcc_assert (op == EXEC_CALL || op == EXEC_ASSIGN);
14179 151 : if (op != EXEC_CALL
14180 74 : && (op != EXEC_ASSIGN || next->expr2->expr_type != EXPR_FUNCTION))
14181 3 : gfc_error (
14182 : "%<OMP DISPATCH%> directive at %L must be followed by a procedure "
14183 : "call with optional assignment",
14184 : &code->loc);
14185 :
14186 77 : if ((op == EXEC_CALL && next->resolved_sym != NULL
14187 76 : && next->resolved_sym->attr.proc_pointer)
14188 150 : || (op == EXEC_ASSIGN && gfc_expr_attr (next->expr2).proc_pointer))
14189 1 : gfc_error ("%<OMP DISPATCH%> directive at %L cannot be followed by a "
14190 : "procedure pointer",
14191 : &code->loc);
14192 : }
14193 :
14194 : /* Resolve OpenMP directive clauses and check various requirements
14195 : of each directive. */
14196 :
14197 : void
14198 21246 : gfc_resolve_omp_directive (gfc_code *code, gfc_namespace *ns)
14199 : {
14200 21246 : resolve_omp_directive_inside_oacc_region (code);
14201 :
14202 21246 : if (code->op != EXEC_OMP_ATOMIC)
14203 19092 : gfc_maybe_initialize_eh ();
14204 :
14205 21246 : switch (code->op)
14206 : {
14207 5432 : case EXEC_OMP_DISTRIBUTE:
14208 5432 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
14209 5432 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
14210 5432 : case EXEC_OMP_DISTRIBUTE_SIMD:
14211 5432 : case EXEC_OMP_DO:
14212 5432 : case EXEC_OMP_DO_SIMD:
14213 5432 : case EXEC_OMP_LOOP:
14214 5432 : case EXEC_OMP_PARALLEL_DO:
14215 5432 : case EXEC_OMP_PARALLEL_DO_SIMD:
14216 5432 : case EXEC_OMP_PARALLEL_LOOP:
14217 5432 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
14218 5432 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
14219 5432 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
14220 5432 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
14221 5432 : case EXEC_OMP_MASKED_TASKLOOP:
14222 5432 : case EXEC_OMP_MASKED_TASKLOOP_SIMD:
14223 5432 : case EXEC_OMP_MASTER_TASKLOOP:
14224 5432 : case EXEC_OMP_MASTER_TASKLOOP_SIMD:
14225 5432 : case EXEC_OMP_SIMD:
14226 5432 : case EXEC_OMP_TARGET_PARALLEL_DO:
14227 5432 : case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
14228 5432 : case EXEC_OMP_TARGET_PARALLEL_LOOP:
14229 5432 : case EXEC_OMP_TARGET_SIMD:
14230 5432 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
14231 5432 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
14232 5432 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
14233 5432 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
14234 5432 : case EXEC_OMP_TARGET_TEAMS_LOOP:
14235 5432 : case EXEC_OMP_TASKLOOP:
14236 5432 : case EXEC_OMP_TASKLOOP_SIMD:
14237 5432 : case EXEC_OMP_TEAMS_DISTRIBUTE:
14238 5432 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
14239 5432 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
14240 5432 : case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
14241 5432 : case EXEC_OMP_TEAMS_LOOP:
14242 5432 : case EXEC_OMP_TILE:
14243 5432 : case EXEC_OMP_UNROLL:
14244 5432 : resolve_omp_do (code);
14245 5432 : break;
14246 2182 : case EXEC_OMP_TARGET:
14247 2182 : resolve_omp_target (code);
14248 10273 : gcc_fallthrough ();
14249 10273 : case EXEC_OMP_ALLOCATE:
14250 10273 : case EXEC_OMP_ALLOCATORS:
14251 10273 : case EXEC_OMP_ASSUME:
14252 10273 : case EXEC_OMP_CANCEL:
14253 10273 : case EXEC_OMP_ERROR:
14254 10273 : case EXEC_OMP_INTEROP:
14255 10273 : case EXEC_OMP_MASKED:
14256 10273 : case EXEC_OMP_ORDERED:
14257 10273 : case EXEC_OMP_PARALLEL_WORKSHARE:
14258 10273 : case EXEC_OMP_PARALLEL:
14259 10273 : case EXEC_OMP_PARALLEL_MASKED:
14260 10273 : case EXEC_OMP_PARALLEL_MASTER:
14261 10273 : case EXEC_OMP_PARALLEL_SECTIONS:
14262 10273 : case EXEC_OMP_SCOPE:
14263 10273 : case EXEC_OMP_SECTIONS:
14264 10273 : case EXEC_OMP_SINGLE:
14265 10273 : case EXEC_OMP_TARGET_DATA:
14266 10273 : case EXEC_OMP_TARGET_ENTER_DATA:
14267 10273 : case EXEC_OMP_TARGET_EXIT_DATA:
14268 10273 : case EXEC_OMP_TARGET_PARALLEL:
14269 10273 : case EXEC_OMP_TARGET_TEAMS:
14270 10273 : case EXEC_OMP_TASK:
14271 10273 : case EXEC_OMP_TASKWAIT:
14272 10273 : case EXEC_OMP_TEAMS:
14273 10273 : case EXEC_OMP_WORKSHARE:
14274 10273 : case EXEC_OMP_DEPOBJ:
14275 10273 : if (code->ext.omp_clauses)
14276 10140 : resolve_omp_clauses (code, code->ext.omp_clauses, NULL);
14277 : break;
14278 1718 : case EXEC_OMP_TARGET_UPDATE:
14279 1718 : if (code->ext.omp_clauses)
14280 1718 : resolve_omp_clauses (code, code->ext.omp_clauses, NULL);
14281 1718 : if (code->ext.omp_clauses == NULL
14282 1718 : || (code->ext.omp_clauses->lists[OMP_LIST_TO] == NULL
14283 994 : && code->ext.omp_clauses->lists[OMP_LIST_FROM] == NULL))
14284 0 : gfc_error ("OMP TARGET UPDATE at %L requires at least one TO or "
14285 : "FROM clause", &code->loc);
14286 : break;
14287 2154 : case EXEC_OMP_ATOMIC:
14288 2154 : resolve_omp_clauses (code, code->block->ext.omp_clauses, NULL);
14289 2154 : resolve_omp_atomic (code);
14290 2154 : break;
14291 159 : case EXEC_OMP_CRITICAL:
14292 159 : resolve_omp_clauses (code, code->ext.omp_clauses, NULL);
14293 159 : if (!code->ext.omp_clauses->critical_name
14294 112 : && code->ext.omp_clauses->hint
14295 3 : && code->ext.omp_clauses->hint->ts.type == BT_INTEGER
14296 3 : && code->ext.omp_clauses->hint->expr_type == EXPR_CONSTANT
14297 3 : && mpz_sgn (code->ext.omp_clauses->hint->value.integer) != 0)
14298 1 : gfc_error ("OMP CRITICAL at %L with HINT clause requires a NAME, "
14299 : "except when omp_sync_hint_none is used", &code->loc);
14300 : break;
14301 49 : case EXEC_OMP_SCAN:
14302 : /* Flag is only used to checking, hence, it is unset afterwards. */
14303 49 : if (!code->ext.omp_clauses->if_present)
14304 10 : gfc_error ("Unexpected !$OMP SCAN at %L outside loop construct with "
14305 : "%<inscan%> REDUCTION clause", &code->loc);
14306 49 : code->ext.omp_clauses->if_present = false;
14307 49 : resolve_omp_clauses (code, code->ext.omp_clauses, ns);
14308 49 : break;
14309 154 : case EXEC_OMP_DISPATCH:
14310 154 : if (code->ext.omp_clauses)
14311 154 : resolve_omp_clauses (code, code->ext.omp_clauses, ns);
14312 154 : resolve_omp_dispatch (code);
14313 154 : break;
14314 138 : case EXEC_OMP_METADIRECTIVE:
14315 138 : resolve_omp_metadirective (code, ns);
14316 138 : break;
14317 : default:
14318 : break;
14319 : }
14320 21246 : }
14321 :
14322 : /* Resolve !$omp declare {variant|simd} constructs in NS.
14323 : Note that !$omp declare target is resolved in resolve_symbol. */
14324 :
14325 : void
14326 360463 : gfc_resolve_omp_declare (gfc_namespace *ns)
14327 : {
14328 360463 : gfc_omp_declare_simd *ods;
14329 360699 : for (ods = ns->omp_declare_simd; ods; ods = ods->next)
14330 : {
14331 236 : if (ods->proc_name != NULL
14332 196 : && ods->proc_name != ns->proc_name)
14333 6 : gfc_error ("!$OMP DECLARE SIMD should refer to containing procedure "
14334 : "%qs at %L", ns->proc_name->name, &ods->where);
14335 236 : if (ods->clauses)
14336 218 : resolve_omp_clauses (NULL, ods->clauses, ns);
14337 : }
14338 :
14339 360463 : gfc_omp_declare_variant *odv;
14340 360463 : gfc_omp_namelist *range_begin = NULL;
14341 :
14342 360917 : for (odv = ns->omp_declare_variant; odv; odv = odv->next)
14343 454 : gfc_resolve_omp_context_selector (odv->set_selectors, false, nullptr);
14344 360917 : for (odv = ns->omp_declare_variant; odv; odv = odv->next)
14345 657 : for (gfc_omp_namelist *n = odv->adjust_args_list; n != NULL; n = n->next)
14346 : {
14347 203 : if ((n->expr == NULL
14348 6 : && (range_begin
14349 4 : || n->u.adj_args.range_start
14350 1 : || n->u.adj_args.omp_num_args_plus
14351 1 : || n->u.adj_args.omp_num_args_minus))
14352 198 : || n->u.adj_args.error_p)
14353 : {
14354 : }
14355 197 : else if (range_begin
14356 191 : || n->u.adj_args.range_start
14357 186 : || n->u.adj_args.omp_num_args_plus
14358 186 : || n->u.adj_args.omp_num_args_minus)
14359 : {
14360 11 : if (!n->expr
14361 11 : || !gfc_resolve_expr (n->expr)
14362 11 : || n->expr->expr_type != EXPR_CONSTANT
14363 10 : || n->expr->ts.type != BT_INTEGER
14364 10 : || n->expr->rank != 0
14365 10 : || mpz_sgn (n->expr->value.integer) < 0
14366 20 : || ((n->u.adj_args.omp_num_args_plus
14367 8 : || n->u.adj_args.omp_num_args_minus)
14368 5 : && mpz_sgn (n->expr->value.integer) == 0))
14369 : {
14370 2 : if (n->u.adj_args.omp_num_args_plus
14371 2 : || n->u.adj_args.omp_num_args_minus)
14372 0 : gfc_error ("Expected constant non-negative scalar integer "
14373 : "offset expression at %L", &n->where);
14374 : else
14375 2 : gfc_error ("For range-based %<adjust_args%>, a constant "
14376 : "positive scalar integer expression is required "
14377 : "at %L", &n->where);
14378 : }
14379 : }
14380 186 : else if (n->expr
14381 186 : && n->expr->expr_type == EXPR_CONSTANT
14382 21 : && n->expr->ts.type == BT_INTEGER
14383 20 : && mpz_sgn (n->expr->value.integer) > 0)
14384 : {
14385 : }
14386 166 : else if (!n->expr
14387 166 : || !gfc_resolve_expr (n->expr)
14388 331 : || n->expr->expr_type != EXPR_VARIABLE)
14389 2 : gfc_error ("Expected dummy parameter name or a positive integer "
14390 : "at %L", &n->where);
14391 164 : else if (n->expr->expr_type == EXPR_VARIABLE)
14392 164 : n->sym = n->expr->symtree->n.sym;
14393 :
14394 203 : range_begin = n->u.adj_args.range_start ? n : NULL;
14395 : }
14396 360463 : }
14397 :
14398 : struct omp_udr_callback_data
14399 : {
14400 : gfc_omp_udr *omp_udr;
14401 : bool is_initializer;
14402 : };
14403 :
14404 : static int
14405 3706 : omp_udr_callback (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
14406 : void *data)
14407 : {
14408 3706 : struct omp_udr_callback_data *cd = (struct omp_udr_callback_data *) data;
14409 3706 : if ((*e)->expr_type == EXPR_VARIABLE)
14410 : {
14411 2276 : if (cd->is_initializer)
14412 : {
14413 539 : if ((*e)->symtree->n.sym != cd->omp_udr->omp_priv
14414 140 : && (*e)->symtree->n.sym != cd->omp_udr->omp_orig)
14415 4 : gfc_error ("Variable other than OMP_PRIV or OMP_ORIG used in "
14416 : "INITIALIZER clause of !$OMP DECLARE REDUCTION at %L",
14417 : &(*e)->where);
14418 : }
14419 : else
14420 : {
14421 1737 : if ((*e)->symtree->n.sym != cd->omp_udr->omp_out
14422 619 : && (*e)->symtree->n.sym != cd->omp_udr->omp_in)
14423 6 : gfc_error ("Variable other than OMP_OUT or OMP_IN used in "
14424 : "combiner of !$OMP DECLARE REDUCTION at %L",
14425 : &(*e)->where);
14426 : }
14427 : }
14428 3706 : return 0;
14429 : }
14430 :
14431 : /* Resolve !$omp declare reduction constructs. */
14432 :
14433 : static void
14434 626 : gfc_resolve_omp_udr (gfc_omp_udr *omp_udr)
14435 : {
14436 626 : gfc_actual_arglist *a;
14437 626 : const char *predef_name = NULL;
14438 :
14439 626 : switch (omp_udr->rop)
14440 : {
14441 625 : case OMP_REDUCTION_PLUS:
14442 625 : case OMP_REDUCTION_TIMES:
14443 625 : case OMP_REDUCTION_MINUS:
14444 625 : case OMP_REDUCTION_AND:
14445 625 : case OMP_REDUCTION_OR:
14446 625 : case OMP_REDUCTION_EQV:
14447 625 : case OMP_REDUCTION_NEQV:
14448 625 : case OMP_REDUCTION_MAX:
14449 625 : case OMP_REDUCTION_USER:
14450 625 : break;
14451 1 : default:
14452 1 : gfc_error ("Invalid operator for !$OMP DECLARE REDUCTION %s at %L",
14453 : omp_udr->name, &omp_udr->where);
14454 26 : return;
14455 : }
14456 :
14457 625 : if (gfc_omp_udr_predef (omp_udr->rop, omp_udr->name,
14458 : &omp_udr->ts, &predef_name))
14459 : {
14460 19 : if (predef_name)
14461 19 : gfc_error ("Redefinition of predefined %qs in "
14462 : "!$OMP DECLARE REDUCTION at %L",
14463 : predef_name, &omp_udr->where);
14464 : else
14465 0 : gfc_error ("Redefinition of predefined %qs in "
14466 : "!$OMP DECLARE REDUCTION at %L", omp_udr->name,
14467 : &omp_udr->where);
14468 19 : return;
14469 : }
14470 :
14471 606 : if (omp_udr->ts.type == BT_CHARACTER
14472 62 : && omp_udr->ts.u.cl->length
14473 32 : && omp_udr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
14474 : {
14475 1 : gfc_error ("CHARACTER length in !$OMP DECLARE REDUCTION %qs not "
14476 : "constant at %L", omp_udr->name, &omp_udr->where);
14477 1 : return;
14478 : }
14479 :
14480 605 : struct omp_udr_callback_data cd;
14481 605 : cd.omp_udr = omp_udr;
14482 605 : cd.is_initializer = false;
14483 605 : gfc_code_walker (&omp_udr->combiner_ns->code, gfc_dummy_code_callback,
14484 : omp_udr_callback, &cd);
14485 605 : if (omp_udr->combiner_ns->code->op == EXEC_CALL)
14486 : {
14487 346 : for (a = omp_udr->combiner_ns->code->ext.actual; a; a = a->next)
14488 237 : if (a->expr == NULL)
14489 : break;
14490 110 : if (a)
14491 1 : gfc_error ("Subroutine call with alternate returns in combiner "
14492 : "of !$OMP DECLARE REDUCTION at %L",
14493 : &omp_udr->combiner_ns->code->loc);
14494 : }
14495 605 : if (omp_udr->initializer_ns)
14496 : {
14497 377 : cd.is_initializer = true;
14498 377 : gfc_code_walker (&omp_udr->initializer_ns->code, gfc_dummy_code_callback,
14499 : omp_udr_callback, &cd);
14500 377 : if (omp_udr->initializer_ns->code->op == EXEC_CALL)
14501 : {
14502 377 : for (a = omp_udr->initializer_ns->code->ext.actual; a; a = a->next)
14503 243 : if (a->expr == NULL)
14504 : break;
14505 135 : if (a)
14506 1 : gfc_error ("Subroutine call with alternate returns in "
14507 : "INITIALIZER clause of !$OMP DECLARE REDUCTION "
14508 : "at %L", &omp_udr->initializer_ns->code->loc);
14509 136 : for (a = omp_udr->initializer_ns->code->ext.actual; a; a = a->next)
14510 135 : if (a->expr
14511 135 : && a->expr->expr_type == EXPR_VARIABLE
14512 135 : && a->expr->symtree->n.sym == omp_udr->omp_priv
14513 134 : && a->expr->ref == NULL)
14514 : break;
14515 135 : if (a == NULL)
14516 1 : gfc_error ("One of actual subroutine arguments in INITIALIZER "
14517 : "clause of !$OMP DECLARE REDUCTION must be OMP_PRIV "
14518 : "at %L", &omp_udr->initializer_ns->code->loc);
14519 : }
14520 : }
14521 228 : else if (omp_udr->ts.type == BT_DERIVED
14522 228 : && !gfc_has_default_initializer (omp_udr->ts.u.derived))
14523 : {
14524 4 : gfc_error ("Missing INITIALIZER clause for !$OMP DECLARE REDUCTION "
14525 : "of derived type without default initializer at %L",
14526 : &omp_udr->where);
14527 4 : return;
14528 : }
14529 : }
14530 :
14531 : void
14532 361517 : gfc_resolve_omp_udrs (gfc_symtree *st)
14533 : {
14534 361517 : gfc_omp_udr *omp_udr;
14535 :
14536 361517 : if (st == NULL)
14537 : return;
14538 527 : gfc_resolve_omp_udrs (st->left);
14539 527 : gfc_resolve_omp_udrs (st->right);
14540 1153 : for (omp_udr = st->n.omp_udr; omp_udr; omp_udr = omp_udr->next)
14541 626 : gfc_resolve_omp_udr (omp_udr);
14542 : }
14543 :
14544 : /* Resolve !$omp declare mapper constructs. */
14545 :
14546 : static void
14547 23 : gfc_resolve_omp_udm (gfc_omp_udm *omp_udm)
14548 : {
14549 23 : resolve_omp_clauses (NULL, omp_udm->clauses, omp_udm->mapper_ns);
14550 :
14551 23 : gfc_omp_namelist *n;
14552 25 : for (n = omp_udm->clauses->lists[OMP_LIST_MAP]; n; n = n->next)
14553 23 : if (n->sym == omp_udm->var_sym)
14554 : break;
14555 23 : if (!n)
14556 2 : gfc_error ("At least one %<map%> clause in !$OMP DECLARE MAPPER at %L must "
14557 : "map %qs or an element of it",
14558 2 : &omp_udm->where, omp_udm->var_sym->name);
14559 23 : }
14560 :
14561 : void
14562 360507 : gfc_resolve_omp_udms (gfc_symtree *st)
14563 : {
14564 360507 : gfc_omp_udm *omp_udm;
14565 :
14566 360507 : if (st == NULL)
14567 : return;
14568 22 : gfc_resolve_omp_udms (st->left);
14569 22 : gfc_resolve_omp_udms (st->right);
14570 45 : for (omp_udm = st->n.omp_udm; omp_udm; omp_udm = omp_udm->next)
14571 23 : gfc_resolve_omp_udm (omp_udm);
14572 : }
|