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 54819 : gfc_match_omp_eos (void)
135 : {
136 54819 : locus old_loc;
137 54819 : char c;
138 :
139 54819 : old_loc = gfc_current_locus;
140 54819 : gfc_gobble_whitespace ();
141 :
142 54819 : if (gfc_matching_omp_context_selector)
143 : {
144 269 : if (gfc_peek_ascii_char () == ')')
145 : return MATCH_YES;
146 : }
147 : else
148 : {
149 54550 : c = gfc_next_ascii_char ();
150 54550 : 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 52842 : case '\n':
159 52842 : return MATCH_YES;
160 : }
161 : }
162 :
163 1709 : gfc_current_locus = old_loc;
164 1709 : return MATCH_NO;
165 : }
166 :
167 : match
168 13157 : gfc_match_omp_eos_error (void)
169 : {
170 13157 : if (gfc_match_omp_eos() == MATCH_YES)
171 : return MATCH_YES;
172 :
173 35 : gfc_error ("Unexpected junk at %C");
174 35 : return MATCH_ERROR;
175 : }
176 :
177 :
178 : /* Free an omp_clauses structure. */
179 :
180 : void
181 60934 : gfc_free_omp_clauses (gfc_omp_clauses *c)
182 : {
183 60934 : if (c == NULL)
184 : return;
185 :
186 34286 : gfc_free_expr (c->if_expr);
187 377146 : for (int i = 0; i < OMP_IF_LAST; i++)
188 342860 : gfc_free_expr (c->if_exprs[i]);
189 34286 : gfc_free_expr (c->self_expr);
190 34286 : gfc_free_expr (c->final_expr);
191 34286 : gfc_free_expr (c->num_threads);
192 34286 : gfc_free_expr (c->chunk_size);
193 34286 : gfc_free_expr (c->safelen_expr);
194 34286 : gfc_free_expr (c->simdlen_expr);
195 34286 : gfc_free_expr (c->num_teams_lower);
196 34286 : gfc_free_expr (c->num_teams_upper);
197 34286 : gfc_free_expr (c->device);
198 34286 : gfc_free_expr (c->dyn_groupprivate);
199 34286 : gfc_free_expr (c->thread_limit);
200 34286 : gfc_free_expr (c->dist_chunk_size);
201 34286 : gfc_free_expr (c->grainsize);
202 34286 : gfc_free_expr (c->hint);
203 34286 : gfc_free_expr (c->num_tasks);
204 34286 : gfc_free_expr (c->priority);
205 34286 : gfc_free_expr (c->detach);
206 34286 : gfc_free_expr (c->novariants);
207 34286 : gfc_free_expr (c->nocontext);
208 34286 : gfc_free_expr (c->async_expr);
209 34286 : gfc_free_expr (c->gang_num_expr);
210 34286 : gfc_free_expr (c->gang_static_expr);
211 34286 : gfc_free_expr (c->worker_expr);
212 34286 : gfc_free_expr (c->vector_expr);
213 34286 : gfc_free_expr (c->num_gangs_expr);
214 34286 : gfc_free_expr (c->num_workers_expr);
215 34286 : gfc_free_expr (c->vector_length_expr);
216 1371440 : for (enum gfc_omp_list_type t = OMP_LIST_FIRST; t < OMP_LIST_NUM;
217 1337154 : t = gfc_omp_list_type (t + 1))
218 1337154 : gfc_free_omp_namelist (c->lists[t], t);
219 34286 : gfc_free_expr_list (c->wait_list);
220 34286 : gfc_free_expr_list (c->tile_list);
221 34286 : gfc_free_expr_list (c->sizes_list);
222 34286 : free (const_cast<char *> (c->critical_name));
223 34286 : if (c->assume)
224 : {
225 23 : free (c->assume->absent);
226 23 : free (c->assume->contains);
227 23 : gfc_free_expr_list (c->assume->holds);
228 23 : free (c->assume);
229 : }
230 34286 : 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 103804 : gfc_free_expr_list (gfc_expr_list *list)
255 : {
256 103804 : gfc_expr_list *n;
257 :
258 105207 : for (; list; list = n)
259 : {
260 1403 : n = list->next;
261 1403 : free (list);
262 : }
263 103804 : }
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 518983 : gfc_free_omp_declare_simd_list (gfc_omp_declare_simd *list)
279 : {
280 519219 : 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 518983 : }
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 518983 : gfc_free_omp_declare_variant_list (gfc_omp_declare_variant *list)
342 : {
343 519437 : 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 518983 : }
352 :
353 : /* Free an !$omp declare reduction. */
354 :
355 : void
356 1118 : gfc_free_omp_udr (gfc_omp_udr *omp_udr)
357 : {
358 1118 : if (omp_udr)
359 : {
360 607 : gfc_free_omp_udr (omp_udr->next);
361 607 : gfc_free_namespace (omp_udr->combiner_ns);
362 607 : if (omp_udr->initializer_ns)
363 377 : gfc_free_namespace (omp_udr->initializer_ns);
364 607 : free (omp_udr);
365 : }
366 1118 : }
367 :
368 : /* Free variants of an !$omp metadirective construct. */
369 :
370 : void
371 93 : gfc_free_omp_variants (gfc_omp_variant *variant)
372 : {
373 284 : while (variant)
374 : {
375 191 : gfc_omp_variant *next_variant = variant->next;
376 191 : gfc_free_omp_set_selector_list (variant->selectors);
377 191 : free (variant);
378 191 : variant = next_variant;
379 : }
380 93 : }
381 :
382 : static gfc_omp_udr *
383 4710 : gfc_find_omp_udr (gfc_namespace *ns, const char *name, gfc_typespec *ts)
384 : {
385 4710 : gfc_symtree *st;
386 :
387 4710 : if (ns == NULL)
388 467 : ns = gfc_current_ns;
389 5658 : do
390 : {
391 5658 : gfc_omp_udr *omp_udr;
392 :
393 5658 : st = gfc_find_symtree (ns->omp_udr_root, name);
394 5658 : if (st != NULL)
395 : {
396 934 : for (omp_udr = st->n.omp_udr; omp_udr; omp_udr = omp_udr->next)
397 934 : if (ts == NULL)
398 : return omp_udr;
399 567 : else if (gfc_compare_types (&omp_udr->ts, ts))
400 : {
401 479 : if (ts->type == BT_CHARACTER)
402 : {
403 60 : if (omp_udr->ts.u.cl->length == NULL)
404 : return omp_udr;
405 36 : if (ts->u.cl->length == NULL)
406 0 : continue;
407 36 : if (gfc_compare_expr (omp_udr->ts.u.cl->length,
408 : ts->u.cl->length,
409 : INTRINSIC_EQ) != 0)
410 12 : continue;
411 : }
412 443 : return omp_udr;
413 : }
414 : }
415 :
416 : /* Don't escape an interface block. */
417 4824 : if (ns && !ns->has_import_set
418 4824 : && ns->proc_name && ns->proc_name->attr.if_source == IFSRC_IFBODY)
419 : break;
420 :
421 4824 : ns = ns->parent;
422 : }
423 4824 : while (ns != NULL);
424 :
425 : return NULL;
426 : }
427 :
428 :
429 : /* Match a variable/common block list and construct a namelist from it;
430 : if has_all_memory != NULL, *has_all_memory is set and omp_all_memory
431 : yields a list->sym NULL entry. */
432 :
433 : static match
434 30982 : gfc_match_omp_variable_list (const char *str, gfc_omp_namelist **list,
435 : bool allow_common, bool *end_colon = NULL,
436 : gfc_omp_namelist ***headp = NULL,
437 : bool allow_sections = false,
438 : bool allow_derived = false,
439 : bool *has_all_memory = NULL,
440 : bool reject_common_vars = false,
441 : bool reverse_order = false)
442 : {
443 30982 : gfc_omp_namelist *head, *tail, *p;
444 30982 : locus old_loc, cur_loc;
445 30982 : char n[GFC_MAX_SYMBOL_LEN+1];
446 30982 : gfc_symbol *sym;
447 30982 : match m;
448 30982 : gfc_symtree *st;
449 :
450 30982 : head = tail = NULL;
451 :
452 30982 : old_loc = gfc_current_locus;
453 30982 : if (has_all_memory)
454 708 : *has_all_memory = false;
455 30982 : m = gfc_match (str);
456 30982 : if (m != MATCH_YES)
457 : return m;
458 :
459 37686 : for (;;)
460 : {
461 37686 : gfc_gobble_whitespace ();
462 37686 : cur_loc = gfc_current_locus;
463 :
464 37686 : m = gfc_match_name (n);
465 37686 : if (m == MATCH_YES && strcmp (n, "omp_all_memory") == 0)
466 : {
467 23 : locus loc = gfc_get_location_range (NULL, 0, &cur_loc, 1,
468 : &gfc_current_locus);
469 23 : if (!has_all_memory)
470 : {
471 2 : gfc_error ("%<omp_all_memory%> at %L not permitted in this "
472 : "clause", &loc);
473 2 : goto cleanup;
474 : }
475 21 : *has_all_memory = true;
476 21 : p = gfc_get_omp_namelist ();
477 21 : if (head == NULL)
478 : head = tail = p;
479 : else
480 : {
481 3 : tail->next = p;
482 3 : tail = tail->next;
483 : }
484 21 : tail->where = loc;
485 21 : goto next_item;
486 : }
487 37409 : if (m == MATCH_YES)
488 : {
489 37409 : gfc_symtree *st;
490 37409 : if ((m = gfc_get_ha_sym_tree (n, &st) ? MATCH_ERROR : MATCH_YES)
491 : == MATCH_YES)
492 37409 : sym = st->n.sym;
493 : }
494 37663 : switch (m)
495 : {
496 37409 : case MATCH_YES:
497 37409 : gfc_expr *expr;
498 37409 : expr = NULL;
499 37409 : gfc_gobble_whitespace ();
500 22789 : if ((allow_sections && gfc_peek_ascii_char () == '(')
501 56100 : || (allow_derived && gfc_peek_ascii_char () == '%'))
502 : {
503 6325 : gfc_current_locus = cur_loc;
504 6325 : m = gfc_match_variable (&expr, 0);
505 6325 : switch (m)
506 : {
507 4 : case MATCH_ERROR:
508 12 : goto cleanup;
509 0 : case MATCH_NO:
510 0 : goto syntax;
511 6321 : default:
512 6321 : break;
513 : }
514 6321 : if (gfc_is_coindexed (expr))
515 : {
516 5 : gfc_error ("List item shall not be coindexed at %L",
517 5 : &expr->where);
518 5 : goto cleanup;
519 : }
520 : }
521 37400 : gfc_set_sym_referenced (sym);
522 37400 : p = gfc_get_omp_namelist ();
523 37400 : if (head == NULL)
524 : head = tail = p;
525 10113 : else if (reverse_order)
526 : {
527 57 : p->next = head;
528 57 : head = p;
529 : }
530 : else
531 : {
532 10056 : tail->next = p;
533 10056 : tail = tail->next;
534 : }
535 37400 : p->sym = sym;
536 37400 : p->expr = expr;
537 37400 : p->where = gfc_get_location_range (NULL, 0, &cur_loc, 1,
538 : &gfc_current_locus);
539 37400 : if (reject_common_vars && sym->attr.in_common)
540 : {
541 3 : gcc_assert (allow_common);
542 3 : gfc_error ("%qs at %L is part of the common block %</%s/%> and "
543 : "may only be specificed implicitly via the named "
544 : "common block", sym->name, &cur_loc,
545 3 : sym->common_head->name);
546 3 : goto cleanup;
547 : }
548 37397 : goto next_item;
549 254 : case MATCH_NO:
550 254 : break;
551 0 : case MATCH_ERROR:
552 0 : goto cleanup;
553 : }
554 :
555 254 : if (!allow_common)
556 10 : goto syntax;
557 :
558 244 : m = gfc_match ("/ %n /", n);
559 244 : if (m == MATCH_ERROR)
560 0 : goto cleanup;
561 244 : if (m == MATCH_NO)
562 19 : goto syntax;
563 :
564 225 : cur_loc = gfc_get_location_range (NULL, 0, &cur_loc, 1,
565 : &gfc_current_locus);
566 225 : st = gfc_find_symtree (gfc_current_ns->common_root, n);
567 225 : if (st == NULL)
568 : {
569 2 : gfc_error ("COMMON block %</%s/%> not found at %L", n, &cur_loc);
570 2 : goto cleanup;
571 : }
572 724 : for (sym = st->n.common->head; sym; sym = sym->common_next)
573 : {
574 501 : gfc_set_sym_referenced (sym);
575 501 : p = gfc_get_omp_namelist ();
576 501 : if (head == NULL)
577 : head = tail = p;
578 325 : else if (reverse_order)
579 : {
580 0 : p->next = head;
581 0 : head = p;
582 : }
583 : else
584 : {
585 325 : tail->next = p;
586 325 : tail = tail->next;
587 : }
588 501 : p->sym = sym;
589 501 : p->where = cur_loc;
590 : }
591 :
592 223 : next_item:
593 37641 : if (end_colon && gfc_match_char (':') == MATCH_YES)
594 : {
595 793 : *end_colon = true;
596 793 : break;
597 : }
598 36848 : if (gfc_match_char (')') == MATCH_YES)
599 : break;
600 10182 : if (gfc_match_char (',') != MATCH_YES)
601 19 : goto syntax;
602 : }
603 :
604 36973 : while (*list)
605 9514 : list = &(*list)->next;
606 :
607 27459 : *list = head;
608 27459 : if (headp)
609 21590 : *headp = list;
610 : return MATCH_YES;
611 :
612 48 : syntax:
613 48 : gfc_error ("Syntax error in OpenMP variable list at %C");
614 :
615 64 : cleanup:
616 64 : gfc_free_omp_namelist (head, OMP_LIST_NONE);
617 64 : gfc_current_locus = old_loc;
618 64 : return MATCH_ERROR;
619 : }
620 :
621 : /* Match a variable/procedure/common block list and construct a namelist
622 : from it. */
623 :
624 : static match
625 362 : gfc_match_omp_to_link (const char *str, gfc_omp_namelist **list)
626 : {
627 362 : gfc_omp_namelist *head, *tail, *p;
628 362 : locus old_loc, cur_loc;
629 362 : char n[GFC_MAX_SYMBOL_LEN+1];
630 362 : gfc_symbol *sym;
631 362 : match m;
632 362 : gfc_symtree *st;
633 :
634 362 : head = tail = NULL;
635 :
636 362 : old_loc = gfc_current_locus;
637 :
638 362 : m = gfc_match (str);
639 362 : if (m != MATCH_YES)
640 : return m;
641 :
642 548 : for (;;)
643 : {
644 548 : cur_loc = gfc_current_locus;
645 548 : m = gfc_match_symbol (&sym, 1);
646 548 : switch (m)
647 : {
648 507 : case MATCH_YES:
649 507 : p = gfc_get_omp_namelist ();
650 507 : if (head == NULL)
651 : head = tail = p;
652 : else
653 : {
654 194 : tail->next = p;
655 194 : tail = tail->next;
656 : }
657 507 : tail->sym = sym;
658 507 : tail->where = cur_loc;
659 507 : goto next_item;
660 : case MATCH_NO:
661 : break;
662 0 : case MATCH_ERROR:
663 0 : goto cleanup;
664 : }
665 :
666 41 : m = gfc_match (" / %n /", n);
667 41 : if (m == MATCH_ERROR)
668 0 : goto cleanup;
669 41 : if (m == MATCH_NO)
670 0 : goto syntax;
671 :
672 41 : st = gfc_find_symtree (gfc_current_ns->common_root, n);
673 41 : if (st == NULL)
674 : {
675 0 : gfc_error ("COMMON block /%s/ not found at %C", n);
676 0 : goto cleanup;
677 : }
678 41 : p = gfc_get_omp_namelist ();
679 41 : if (head == NULL)
680 : head = tail = p;
681 : else
682 : {
683 4 : tail->next = p;
684 4 : tail = tail->next;
685 : }
686 41 : tail->u.common = st->n.common;
687 41 : tail->where = cur_loc;
688 :
689 548 : next_item:
690 548 : if (gfc_match_char (')') == MATCH_YES)
691 : break;
692 198 : if (gfc_match_char (',') != MATCH_YES)
693 0 : goto syntax;
694 : }
695 :
696 361 : while (*list)
697 11 : list = &(*list)->next;
698 :
699 350 : *list = head;
700 350 : return MATCH_YES;
701 :
702 0 : syntax:
703 0 : gfc_error ("Syntax error in OpenMP variable list at %C");
704 :
705 0 : cleanup:
706 0 : gfc_free_omp_namelist (head, OMP_LIST_NONE);
707 0 : gfc_current_locus = old_loc;
708 0 : return MATCH_ERROR;
709 : }
710 :
711 : /* Match detach(event-handle). */
712 :
713 : static match
714 126 : gfc_match_omp_detach (gfc_expr **expr)
715 : {
716 126 : locus old_loc = gfc_current_locus;
717 :
718 126 : if (gfc_match ("detach ( ") != MATCH_YES)
719 0 : goto syntax_error;
720 :
721 126 : if (gfc_match_variable (expr, 0) != MATCH_YES)
722 0 : goto syntax_error;
723 :
724 126 : if (gfc_match_char (')') != MATCH_YES)
725 0 : goto syntax_error;
726 :
727 : return MATCH_YES;
728 :
729 0 : syntax_error:
730 0 : gfc_error ("Syntax error in OpenMP detach clause at %C");
731 0 : gfc_current_locus = old_loc;
732 0 : return MATCH_ERROR;
733 :
734 : }
735 :
736 : /* Match doacross(sink : ...) construct a namelist from it;
737 : if depend is true, match legacy 'depend(sink : ...)'. */
738 :
739 : static match
740 241 : gfc_match_omp_doacross_sink (gfc_omp_namelist **list, bool depend)
741 : {
742 241 : char n[GFC_MAX_SYMBOL_LEN+1];
743 241 : gfc_omp_namelist *head, *tail, *p;
744 241 : locus old_loc, cur_loc;
745 241 : gfc_symbol *sym;
746 :
747 241 : head = tail = NULL;
748 :
749 241 : old_loc = gfc_current_locus;
750 :
751 2231 : for (;;)
752 : {
753 1236 : gfc_gobble_whitespace ();
754 1236 : cur_loc = gfc_current_locus;
755 :
756 1236 : if (gfc_match_name (n) != MATCH_YES)
757 1 : goto syntax;
758 1235 : locus loc = gfc_get_location_range (NULL, 0, &cur_loc, 1,
759 : &gfc_current_locus);
760 1235 : if (UNLIKELY (strcmp (n, "omp_all_memory") == 0))
761 : {
762 1 : gfc_error ("%<omp_all_memory%> used with dependence-type "
763 : "other than OUT or INOUT at %L", &loc);
764 1 : goto cleanup;
765 : }
766 1234 : sym = NULL;
767 1234 : if (!(strcmp (n, "omp_cur_iteration") == 0))
768 : {
769 1229 : gfc_symtree *st;
770 1229 : if (gfc_get_ha_sym_tree (n, &st))
771 0 : goto syntax;
772 1229 : sym = st->n.sym;
773 1229 : gfc_set_sym_referenced (sym);
774 : }
775 1234 : p = gfc_get_omp_namelist ();
776 1234 : if (head == NULL)
777 : {
778 239 : head = tail = p;
779 253 : head->u.depend_doacross_op = (depend ? OMP_DEPEND_SINK_FIRST
780 : : OMP_DOACROSS_SINK_FIRST);
781 : }
782 : else
783 : {
784 995 : tail->next = p;
785 995 : tail = tail->next;
786 995 : tail->u.depend_doacross_op = OMP_DOACROSS_SINK;
787 : }
788 1234 : tail->sym = sym;
789 1234 : tail->expr = NULL;
790 1234 : tail->where = loc;
791 1234 : if (gfc_match_char ('+') == MATCH_YES)
792 : {
793 154 : if (gfc_match_literal_constant (&tail->expr, 0) != MATCH_YES)
794 0 : goto syntax;
795 : }
796 1080 : else if (gfc_match_char ('-') == MATCH_YES)
797 : {
798 418 : if (gfc_match_literal_constant (&tail->expr, 0) != MATCH_YES)
799 1 : goto syntax;
800 417 : tail->expr = gfc_uminus (tail->expr);
801 : }
802 1233 : if (gfc_match_char (')') == MATCH_YES)
803 : break;
804 995 : if (gfc_match_char (',') != MATCH_YES)
805 0 : goto syntax;
806 995 : }
807 :
808 1030 : while (*list)
809 792 : list = &(*list)->next;
810 :
811 238 : *list = head;
812 238 : return MATCH_YES;
813 :
814 2 : syntax:
815 2 : gfc_error ("Syntax error in OpenMP SINK dependence-type list at %C");
816 :
817 3 : cleanup:
818 3 : gfc_free_omp_namelist (head, OMP_LIST_DEPEND);
819 3 : gfc_current_locus = old_loc;
820 3 : return MATCH_ERROR;
821 : }
822 :
823 : static match
824 819 : match_omp_oacc_expr_list (const char *str, gfc_expr_list **list,
825 : bool allow_asterisk, bool is_omp)
826 : {
827 819 : gfc_expr_list *head, *tail, *p;
828 819 : locus old_loc;
829 819 : gfc_expr *expr;
830 819 : match m;
831 :
832 819 : head = tail = NULL;
833 :
834 819 : old_loc = gfc_current_locus;
835 :
836 819 : m = gfc_match (str);
837 819 : if (m != MATCH_YES)
838 : return m;
839 :
840 1030 : for (;;)
841 : {
842 1030 : m = gfc_match_expr (&expr);
843 1030 : if (m == MATCH_YES || allow_asterisk)
844 : {
845 1018 : p = gfc_get_expr_list ();
846 1018 : if (head == NULL)
847 : head = tail = p;
848 : else
849 : {
850 335 : tail->next = p;
851 335 : tail = tail->next;
852 : }
853 1018 : if (m == MATCH_YES)
854 885 : tail->expr = expr;
855 133 : else if (gfc_match (" *") != MATCH_YES)
856 18 : goto syntax;
857 1000 : goto next_item;
858 : }
859 12 : if (m == MATCH_ERROR)
860 0 : goto cleanup;
861 12 : goto syntax;
862 :
863 1000 : next_item:
864 1000 : if (gfc_match_char (')') == MATCH_YES)
865 : break;
866 346 : if (gfc_match_char (',') != MATCH_YES)
867 6 : goto syntax;
868 : }
869 :
870 660 : while (*list)
871 6 : list = &(*list)->next;
872 :
873 654 : *list = head;
874 654 : return MATCH_YES;
875 :
876 36 : syntax:
877 36 : if (is_omp)
878 7 : gfc_error ("Syntax error in OpenMP expression list at %C");
879 : else
880 29 : gfc_error ("Syntax error in OpenACC expression list at %C");
881 :
882 36 : cleanup:
883 36 : gfc_free_expr_list (head);
884 36 : gfc_current_locus = old_loc;
885 36 : return MATCH_ERROR;
886 : }
887 :
888 : static match
889 3056 : match_oacc_clause_gwv (gfc_omp_clauses *cp, unsigned gwv)
890 : {
891 3056 : match ret = MATCH_YES;
892 :
893 3056 : if (gfc_match (" ( ") != MATCH_YES)
894 : return MATCH_NO;
895 :
896 470 : if (gwv == GOMP_DIM_GANG)
897 : {
898 : /* The gang clause accepts two optional arguments, num and static.
899 : The num argument may either be explicit (num: <val>) or
900 : implicit without (<val> without num:). */
901 :
902 457 : while (ret == MATCH_YES)
903 : {
904 236 : if (gfc_match (" static :") == MATCH_YES)
905 : {
906 114 : if (cp->gang_static)
907 : return MATCH_ERROR;
908 : else
909 113 : cp->gang_static = true;
910 113 : if (gfc_match_char ('*') == MATCH_YES)
911 18 : cp->gang_static_expr = NULL;
912 95 : else if (gfc_match (" %e ", &cp->gang_static_expr) != MATCH_YES)
913 : return MATCH_ERROR;
914 : }
915 : else
916 : {
917 122 : if (cp->gang_num_expr)
918 : return MATCH_ERROR;
919 :
920 : /* The 'num' argument is optional. */
921 121 : gfc_match (" num :");
922 :
923 121 : if (gfc_match (" %e ", &cp->gang_num_expr) != MATCH_YES)
924 : return MATCH_ERROR;
925 : }
926 :
927 231 : ret = gfc_match (" , ");
928 : }
929 : }
930 244 : else if (gwv == GOMP_DIM_WORKER)
931 : {
932 : /* The 'num' argument is optional. */
933 107 : gfc_match (" num :");
934 :
935 107 : if (gfc_match (" %e ", &cp->worker_expr) != MATCH_YES)
936 : return MATCH_ERROR;
937 : }
938 137 : else if (gwv == GOMP_DIM_VECTOR)
939 : {
940 : /* The 'length' argument is optional. */
941 137 : gfc_match (" length :");
942 :
943 137 : if (gfc_match (" %e ", &cp->vector_expr) != MATCH_YES)
944 : return MATCH_ERROR;
945 : }
946 : else
947 0 : gfc_fatal_error ("Unexpected OpenACC parallelism.");
948 :
949 459 : return gfc_match (" )");
950 : }
951 :
952 : static match
953 8 : gfc_match_oacc_clause_link (const char *str, gfc_omp_namelist **list)
954 : {
955 8 : gfc_omp_namelist *head = NULL;
956 8 : gfc_omp_namelist *tail, *p;
957 8 : locus old_loc;
958 8 : char n[GFC_MAX_SYMBOL_LEN+1];
959 8 : gfc_symbol *sym;
960 8 : match m;
961 8 : gfc_symtree *st;
962 :
963 8 : old_loc = gfc_current_locus;
964 :
965 8 : m = gfc_match (str);
966 8 : if (m != MATCH_YES)
967 : return m;
968 :
969 8 : m = gfc_match (" (");
970 :
971 14 : for (;;)
972 : {
973 14 : m = gfc_match_symbol (&sym, 0);
974 14 : switch (m)
975 : {
976 8 : case MATCH_YES:
977 8 : if (sym->attr.in_common)
978 : {
979 2 : gfc_error_now ("Variable at %C is an element of a COMMON block");
980 2 : goto cleanup;
981 : }
982 6 : gfc_set_sym_referenced (sym);
983 6 : p = gfc_get_omp_namelist ();
984 6 : if (head == NULL)
985 : head = tail = p;
986 : else
987 : {
988 4 : tail->next = p;
989 4 : tail = tail->next;
990 : }
991 6 : tail->sym = sym;
992 6 : tail->expr = NULL;
993 6 : tail->where = gfc_current_locus;
994 6 : goto next_item;
995 : case MATCH_NO:
996 : break;
997 :
998 0 : case MATCH_ERROR:
999 0 : goto cleanup;
1000 : }
1001 :
1002 6 : m = gfc_match (" / %n /", n);
1003 6 : if (m == MATCH_ERROR)
1004 0 : goto cleanup;
1005 6 : if (m == MATCH_NO || n[0] == '\0')
1006 0 : goto syntax;
1007 :
1008 6 : st = gfc_find_symtree (gfc_current_ns->common_root, n);
1009 6 : if (st == NULL)
1010 : {
1011 1 : gfc_error ("COMMON block /%s/ not found at %C", n);
1012 1 : goto cleanup;
1013 : }
1014 :
1015 20 : for (sym = st->n.common->head; sym; sym = sym->common_next)
1016 : {
1017 15 : gfc_set_sym_referenced (sym);
1018 15 : p = gfc_get_omp_namelist ();
1019 15 : if (head == NULL)
1020 : head = tail = p;
1021 : else
1022 : {
1023 12 : tail->next = p;
1024 12 : tail = tail->next;
1025 : }
1026 15 : tail->sym = sym;
1027 15 : tail->where = gfc_current_locus;
1028 : }
1029 :
1030 5 : next_item:
1031 11 : if (gfc_match_char (')') == MATCH_YES)
1032 : break;
1033 6 : if (gfc_match_char (',') != MATCH_YES)
1034 0 : goto syntax;
1035 : }
1036 :
1037 5 : if (gfc_match_omp_eos () != MATCH_YES)
1038 : {
1039 1 : gfc_error ("Unexpected junk after !$ACC DECLARE at %C");
1040 1 : goto cleanup;
1041 : }
1042 :
1043 4 : while (*list)
1044 0 : list = &(*list)->next;
1045 4 : *list = head;
1046 4 : return MATCH_YES;
1047 :
1048 0 : syntax:
1049 0 : gfc_error ("Syntax error in !$ACC DECLARE list at %C");
1050 :
1051 4 : cleanup:
1052 4 : gfc_current_locus = old_loc;
1053 4 : return MATCH_ERROR;
1054 : }
1055 :
1056 : /* OpenMP clauses. */
1057 : enum omp_mask1
1058 : {
1059 : OMP_CLAUSE_PRIVATE,
1060 : OMP_CLAUSE_FIRSTPRIVATE,
1061 : OMP_CLAUSE_LASTPRIVATE,
1062 : OMP_CLAUSE_COPYPRIVATE,
1063 : OMP_CLAUSE_SHARED,
1064 : OMP_CLAUSE_COPYIN,
1065 : OMP_CLAUSE_REDUCTION,
1066 : OMP_CLAUSE_IN_REDUCTION,
1067 : OMP_CLAUSE_TASK_REDUCTION,
1068 : OMP_CLAUSE_IF,
1069 : OMP_CLAUSE_NUM_THREADS,
1070 : OMP_CLAUSE_SCHEDULE,
1071 : OMP_CLAUSE_DEFAULT,
1072 : OMP_CLAUSE_ORDER,
1073 : OMP_CLAUSE_ORDERED,
1074 : OMP_CLAUSE_COLLAPSE,
1075 : OMP_CLAUSE_UNTIED,
1076 : OMP_CLAUSE_FINAL,
1077 : OMP_CLAUSE_MERGEABLE,
1078 : OMP_CLAUSE_ALIGNED,
1079 : OMP_CLAUSE_DEPEND,
1080 : OMP_CLAUSE_INBRANCH,
1081 : OMP_CLAUSE_LINEAR,
1082 : OMP_CLAUSE_NOTINBRANCH,
1083 : OMP_CLAUSE_PROC_BIND,
1084 : OMP_CLAUSE_SAFELEN,
1085 : OMP_CLAUSE_SIMDLEN,
1086 : OMP_CLAUSE_UNIFORM,
1087 : OMP_CLAUSE_DEVICE,
1088 : OMP_CLAUSE_MAP,
1089 : OMP_CLAUSE_TO,
1090 : OMP_CLAUSE_FROM,
1091 : OMP_CLAUSE_NUM_TEAMS,
1092 : OMP_CLAUSE_THREAD_LIMIT,
1093 : OMP_CLAUSE_DIST_SCHEDULE,
1094 : OMP_CLAUSE_DEFAULTMAP,
1095 : OMP_CLAUSE_GRAINSIZE,
1096 : OMP_CLAUSE_HINT,
1097 : OMP_CLAUSE_IS_DEVICE_PTR,
1098 : OMP_CLAUSE_LINK,
1099 : OMP_CLAUSE_NOGROUP,
1100 : OMP_CLAUSE_NOTEMPORAL,
1101 : OMP_CLAUSE_NUM_TASKS,
1102 : OMP_CLAUSE_PRIORITY,
1103 : OMP_CLAUSE_SIMD,
1104 : OMP_CLAUSE_THREADS,
1105 : OMP_CLAUSE_USE_DEVICE_PTR,
1106 : OMP_CLAUSE_USE_DEVICE_ADDR, /* OpenMP 5.0. */
1107 : OMP_CLAUSE_DEVICE_TYPE, /* OpenMP 5.0. */
1108 : OMP_CLAUSE_ATOMIC, /* OpenMP 5.0. */
1109 : OMP_CLAUSE_CAPTURE, /* OpenMP 5.0. */
1110 : OMP_CLAUSE_MEMORDER, /* OpenMP 5.0. */
1111 : OMP_CLAUSE_DETACH, /* OpenMP 5.0. */
1112 : OMP_CLAUSE_AFFINITY, /* OpenMP 5.0. */
1113 : OMP_CLAUSE_ALLOCATE, /* OpenMP 5.0. */
1114 : OMP_CLAUSE_BIND, /* OpenMP 5.0. */
1115 : OMP_CLAUSE_FILTER, /* OpenMP 5.1. */
1116 : OMP_CLAUSE_AT, /* OpenMP 5.1. */
1117 : OMP_CLAUSE_MESSAGE, /* OpenMP 5.1. */
1118 : OMP_CLAUSE_SEVERITY, /* OpenMP 5.1. */
1119 : OMP_CLAUSE_COMPARE, /* OpenMP 5.1. */
1120 : OMP_CLAUSE_FAIL, /* OpenMP 5.1. */
1121 : OMP_CLAUSE_WEAK, /* OpenMP 5.1. */
1122 : OMP_CLAUSE_NOWAIT,
1123 : /* This must come last. */
1124 : OMP_MASK1_LAST
1125 : };
1126 :
1127 : /* More OpenMP clauses and OpenACC 2.0+ specific clauses. */
1128 : enum omp_mask2
1129 : {
1130 : OMP_CLAUSE_ASYNC,
1131 : OMP_CLAUSE_NUM_GANGS,
1132 : OMP_CLAUSE_NUM_WORKERS,
1133 : OMP_CLAUSE_VECTOR_LENGTH,
1134 : OMP_CLAUSE_COPY,
1135 : OMP_CLAUSE_COPYOUT,
1136 : OMP_CLAUSE_CREATE,
1137 : OMP_CLAUSE_NO_CREATE,
1138 : OMP_CLAUSE_PRESENT,
1139 : OMP_CLAUSE_DEVICEPTR,
1140 : OMP_CLAUSE_GANG,
1141 : OMP_CLAUSE_WORKER,
1142 : OMP_CLAUSE_VECTOR,
1143 : OMP_CLAUSE_SEQ,
1144 : OMP_CLAUSE_INDEPENDENT,
1145 : OMP_CLAUSE_USE_DEVICE,
1146 : OMP_CLAUSE_DEVICE_RESIDENT,
1147 : OMP_CLAUSE_SELF,
1148 : OMP_CLAUSE_HOST,
1149 : OMP_CLAUSE_WAIT,
1150 : OMP_CLAUSE_DELETE,
1151 : OMP_CLAUSE_AUTO,
1152 : OMP_CLAUSE_TILE,
1153 : OMP_CLAUSE_IF_PRESENT,
1154 : OMP_CLAUSE_FINALIZE,
1155 : OMP_CLAUSE_ATTACH,
1156 : OMP_CLAUSE_NOHOST,
1157 : OMP_CLAUSE_HAS_DEVICE_ADDR, /* OpenMP 5.1 */
1158 : OMP_CLAUSE_ENTER, /* OpenMP 5.2 */
1159 : OMP_CLAUSE_DOACROSS, /* OpenMP 5.2 */
1160 : OMP_CLAUSE_ASSUMPTIONS, /* OpenMP 5.1. */
1161 : OMP_CLAUSE_USES_ALLOCATORS, /* OpenMP 5.0 */
1162 : OMP_CLAUSE_INDIRECT, /* OpenMP 5.1 */
1163 : OMP_CLAUSE_FULL, /* OpenMP 5.1. */
1164 : OMP_CLAUSE_PARTIAL, /* OpenMP 5.1. */
1165 : OMP_CLAUSE_SIZES, /* OpenMP 5.1. */
1166 : OMP_CLAUSE_INIT, /* OpenMP 5.1. */
1167 : OMP_CLAUSE_DESTROY, /* OpenMP 5.1. */
1168 : OMP_CLAUSE_USE, /* OpenMP 5.1. */
1169 : OMP_CLAUSE_NOVARIANTS, /* OpenMP 5.1 */
1170 : OMP_CLAUSE_NOCONTEXT, /* OpenMP 5.1 */
1171 : OMP_CLAUSE_INTEROP, /* OpenMP 5.1 */
1172 : OMP_CLAUSE_LOCAL, /* OpenMP 6.0 */
1173 : OMP_CLAUSE_DYN_GROUPPRIVATE, /* OpenMP 6.1 */
1174 : /* This must come last. */
1175 : OMP_MASK2_LAST
1176 : };
1177 :
1178 : struct omp_inv_mask;
1179 :
1180 : /* Customized bitset for up to 128-bits.
1181 : The two enums above provide bit numbers to use, and which of the
1182 : two enums it is determines which of the two mask fields is used.
1183 : Supported operations are defining a mask, like:
1184 : #define XXX_CLAUSES \
1185 : (omp_mask (OMP_CLAUSE_XXX) | OMP_CLAUSE_YYY | OMP_CLAUSE_ZZZ)
1186 : oring such bitsets together or removing selected bits:
1187 : (XXX_CLAUSES | YYY_CLAUSES) & ~(omp_mask (OMP_CLAUSE_VVV))
1188 : and testing individual bits:
1189 : if (mask & OMP_CLAUSE_UUU) */
1190 :
1191 : struct omp_mask {
1192 : const uint64_t mask1;
1193 : const uint64_t mask2;
1194 : inline omp_mask ();
1195 : inline omp_mask (omp_mask1);
1196 : inline omp_mask (omp_mask2);
1197 : inline omp_mask (uint64_t, uint64_t);
1198 : inline omp_mask operator| (omp_mask1) const;
1199 : inline omp_mask operator| (omp_mask2) const;
1200 : inline omp_mask operator| (omp_mask) const;
1201 : inline omp_mask operator& (const omp_inv_mask &) const;
1202 : inline bool operator& (omp_mask1) const;
1203 : inline bool operator& (omp_mask2) const;
1204 : inline omp_inv_mask operator~ () const;
1205 : };
1206 :
1207 : struct omp_inv_mask : public omp_mask {
1208 : inline omp_inv_mask (const omp_mask &);
1209 : };
1210 :
1211 : omp_mask::omp_mask () : mask1 (0), mask2 (0)
1212 : {
1213 : }
1214 :
1215 31919 : omp_mask::omp_mask (omp_mask1 m) : mask1 (((uint64_t) 1) << m), mask2 (0)
1216 : {
1217 : }
1218 :
1219 2205 : omp_mask::omp_mask (omp_mask2 m) : mask1 (0), mask2 (((uint64_t) 1) << m)
1220 : {
1221 : }
1222 :
1223 32827 : omp_mask::omp_mask (uint64_t m1, uint64_t m2) : mask1 (m1), mask2 (m2)
1224 : {
1225 : }
1226 :
1227 : omp_mask
1228 31876 : omp_mask::operator| (omp_mask1 m) const
1229 : {
1230 31876 : return omp_mask (mask1 | (((uint64_t) 1) << m), mask2);
1231 : }
1232 :
1233 : omp_mask
1234 16598 : omp_mask::operator| (omp_mask2 m) const
1235 : {
1236 16598 : return omp_mask (mask1, mask2 | (((uint64_t) 1) << m));
1237 : }
1238 :
1239 : omp_mask
1240 4357 : omp_mask::operator| (omp_mask m) const
1241 : {
1242 4357 : return omp_mask (mask1 | m.mask1, mask2 | m.mask2);
1243 : }
1244 :
1245 : omp_mask
1246 2018 : omp_mask::operator& (const omp_inv_mask &m) const
1247 : {
1248 2018 : return omp_mask (mask1 & ~m.mask1, mask2 & ~m.mask2);
1249 : }
1250 :
1251 : bool
1252 124821 : omp_mask::operator& (omp_mask1 m) const
1253 : {
1254 124821 : return (mask1 & (((uint64_t) 1) << m)) != 0;
1255 : }
1256 :
1257 : bool
1258 88265 : omp_mask::operator& (omp_mask2 m) const
1259 : {
1260 88265 : return (mask2 & (((uint64_t) 1) << m)) != 0;
1261 : }
1262 :
1263 : omp_inv_mask
1264 2018 : omp_mask::operator~ () const
1265 : {
1266 2018 : return omp_inv_mask (*this);
1267 : }
1268 :
1269 2018 : omp_inv_mask::omp_inv_mask (const omp_mask &m) : omp_mask (m)
1270 : {
1271 : }
1272 :
1273 : /* Helper function for OpenACC and OpenMP clauses involving memory
1274 : mapping. */
1275 :
1276 : static bool
1277 5544 : gfc_match_omp_map_clause (gfc_omp_namelist **list, gfc_omp_map_op map_op,
1278 : bool allow_common, bool allow_derived)
1279 : {
1280 5544 : gfc_omp_namelist **head = NULL;
1281 5544 : if (gfc_match_omp_variable_list ("", list, allow_common, NULL, &head, true,
1282 : allow_derived)
1283 : == MATCH_YES)
1284 : {
1285 5535 : gfc_omp_namelist *n;
1286 13409 : for (n = *head; n; n = n->next)
1287 7874 : n->u.map.op = map_op;
1288 : return true;
1289 : }
1290 :
1291 : return false;
1292 : }
1293 :
1294 : static match
1295 1114 : gfc_match_iterator (gfc_namespace **ns, bool permit_var)
1296 : {
1297 1114 : locus old_loc = gfc_current_locus;
1298 :
1299 1114 : if (gfc_match ("iterator ( ") != MATCH_YES)
1300 : return MATCH_NO;
1301 :
1302 80 : gfc_typespec ts;
1303 80 : gfc_symbol *last = NULL;
1304 80 : gfc_expr *begin, *end, *step;
1305 80 : *ns = gfc_build_block_ns (gfc_current_ns);
1306 86 : char name[GFC_MAX_SYMBOL_LEN + 1];
1307 92 : while (true)
1308 : {
1309 86 : locus prev_loc = gfc_current_locus;
1310 86 : if (gfc_match_type_spec (&ts) == MATCH_YES
1311 86 : && gfc_match (" :: ") == MATCH_YES)
1312 : {
1313 5 : if (ts.type != BT_INTEGER)
1314 : {
1315 2 : gfc_error ("Expected INTEGER type at %L", &prev_loc);
1316 5 : return MATCH_ERROR;
1317 : }
1318 : permit_var = false;
1319 : }
1320 : else
1321 : {
1322 81 : ts.type = BT_INTEGER;
1323 81 : ts.kind = gfc_default_integer_kind;
1324 81 : gfc_current_locus = prev_loc;
1325 : }
1326 84 : prev_loc = gfc_current_locus;
1327 84 : if (gfc_match_name (name) != MATCH_YES)
1328 : {
1329 4 : gfc_error ("Expected identifier at %C");
1330 4 : goto failed;
1331 : }
1332 80 : if (gfc_find_symtree ((*ns)->sym_root, name))
1333 : {
1334 2 : gfc_error ("Same identifier %qs specified again at %C", name);
1335 2 : goto failed;
1336 : }
1337 :
1338 78 : gfc_symbol *sym = gfc_new_symbol (name, *ns);
1339 78 : if (last)
1340 4 : last->tlink = sym;
1341 : else
1342 74 : (*ns)->omp_affinity_iterators = sym;
1343 78 : last = sym;
1344 78 : sym->declared_at = prev_loc;
1345 78 : sym->ts = ts;
1346 78 : sym->attr.flavor = FL_VARIABLE;
1347 78 : sym->attr.artificial = 1;
1348 78 : sym->attr.referenced = 1;
1349 78 : sym->refs++;
1350 78 : gfc_symtree *st = gfc_new_symtree (&(*ns)->sym_root, name);
1351 78 : st->n.sym = sym;
1352 :
1353 78 : prev_loc = gfc_current_locus;
1354 78 : if (gfc_match (" = ") != MATCH_YES)
1355 3 : goto failed;
1356 75 : permit_var = false;
1357 75 : begin = end = step = NULL;
1358 75 : if (gfc_match ("%e : ", &begin) != MATCH_YES
1359 75 : || gfc_match ("%e ", &end) != MATCH_YES)
1360 : {
1361 3 : gfc_error ("Expected range-specification at %C");
1362 3 : gfc_free_expr (begin);
1363 3 : gfc_free_expr (end);
1364 3 : return MATCH_ERROR;
1365 : }
1366 72 : if (':' == gfc_peek_ascii_char ())
1367 : {
1368 23 : if (gfc_match (": %e ", &step) != MATCH_YES)
1369 : {
1370 5 : gfc_free_expr (begin);
1371 5 : gfc_free_expr (end);
1372 5 : gfc_free_expr (step);
1373 5 : goto failed;
1374 : }
1375 : }
1376 :
1377 67 : gfc_expr *e = gfc_get_expr ();
1378 67 : e->where = prev_loc;
1379 67 : e->expr_type = EXPR_ARRAY;
1380 67 : e->ts = ts;
1381 67 : e->rank = 1;
1382 67 : e->shape = gfc_get_shape (1);
1383 116 : mpz_init_set_ui (e->shape[0], step ? 3 : 2);
1384 67 : gfc_constructor_append_expr (&e->value.constructor, begin, &begin->where);
1385 67 : gfc_constructor_append_expr (&e->value.constructor, end, &end->where);
1386 67 : if (step)
1387 18 : gfc_constructor_append_expr (&e->value.constructor, step, &step->where);
1388 67 : sym->value = e;
1389 :
1390 67 : if (gfc_match (") ") == MATCH_YES)
1391 : break;
1392 6 : if (gfc_match (", ") != MATCH_YES)
1393 0 : goto failed;
1394 6 : }
1395 61 : return MATCH_YES;
1396 :
1397 14 : failed:
1398 14 : gfc_namespace *prev_ns = NULL;
1399 14 : for (gfc_namespace *it = gfc_current_ns->contained; it; it = it->sibling)
1400 : {
1401 0 : if (it == *ns)
1402 : {
1403 0 : if (prev_ns)
1404 0 : prev_ns->sibling = it->sibling;
1405 : else
1406 0 : gfc_current_ns->contained = it->sibling;
1407 0 : gfc_free_namespace (it);
1408 0 : break;
1409 : }
1410 0 : prev_ns = it;
1411 : }
1412 14 : *ns = NULL;
1413 14 : if (!permit_var)
1414 : return MATCH_ERROR;
1415 4 : gfc_current_locus = old_loc;
1416 4 : return MATCH_NO;
1417 : }
1418 :
1419 : /* Match target update's to/from( [present:] var-list). */
1420 :
1421 : static match
1422 1715 : gfc_match_motion_var_list (const char *str, gfc_omp_namelist **list,
1423 : gfc_omp_namelist ***headp)
1424 : {
1425 1715 : match m = gfc_match (str);
1426 1715 : if (m != MATCH_YES)
1427 : return m;
1428 :
1429 1715 : match m_present = gfc_match (" present : ");
1430 :
1431 1715 : m = gfc_match_omp_variable_list ("", list, false, NULL, headp, true, true);
1432 1715 : if (m != MATCH_YES)
1433 : return m;
1434 1715 : if (m_present == MATCH_YES)
1435 : {
1436 5 : gfc_omp_namelist *n;
1437 10 : for (n = **headp; n; n = n->next)
1438 5 : n->u.present_modifier = true;
1439 : }
1440 : return MATCH_YES;
1441 : }
1442 :
1443 : /* reduction ( reduction-modifier, reduction-operator : variable-list )
1444 : in_reduction ( reduction-operator : variable-list )
1445 : task_reduction ( reduction-operator : variable-list ) */
1446 :
1447 : static match
1448 4357 : gfc_match_omp_clause_reduction (char pc, gfc_omp_clauses *c, bool openacc,
1449 : bool allow_derived, bool openmp_target = false)
1450 : {
1451 4357 : if (pc == 'r' && gfc_match ("reduction ( ") != MATCH_YES)
1452 : return MATCH_NO;
1453 4357 : else if (pc == 'i' && gfc_match ("in_reduction ( ") != MATCH_YES)
1454 : return MATCH_NO;
1455 4245 : else if (pc == 't' && gfc_match ("task_reduction ( ") != MATCH_YES)
1456 : return MATCH_NO;
1457 :
1458 4245 : locus old_loc = gfc_current_locus;
1459 4245 : enum gfc_omp_list_type list_idx = OMP_LIST_NONE;
1460 :
1461 4245 : if (pc == 'r' && !openacc)
1462 : {
1463 2118 : if (gfc_match ("inscan") == MATCH_YES)
1464 : list_idx = OMP_LIST_REDUCTION_INSCAN;
1465 2048 : else if (gfc_match ("task") == MATCH_YES)
1466 : list_idx = OMP_LIST_REDUCTION_TASK;
1467 1943 : else if (gfc_match ("default") == MATCH_YES)
1468 : list_idx = OMP_LIST_REDUCTION;
1469 231 : if (list_idx != OMP_LIST_NONE && gfc_match (", ") != MATCH_YES)
1470 : {
1471 1 : gfc_error ("Comma expected at %C");
1472 1 : gfc_current_locus = old_loc;
1473 1 : return MATCH_NO;
1474 : }
1475 2117 : if (list_idx == OMP_LIST_NONE)
1476 3831 : list_idx = OMP_LIST_REDUCTION;
1477 : }
1478 2127 : else if (pc == 'i')
1479 : list_idx = OMP_LIST_IN_REDUCTION;
1480 2009 : else if (pc == 't')
1481 : list_idx = OMP_LIST_TASK_REDUCTION;
1482 : else
1483 3831 : list_idx = OMP_LIST_REDUCTION;
1484 :
1485 4244 : gfc_omp_reduction_op rop = OMP_REDUCTION_NONE;
1486 4244 : char buffer[GFC_MAX_SYMBOL_LEN + 3];
1487 4244 : if (gfc_match_char ('+') == MATCH_YES)
1488 : rop = OMP_REDUCTION_PLUS;
1489 2223 : else if (gfc_match_char ('*') == MATCH_YES)
1490 : rop = OMP_REDUCTION_TIMES;
1491 1991 : else if (gfc_match_char ('-') == MATCH_YES)
1492 : {
1493 171 : if (!openacc)
1494 16 : gfc_warning (OPT_Wdeprecated_openmp,
1495 : "%<-%> operator at %C for reductions deprecated in "
1496 : "OpenMP 5.2");
1497 : rop = OMP_REDUCTION_MINUS;
1498 : }
1499 1820 : else if (gfc_match (".and.") == MATCH_YES)
1500 : rop = OMP_REDUCTION_AND;
1501 1714 : else if (gfc_match (".or.") == MATCH_YES)
1502 : rop = OMP_REDUCTION_OR;
1503 929 : else if (gfc_match (".eqv.") == MATCH_YES)
1504 : rop = OMP_REDUCTION_EQV;
1505 831 : else if (gfc_match (".neqv.") == MATCH_YES)
1506 : rop = OMP_REDUCTION_NEQV;
1507 736 : if (rop != OMP_REDUCTION_NONE)
1508 3508 : snprintf (buffer, sizeof buffer, "operator %s",
1509 : gfc_op2string ((gfc_intrinsic_op) rop));
1510 736 : else if (gfc_match_defined_op_name (buffer + 1, 1) == MATCH_YES)
1511 : {
1512 38 : buffer[0] = '.';
1513 38 : strcat (buffer, ".");
1514 : }
1515 698 : else if (gfc_match_name (buffer) == MATCH_YES)
1516 : {
1517 697 : gfc_symbol *sym;
1518 697 : const char *n = buffer;
1519 :
1520 697 : gfc_find_symbol (buffer, NULL, 1, &sym);
1521 697 : if (sym != NULL)
1522 : {
1523 216 : if (sym->attr.intrinsic)
1524 139 : n = sym->name;
1525 77 : else if ((sym->attr.flavor != FL_UNKNOWN
1526 75 : && sym->attr.flavor != FL_PROCEDURE)
1527 75 : || sym->attr.external
1528 64 : || sym->attr.generic
1529 64 : || sym->attr.entry
1530 64 : || sym->attr.result
1531 64 : || sym->attr.dummy
1532 64 : || sym->attr.subroutine
1533 63 : || sym->attr.pointer
1534 63 : || sym->attr.target
1535 63 : || sym->attr.cray_pointer
1536 63 : || sym->attr.cray_pointee
1537 63 : || (sym->attr.proc != PROC_UNKNOWN
1538 1 : && sym->attr.proc != PROC_INTRINSIC)
1539 62 : || sym->attr.if_source != IFSRC_UNKNOWN
1540 62 : || sym == sym->ns->proc_name)
1541 : {
1542 : sym = NULL;
1543 : n = NULL;
1544 : }
1545 : else
1546 62 : n = sym->name;
1547 : }
1548 201 : if (n == NULL)
1549 : rop = OMP_REDUCTION_NONE;
1550 682 : else if (strcmp (n, "max") == 0)
1551 : rop = OMP_REDUCTION_MAX;
1552 517 : else if (strcmp (n, "min") == 0)
1553 : rop = OMP_REDUCTION_MIN;
1554 376 : else if (strcmp (n, "iand") == 0)
1555 : rop = OMP_REDUCTION_IAND;
1556 321 : else if (strcmp (n, "ior") == 0)
1557 : rop = OMP_REDUCTION_IOR;
1558 255 : else if (strcmp (n, "ieor") == 0)
1559 : rop = OMP_REDUCTION_IEOR;
1560 : if (rop != OMP_REDUCTION_NONE
1561 477 : && sym != NULL
1562 200 : && ! sym->attr.intrinsic
1563 61 : && ! sym->attr.use_assoc
1564 61 : && ((sym->attr.flavor == FL_UNKNOWN
1565 2 : && !gfc_add_flavor (&sym->attr, FL_PROCEDURE,
1566 : sym->name, NULL))
1567 61 : || !gfc_add_intrinsic (&sym->attr, NULL)))
1568 : rop = OMP_REDUCTION_NONE;
1569 : }
1570 : else
1571 1 : buffer[0] = '\0';
1572 4244 : gfc_omp_udr *udr = (buffer[0] ? gfc_find_omp_udr (gfc_current_ns, buffer, NULL)
1573 : : NULL);
1574 4244 : gfc_omp_namelist **head = NULL;
1575 4244 : if (rop == OMP_REDUCTION_NONE && udr)
1576 250 : rop = OMP_REDUCTION_USER;
1577 :
1578 4244 : if (gfc_match_omp_variable_list (" :", &c->lists[list_idx], false, NULL,
1579 : &head, openacc, allow_derived) != MATCH_YES)
1580 : {
1581 9 : gfc_current_locus = old_loc;
1582 9 : return MATCH_NO;
1583 : }
1584 4235 : gfc_omp_namelist *n;
1585 4235 : if (rop == OMP_REDUCTION_NONE)
1586 : {
1587 6 : n = *head;
1588 6 : *head = NULL;
1589 6 : gfc_error_now ("!$OMP DECLARE REDUCTION %s not found at %L",
1590 : buffer, &old_loc);
1591 6 : gfc_free_omp_namelist (n, OMP_LIST_NONE);
1592 : }
1593 : else
1594 9110 : for (n = *head; n; n = n->next)
1595 : {
1596 4881 : n->u.reduction_op = rop;
1597 4881 : if (udr)
1598 : {
1599 473 : n->u2.udr = gfc_get_omp_namelist_udr ();
1600 473 : n->u2.udr->udr = udr;
1601 : }
1602 4881 : if (openmp_target && list_idx == OMP_LIST_IN_REDUCTION)
1603 : {
1604 40 : gfc_omp_namelist *p = gfc_get_omp_namelist (), **tl;
1605 40 : p->sym = n->sym;
1606 40 : p->where = n->where;
1607 40 : p->u.map.op = OMP_MAP_ALWAYS_TOFROM;
1608 :
1609 40 : tl = &c->lists[OMP_LIST_MAP];
1610 52 : while (*tl)
1611 12 : tl = &((*tl)->next);
1612 40 : *tl = p;
1613 40 : p->next = NULL;
1614 : }
1615 : }
1616 : return MATCH_YES;
1617 : }
1618 :
1619 : static match
1620 39 : gfc_omp_absent_contains_clause (gfc_omp_assumptions **assume, bool is_absent)
1621 : {
1622 39 : if (*assume == NULL)
1623 14 : *assume = gfc_get_omp_assumptions ();
1624 61 : do
1625 : {
1626 50 : gfc_statement st = ST_NONE;
1627 50 : gfc_gobble_whitespace ();
1628 50 : locus old_loc = gfc_current_locus;
1629 50 : char c = gfc_peek_ascii_char ();
1630 50 : enum gfc_omp_directive_kind kind
1631 : = GFC_OMP_DIR_DECLARATIVE; /* Silence warning. */
1632 1524 : for (size_t i = 0; i < ARRAY_SIZE (gfc_omp_directives); i++)
1633 : {
1634 1524 : if (gfc_omp_directives[i].name[0] > c)
1635 : break;
1636 1474 : if (gfc_omp_directives[i].name[0] != c)
1637 1135 : continue;
1638 339 : if (gfc_match (gfc_omp_directives[i].name) == MATCH_YES)
1639 : {
1640 50 : st = gfc_omp_directives[i].st;
1641 50 : kind = gfc_omp_directives[i].kind;
1642 : }
1643 : }
1644 50 : gfc_gobble_whitespace ();
1645 50 : c = gfc_peek_ascii_char ();
1646 50 : if (st == ST_NONE || (c != ',' && c != ')'))
1647 : {
1648 0 : if (st == ST_NONE)
1649 0 : gfc_error ("Unknown directive at %L", &old_loc);
1650 : else
1651 0 : gfc_error ("Invalid combined or composite directive at %L",
1652 : &old_loc);
1653 3 : return MATCH_ERROR;
1654 : }
1655 50 : if (kind == GFC_OMP_DIR_DECLARATIVE
1656 50 : || kind == GFC_OMP_DIR_INFORMATIONAL
1657 : || kind == GFC_OMP_DIR_META)
1658 : {
1659 3 : gfc_error ("Invalid %qs directive at %L in %s clause: declarative, "
1660 : "informational, and meta directives not permitted",
1661 : gfc_ascii_statement (st, true), &old_loc,
1662 : is_absent ? "ABSENT" : "CONTAINS");
1663 3 : return MATCH_ERROR;
1664 : }
1665 47 : if (is_absent)
1666 : {
1667 : /* Use exponential allocation; equivalent to pow2p(x). */
1668 33 : int i = (*assume)->n_absent;
1669 33 : int size = ((i == 0) ? 4
1670 10 : : pow2p_hwi (i) == 1 ? i*2 : 0);
1671 8 : if (size != 0)
1672 31 : (*assume)->absent = XRESIZEVEC (gfc_statement,
1673 : (*assume)->absent, size);
1674 33 : (*assume)->absent[(*assume)->n_absent++] = st;
1675 : }
1676 : else
1677 : {
1678 14 : int i = (*assume)->n_contains;
1679 14 : int size = ((i == 0) ? 4
1680 4 : : pow2p_hwi (i) == 1 ? i*2 : 0);
1681 4 : if (size != 0)
1682 14 : (*assume)->contains = XRESIZEVEC (gfc_statement,
1683 : (*assume)->contains, size);
1684 14 : (*assume)->contains[(*assume)->n_contains++] = st;
1685 : }
1686 47 : gfc_gobble_whitespace ();
1687 47 : if (gfc_match(",") == MATCH_YES)
1688 11 : continue;
1689 36 : if (gfc_match(")") == MATCH_YES)
1690 : break;
1691 0 : gfc_error ("Expected %<,%> or %<)%> at %C");
1692 0 : return MATCH_ERROR;
1693 : }
1694 : while (true);
1695 :
1696 36 : return MATCH_YES;
1697 : }
1698 :
1699 : /* Check 'check' argument for duplicated statements in absent and/or contains
1700 : clauses. If 'merge', merge them from check to 'merge'. */
1701 :
1702 : static match
1703 43 : omp_verify_merge_absent_contains (gfc_statement st, gfc_omp_assumptions *check,
1704 : gfc_omp_assumptions *merge, locus *loc)
1705 : {
1706 43 : if (check == NULL)
1707 : return MATCH_YES;
1708 43 : bitmap_head absent_head, contains_head;
1709 43 : bitmap_obstack_initialize (NULL);
1710 43 : bitmap_initialize (&absent_head, &bitmap_default_obstack);
1711 43 : bitmap_initialize (&contains_head, &bitmap_default_obstack);
1712 :
1713 43 : match m = MATCH_YES;
1714 76 : for (int i = 0; i < check->n_absent; i++)
1715 33 : if (!bitmap_set_bit (&absent_head, check->absent[i]))
1716 : {
1717 2 : gfc_error ("%qs directive mentioned multiple times in %s clause in %s "
1718 : "directive at %L",
1719 2 : gfc_ascii_statement (check->absent[i], true),
1720 : "ABSENT", gfc_ascii_statement (st), loc);
1721 2 : m = MATCH_ERROR;
1722 : }
1723 57 : for (int i = 0; i < check->n_contains; i++)
1724 : {
1725 14 : if (!bitmap_set_bit (&contains_head, check->contains[i]))
1726 : {
1727 2 : gfc_error ("%qs directive mentioned multiple times in %s clause in %s "
1728 : "directive at %L",
1729 2 : gfc_ascii_statement (check->contains[i], true),
1730 : "CONTAINS", gfc_ascii_statement (st), loc);
1731 2 : m = MATCH_ERROR;
1732 : }
1733 14 : if (bitmap_bit_p (&absent_head, check->contains[i]))
1734 : {
1735 2 : gfc_error ("%qs directive mentioned both times in ABSENT and CONTAINS "
1736 : "clauses in %s directive at %L",
1737 2 : gfc_ascii_statement (check->absent[i], true),
1738 : gfc_ascii_statement (st), loc);
1739 2 : m = MATCH_ERROR;
1740 : }
1741 : }
1742 :
1743 43 : if (m == MATCH_ERROR)
1744 : return MATCH_ERROR;
1745 37 : if (merge == NULL)
1746 : return MATCH_YES;
1747 2 : if (merge->absent == NULL && check->absent)
1748 : {
1749 1 : merge->n_absent = check->n_absent;
1750 1 : merge->absent = check->absent;
1751 1 : check->absent = NULL;
1752 : }
1753 1 : else if (merge->absent && check->absent)
1754 : {
1755 0 : check->absent = XRESIZEVEC (gfc_statement, check->absent,
1756 : merge->n_absent + check->n_absent);
1757 0 : for (int i = 0; i < merge->n_absent; i++)
1758 0 : if (!bitmap_bit_p (&absent_head, merge->absent[i]))
1759 0 : check->absent[check->n_absent++] = merge->absent[i];
1760 0 : free (merge->absent);
1761 0 : merge->absent = check->absent;
1762 0 : merge->n_absent = check->n_absent;
1763 0 : check->absent = NULL;
1764 : }
1765 2 : if (merge->contains == NULL && check->contains)
1766 : {
1767 0 : merge->n_contains = check->n_contains;
1768 0 : merge->contains = check->contains;
1769 0 : check->contains = NULL;
1770 : }
1771 2 : else if (merge->contains && check->contains)
1772 : {
1773 0 : check->contains = XRESIZEVEC (gfc_statement, check->contains,
1774 : merge->n_contains + check->n_contains);
1775 0 : for (int i = 0; i < merge->n_contains; i++)
1776 0 : if (!bitmap_bit_p (&contains_head, merge->contains[i]))
1777 0 : check->contains[check->n_contains++] = merge->contains[i];
1778 0 : free (merge->contains);
1779 0 : merge->contains = check->contains;
1780 0 : merge->n_contains = check->n_contains;
1781 0 : check->contains = NULL;
1782 : }
1783 : return MATCH_YES;
1784 : }
1785 :
1786 : /* OpenMP 5.0
1787 : uses_allocators ( allocator-list )
1788 :
1789 : allocator:
1790 : predefined-allocator
1791 : variable ( traits-array )
1792 :
1793 : OpenMP 5.2 deprecated, 6.0 deleted: 'variable ( traits-array )'
1794 :
1795 : OpenMP 5.2:
1796 : uses_allocators ( [modifier-list :] allocator-list )
1797 :
1798 : OpenMP 6.0:
1799 : uses_allocators ( [modifier-list :] allocator-list [; ...])
1800 :
1801 : allocator:
1802 : variable or predefined-allocator
1803 : modifier:
1804 : traits ( traits-array )
1805 : memspace ( mem-space-handle ) */
1806 :
1807 : static match
1808 56 : gfc_match_omp_clause_uses_allocators (gfc_omp_clauses *c)
1809 : {
1810 60 : parse_next:
1811 60 : gfc_symbol *memspace_sym = NULL;
1812 60 : gfc_symbol *traits_sym = NULL;
1813 60 : gfc_omp_namelist *head = NULL;
1814 60 : gfc_omp_namelist *p, *tail, **list;
1815 60 : int ntraits, nmemspace;
1816 60 : bool has_modifiers;
1817 60 : locus old_loc, cur_loc;
1818 :
1819 60 : gfc_gobble_whitespace ();
1820 60 : old_loc = gfc_current_locus;
1821 60 : ntraits = nmemspace = 0;
1822 92 : do
1823 : {
1824 76 : cur_loc = gfc_current_locus;
1825 76 : if (gfc_match ("traits ( %S ) ", &traits_sym) == MATCH_YES)
1826 24 : ntraits++;
1827 52 : else if (gfc_match ("memspace ( %S ) ", &memspace_sym) == MATCH_YES)
1828 23 : nmemspace++;
1829 76 : if (ntraits > 1 || nmemspace > 1)
1830 : {
1831 2 : gfc_error ("Duplicate %s modifier at %L in USES_ALLOCATORS clause",
1832 : ntraits > 1 ? "TRAITS" : "MEMSPACE", &cur_loc);
1833 2 : return MATCH_ERROR;
1834 : }
1835 74 : if (gfc_match (", ") == MATCH_YES)
1836 16 : continue;
1837 58 : if (gfc_match (": ") != MATCH_YES)
1838 : {
1839 : /* Assume no modifier. */
1840 31 : memspace_sym = traits_sym = NULL;
1841 31 : gfc_current_locus = old_loc;
1842 31 : break;
1843 : }
1844 : break;
1845 : } while (true);
1846 :
1847 85 : has_modifiers = traits_sym != NULL || memspace_sym != NULL;
1848 150 : do
1849 : {
1850 104 : p = gfc_get_omp_namelist ();
1851 104 : p->where = gfc_current_locus;
1852 104 : if (head == NULL)
1853 : head = tail = p;
1854 : else
1855 : {
1856 46 : tail->next = p;
1857 46 : tail = tail->next;
1858 : }
1859 104 : if (gfc_match ("%S ", &p->sym) != MATCH_YES)
1860 0 : goto error;
1861 104 : if (!has_modifiers)
1862 : {
1863 72 : if (gfc_match ("( %S ) ", &p->u2.traits_sym) == MATCH_YES)
1864 17 : gfc_warning (OPT_Wdeprecated_openmp,
1865 : "The specification of arguments to "
1866 : "%<uses_allocators%> at %L where each item is of "
1867 : "the form %<allocator(traits)%> is deprecated since "
1868 : "OpenMP 5.2; instead use %<uses_allocators(traits(%s"
1869 17 : "): %s)%>", &p->where, p->u2.traits_sym->name,
1870 17 : p->sym->name);
1871 : }
1872 32 : else if (gfc_peek_ascii_char () == '(')
1873 : {
1874 0 : gfc_error ("Unexpected %<(%> at %C");
1875 0 : goto error;
1876 : }
1877 : else
1878 : {
1879 32 : p->u.memspace_sym = memspace_sym;
1880 32 : p->u2.traits_sym = traits_sym;
1881 : }
1882 104 : gfc_gobble_whitespace ();
1883 104 : const char c = gfc_peek_ascii_char ();
1884 104 : if (c == ';' || c == ')')
1885 : break;
1886 48 : if (c != ',')
1887 : {
1888 2 : gfc_error ("Expected %<,%>, %<)%> or %<;%> at %C");
1889 2 : goto error;
1890 : }
1891 46 : gfc_match_char (',');
1892 46 : gfc_gobble_whitespace ();
1893 46 : } while (true);
1894 :
1895 56 : list = &c->lists[OMP_LIST_USES_ALLOCATORS];
1896 74 : while (*list)
1897 18 : list = &(*list)->next;
1898 56 : *list = head;
1899 :
1900 56 : if (gfc_match_char (';') == MATCH_YES)
1901 4 : goto parse_next;
1902 :
1903 52 : gfc_match_char (')');
1904 52 : return MATCH_YES;
1905 :
1906 2 : error:
1907 2 : gfc_free_omp_namelist (head, OMP_LIST_USES_ALLOCATORS);
1908 2 : return MATCH_ERROR;
1909 : }
1910 :
1911 :
1912 : /* Match the 'prefer_type' modifier of the interop 'init' clause:
1913 : with either OpenMP 5.1's
1914 : prefer_type ( <const-int-expr|string literal> [, ...]
1915 : or
1916 : prefer_type ( '{' <fr(...) | attr (...)>, ...] '}' [, '{' ... '}' ] )
1917 : where 'fr' takes a constant expression or a string literal
1918 : and 'attr takes a list of string literals, starting with 'ompx_')
1919 :
1920 : For the foreign runtime identifiers, string values are converted to
1921 : their integer value; unknown string or integer values are set to
1922 : GOMP_INTEROP_IFR_KNOWN.
1923 :
1924 : Data format:
1925 : For the foreign runtime identifiers, string values are converted to
1926 : their integer value; unknown string or integer values are set to 0.
1927 :
1928 : Each item (a) GOMP_INTEROP_IFR_SEPARATOR
1929 : (b) for any 'fr', its integer value.
1930 : Note: Spec only permits 1 'fr' entry (6.0; changed after TR13)
1931 : (c) GOMP_INTEROP_IFR_SEPARATOR
1932 : (d) list of \0-terminated non-empty strings for 'attr'
1933 : (e) '\0'
1934 : Tailing '\0'. */
1935 :
1936 : static match
1937 82 : gfc_match_omp_prefer_type (char **type_str, int *type_str_len)
1938 : {
1939 82 : gfc_expr *e;
1940 82 : std::string type_string, attr_string;
1941 : /* New syntax. */
1942 82 : if (gfc_peek_ascii_char () == '{')
1943 115 : do
1944 : {
1945 85 : attr_string.clear ();
1946 85 : type_string += (char) GOMP_INTEROP_IFR_SEPARATOR;
1947 85 : if (gfc_match ("{ ") != MATCH_YES)
1948 : {
1949 1 : gfc_error ("Expected %<{%> at %C");
1950 1 : return MATCH_ERROR;
1951 : }
1952 : bool fr_found = false;
1953 148 : do
1954 : {
1955 116 : if (gfc_match ("fr ( ") == MATCH_YES)
1956 : {
1957 62 : if (fr_found)
1958 : {
1959 1 : gfc_error ("Duplicated %<fr%> preference-selector-name "
1960 : "at %C");
1961 1 : return MATCH_ERROR;
1962 : }
1963 61 : fr_found = true;
1964 61 : do
1965 : {
1966 61 : bool found_literal = false;
1967 61 : match m = MATCH_YES;
1968 61 : if (gfc_match_literal_constant (&e, false) == MATCH_YES)
1969 : found_literal = true;
1970 : else
1971 12 : m = gfc_match_expr (&e);
1972 12 : if (m != MATCH_YES
1973 61 : || !gfc_resolve_expr (e)
1974 61 : || e->rank != 0
1975 60 : || e->expr_type != EXPR_CONSTANT
1976 59 : || (e->ts.type != BT_INTEGER
1977 43 : && (!found_literal || e->ts.type != BT_CHARACTER))
1978 58 : || (e->ts.type == BT_INTEGER
1979 16 : && !mpz_fits_sint_p (e->value.integer))
1980 70 : || (e->ts.type == BT_CHARACTER
1981 42 : && (e->ts.kind != gfc_default_character_kind
1982 41 : || e->value.character.length == 0)))
1983 : {
1984 5 : gfc_error ("Expected constant scalar integer expression"
1985 : " or non-empty default-kind character "
1986 5 : "literal at %L", &e->where);
1987 5 : gfc_free_expr (e);
1988 5 : return MATCH_ERROR;
1989 : }
1990 56 : gfc_gobble_whitespace ();
1991 56 : int val;
1992 56 : if (e->ts.type == BT_INTEGER)
1993 : {
1994 16 : val = mpz_get_si (e->value.integer);
1995 16 : if (val < 1 || val > GOMP_INTEROP_IFR_LAST)
1996 : {
1997 0 : gfc_warning_now (OPT_Wopenmp,
1998 : "Unknown foreign runtime "
1999 : "identifier %qd at %L",
2000 : val, &e->where);
2001 0 : val = GOMP_INTEROP_IFR_UNKNOWN;
2002 : }
2003 : }
2004 : else
2005 : {
2006 40 : char *str = XALLOCAVEC (char,
2007 : e->value.character.length+1);
2008 229 : for (int i = 0; i < e->value.character.length + 1; i++)
2009 189 : str[i] = e->value.character.string[i];
2010 40 : if (memchr (str, '\0', e->value.character.length) != 0)
2011 : {
2012 0 : gfc_error ("Unexpected null character in character "
2013 : "literal at %L", &e->where);
2014 0 : return MATCH_ERROR;
2015 : }
2016 40 : val = omp_get_fr_id_from_name (str);
2017 40 : if (val == GOMP_INTEROP_IFR_UNKNOWN)
2018 2 : gfc_warning_now (OPT_Wopenmp,
2019 : "Unknown foreign runtime identifier "
2020 2 : "%qs at %L", str, &e->where);
2021 : }
2022 :
2023 56 : type_string += (char) val;
2024 56 : if (gfc_match (") ") == MATCH_YES)
2025 : break;
2026 4 : gfc_error ("Expected %<)%> at %C");
2027 4 : return MATCH_ERROR;
2028 : }
2029 : while (true);
2030 : }
2031 54 : else if (gfc_match ("attr ( ") == MATCH_YES)
2032 : {
2033 60 : do
2034 : {
2035 57 : if (gfc_match_literal_constant (&e, false) != MATCH_YES
2036 56 : || !gfc_resolve_expr (e)
2037 56 : || e->expr_type != EXPR_CONSTANT
2038 56 : || e->rank != 0
2039 56 : || e->ts.type != BT_CHARACTER
2040 113 : || e->ts.kind != gfc_default_character_kind)
2041 : {
2042 1 : gfc_error ("Expected default-kind character literal "
2043 1 : "at %L", &e->where);
2044 1 : gfc_free_expr (e);
2045 1 : return MATCH_ERROR;
2046 : }
2047 56 : gfc_gobble_whitespace ();
2048 56 : char *str = XALLOCAVEC (char, e->value.character.length+1);
2049 564 : for (int i = 0; i < e->value.character.length + 1; i++)
2050 508 : str[i] = e->value.character.string[i];
2051 56 : if (!startswith (str, "ompx_"))
2052 : {
2053 1 : gfc_error ("Character literal at %L must start with "
2054 : "%<ompx_%>", &e->where);
2055 1 : gfc_free_expr (e);
2056 1 : return MATCH_ERROR;
2057 : }
2058 55 : if (memchr (str, '\0', e->value.character.length) != 0
2059 55 : || memchr (str, ',', e->value.character.length) != 0)
2060 : {
2061 1 : gfc_error ("Unexpected null or %<,%> character in "
2062 : "character literal at %L", &e->where);
2063 1 : return MATCH_ERROR;
2064 : }
2065 54 : attr_string += str;
2066 54 : attr_string += '\0';
2067 54 : if (gfc_match (", ") == MATCH_YES)
2068 3 : continue;
2069 51 : if (gfc_match (") ") == MATCH_YES)
2070 : break;
2071 0 : gfc_error ("Expected %<,%> or %<)%> at %C");
2072 0 : return MATCH_ERROR;
2073 3 : }
2074 : while (true);
2075 : }
2076 : else
2077 : {
2078 0 : gfc_error ("Expected %<fr(%> or %<attr(%> at %C");
2079 0 : return MATCH_ERROR;
2080 : }
2081 103 : if (gfc_match (", ") == MATCH_YES)
2082 32 : continue;
2083 71 : if (gfc_match ("} ") == MATCH_YES)
2084 : break;
2085 2 : gfc_error ("Expected %<,%> or %<}%> at %C");
2086 2 : return MATCH_ERROR;
2087 32 : }
2088 : while (true);
2089 69 : type_string += (char) GOMP_INTEROP_IFR_SEPARATOR;
2090 69 : type_string += attr_string;
2091 69 : type_string += '\0';
2092 69 : if (gfc_match (", ") == MATCH_YES)
2093 30 : continue;
2094 39 : if (gfc_match (") ") == MATCH_YES)
2095 : break;
2096 1 : gfc_error ("Expected %<,%> or %<)%> at %C");
2097 1 : return MATCH_ERROR;
2098 30 : }
2099 : while (true);
2100 : else
2101 75 : do
2102 : {
2103 51 : type_string += (char) GOMP_INTEROP_IFR_SEPARATOR;
2104 51 : bool found_literal = false;
2105 51 : match m = MATCH_YES;
2106 51 : if (gfc_match_literal_constant (&e, false) == MATCH_YES)
2107 : found_literal = true;
2108 : else
2109 19 : m = gfc_match_expr (&e);
2110 19 : if (m != MATCH_YES
2111 51 : || !gfc_resolve_expr (e)
2112 51 : || e->rank != 0
2113 50 : || e->expr_type != EXPR_CONSTANT
2114 49 : || (e->ts.type != BT_INTEGER
2115 28 : && (!found_literal || e->ts.type != BT_CHARACTER))
2116 48 : || (e->ts.type == BT_INTEGER
2117 21 : && !mpz_fits_sint_p (e->value.integer))
2118 67 : || (e->ts.type == BT_CHARACTER
2119 27 : && (e->ts.kind != gfc_default_character_kind
2120 27 : || e->value.character.length == 0)))
2121 : {
2122 3 : gfc_error ("Expected constant scalar integer expression or "
2123 3 : "non-empty default-kind character literal at %L", &e->where);
2124 3 : gfc_free_expr (e);
2125 3 : return MATCH_ERROR;
2126 : }
2127 48 : gfc_gobble_whitespace ();
2128 48 : int val;
2129 48 : if (e->ts.type == BT_INTEGER)
2130 : {
2131 21 : val = mpz_get_si (e->value.integer);
2132 21 : if (val < 1 || val > GOMP_INTEROP_IFR_LAST)
2133 : {
2134 3 : gfc_warning_now (OPT_Wopenmp,
2135 : "Unknown foreign runtime identifier %qd at %L",
2136 : val, &e->where);
2137 3 : val = 0;
2138 : }
2139 : }
2140 : else
2141 : {
2142 27 : char *str = XALLOCAVEC (char, e->value.character.length+1);
2143 169 : for (int i = 0; i < e->value.character.length + 1; i++)
2144 142 : str[i] = e->value.character.string[i];
2145 27 : if (memchr (str, '\0', e->value.character.length) != 0)
2146 : {
2147 0 : gfc_error ("Unexpected null character in character "
2148 : "literal at %L", &e->where);
2149 0 : return MATCH_ERROR;
2150 : }
2151 27 : val = omp_get_fr_id_from_name (str);
2152 27 : if (val == GOMP_INTEROP_IFR_UNKNOWN)
2153 5 : gfc_warning_now (OPT_Wopenmp,
2154 : "Unknown foreign runtime identifier %qs at %L",
2155 5 : str, &e->where);
2156 : }
2157 48 : type_string += (char) val;
2158 48 : type_string += (char) GOMP_INTEROP_IFR_SEPARATOR;
2159 48 : type_string += '\0';
2160 48 : gfc_free_expr (e);
2161 48 : if (gfc_match (", ") == MATCH_YES)
2162 24 : continue;
2163 24 : if (gfc_match (") ") == MATCH_YES)
2164 : break;
2165 2 : gfc_error ("Expected %<,%> or %<)%> at %C");
2166 2 : return MATCH_ERROR;
2167 24 : }
2168 : while (true);
2169 60 : type_string += '\0';
2170 60 : *type_str_len = type_string.length();
2171 60 : *type_str = XNEWVEC (char, type_string.length ());
2172 60 : memcpy (*type_str, type_string.data (), type_string.length ());
2173 60 : return MATCH_YES;
2174 82 : }
2175 :
2176 :
2177 : /* Match OpenMP 5.1's 'init'-clause modifiers, used by the 'init' clause of
2178 : the 'interop' directive and the 'append_args' directive of 'declare variant'.
2179 : [prefer_type(...)][,][<target|targetsync>, ...])
2180 :
2181 : If is_init_clause, the modifier parsing ends with a ':'.
2182 : If not is_init_clause (i.e. append_args), the parsing ends with ')'. */
2183 :
2184 : static match
2185 164 : gfc_parser_omp_clause_init_modifiers (bool &target, bool &targetsync,
2186 : char **type_str, int &type_str_len,
2187 : bool is_init_clause)
2188 : {
2189 164 : target = false;
2190 164 : targetsync = false;
2191 164 : *type_str = NULL;
2192 164 : type_str_len = 0;
2193 286 : match m;
2194 :
2195 286 : do
2196 : {
2197 286 : if (gfc_match ("prefer_type ( ") == MATCH_YES)
2198 : {
2199 83 : if (*type_str)
2200 : {
2201 1 : gfc_error ("Duplicate %<prefer_type%> modifier at %C");
2202 1 : return MATCH_ERROR;
2203 : }
2204 82 : m = gfc_match_omp_prefer_type (type_str, &type_str_len);
2205 82 : if (m != MATCH_YES)
2206 : return m;
2207 60 : if (gfc_match (", ") == MATCH_YES)
2208 14 : continue;
2209 46 : if (is_init_clause)
2210 : {
2211 24 : if (gfc_match (": ") == MATCH_YES)
2212 : break;
2213 0 : gfc_error ("Expected %<,%> or %<:%> at %C");
2214 : }
2215 : else
2216 : {
2217 22 : if (gfc_match (") ") == MATCH_YES)
2218 : break;
2219 0 : gfc_error ("Expected %<,%> or %<)%> at %C");
2220 : }
2221 0 : return MATCH_ERROR;
2222 : }
2223 :
2224 203 : if (gfc_match ("prefer_type ") == MATCH_YES)
2225 : {
2226 2 : gfc_error ("Expected %<(%> after %<prefer_type%> at %C");
2227 2 : return MATCH_ERROR;
2228 : }
2229 :
2230 201 : if (gfc_match ("targetsync ") == MATCH_YES)
2231 : {
2232 57 : if (targetsync)
2233 : {
2234 3 : gfc_error ("Duplicate %<targetsync%> at %C");
2235 3 : return MATCH_ERROR;
2236 : }
2237 54 : targetsync = true;
2238 54 : if (gfc_match (", ") == MATCH_YES)
2239 13 : continue;
2240 41 : if (!is_init_clause)
2241 : {
2242 23 : if (gfc_match (") ") == MATCH_YES)
2243 : break;
2244 0 : gfc_error ("Expected %<,%> or %<)%> at %C");
2245 0 : return MATCH_ERROR;
2246 : }
2247 18 : if (gfc_match (": ") == MATCH_YES)
2248 : break;
2249 1 : gfc_error ("Expected %<,%> or %<:%> at %C");
2250 1 : return MATCH_ERROR;
2251 : }
2252 144 : if (gfc_match ("target ") == MATCH_YES)
2253 : {
2254 135 : if (target)
2255 : {
2256 3 : gfc_error ("Duplicate %<target%> at %C");
2257 3 : return MATCH_ERROR;
2258 : }
2259 132 : target = true;
2260 132 : if (gfc_match (", ") == MATCH_YES)
2261 95 : continue;
2262 37 : if (!is_init_clause)
2263 : {
2264 11 : if (gfc_match (") ") == MATCH_YES)
2265 : break;
2266 0 : gfc_error ("Expected %<,%> or %<)%> at %C");
2267 0 : return MATCH_ERROR;
2268 : }
2269 26 : if (gfc_match (": ") == MATCH_YES)
2270 : break;
2271 1 : gfc_error ("Expected %<,%> or %<:%> at %C");
2272 1 : return MATCH_ERROR;
2273 : }
2274 9 : gfc_error ("Expected %<prefer_type%>, %<target%>, or %<targetsync%> "
2275 : "at %C");
2276 9 : return MATCH_ERROR;
2277 : }
2278 : while (true);
2279 :
2280 122 : if (!target && !targetsync)
2281 : {
2282 4 : gfc_error ("Missing required %<target%> and/or %<targetsync%> "
2283 : "modifier at %C");
2284 4 : return MATCH_ERROR;
2285 : }
2286 : return MATCH_YES;
2287 : }
2288 :
2289 : /* Match OpenMP 5.1's 'init' clause for 'interop' objects:
2290 : init([prefer_type(...)][,][<target|targetsync>, ...] :] interop-obj-list) */
2291 :
2292 : static match
2293 108 : gfc_match_omp_init (gfc_omp_namelist **list)
2294 : {
2295 108 : bool target, targetsync;
2296 108 : char *type_str = NULL;
2297 108 : int type_str_len;
2298 108 : if (gfc_parser_omp_clause_init_modifiers (target, targetsync, &type_str,
2299 : type_str_len, true) == MATCH_ERROR)
2300 : return MATCH_ERROR;
2301 :
2302 64 : gfc_omp_namelist **head = NULL;
2303 64 : if (gfc_match_omp_variable_list ("", list, false, NULL, &head) != MATCH_YES)
2304 : return MATCH_ERROR;
2305 147 : for (gfc_omp_namelist *n = *head; n; n = n->next)
2306 : {
2307 84 : n->u.init.target = target;
2308 84 : n->u.init.targetsync = targetsync;
2309 84 : n->u.init.len = type_str_len;
2310 84 : n->u2.init_interop = type_str;
2311 : }
2312 : return MATCH_YES;
2313 : }
2314 :
2315 :
2316 : /* Match with duplicate check. Matches 'name'. If expr != NULL, it
2317 : then matches '(expr)', otherwise, if open_parens is true,
2318 : it matches a ' ( ' after 'name'.
2319 : dupl_message requires '%qs %L' - and is used by
2320 : gfc_match_dupl_memorder and gfc_match_dupl_atomic. */
2321 :
2322 : static match
2323 22380 : gfc_match_dupl_check (bool not_dupl, const char *name, bool open_parens = false,
2324 : gfc_expr **expr = NULL, const char *dupl_msg = NULL)
2325 : {
2326 22380 : match m;
2327 22380 : char c;
2328 22380 : locus old_loc = gfc_current_locus;
2329 22380 : if ((m = gfc_match (name)) != MATCH_YES)
2330 : return m;
2331 : /* Ensure that no partial string is matched. */
2332 17417 : if (gfc_current_form == FORM_FREE
2333 16919 : && gfc_match_eos () != MATCH_YES
2334 30200 : && ((c = gfc_peek_ascii_char ()) == '_' || ISALNUM (c)))
2335 : {
2336 8 : gfc_current_locus = old_loc;
2337 8 : return MATCH_NO;
2338 : }
2339 17409 : if (!not_dupl)
2340 : {
2341 44 : if (dupl_msg)
2342 2 : gfc_error (dupl_msg, name, &old_loc);
2343 : else
2344 42 : gfc_error ("Duplicated %qs clause at %L", name, &old_loc);
2345 44 : return MATCH_ERROR;
2346 : }
2347 17365 : if (open_parens || expr)
2348 : {
2349 9475 : if (gfc_match (" ( ") != MATCH_YES)
2350 : {
2351 22 : gfc_error ("Expected %<(%> after %qs at %C", name);
2352 22 : return MATCH_ERROR;
2353 : }
2354 9453 : if (expr)
2355 : {
2356 4419 : if (gfc_match ("%e )", expr) != MATCH_YES)
2357 : {
2358 9 : gfc_error ("Invalid expression after %<%s(%> at %C", name);
2359 9 : return MATCH_ERROR;
2360 : }
2361 : }
2362 : }
2363 : return MATCH_YES;
2364 : }
2365 :
2366 : static match
2367 211 : gfc_match_dupl_memorder (bool not_dupl, const char *name)
2368 : {
2369 0 : return gfc_match_dupl_check (not_dupl, name, false, NULL,
2370 : "Duplicated memory-order clause: unexpected %s "
2371 0 : "clause at %L");
2372 : }
2373 :
2374 : static match
2375 1175 : gfc_match_dupl_atomic (bool not_dupl, const char *name)
2376 : {
2377 0 : return gfc_match_dupl_check (not_dupl, name, false, NULL,
2378 : "Duplicated atomic clause: unexpected %s "
2379 0 : "clause at %L");
2380 : }
2381 :
2382 : /* Match OpenMP and OpenACC directive clauses. MASK is a bitmask of
2383 : clauses that are allowed for a particular directive. */
2384 :
2385 : static match
2386 34124 : gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
2387 : bool first = true, bool needs_space = true,
2388 : bool openacc = false, bool openmp_target = false)
2389 : {
2390 34124 : bool error = false;
2391 34124 : gfc_omp_clauses *c = gfc_get_omp_clauses ();
2392 34124 : locus old_loc;
2393 : /* Determine whether we're dealing with an OpenACC directive that permits
2394 : derived type member accesses. This in particular disallows
2395 : "!$acc declare" from using such accesses, because it's not clear if/how
2396 : that should work. */
2397 34124 : bool allow_derived = (openacc
2398 34124 : && ((mask & OMP_CLAUSE_ATTACH)
2399 5933 : || (mask & OMP_CLAUSE_DETACH)));
2400 :
2401 34124 : gcc_checking_assert (OMP_MASK1_LAST <= 64 && OMP_MASK2_LAST <= 64);
2402 34124 : *cp = NULL;
2403 125046 : while (1)
2404 : {
2405 79585 : match m = MATCH_NO;
2406 59231 : if ((first || (m = gfc_match_char (',')) != MATCH_YES)
2407 138460 : && (needs_space && gfc_match_space () != MATCH_YES))
2408 : break;
2409 75037 : needs_space = false;
2410 75037 : first = false;
2411 75037 : gfc_gobble_whitespace ();
2412 75037 : bool end_colon;
2413 75037 : gfc_omp_namelist **head;
2414 75037 : old_loc = gfc_current_locus;
2415 75037 : char pc = gfc_peek_ascii_char ();
2416 75037 : if (pc == '\n' && m == MATCH_YES)
2417 : {
2418 1 : gfc_error ("Clause expected at %C after trailing comma");
2419 1 : goto error;
2420 : }
2421 75036 : switch (pc)
2422 : {
2423 1312 : case 'a':
2424 1312 : end_colon = false;
2425 1312 : head = NULL;
2426 1336 : if ((mask & OMP_CLAUSE_ASSUMPTIONS)
2427 1312 : && gfc_match ("absent ( ") == MATCH_YES)
2428 : {
2429 27 : if (gfc_omp_absent_contains_clause (&c->assume, true)
2430 : != MATCH_YES)
2431 3 : goto error;
2432 24 : continue;
2433 : }
2434 1285 : if ((mask & OMP_CLAUSE_ALIGNED)
2435 1285 : && gfc_match_omp_variable_list ("aligned (",
2436 : &c->lists[OMP_LIST_ALIGNED],
2437 : false, &end_colon,
2438 : &head) == MATCH_YES)
2439 : {
2440 112 : gfc_expr *alignment = NULL;
2441 112 : gfc_omp_namelist *n;
2442 :
2443 112 : if (end_colon && gfc_match (" %e )", &alignment) != MATCH_YES)
2444 : {
2445 0 : gfc_free_omp_namelist (*head, OMP_LIST_ALIGNED);
2446 0 : gfc_current_locus = old_loc;
2447 0 : *head = NULL;
2448 0 : break;
2449 : }
2450 268 : for (n = *head; n; n = n->next)
2451 156 : if (n->next && alignment)
2452 42 : n->expr = gfc_copy_expr (alignment);
2453 : else
2454 114 : n->expr = alignment;
2455 112 : continue;
2456 112 : }
2457 1183 : if ((mask & OMP_CLAUSE_MEMORDER)
2458 1190 : && (m = gfc_match_dupl_memorder ((c->memorder
2459 17 : == OMP_MEMORDER_UNSET),
2460 : "acq_rel")) != MATCH_NO)
2461 : {
2462 10 : if (m == MATCH_ERROR)
2463 0 : goto error;
2464 10 : c->memorder = OMP_MEMORDER_ACQ_REL;
2465 10 : continue;
2466 : }
2467 1170 : if ((mask & OMP_CLAUSE_MEMORDER)
2468 1170 : && (m = gfc_match_dupl_memorder ((c->memorder
2469 7 : == OMP_MEMORDER_UNSET),
2470 : "acquire")) != MATCH_NO)
2471 : {
2472 7 : if (m == MATCH_ERROR)
2473 0 : goto error;
2474 7 : c->memorder = OMP_MEMORDER_ACQUIRE;
2475 7 : continue;
2476 : }
2477 1156 : if ((mask & OMP_CLAUSE_AFFINITY)
2478 1156 : && gfc_match ("affinity ( ") == MATCH_YES)
2479 : {
2480 41 : gfc_namespace *ns_iter = NULL, *ns_curr = gfc_current_ns;
2481 41 : m = gfc_match_iterator (&ns_iter, true);
2482 41 : if (m == MATCH_ERROR)
2483 : break;
2484 31 : if (m == MATCH_YES && gfc_match (" : ") != MATCH_YES)
2485 : {
2486 1 : gfc_error ("Expected %<:%> at %C");
2487 1 : break;
2488 : }
2489 30 : if (ns_iter)
2490 18 : gfc_current_ns = ns_iter;
2491 30 : head = NULL;
2492 30 : m = gfc_match_omp_variable_list ("", &c->lists[OMP_LIST_AFFINITY],
2493 : false, NULL, &head, true);
2494 30 : gfc_current_ns = ns_curr;
2495 30 : if (m == MATCH_ERROR)
2496 : break;
2497 27 : if (ns_iter)
2498 : {
2499 45 : for (gfc_omp_namelist *n = *head; n; n = n->next)
2500 : {
2501 27 : n->u2.ns = ns_iter;
2502 27 : ns_iter->refs++;
2503 : }
2504 : }
2505 27 : continue;
2506 27 : }
2507 1115 : if ((mask & OMP_CLAUSE_ALLOCATE)
2508 1115 : && gfc_match ("allocate ( ") == MATCH_YES)
2509 : {
2510 279 : gfc_expr *allocator = NULL;
2511 279 : gfc_expr *align = NULL;
2512 279 : old_loc = gfc_current_locus;
2513 279 : if ((m = gfc_match ("allocator ( %e )", &allocator)) == MATCH_YES)
2514 50 : gfc_match (" , align ( %e )", &align);
2515 229 : else if ((m = gfc_match ("align ( %e )", &align)) == MATCH_YES)
2516 29 : gfc_match (" , allocator ( %e )", &allocator);
2517 :
2518 279 : if (m == MATCH_YES)
2519 : {
2520 79 : if (gfc_match (" : ") != MATCH_YES)
2521 : {
2522 5 : gfc_error ("Expected %<:%> at %C");
2523 8 : goto error;
2524 : }
2525 : }
2526 : else
2527 : {
2528 200 : m = gfc_match_expr (&allocator);
2529 200 : if (m == MATCH_YES && gfc_match (" : ") != MATCH_YES)
2530 : {
2531 : /* If no ":" then there is no allocator, we backtrack
2532 : and read the variable list. */
2533 101 : gfc_free_expr (allocator);
2534 101 : allocator = NULL;
2535 101 : gfc_current_locus = old_loc;
2536 : }
2537 : }
2538 274 : gfc_omp_namelist **head = NULL;
2539 274 : m = gfc_match_omp_variable_list ("", &c->lists[OMP_LIST_ALLOCATE],
2540 : true, NULL, &head);
2541 :
2542 274 : if (m != MATCH_YES)
2543 : {
2544 3 : gfc_free_expr (allocator);
2545 3 : gfc_free_expr (align);
2546 3 : gfc_error ("Expected variable list at %C");
2547 3 : goto error;
2548 : }
2549 :
2550 725 : for (gfc_omp_namelist *n = *head; n; n = n->next)
2551 : {
2552 454 : n->u2.allocator = allocator;
2553 454 : n->u.align = (align) ? gfc_copy_expr (align) : NULL;
2554 : }
2555 271 : gfc_free_expr (align);
2556 271 : continue;
2557 271 : }
2558 896 : if ((mask & OMP_CLAUSE_AT)
2559 836 : && (m = gfc_match_dupl_check (c->at == OMP_AT_UNSET, "at", true))
2560 : != MATCH_NO)
2561 : {
2562 66 : if (m == MATCH_ERROR)
2563 2 : goto error;
2564 64 : if (gfc_match ("compilation )") == MATCH_YES)
2565 15 : c->at = OMP_AT_COMPILATION;
2566 49 : else if (gfc_match ("execution )") == MATCH_YES)
2567 45 : c->at = OMP_AT_EXECUTION;
2568 : else
2569 : {
2570 4 : gfc_error ("Expected COMPILATION or EXECUTION in AT clause "
2571 : "at %C");
2572 4 : goto error;
2573 : }
2574 60 : continue;
2575 : }
2576 1413 : if ((mask & OMP_CLAUSE_ASYNC)
2577 770 : && (m = gfc_match_dupl_check (!c->async, "async")) != MATCH_NO)
2578 : {
2579 643 : if (m == MATCH_ERROR)
2580 0 : goto error;
2581 643 : c->async = true;
2582 643 : m = gfc_match (" ( %e )", &c->async_expr);
2583 643 : if (m == MATCH_ERROR)
2584 : {
2585 0 : gfc_current_locus = old_loc;
2586 0 : break;
2587 : }
2588 643 : else if (m == MATCH_NO)
2589 : {
2590 133 : c->async_expr
2591 133 : = gfc_get_constant_expr (BT_INTEGER,
2592 : gfc_default_integer_kind,
2593 : &gfc_current_locus);
2594 133 : mpz_set_si (c->async_expr->value.integer, GOMP_ASYNC_NOVAL);
2595 : }
2596 643 : continue;
2597 : }
2598 190 : if ((mask & OMP_CLAUSE_AUTO)
2599 127 : && (m = gfc_match_dupl_check (!c->par_auto, "auto"))
2600 : != MATCH_NO)
2601 : {
2602 63 : if (m == MATCH_ERROR)
2603 0 : goto error;
2604 63 : c->par_auto = true;
2605 63 : continue;
2606 : }
2607 125 : if ((mask & OMP_CLAUSE_ATTACH)
2608 62 : && gfc_match ("attach ( ") == MATCH_YES
2609 125 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
2610 : OMP_MAP_ATTACH, false,
2611 : allow_derived))
2612 61 : continue;
2613 : break;
2614 36 : case 'b':
2615 70 : if ((mask & OMP_CLAUSE_BIND)
2616 36 : && (m = gfc_match_dupl_check (c->bind == OMP_BIND_UNSET, "bind",
2617 : true)) != MATCH_NO)
2618 : {
2619 36 : if (m == MATCH_ERROR)
2620 1 : goto error;
2621 35 : if (gfc_match ("teams )") == MATCH_YES)
2622 11 : c->bind = OMP_BIND_TEAMS;
2623 24 : else if (gfc_match ("parallel )") == MATCH_YES)
2624 15 : c->bind = OMP_BIND_PARALLEL;
2625 9 : else if (gfc_match ("thread )") == MATCH_YES)
2626 8 : c->bind = OMP_BIND_THREAD;
2627 : else
2628 : {
2629 1 : gfc_error ("Expected TEAMS, PARALLEL or THREAD as binding in "
2630 : "BIND at %C");
2631 1 : break;
2632 : }
2633 34 : continue;
2634 : }
2635 : break;
2636 7109 : case 'c':
2637 7382 : if ((mask & OMP_CLAUSE_CAPTURE)
2638 7109 : && (m = gfc_match_dupl_check (!c->capture, "capture"))
2639 : != MATCH_NO)
2640 : {
2641 274 : if (m == MATCH_ERROR)
2642 1 : goto error;
2643 273 : c->capture = true;
2644 273 : continue;
2645 : }
2646 6835 : if (mask & OMP_CLAUSE_COLLAPSE)
2647 : {
2648 1996 : gfc_expr *cexpr = NULL;
2649 1996 : if ((m = gfc_match_dupl_check (!c->collapse, "collapse", true,
2650 : &cexpr)) != MATCH_NO)
2651 : {
2652 1506 : int collapse;
2653 1506 : if (m == MATCH_ERROR)
2654 0 : goto error;
2655 1506 : if (gfc_extract_int (cexpr, &collapse, -1))
2656 4 : collapse = 1;
2657 1502 : else if (collapse <= 0)
2658 : {
2659 8 : gfc_error_now ("COLLAPSE clause argument not constant "
2660 : "positive integer at %C");
2661 8 : collapse = 1;
2662 : }
2663 1506 : gfc_free_expr (cexpr);
2664 1506 : c->collapse = collapse;
2665 1506 : continue;
2666 1506 : }
2667 : }
2668 5495 : if ((mask & OMP_CLAUSE_COMPARE)
2669 5329 : && (m = gfc_match_dupl_check (!c->compare, "compare"))
2670 : != MATCH_NO)
2671 : {
2672 167 : if (m == MATCH_ERROR)
2673 1 : goto error;
2674 166 : c->compare = true;
2675 166 : continue;
2676 : }
2677 5174 : if ((mask & OMP_CLAUSE_ASSUMPTIONS)
2678 5162 : && gfc_match ("contains ( ") == MATCH_YES)
2679 : {
2680 12 : if (gfc_omp_absent_contains_clause (&c->assume, false)
2681 : != MATCH_YES)
2682 0 : goto error;
2683 12 : continue;
2684 : }
2685 7266 : if ((mask & OMP_CLAUSE_COPY)
2686 3723 : && gfc_match ("copy ( ") == MATCH_YES
2687 7267 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
2688 : OMP_MAP_TOFROM, true,
2689 : allow_derived))
2690 2116 : continue;
2691 3034 : if (mask & OMP_CLAUSE_COPYIN)
2692 : {
2693 2628 : if (openacc)
2694 : {
2695 2529 : if (gfc_match ("copyin ( ") == MATCH_YES)
2696 : {
2697 1458 : bool readonly = gfc_match ("readonly : ") == MATCH_YES;
2698 1458 : head = NULL;
2699 1458 : if (gfc_match_omp_variable_list ("",
2700 : &c->lists[OMP_LIST_MAP],
2701 : true, NULL, &head, true,
2702 : allow_derived)
2703 : == MATCH_YES)
2704 : {
2705 1452 : gfc_omp_namelist *n;
2706 3349 : for (n = *head; n; n = n->next)
2707 : {
2708 1897 : n->u.map.op = OMP_MAP_TO;
2709 1897 : n->u.map.readonly = readonly;
2710 : }
2711 1452 : continue;
2712 1452 : }
2713 : }
2714 : }
2715 99 : else if (gfc_match_omp_variable_list ("copyin (",
2716 : &c->lists[OMP_LIST_COPYIN],
2717 : true) == MATCH_YES)
2718 97 : continue;
2719 : }
2720 2556 : if ((mask & OMP_CLAUSE_COPYOUT)
2721 1216 : && gfc_match ("copyout ( ") == MATCH_YES
2722 2556 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
2723 : OMP_MAP_FROM, true, allow_derived))
2724 1071 : continue;
2725 498 : if ((mask & OMP_CLAUSE_COPYPRIVATE)
2726 414 : && gfc_match_omp_variable_list ("copyprivate (",
2727 : &c->lists[OMP_LIST_COPYPRIVATE],
2728 : true) == MATCH_YES)
2729 84 : continue;
2730 651 : if ((mask & OMP_CLAUSE_CREATE)
2731 328 : && gfc_match ("create ( ") == MATCH_YES
2732 651 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
2733 : OMP_MAP_ALLOC, true, allow_derived))
2734 321 : continue;
2735 : break;
2736 3739 : case 'd':
2737 3739 : if ((mask & OMP_CLAUSE_DEFAULTMAP)
2738 3739 : && gfc_match ("defaultmap ( ") == MATCH_YES)
2739 : {
2740 180 : enum gfc_omp_defaultmap behavior;
2741 180 : gfc_omp_defaultmap_category category
2742 : = OMP_DEFAULTMAP_CAT_UNCATEGORIZED;
2743 180 : if (gfc_match ("alloc ") == MATCH_YES)
2744 : behavior = OMP_DEFAULTMAP_ALLOC;
2745 174 : else if (gfc_match ("tofrom ") == MATCH_YES)
2746 : behavior = OMP_DEFAULTMAP_TOFROM;
2747 142 : else if (gfc_match ("to ") == MATCH_YES)
2748 : behavior = OMP_DEFAULTMAP_TO;
2749 132 : else if (gfc_match ("from ") == MATCH_YES)
2750 : behavior = OMP_DEFAULTMAP_FROM;
2751 129 : else if (gfc_match ("firstprivate ") == MATCH_YES)
2752 : behavior = OMP_DEFAULTMAP_FIRSTPRIVATE;
2753 94 : else if (gfc_match ("present ") == MATCH_YES)
2754 : behavior = OMP_DEFAULTMAP_PRESENT;
2755 90 : else if (gfc_match ("none ") == MATCH_YES)
2756 : behavior = OMP_DEFAULTMAP_NONE;
2757 10 : else if (gfc_match ("default ") == MATCH_YES)
2758 : behavior = OMP_DEFAULTMAP_DEFAULT;
2759 : else
2760 : {
2761 1 : gfc_error ("Expected ALLOC, TO, FROM, TOFROM, FIRSTPRIVATE, "
2762 : "PRESENT, NONE or DEFAULT at %C");
2763 1 : break;
2764 : }
2765 179 : if (')' == gfc_peek_ascii_char ())
2766 : ;
2767 102 : else if (gfc_match (": ") != MATCH_YES)
2768 : break;
2769 : else
2770 : {
2771 102 : if (gfc_match ("scalar ") == MATCH_YES)
2772 : category = OMP_DEFAULTMAP_CAT_SCALAR;
2773 67 : else if (gfc_match ("aggregate ") == MATCH_YES)
2774 : category = OMP_DEFAULTMAP_CAT_AGGREGATE;
2775 43 : else if (gfc_match ("allocatable ") == MATCH_YES)
2776 : category = OMP_DEFAULTMAP_CAT_ALLOCATABLE;
2777 31 : else if (gfc_match ("pointer ") == MATCH_YES)
2778 : category = OMP_DEFAULTMAP_CAT_POINTER;
2779 14 : else if (gfc_match ("all ") == MATCH_YES)
2780 : category = OMP_DEFAULTMAP_CAT_ALL;
2781 : else
2782 : {
2783 1 : gfc_error ("Expected SCALAR, AGGREGATE, ALLOCATABLE, "
2784 : "POINTER or ALL at %C");
2785 1 : break;
2786 : }
2787 : }
2788 1193 : for (int i = 0; i < OMP_DEFAULTMAP_CAT_NUM; ++i)
2789 : {
2790 1028 : if (i != category
2791 1028 : && category != OMP_DEFAULTMAP_CAT_UNCATEGORIZED
2792 486 : && category != OMP_DEFAULTMAP_CAT_ALL
2793 486 : && i != OMP_DEFAULTMAP_CAT_UNCATEGORIZED
2794 341 : && i != OMP_DEFAULTMAP_CAT_ALL)
2795 254 : continue;
2796 774 : if (c->defaultmap[i] != OMP_DEFAULTMAP_UNSET)
2797 : {
2798 13 : const char *pcategory = NULL;
2799 13 : switch (i)
2800 : {
2801 : case OMP_DEFAULTMAP_CAT_UNCATEGORIZED: break;
2802 : case OMP_DEFAULTMAP_CAT_ALL: pcategory = "ALL"; break;
2803 1 : case OMP_DEFAULTMAP_CAT_SCALAR: pcategory = "SCALAR"; break;
2804 2 : case OMP_DEFAULTMAP_CAT_AGGREGATE:
2805 2 : pcategory = "AGGREGATE";
2806 2 : break;
2807 1 : case OMP_DEFAULTMAP_CAT_ALLOCATABLE:
2808 1 : pcategory = "ALLOCATABLE";
2809 1 : break;
2810 2 : case OMP_DEFAULTMAP_CAT_POINTER:
2811 2 : pcategory = "POINTER";
2812 2 : break;
2813 : default: gcc_unreachable ();
2814 : }
2815 6 : if (i == OMP_DEFAULTMAP_CAT_UNCATEGORIZED)
2816 4 : gfc_error ("DEFAULTMAP at %C but prior DEFAULTMAP with "
2817 : "unspecified category");
2818 : else
2819 9 : gfc_error ("DEFAULTMAP at %C but prior DEFAULTMAP for "
2820 : "category %s", pcategory);
2821 13 : goto error;
2822 : }
2823 : }
2824 165 : c->defaultmap[category] = behavior;
2825 165 : if (gfc_match (")") != MATCH_YES)
2826 : break;
2827 165 : continue;
2828 165 : }
2829 4526 : if ((mask & OMP_CLAUSE_DEFAULT)
2830 3559 : && (m = gfc_match_dupl_check (c->default_sharing
2831 : == OMP_DEFAULT_UNKNOWN, "default",
2832 : true)) != MATCH_NO)
2833 : {
2834 1012 : if (m == MATCH_ERROR)
2835 6 : goto error;
2836 1006 : if (gfc_match ("none") == MATCH_YES)
2837 596 : c->default_sharing = OMP_DEFAULT_NONE;
2838 410 : else if (openacc)
2839 : {
2840 225 : if (gfc_match ("present") == MATCH_YES)
2841 195 : c->default_sharing = OMP_DEFAULT_PRESENT;
2842 : }
2843 : else
2844 : {
2845 185 : if (gfc_match ("firstprivate") == MATCH_YES)
2846 8 : c->default_sharing = OMP_DEFAULT_FIRSTPRIVATE;
2847 177 : else if (gfc_match ("private") == MATCH_YES)
2848 24 : c->default_sharing = OMP_DEFAULT_PRIVATE;
2849 153 : else if (gfc_match ("shared") == MATCH_YES)
2850 153 : c->default_sharing = OMP_DEFAULT_SHARED;
2851 : }
2852 1006 : if (c->default_sharing == OMP_DEFAULT_UNKNOWN)
2853 : {
2854 30 : if (openacc)
2855 30 : gfc_error ("Expected NONE or PRESENT in DEFAULT clause "
2856 : "at %C");
2857 : else
2858 0 : gfc_error ("Expected NONE, FIRSTPRIVATE, PRIVATE or SHARED "
2859 : "in DEFAULT clause at %C");
2860 30 : goto error;
2861 : }
2862 976 : if (gfc_match (" )") != MATCH_YES)
2863 9 : goto error;
2864 967 : continue;
2865 : }
2866 2855 : if ((mask & OMP_CLAUSE_DELETE)
2867 345 : && gfc_match ("delete ( ") == MATCH_YES
2868 2855 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
2869 : OMP_MAP_RELEASE, true,
2870 : allow_derived))
2871 308 : continue;
2872 : /* DOACROSS: match 'doacross' and 'depend' with sink/source.
2873 : DEPEND: match 'depend' but not sink/source. */
2874 2239 : m = MATCH_NO;
2875 2239 : if (((mask & OMP_CLAUSE_DOACROSS)
2876 383 : && gfc_match ("doacross ( ") == MATCH_YES)
2877 2595 : || (((mask & OMP_CLAUSE_DEPEND) || (mask & OMP_CLAUSE_DOACROSS))
2878 1598 : && (m = gfc_match ("depend ( ")) == MATCH_YES))
2879 : {
2880 1100 : bool has_omp_all_memory;
2881 1100 : bool is_depend = m == MATCH_YES;
2882 1100 : gfc_namespace *ns_iter = NULL, *ns_curr = gfc_current_ns;
2883 1100 : match m_it = MATCH_NO;
2884 1100 : if (is_depend)
2885 1073 : m_it = gfc_match_iterator (&ns_iter, false);
2886 1073 : if (m_it == MATCH_ERROR)
2887 : break;
2888 1095 : if (m_it == MATCH_YES && gfc_match (" , ") != MATCH_YES)
2889 : break;
2890 1095 : m = MATCH_YES;
2891 1095 : gfc_omp_depend_doacross_op depend_op = OMP_DEPEND_OUT;
2892 1095 : if (gfc_match ("inoutset") == MATCH_YES)
2893 : depend_op = OMP_DEPEND_INOUTSET;
2894 1083 : else if (gfc_match ("inout") == MATCH_YES)
2895 : depend_op = OMP_DEPEND_INOUT;
2896 991 : else if (gfc_match ("in") == MATCH_YES)
2897 : depend_op = OMP_DEPEND_IN;
2898 704 : else if (gfc_match ("out") == MATCH_YES)
2899 : depend_op = OMP_DEPEND_OUT;
2900 442 : else if (gfc_match ("mutexinoutset") == MATCH_YES)
2901 : depend_op = OMP_DEPEND_MUTEXINOUTSET;
2902 424 : else if (gfc_match ("depobj") == MATCH_YES)
2903 : depend_op = OMP_DEPEND_DEPOBJ;
2904 387 : else if (gfc_match ("source") == MATCH_YES)
2905 : {
2906 143 : if (m_it == MATCH_YES)
2907 : {
2908 1 : gfc_error ("ITERATOR may not be combined with SOURCE "
2909 : "at %C");
2910 17 : goto error;
2911 : }
2912 142 : if (!(mask & OMP_CLAUSE_DOACROSS))
2913 : {
2914 1 : gfc_error ("SOURCE at %C not permitted as dependence-type"
2915 : " for this directive");
2916 1 : goto error;
2917 : }
2918 141 : if (c->doacross_source)
2919 : {
2920 0 : gfc_error ("Duplicated clause with SOURCE dependence-type"
2921 : " at %C");
2922 0 : goto error;
2923 : }
2924 141 : gfc_gobble_whitespace ();
2925 141 : m = gfc_match (": ");
2926 141 : if (m != MATCH_YES && !is_depend)
2927 : {
2928 1 : gfc_error ("Expected %<:%> at %C");
2929 1 : goto error;
2930 : }
2931 140 : if (gfc_match (")") != MATCH_YES
2932 146 : && !(m == MATCH_YES
2933 6 : && gfc_match ("omp_cur_iteration )") == MATCH_YES))
2934 : {
2935 2 : gfc_error ("Expected %<)%> or %<omp_cur_iteration)%> "
2936 : "at %C");
2937 2 : goto error;
2938 : }
2939 138 : if (is_depend)
2940 130 : gfc_warning (OPT_Wdeprecated_openmp,
2941 : "%<source%> modifier with %<depend%> clause "
2942 : "at %L deprecated since OpenMP 5.2, use with "
2943 : "%<doacross%>", &old_loc);
2944 138 : c->doacross_source = true;
2945 138 : c->depend_source = is_depend;
2946 1078 : continue;
2947 : }
2948 244 : else if (gfc_match ("sink ") == MATCH_YES)
2949 : {
2950 244 : if (!(mask & OMP_CLAUSE_DOACROSS))
2951 : {
2952 2 : gfc_error ("SINK at %C not permitted as dependence-type "
2953 : "for this directive");
2954 2 : goto error;
2955 : }
2956 242 : if (gfc_match (": ") != MATCH_YES)
2957 : {
2958 1 : gfc_error ("Expected %<:%> at %C");
2959 1 : goto error;
2960 : }
2961 241 : if (m_it == MATCH_YES)
2962 : {
2963 0 : gfc_error ("ITERATOR may not be combined with SINK "
2964 : "at %C");
2965 0 : goto error;
2966 : }
2967 241 : if (is_depend)
2968 226 : gfc_warning (OPT_Wdeprecated_openmp,
2969 : "%<sink%> modifier with %<depend%> clause at "
2970 : "%L deprecated since OpenMP 5.2, use with "
2971 : "%<doacross%>", &old_loc);
2972 241 : m = gfc_match_omp_doacross_sink (&c->lists[OMP_LIST_DEPEND],
2973 : is_depend);
2974 241 : if (m == MATCH_YES)
2975 238 : continue;
2976 3 : goto error;
2977 : }
2978 : else
2979 : m = MATCH_NO;
2980 708 : if (!(mask & OMP_CLAUSE_DEPEND))
2981 : {
2982 0 : gfc_error ("Expected dependence-type SINK or SOURCE at %C");
2983 0 : goto error;
2984 : }
2985 708 : head = NULL;
2986 708 : if (ns_iter)
2987 40 : gfc_current_ns = ns_iter;
2988 708 : if (m == MATCH_YES)
2989 708 : m = gfc_match_omp_variable_list (" : ",
2990 : &c->lists[OMP_LIST_DEPEND],
2991 : false, NULL, &head, true,
2992 : false, &has_omp_all_memory);
2993 708 : if (m != MATCH_YES)
2994 2 : goto error;
2995 706 : gfc_current_ns = ns_curr;
2996 706 : if (has_omp_all_memory && depend_op != OMP_DEPEND_INOUT
2997 21 : && depend_op != OMP_DEPEND_OUT)
2998 : {
2999 4 : gfc_error ("%<omp_all_memory%> used with DEPEND kind "
3000 : "other than OUT or INOUT at %C");
3001 4 : goto error;
3002 : }
3003 702 : gfc_omp_namelist *n;
3004 1435 : for (n = *head; n; n = n->next)
3005 : {
3006 733 : n->u.depend_doacross_op = depend_op;
3007 733 : n->u2.ns = ns_iter;
3008 733 : if (ns_iter)
3009 39 : ns_iter->refs++;
3010 : }
3011 702 : continue;
3012 702 : }
3013 1160 : if ((mask & OMP_CLAUSE_DESTROY)
3014 1139 : && gfc_match_omp_variable_list ("destroy (",
3015 : &c->lists[OMP_LIST_DESTROY],
3016 : true) == MATCH_YES)
3017 21 : continue;
3018 1244 : if ((mask & OMP_CLAUSE_DETACH)
3019 164 : && !openacc
3020 127 : && !c->detach
3021 1244 : && gfc_match_omp_detach (&c->detach) == MATCH_YES)
3022 126 : continue;
3023 1029 : if ((mask & OMP_CLAUSE_DETACH)
3024 38 : && openacc
3025 37 : && gfc_match ("detach ( ") == MATCH_YES
3026 1029 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
3027 : OMP_MAP_DETACH, false,
3028 : allow_derived))
3029 37 : continue;
3030 991 : if ((mask & OMP_CLAUSE_DEVICEPTR)
3031 87 : && gfc_match ("deviceptr ( ") == MATCH_YES
3032 993 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
3033 : OMP_MAP_FORCE_DEVICEPTR, false,
3034 : allow_derived))
3035 36 : continue;
3036 1010 : if ((mask & OMP_CLAUSE_DEVICE_TYPE)
3037 919 : && gfc_match_dupl_check (c->device_type == OMP_DEVICE_TYPE_UNSET,
3038 : "device_type", true) == MATCH_YES)
3039 : {
3040 92 : if (gfc_match ("host") == MATCH_YES)
3041 32 : c->device_type = OMP_DEVICE_TYPE_HOST;
3042 60 : else if (gfc_match ("nohost") == MATCH_YES)
3043 21 : c->device_type = OMP_DEVICE_TYPE_NOHOST;
3044 39 : else if (gfc_match ("any") == MATCH_YES)
3045 38 : c->device_type = OMP_DEVICE_TYPE_ANY;
3046 : else
3047 : {
3048 1 : gfc_error ("Expected HOST, NOHOST or ANY at %C");
3049 1 : break;
3050 : }
3051 91 : if (gfc_match (" )") != MATCH_YES)
3052 : break;
3053 91 : continue;
3054 : }
3055 875 : if ((mask & OMP_CLAUSE_DEVICE_RESIDENT)
3056 876 : && gfc_match_omp_variable_list
3057 49 : ("device_resident (",
3058 : &c->lists[OMP_LIST_DEVICE_RESIDENT], true) == MATCH_YES)
3059 48 : continue;
3060 1091 : if ((mask & OMP_CLAUSE_DEVICE)
3061 703 : && openacc
3062 314 : && gfc_match ("device ( ") == MATCH_YES
3063 1092 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
3064 : OMP_MAP_FORCE_TO, true,
3065 : /* allow_derived = */ true))
3066 312 : continue;
3067 467 : if ((mask & OMP_CLAUSE_DEVICE)
3068 391 : && !openacc
3069 856 : && ((m = gfc_match_dupl_check (!c->device, "device", true))
3070 : != MATCH_NO))
3071 : {
3072 349 : if (m == MATCH_ERROR)
3073 0 : goto error;
3074 349 : c->ancestor = false;
3075 349 : if (gfc_match ("device_num : ") == MATCH_YES)
3076 : {
3077 18 : if (gfc_match ("%e )", &c->device) != MATCH_YES)
3078 : {
3079 1 : gfc_error ("Expected integer expression at %C");
3080 1 : break;
3081 : }
3082 : }
3083 331 : else if (gfc_match ("ancestor : ") == MATCH_YES)
3084 : {
3085 45 : bool has_requires = false;
3086 45 : c->ancestor = true;
3087 82 : for (gfc_namespace *ns = gfc_current_ns; ns; ns = ns->parent)
3088 80 : if (ns->omp_requires & OMP_REQ_REVERSE_OFFLOAD)
3089 : {
3090 : has_requires = true;
3091 : break;
3092 : }
3093 45 : if (!has_requires)
3094 : {
3095 2 : gfc_error ("%<ancestor%> device modifier not "
3096 : "preceded by %<requires%> directive "
3097 : "with %<reverse_offload%> clause at %C");
3098 5 : break;
3099 : }
3100 43 : locus old_loc2 = gfc_current_locus;
3101 43 : if (gfc_match ("%e )", &c->device) == MATCH_YES)
3102 : {
3103 43 : int device = 0;
3104 43 : if (!gfc_extract_int (c->device, &device) && device != 1)
3105 : {
3106 1 : gfc_current_locus = old_loc2;
3107 1 : gfc_error ("the %<device%> clause expression must "
3108 : "evaluate to %<1%> at %C");
3109 1 : break;
3110 : }
3111 : }
3112 : else
3113 : {
3114 0 : gfc_error ("Expected integer expression at %C");
3115 0 : break;
3116 : }
3117 : }
3118 286 : else if (gfc_match ("%e )", &c->device) != MATCH_YES)
3119 : {
3120 13 : gfc_error ("Expected integer expression or a single device-"
3121 : "modifier %<device_num%> or %<ancestor%> at %C");
3122 13 : break;
3123 : }
3124 332 : continue;
3125 332 : }
3126 118 : if ((mask & OMP_CLAUSE_DIST_SCHEDULE)
3127 97 : && c->dist_sched_kind == OMP_SCHED_NONE
3128 215 : && gfc_match ("dist_schedule ( static") == MATCH_YES)
3129 : {
3130 97 : m = MATCH_NO;
3131 97 : c->dist_sched_kind = OMP_SCHED_STATIC;
3132 97 : m = gfc_match (" , %e )", &c->dist_chunk_size);
3133 97 : if (m != MATCH_YES)
3134 14 : m = gfc_match_char (')');
3135 14 : if (m != MATCH_YES)
3136 : {
3137 0 : c->dist_sched_kind = OMP_SCHED_NONE;
3138 0 : gfc_current_locus = old_loc;
3139 : }
3140 : else
3141 97 : continue;
3142 : }
3143 32 : if ((mask & OMP_CLAUSE_DYN_GROUPPRIVATE)
3144 21 : && gfc_match_dupl_check (!c->dyn_groupprivate,
3145 : "dyn_groupprivate", true) == MATCH_YES)
3146 : {
3147 12 : if (gfc_match ("fallback ( abort ) : ") == MATCH_YES)
3148 1 : c->fallback = OMP_FALLBACK_ABORT;
3149 11 : else if (gfc_match ("fallback ( default_mem ) : ") == MATCH_YES)
3150 1 : c->fallback = OMP_FALLBACK_DEFAULT_MEM;
3151 10 : else if (gfc_match ("fallback ( null ) : ") == MATCH_YES)
3152 1 : c->fallback = OMP_FALLBACK_NULL;
3153 12 : if (gfc_match_expr (&c->dyn_groupprivate) != MATCH_YES)
3154 0 : return MATCH_ERROR;
3155 12 : if (gfc_match (" )") != MATCH_YES)
3156 1 : goto error;
3157 11 : continue;
3158 : }
3159 : break;
3160 90 : case 'e':
3161 90 : if ((mask & OMP_CLAUSE_ENTER))
3162 : {
3163 90 : m = gfc_match_omp_to_link ("enter (", &c->lists[OMP_LIST_ENTER]);
3164 90 : if (m == MATCH_ERROR)
3165 0 : goto error;
3166 90 : if (m == MATCH_YES)
3167 90 : continue;
3168 : }
3169 : break;
3170 2282 : case 'f':
3171 2331 : if ((mask & OMP_CLAUSE_FAIL)
3172 2282 : && (m = gfc_match_dupl_check (c->fail == OMP_MEMORDER_UNSET,
3173 : "fail", true)) != MATCH_NO)
3174 : {
3175 58 : if (m == MATCH_ERROR)
3176 3 : goto error;
3177 55 : if (gfc_match ("seq_cst") == MATCH_YES)
3178 6 : c->fail = OMP_MEMORDER_SEQ_CST;
3179 49 : else if (gfc_match ("acquire") == MATCH_YES)
3180 14 : c->fail = OMP_MEMORDER_ACQUIRE;
3181 35 : else if (gfc_match ("relaxed") == MATCH_YES)
3182 30 : c->fail = OMP_MEMORDER_RELAXED;
3183 : else
3184 : {
3185 5 : gfc_error ("Expected SEQ_CST, ACQUIRE or RELAXED at %C");
3186 5 : break;
3187 : }
3188 50 : if (gfc_match (" )") != MATCH_YES)
3189 1 : goto error;
3190 49 : continue;
3191 : }
3192 2267 : if ((mask & OMP_CLAUSE_FILTER)
3193 2224 : && (m = gfc_match_dupl_check (!c->filter, "filter", true,
3194 : &c->filter)) != MATCH_NO)
3195 : {
3196 44 : if (m == MATCH_ERROR)
3197 1 : goto error;
3198 43 : continue;
3199 : }
3200 2244 : if ((mask & OMP_CLAUSE_FINAL)
3201 2180 : && (m = gfc_match_dupl_check (!c->final_expr, "final", true,
3202 : &c->final_expr)) != MATCH_NO)
3203 : {
3204 64 : if (m == MATCH_ERROR)
3205 0 : goto error;
3206 64 : continue;
3207 : }
3208 2142 : if ((mask & OMP_CLAUSE_FINALIZE)
3209 2116 : && (m = gfc_match_dupl_check (!c->finalize, "finalize"))
3210 : != MATCH_NO)
3211 : {
3212 26 : if (m == MATCH_ERROR)
3213 0 : goto error;
3214 26 : c->finalize = true;
3215 26 : continue;
3216 : }
3217 3104 : if ((mask & OMP_CLAUSE_FIRSTPRIVATE)
3218 2090 : && gfc_match_omp_variable_list ("firstprivate (",
3219 : &c->lists[OMP_LIST_FIRSTPRIVATE],
3220 : true) == MATCH_YES)
3221 1014 : continue;
3222 2075 : if ((mask & OMP_CLAUSE_FROM)
3223 1076 : && gfc_match_motion_var_list ("from (", &c->lists[OMP_LIST_FROM],
3224 : &head) == MATCH_YES)
3225 999 : continue;
3226 142 : if ((mask & OMP_CLAUSE_FULL)
3227 77 : && (m = gfc_match_dupl_check (!c->full, "full")) != MATCH_NO)
3228 : {
3229 65 : if (m == MATCH_ERROR)
3230 0 : goto error;
3231 65 : c->full = true;
3232 65 : continue;
3233 : }
3234 : break;
3235 1231 : case 'g':
3236 2423 : if ((mask & OMP_CLAUSE_GANG)
3237 1231 : && (m = gfc_match_dupl_check (!c->gang, "gang")) != MATCH_NO)
3238 : {
3239 1197 : if (m == MATCH_ERROR)
3240 0 : goto error;
3241 1197 : c->gang = true;
3242 1197 : m = match_oacc_clause_gwv (c, GOMP_DIM_GANG);
3243 1197 : if (m == MATCH_ERROR)
3244 : {
3245 5 : gfc_current_locus = old_loc;
3246 5 : break;
3247 : }
3248 1192 : continue;
3249 : }
3250 68 : if ((mask & OMP_CLAUSE_GRAINSIZE)
3251 34 : && (m = gfc_match_dupl_check (!c->grainsize, "grainsize", true))
3252 : != MATCH_NO)
3253 : {
3254 34 : if (m == MATCH_ERROR)
3255 0 : goto error;
3256 34 : if (gfc_match ("strict : ") == MATCH_YES)
3257 1 : c->grainsize_strict = true;
3258 34 : if (gfc_match (" %e )", &c->grainsize) != MATCH_YES)
3259 0 : goto error;
3260 34 : continue;
3261 : }
3262 : break;
3263 465 : case 'h':
3264 513 : if ((mask & OMP_CLAUSE_HAS_DEVICE_ADDR)
3265 513 : && gfc_match_omp_variable_list
3266 48 : ("has_device_addr (", &c->lists[OMP_LIST_HAS_DEVICE_ADDR],
3267 : false, NULL, NULL, true) == MATCH_YES)
3268 48 : continue;
3269 460 : if ((mask & OMP_CLAUSE_HINT)
3270 417 : && (m = gfc_match_dupl_check (!c->hint, "hint", true, &c->hint))
3271 : != MATCH_NO)
3272 : {
3273 43 : if (m == MATCH_ERROR)
3274 0 : goto error;
3275 43 : continue;
3276 : }
3277 374 : if ((mask & OMP_CLAUSE_ASSUMPTIONS)
3278 374 : && gfc_match ("holds ( ") == MATCH_YES)
3279 : {
3280 19 : gfc_expr *e;
3281 19 : if (gfc_match ("%e )", &e) != MATCH_YES)
3282 0 : goto error;
3283 19 : if (c->assume == NULL)
3284 12 : c->assume = gfc_get_omp_assumptions ();
3285 19 : gfc_expr_list *el = XCNEW (gfc_expr_list);
3286 19 : el->expr = e;
3287 19 : el->next = c->assume->holds;
3288 19 : c->assume->holds = el;
3289 19 : continue;
3290 19 : }
3291 709 : if ((mask & OMP_CLAUSE_HOST)
3292 355 : && gfc_match ("host ( ") == MATCH_YES
3293 710 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
3294 : OMP_MAP_FORCE_FROM, true,
3295 : /* allow_derived = */ true))
3296 354 : continue;
3297 : break;
3298 2119 : case 'i':
3299 2142 : if ((mask & OMP_CLAUSE_IF_PRESENT)
3300 2119 : && (m = gfc_match_dupl_check (!c->if_present, "if_present"))
3301 : != MATCH_NO)
3302 : {
3303 23 : if (m == MATCH_ERROR)
3304 0 : goto error;
3305 23 : c->if_present = true;
3306 23 : continue;
3307 : }
3308 2096 : if ((mask & OMP_CLAUSE_IF)
3309 2096 : && (m = gfc_match_dupl_check (!c->if_expr, "if", true))
3310 : != MATCH_NO)
3311 : {
3312 1347 : if (m == MATCH_ERROR)
3313 12 : goto error;
3314 1335 : if (!openacc)
3315 : {
3316 : /* This should match the enum gfc_omp_if_kind order. */
3317 : static const char *ifs[OMP_IF_LAST] = {
3318 : "cancel : %e )",
3319 : "parallel : %e )",
3320 : "simd : %e )",
3321 : "task : %e )",
3322 : "taskloop : %e )",
3323 : "target : %e )",
3324 : "target data : %e )",
3325 : "target update : %e )",
3326 : "target enter data : %e )",
3327 : "target exit data : %e )" };
3328 : int i;
3329 4841 : for (i = 0; i < OMP_IF_LAST; i++)
3330 4443 : if (c->if_exprs[i] == NULL
3331 4443 : && gfc_match (ifs[i], &c->if_exprs[i]) == MATCH_YES)
3332 : break;
3333 536 : if (i < OMP_IF_LAST)
3334 138 : continue;
3335 : }
3336 1197 : if (gfc_match (" %e )", &c->if_expr) == MATCH_YES)
3337 1192 : continue;
3338 5 : goto error;
3339 : }
3340 866 : if ((mask & OMP_CLAUSE_IN_REDUCTION)
3341 749 : && gfc_match_omp_clause_reduction (pc, c, openacc, allow_derived,
3342 : openmp_target) == MATCH_YES)
3343 117 : continue;
3344 657 : if ((mask & OMP_CLAUSE_INBRANCH)
3345 632 : && (m = gfc_match_dupl_check (!c->inbranch && !c->notinbranch,
3346 : "inbranch")) != MATCH_NO)
3347 : {
3348 25 : if (m == MATCH_ERROR)
3349 0 : goto error;
3350 25 : c->inbranch = true;
3351 25 : continue;
3352 : }
3353 849 : if ((mask & OMP_CLAUSE_INDEPENDENT)
3354 607 : && (m = gfc_match_dupl_check (!c->independent, "independent"))
3355 : != MATCH_NO)
3356 : {
3357 242 : if (m == MATCH_ERROR)
3358 0 : goto error;
3359 242 : c->independent = true;
3360 242 : continue;
3361 : }
3362 365 : if ((mask & OMP_CLAUSE_INDIRECT)
3363 365 : && (m = gfc_match_dupl_check (!c->indirect, "indirect"))
3364 : != MATCH_NO)
3365 : {
3366 61 : if (m == MATCH_ERROR)
3367 5 : goto error;
3368 60 : gfc_expr *indirect_expr = NULL;
3369 60 : m = gfc_match (" ( %e )", &indirect_expr);
3370 60 : if (m == MATCH_YES)
3371 : {
3372 13 : if (!gfc_resolve_expr (indirect_expr)
3373 13 : || indirect_expr->ts.type != BT_LOGICAL
3374 23 : || indirect_expr->expr_type != EXPR_CONSTANT)
3375 : {
3376 4 : gfc_error ("INDIRECT clause at %C requires a constant "
3377 : "logical expression");
3378 4 : gfc_free_expr (indirect_expr);
3379 4 : goto error;
3380 : }
3381 9 : c->indirect = indirect_expr->value.logical;
3382 9 : gfc_free_expr (indirect_expr);
3383 : }
3384 : else
3385 47 : c->indirect = 1;
3386 56 : continue;
3387 56 : }
3388 304 : if ((mask & OMP_CLAUSE_INIT)
3389 304 : && gfc_match ("init ( ") == MATCH_YES)
3390 : {
3391 108 : m = gfc_match_omp_init (&c->lists[OMP_LIST_INIT]);
3392 108 : if (m == MATCH_YES)
3393 63 : continue;
3394 45 : goto error;
3395 : }
3396 196 : if ((mask & OMP_CLAUSE_INTEROP)
3397 196 : && (m = gfc_match_dupl_check (!c->lists[OMP_LIST_INTEROP],
3398 : "interop", true)) != MATCH_NO)
3399 : {
3400 : /* Note: the interop objects are saved in reverse order to match
3401 : the order in C/C++. */
3402 125 : if (m == MATCH_YES
3403 63 : && (gfc_match_omp_variable_list ("",
3404 : &c->lists[OMP_LIST_INTEROP],
3405 : false, NULL, NULL, false,
3406 : false, NULL, false, true)
3407 : == MATCH_YES))
3408 62 : continue;
3409 1 : goto error;
3410 : }
3411 253 : if ((mask & OMP_CLAUSE_IS_DEVICE_PTR)
3412 253 : && gfc_match_omp_variable_list
3413 120 : ("is_device_ptr (",
3414 : &c->lists[OMP_LIST_IS_DEVICE_PTR], false) == MATCH_YES)
3415 120 : continue;
3416 : break;
3417 2334 : case 'l':
3418 2334 : if ((mask & OMP_CLAUSE_LASTPRIVATE)
3419 2334 : && gfc_match ("lastprivate ( ") == MATCH_YES)
3420 : {
3421 1431 : bool conditional = gfc_match ("conditional : ") == MATCH_YES;
3422 1431 : head = NULL;
3423 1431 : if (gfc_match_omp_variable_list ("",
3424 : &c->lists[OMP_LIST_LASTPRIVATE],
3425 : false, NULL, &head) == MATCH_YES)
3426 : {
3427 1431 : gfc_omp_namelist *n;
3428 3737 : for (n = *head; n; n = n->next)
3429 2306 : n->u.lastprivate_conditional = conditional;
3430 1431 : continue;
3431 1431 : }
3432 0 : gfc_current_locus = old_loc;
3433 0 : break;
3434 : }
3435 903 : end_colon = false;
3436 903 : head = NULL;
3437 903 : if ((mask & OMP_CLAUSE_LINEAR)
3438 903 : && gfc_match ("linear (") == MATCH_YES)
3439 : {
3440 836 : bool old_linear_modifier = false;
3441 836 : gfc_omp_linear_op linear_op = OMP_LINEAR_DEFAULT;
3442 836 : gfc_expr *step = NULL;
3443 836 : locus saved_loc = gfc_current_locus;
3444 :
3445 836 : if (gfc_match_omp_variable_list (" ref (",
3446 : &c->lists[OMP_LIST_LINEAR],
3447 : false, NULL, &head)
3448 : == MATCH_YES)
3449 : {
3450 : linear_op = OMP_LINEAR_REF;
3451 : old_linear_modifier = true;
3452 : }
3453 808 : else if (gfc_match_omp_variable_list (" val (",
3454 : &c->lists[OMP_LIST_LINEAR],
3455 : false, NULL, &head)
3456 : == MATCH_YES)
3457 : {
3458 : linear_op = OMP_LINEAR_VAL;
3459 : old_linear_modifier = true;
3460 : }
3461 797 : else if (gfc_match_omp_variable_list (" uval (",
3462 : &c->lists[OMP_LIST_LINEAR],
3463 : false, NULL, &head)
3464 : == MATCH_YES)
3465 : {
3466 : linear_op = OMP_LINEAR_UVAL;
3467 : old_linear_modifier = true;
3468 : }
3469 788 : else if (gfc_match_omp_variable_list ("",
3470 : &c->lists[OMP_LIST_LINEAR],
3471 : false, &end_colon, &head)
3472 : == MATCH_YES)
3473 : linear_op = OMP_LINEAR_DEFAULT;
3474 : else
3475 : {
3476 2 : gfc_current_locus = old_loc;
3477 2 : break;
3478 : }
3479 : if (linear_op != OMP_LINEAR_DEFAULT)
3480 : {
3481 48 : if (gfc_match (" :") == MATCH_YES)
3482 31 : end_colon = true;
3483 17 : else if (gfc_match (" )") != MATCH_YES)
3484 : {
3485 0 : gfc_free_omp_namelist (*head, OMP_LIST_LINEAR);
3486 0 : gfc_current_locus = old_loc;
3487 0 : *head = NULL;
3488 0 : break;
3489 : }
3490 : }
3491 834 : gfc_gobble_whitespace ();
3492 834 : if (old_linear_modifier && end_colon)
3493 : {
3494 31 : if (gfc_match (" %e )", &step) != MATCH_YES)
3495 : {
3496 1 : gfc_free_omp_namelist (*head, OMP_LIST_LINEAR);
3497 1 : gfc_current_locus = old_loc;
3498 1 : *head = NULL;
3499 5 : goto error;
3500 : }
3501 : }
3502 833 : if (old_linear_modifier)
3503 : {
3504 47 : char var_names[512]{};
3505 47 : int count, offset = 0;
3506 106 : for (gfc_omp_namelist *n = *head; n; n = n->next)
3507 : {
3508 59 : if (!n->next)
3509 47 : count = snprintf (var_names + offset,
3510 47 : sizeof (var_names) - offset,
3511 47 : "%s", n->sym->name);
3512 : else
3513 12 : count = snprintf (var_names + offset,
3514 12 : sizeof (var_names) - offset,
3515 12 : "%s, ", n->sym->name);
3516 59 : if (count < 0 || count >= ((int)sizeof (var_names))
3517 59 : - offset)
3518 : {
3519 0 : snprintf (var_names, 512, "%s, ..., ",
3520 0 : (*head)->sym->name);
3521 0 : while (n->next)
3522 : n = n->next;
3523 0 : offset = strlen (var_names);
3524 0 : snprintf (var_names + offset,
3525 0 : sizeof (var_names) - offset,
3526 0 : "%s", n->sym->name);
3527 0 : break;
3528 : }
3529 59 : offset += count;
3530 : }
3531 47 : char *var_names_for_warn = var_names;
3532 47 : const char *op_name;
3533 47 : switch (linear_op)
3534 : {
3535 : case OMP_LINEAR_REF: op_name = "ref"; break;
3536 10 : case OMP_LINEAR_VAL: op_name = "val"; break;
3537 9 : case OMP_LINEAR_UVAL: op_name = "uval"; break;
3538 0 : default: gcc_unreachable ();
3539 : }
3540 47 : gfc_warning (OPT_Wdeprecated_openmp,
3541 : "Specification of the list items as "
3542 : "arguments to the modifiers at %L is "
3543 : "deprecated; since OpenMP 5.2, use "
3544 : "%<linear(%s : %s%s)%>", &saved_loc,
3545 : var_names_for_warn, op_name,
3546 47 : step == nullptr ? "" : ", step(...)");
3547 : }
3548 786 : else if (end_colon)
3549 : {
3550 713 : bool has_error = false;
3551 : bool has_modifiers = false;
3552 : bool has_step = false;
3553 713 : bool duplicate_step = false;
3554 713 : bool duplicate_mod = false;
3555 713 : while (true)
3556 : {
3557 713 : old_loc = gfc_current_locus;
3558 713 : bool close_paren = gfc_match ("val )") == MATCH_YES;
3559 713 : if (close_paren || gfc_match ("val , ") == MATCH_YES)
3560 : {
3561 17 : if (linear_op != OMP_LINEAR_DEFAULT)
3562 : {
3563 : duplicate_mod = true;
3564 : break;
3565 : }
3566 16 : linear_op = OMP_LINEAR_VAL;
3567 16 : has_modifiers = true;
3568 16 : if (close_paren)
3569 : break;
3570 10 : continue;
3571 : }
3572 696 : close_paren = gfc_match ("uval )") == MATCH_YES;
3573 696 : if (close_paren || gfc_match ("uval , ") == MATCH_YES)
3574 : {
3575 7 : if (linear_op != OMP_LINEAR_DEFAULT)
3576 : {
3577 : duplicate_mod = true;
3578 : break;
3579 : }
3580 7 : linear_op = OMP_LINEAR_UVAL;
3581 7 : has_modifiers = true;
3582 7 : if (close_paren)
3583 : break;
3584 2 : continue;
3585 : }
3586 689 : close_paren = gfc_match ("ref )") == MATCH_YES;
3587 689 : if (close_paren || gfc_match ("ref , ") == MATCH_YES)
3588 : {
3589 16 : if (linear_op != OMP_LINEAR_DEFAULT)
3590 : {
3591 : duplicate_mod = true;
3592 : break;
3593 : }
3594 15 : linear_op = OMP_LINEAR_REF;
3595 15 : has_modifiers = true;
3596 15 : if (close_paren)
3597 : break;
3598 7 : continue;
3599 : }
3600 673 : close_paren = (gfc_match ("step ( %e ) )", &step)
3601 : == MATCH_YES);
3602 684 : if (close_paren
3603 673 : || gfc_match ("step ( %e ) , ", &step) == MATCH_YES)
3604 : {
3605 38 : if (has_step)
3606 : {
3607 : duplicate_step = true;
3608 : break;
3609 : }
3610 37 : has_modifiers = has_step = true;
3611 37 : if (close_paren)
3612 : break;
3613 11 : continue;
3614 : }
3615 635 : if (!has_modifiers
3616 635 : && gfc_match ("%e )", &step) == MATCH_YES)
3617 : {
3618 635 : if ((step->expr_type == EXPR_FUNCTION
3619 634 : || step->expr_type == EXPR_VARIABLE)
3620 31 : && strcmp (step->symtree->name, "step") == 0)
3621 : {
3622 1 : gfc_current_locus = old_loc;
3623 1 : gfc_match ("step (");
3624 1 : has_error = true;
3625 : }
3626 : break;
3627 : }
3628 : has_error = true;
3629 : break;
3630 : }
3631 49 : if (duplicate_mod || duplicate_step)
3632 : {
3633 3 : gfc_error ("Multiple %qs modifiers specified at %C",
3634 : duplicate_mod ? "linear" : "step");
3635 3 : has_error = true;
3636 : }
3637 683 : if (has_error)
3638 : {
3639 4 : gfc_free_omp_namelist (*head, OMP_LIST_LINEAR);
3640 4 : *head = NULL;
3641 4 : goto error;
3642 : }
3643 : }
3644 829 : if (step == NULL)
3645 : {
3646 130 : step = gfc_get_constant_expr (BT_INTEGER,
3647 : gfc_default_integer_kind,
3648 : &old_loc);
3649 130 : mpz_set_si (step->value.integer, 1);
3650 : }
3651 829 : (*head)->expr = step;
3652 829 : if (linear_op != OMP_LINEAR_DEFAULT || old_linear_modifier)
3653 176 : for (gfc_omp_namelist *n = *head; n; n = n->next)
3654 : {
3655 94 : n->u.linear.op = linear_op;
3656 94 : n->u.linear.old_modifier = old_linear_modifier;
3657 : }
3658 829 : continue;
3659 829 : }
3660 71 : if ((mask & OMP_CLAUSE_LINK)
3661 67 : && openacc
3662 75 : && (gfc_match_oacc_clause_link ("link (",
3663 : &c->lists[OMP_LIST_LINK])
3664 : == MATCH_YES))
3665 4 : continue;
3666 110 : else if ((mask & OMP_CLAUSE_LINK)
3667 63 : && !openacc
3668 122 : && (gfc_match_omp_to_link ("link (",
3669 : &c->lists[OMP_LIST_LINK])
3670 : == MATCH_YES))
3671 47 : continue;
3672 28 : if ((mask & OMP_CLAUSE_LOCAL)
3673 16 : && (gfc_match_omp_to_link ("local (", &c->lists[OMP_LIST_LOCAL])
3674 : == MATCH_YES))
3675 12 : continue;
3676 : break;
3677 5222 : case 'm':
3678 5222 : if ((mask & OMP_CLAUSE_MAP)
3679 5222 : && gfc_match ("map ( ") == MATCH_YES)
3680 : {
3681 5130 : locus old_loc2 = gfc_current_locus;
3682 5130 : int always_modifier = 0;
3683 5130 : int close_modifier = 0;
3684 5130 : int present_modifier = 0;
3685 5130 : locus second_always_locus = old_loc2;
3686 5130 : locus second_close_locus = old_loc2;
3687 5130 : locus second_present_locus = old_loc2;
3688 :
3689 5654 : for (;;)
3690 : {
3691 5392 : locus current_locus = gfc_current_locus;
3692 5392 : if (gfc_match ("always ") == MATCH_YES)
3693 : {
3694 141 : if (always_modifier++ == 1)
3695 5 : second_always_locus = current_locus;
3696 : }
3697 5251 : else if (gfc_match ("close ") == MATCH_YES)
3698 : {
3699 66 : if (close_modifier++ == 1)
3700 5 : second_close_locus = current_locus;
3701 : }
3702 5185 : else if (gfc_match ("present ") == MATCH_YES)
3703 : {
3704 55 : if (present_modifier++ == 1)
3705 4 : second_present_locus = current_locus;
3706 : }
3707 : else
3708 : break;
3709 262 : if (gfc_match (", ") != MATCH_YES)
3710 62 : gfc_warning (OPT_Wdeprecated_openmp,
3711 : "The specification of modifiers without "
3712 : "comma separators for the %<map%> clause "
3713 : "at %C has been deprecated since "
3714 : "OpenMP 5.2");
3715 262 : }
3716 :
3717 5130 : gfc_omp_map_op map_op = OMP_MAP_TOFROM;
3718 5130 : int always_present_modifier
3719 5130 : = always_modifier && present_modifier;
3720 :
3721 5130 : if (gfc_match ("alloc : ") == MATCH_YES)
3722 601 : map_op = (present_modifier ? OMP_MAP_PRESENT_ALLOC
3723 : : OMP_MAP_ALLOC);
3724 4529 : else if (gfc_match ("tofrom : ") == MATCH_YES)
3725 841 : map_op = (always_present_modifier ? OMP_MAP_ALWAYS_PRESENT_TOFROM
3726 837 : : present_modifier ? OMP_MAP_PRESENT_TOFROM
3727 833 : : always_modifier ? OMP_MAP_ALWAYS_TOFROM
3728 : : OMP_MAP_TOFROM);
3729 3688 : else if (gfc_match ("to : ") == MATCH_YES)
3730 1629 : map_op = (always_present_modifier ? OMP_MAP_ALWAYS_PRESENT_TO
3731 1623 : : present_modifier ? OMP_MAP_PRESENT_TO
3732 1612 : : always_modifier ? OMP_MAP_ALWAYS_TO
3733 : : OMP_MAP_TO);
3734 2059 : else if (gfc_match ("from : ") == MATCH_YES)
3735 1529 : map_op = (always_present_modifier ? OMP_MAP_ALWAYS_PRESENT_FROM
3736 1525 : : present_modifier ? OMP_MAP_PRESENT_FROM
3737 1521 : : always_modifier ? OMP_MAP_ALWAYS_FROM
3738 : : OMP_MAP_FROM);
3739 530 : else if (gfc_match ("release : ") == MATCH_YES)
3740 : map_op = OMP_MAP_RELEASE;
3741 513 : else if (gfc_match ("delete : ") == MATCH_YES)
3742 : map_op = OMP_MAP_DELETE;
3743 : else
3744 : {
3745 466 : gfc_current_locus = old_loc2;
3746 466 : always_modifier = 0;
3747 466 : close_modifier = 0;
3748 : }
3749 :
3750 1270 : if (always_modifier > 1)
3751 : {
3752 5 : gfc_error ("too many %<always%> modifiers at %L",
3753 : &second_always_locus);
3754 21 : break;
3755 : }
3756 5125 : if (close_modifier > 1)
3757 : {
3758 4 : gfc_error ("too many %<close%> modifiers at %L",
3759 : &second_close_locus);
3760 4 : break;
3761 : }
3762 5121 : if (present_modifier > 1)
3763 : {
3764 4 : gfc_error ("too many %<present%> modifiers at %L",
3765 : &second_present_locus);
3766 4 : break;
3767 : }
3768 :
3769 5117 : head = NULL;
3770 5117 : if (gfc_match_omp_variable_list ("", &c->lists[OMP_LIST_MAP],
3771 : false, NULL, &head,
3772 : true, true) == MATCH_YES)
3773 : {
3774 5114 : gfc_omp_namelist *n;
3775 11799 : for (n = *head; n; n = n->next)
3776 6685 : n->u.map.op = map_op;
3777 5114 : continue;
3778 5114 : }
3779 3 : gfc_current_locus = old_loc;
3780 3 : break;
3781 : }
3782 126 : if ((mask & OMP_CLAUSE_MERGEABLE)
3783 92 : && (m = gfc_match_dupl_check (!c->mergeable, "mergeable"))
3784 : != MATCH_NO)
3785 : {
3786 34 : if (m == MATCH_ERROR)
3787 0 : goto error;
3788 34 : c->mergeable = true;
3789 34 : continue;
3790 : }
3791 111 : if ((mask & OMP_CLAUSE_MESSAGE)
3792 58 : && (m = gfc_match_dupl_check (!c->message, "message", true,
3793 : &c->message)) != MATCH_NO)
3794 : {
3795 58 : if (m == MATCH_ERROR)
3796 5 : goto error;
3797 53 : continue;
3798 : }
3799 : break;
3800 2910 : case 'n':
3801 2962 : if ((mask & OMP_CLAUSE_NO_CREATE)
3802 1343 : && gfc_match ("no_create ( ") == MATCH_YES
3803 2962 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
3804 : OMP_MAP_IF_PRESENT, true,
3805 : allow_derived))
3806 52 : continue;
3807 2859 : if ((mask & OMP_CLAUSE_ASSUMPTIONS)
3808 2884 : && (m = gfc_match_dupl_check (!c->assume
3809 26 : || !c->assume->no_openmp_constructs,
3810 : "no_openmp_constructs")) != MATCH_NO)
3811 : {
3812 2 : if (m == MATCH_ERROR)
3813 1 : goto error;
3814 1 : if (c->assume == NULL)
3815 0 : c->assume = gfc_get_omp_assumptions ();
3816 1 : c->assume->no_openmp_constructs = true;
3817 1 : continue;
3818 : }
3819 2869 : if ((mask & OMP_CLAUSE_ASSUMPTIONS)
3820 2880 : && (m = gfc_match_dupl_check (!c->assume
3821 24 : || !c->assume->no_openmp_routines,
3822 : "no_openmp_routines")) != MATCH_NO)
3823 : {
3824 13 : if (m == MATCH_ERROR)
3825 0 : goto error;
3826 13 : if (c->assume == NULL)
3827 12 : c->assume = gfc_get_omp_assumptions ();
3828 13 : c->assume->no_openmp_routines = true;
3829 13 : continue;
3830 : }
3831 2847 : if ((mask & OMP_CLAUSE_ASSUMPTIONS)
3832 2853 : && (m = gfc_match_dupl_check (!c->assume || !c->assume->no_openmp,
3833 : "no_openmp")) != MATCH_NO)
3834 : {
3835 4 : if (m == MATCH_ERROR)
3836 0 : goto error;
3837 4 : if (c->assume == NULL)
3838 4 : c->assume = gfc_get_omp_assumptions ();
3839 4 : c->assume->no_openmp = true;
3840 4 : continue;
3841 : }
3842 2845 : if ((mask & OMP_CLAUSE_ASSUMPTIONS)
3843 2846 : && (m = gfc_match_dupl_check (!c->assume
3844 7 : || !c->assume->no_parallelism,
3845 : "no_parallelism")) != MATCH_NO)
3846 : {
3847 6 : if (m == MATCH_ERROR)
3848 0 : goto error;
3849 6 : if (c->assume == NULL)
3850 6 : c->assume = gfc_get_omp_assumptions ();
3851 6 : c->assume->no_parallelism = true;
3852 6 : continue;
3853 : }
3854 :
3855 2843 : if ((mask & OMP_CLAUSE_NOVARIANTS)
3856 2833 : && (m = gfc_match_dupl_check (!c->novariants, "novariants", true,
3857 : &c->novariants))
3858 : != MATCH_NO)
3859 : {
3860 12 : if (m == MATCH_ERROR)
3861 2 : goto error;
3862 10 : continue;
3863 : }
3864 2834 : if ((mask & OMP_CLAUSE_NOCONTEXT)
3865 2821 : && (m = gfc_match_dupl_check (!c->nocontext, "nocontext", true,
3866 : &c->nocontext))
3867 : != MATCH_NO)
3868 : {
3869 15 : if (m == MATCH_ERROR)
3870 2 : goto error;
3871 13 : continue;
3872 : }
3873 2820 : if ((mask & OMP_CLAUSE_NOGROUP)
3874 2806 : && (m = gfc_match_dupl_check (!c->nogroup, "nogroup"))
3875 : != MATCH_NO)
3876 : {
3877 14 : if (m == MATCH_ERROR)
3878 0 : goto error;
3879 14 : c->nogroup = true;
3880 14 : continue;
3881 : }
3882 2942 : if ((mask & OMP_CLAUSE_NOHOST)
3883 2792 : && (m = gfc_match_dupl_check (!c->nohost, "nohost")) != MATCH_NO)
3884 : {
3885 151 : if (m == MATCH_ERROR)
3886 1 : goto error;
3887 150 : c->nohost = true;
3888 150 : continue;
3889 : }
3890 2683 : if ((mask & OMP_CLAUSE_NOTEMPORAL)
3891 2641 : && gfc_match_omp_variable_list ("nontemporal (",
3892 : &c->lists[OMP_LIST_NONTEMPORAL],
3893 : true) == MATCH_YES)
3894 42 : continue;
3895 2623 : if ((mask & OMP_CLAUSE_NOTINBRANCH)
3896 2600 : && (m = gfc_match_dupl_check (!c->notinbranch && !c->inbranch,
3897 : "notinbranch")) != MATCH_NO)
3898 : {
3899 25 : if (m == MATCH_ERROR)
3900 1 : goto error;
3901 24 : c->notinbranch = true;
3902 24 : continue;
3903 : }
3904 2703 : if ((mask & OMP_CLAUSE_NOWAIT)
3905 2574 : && (m = gfc_match_dupl_check (!c->nowait, "nowait")) != MATCH_NO)
3906 : {
3907 132 : if (m == MATCH_ERROR)
3908 3 : goto error;
3909 129 : c->nowait = true;
3910 129 : continue;
3911 : }
3912 3124 : if ((mask & OMP_CLAUSE_NUM_GANGS)
3913 2442 : && (m = gfc_match_dupl_check (!c->num_gangs_expr, "num_gangs",
3914 : true)) != MATCH_NO)
3915 : {
3916 686 : if (m == MATCH_ERROR)
3917 2 : goto error;
3918 684 : if (gfc_match (" %e )", &c->num_gangs_expr) != MATCH_YES)
3919 2 : goto error;
3920 682 : continue;
3921 : }
3922 1782 : if ((mask & OMP_CLAUSE_NUM_TASKS)
3923 1756 : && (m = gfc_match_dupl_check (!c->num_tasks, "num_tasks", true))
3924 : != MATCH_NO)
3925 : {
3926 26 : if (m == MATCH_ERROR)
3927 0 : goto error;
3928 26 : if (gfc_match ("strict : ") == MATCH_YES)
3929 1 : c->num_tasks_strict = true;
3930 26 : if (gfc_match (" %e )", &c->num_tasks) != MATCH_YES)
3931 0 : goto error;
3932 26 : continue;
3933 : }
3934 1857 : if ((mask & OMP_CLAUSE_NUM_TEAMS)
3935 1730 : && (m = gfc_match_dupl_check (!c->num_teams_upper, "num_teams",
3936 : true)) != MATCH_NO)
3937 : {
3938 127 : if (m == MATCH_ERROR)
3939 0 : goto error;
3940 127 : if (gfc_match ("%e ", &c->num_teams_upper) != MATCH_YES)
3941 0 : goto error;
3942 127 : if (gfc_peek_ascii_char () == ':')
3943 : {
3944 21 : c->num_teams_lower = c->num_teams_upper;
3945 21 : c->num_teams_upper = NULL;
3946 21 : if (gfc_match (": %e ", &c->num_teams_upper) != MATCH_YES)
3947 0 : goto error;
3948 : }
3949 127 : if (gfc_match (") ") != MATCH_YES)
3950 0 : goto error;
3951 127 : continue;
3952 : }
3953 2565 : if ((mask & OMP_CLAUSE_NUM_THREADS)
3954 1603 : && (m = gfc_match_dupl_check (!c->num_threads, "num_threads", true,
3955 : &c->num_threads)) != MATCH_NO)
3956 : {
3957 962 : if (m == MATCH_ERROR)
3958 0 : goto error;
3959 962 : continue;
3960 : }
3961 1240 : if ((mask & OMP_CLAUSE_NUM_WORKERS)
3962 641 : && (m = gfc_match_dupl_check (!c->num_workers_expr, "num_workers",
3963 : true, &c->num_workers_expr))
3964 : != MATCH_NO)
3965 : {
3966 603 : if (m == MATCH_ERROR)
3967 4 : goto error;
3968 599 : continue;
3969 : }
3970 : break;
3971 591 : case 'o':
3972 591 : if ((mask & OMP_CLAUSE_ORDERED)
3973 591 : && (m = gfc_match_dupl_check (!c->ordered, "ordered"))
3974 : != MATCH_NO)
3975 : {
3976 343 : if (m == MATCH_ERROR)
3977 0 : goto error;
3978 343 : gfc_expr *cexpr = NULL;
3979 343 : m = gfc_match (" ( %e )", &cexpr);
3980 :
3981 343 : c->ordered = true;
3982 343 : if (m == MATCH_YES)
3983 : {
3984 144 : int ordered = 0;
3985 144 : if (gfc_extract_int (cexpr, &ordered, -1))
3986 0 : ordered = 0;
3987 144 : else if (ordered <= 0)
3988 : {
3989 0 : gfc_error_now ("ORDERED clause argument not"
3990 : " constant positive integer at %C");
3991 0 : ordered = 0;
3992 : }
3993 144 : c->orderedc = ordered;
3994 144 : gfc_free_expr (cexpr);
3995 144 : continue;
3996 144 : }
3997 :
3998 199 : continue;
3999 199 : }
4000 482 : if ((mask & OMP_CLAUSE_ORDER)
4001 248 : && (m = gfc_match_dupl_check (!c->order_concurrent, "order", true))
4002 : != MATCH_NO)
4003 : {
4004 247 : if (m == MATCH_ERROR)
4005 10 : goto error;
4006 237 : if (gfc_match (" reproducible : concurrent )") == MATCH_YES)
4007 55 : c->order_reproducible = true;
4008 182 : else if (gfc_match (" concurrent )") == MATCH_YES)
4009 : ;
4010 50 : else if (gfc_match (" unconstrained : concurrent )") == MATCH_YES)
4011 47 : c->order_unconstrained = true;
4012 : else
4013 : {
4014 3 : gfc_error ("Expected ORDER(CONCURRENT) at %C "
4015 : "with optional %<reproducible%> or "
4016 : "%<unconstrained%> modifier");
4017 3 : goto error;
4018 : }
4019 234 : c->order_concurrent = true;
4020 234 : continue;
4021 : }
4022 : break;
4023 3101 : case 'p':
4024 3101 : if (mask & OMP_CLAUSE_PARTIAL)
4025 : {
4026 276 : if ((m = gfc_match_dupl_check (!c->partial, "partial"))
4027 : != MATCH_NO)
4028 : {
4029 276 : int expr;
4030 276 : if (m == MATCH_ERROR)
4031 0 : goto error;
4032 :
4033 276 : c->partial = -1;
4034 :
4035 276 : gfc_expr *cexpr = NULL;
4036 276 : m = gfc_match (" ( %e )", &cexpr);
4037 276 : if (m == MATCH_NO)
4038 : ;
4039 251 : else if (m == MATCH_YES
4040 251 : && !gfc_extract_int (cexpr, &expr, -1)
4041 502 : && expr > 0)
4042 247 : c->partial = expr;
4043 : else
4044 4 : gfc_error_now ("PARTIAL clause argument not constant "
4045 : "positive integer at %C");
4046 276 : gfc_free_expr (cexpr);
4047 276 : continue;
4048 276 : }
4049 : }
4050 2894 : if ((mask & OMP_CLAUSE_COPY)
4051 877 : && gfc_match ("pcopy ( ") == MATCH_YES
4052 2895 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4053 : OMP_MAP_TOFROM, true, allow_derived))
4054 69 : continue;
4055 2830 : if ((mask & OMP_CLAUSE_COPYIN)
4056 1910 : && gfc_match ("pcopyin ( ") == MATCH_YES
4057 2830 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4058 : OMP_MAP_TO, true, allow_derived))
4059 74 : continue;
4060 2755 : if ((mask & OMP_CLAUSE_COPYOUT)
4061 735 : && gfc_match ("pcopyout ( ") == MATCH_YES
4062 2755 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4063 : OMP_MAP_FROM, true, allow_derived))
4064 73 : continue;
4065 2624 : if ((mask & OMP_CLAUSE_CREATE)
4066 672 : && gfc_match ("pcreate ( ") == MATCH_YES
4067 2624 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4068 : OMP_MAP_ALLOC, true, allow_derived))
4069 15 : continue;
4070 3010 : if ((mask & OMP_CLAUSE_PRESENT)
4071 647 : && gfc_match ("present ( ") == MATCH_YES
4072 3012 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4073 : OMP_MAP_FORCE_PRESENT, false,
4074 : allow_derived))
4075 416 : continue;
4076 2201 : if ((mask & OMP_CLAUSE_COPY)
4077 231 : && gfc_match ("present_or_copy ( ") == MATCH_YES
4078 2201 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4079 : OMP_MAP_TOFROM, true,
4080 : allow_derived))
4081 23 : continue;
4082 2195 : if ((mask & OMP_CLAUSE_COPYIN)
4083 1309 : && gfc_match ("present_or_copyin ( ") == MATCH_YES
4084 2195 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4085 : OMP_MAP_TO, true, allow_derived))
4086 40 : continue;
4087 2150 : if ((mask & OMP_CLAUSE_COPYOUT)
4088 173 : && gfc_match ("present_or_copyout ( ") == MATCH_YES
4089 2150 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4090 : OMP_MAP_FROM, true, allow_derived))
4091 35 : continue;
4092 2108 : if ((mask & OMP_CLAUSE_CREATE)
4093 143 : && gfc_match ("present_or_create ( ") == MATCH_YES
4094 2108 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4095 : OMP_MAP_ALLOC, true, allow_derived))
4096 28 : continue;
4097 2086 : if ((mask & OMP_CLAUSE_PRIORITY)
4098 2052 : && (m = gfc_match_dupl_check (!c->priority, "priority", true,
4099 : &c->priority)) != MATCH_NO)
4100 : {
4101 34 : if (m == MATCH_ERROR)
4102 0 : goto error;
4103 34 : continue;
4104 : }
4105 3959 : if ((mask & OMP_CLAUSE_PRIVATE)
4106 2018 : && gfc_match_omp_variable_list ("private (",
4107 : &c->lists[OMP_LIST_PRIVATE],
4108 : true) == MATCH_YES)
4109 1941 : continue;
4110 141 : if ((mask & OMP_CLAUSE_PROC_BIND)
4111 141 : && (m = gfc_match_dupl_check ((c->proc_bind
4112 64 : == OMP_PROC_BIND_UNKNOWN),
4113 : "proc_bind", true)) != MATCH_NO)
4114 : {
4115 64 : if (m == MATCH_ERROR)
4116 0 : goto error;
4117 64 : if (gfc_match ("primary )") == MATCH_YES)
4118 1 : c->proc_bind = OMP_PROC_BIND_PRIMARY;
4119 63 : else if (gfc_match ("master )") == MATCH_YES)
4120 : {
4121 9 : gfc_warning (OPT_Wdeprecated_openmp,
4122 : "%<master%> affinity policy at %C deprecated "
4123 : "since OpenMP 5.1, use %<primary%>");
4124 9 : c->proc_bind = OMP_PROC_BIND_MASTER;
4125 : }
4126 54 : else if (gfc_match ("spread )") == MATCH_YES)
4127 53 : c->proc_bind = OMP_PROC_BIND_SPREAD;
4128 1 : else if (gfc_match ("close )") == MATCH_YES)
4129 1 : c->proc_bind = OMP_PROC_BIND_CLOSE;
4130 : else
4131 0 : goto error;
4132 64 : continue;
4133 : }
4134 : break;
4135 4580 : case 'r':
4136 5070 : if ((mask & OMP_CLAUSE_ATOMIC)
4137 4580 : && (m = gfc_match_dupl_atomic ((c->atomic_op
4138 : == GFC_OMP_ATOMIC_UNSET),
4139 : "read")) != MATCH_NO)
4140 : {
4141 490 : if (m == MATCH_ERROR)
4142 0 : goto error;
4143 490 : c->atomic_op = GFC_OMP_ATOMIC_READ;
4144 490 : continue;
4145 : }
4146 8143 : if ((mask & OMP_CLAUSE_REDUCTION)
4147 4090 : && gfc_match_omp_clause_reduction (pc, c, openacc,
4148 : allow_derived) == MATCH_YES)
4149 4053 : continue;
4150 47 : if ((mask & OMP_CLAUSE_MEMORDER)
4151 65 : && (m = gfc_match_dupl_memorder ((c->memorder
4152 28 : == OMP_MEMORDER_UNSET),
4153 : "relaxed")) != MATCH_NO)
4154 : {
4155 10 : if (m == MATCH_ERROR)
4156 0 : goto error;
4157 10 : c->memorder = OMP_MEMORDER_RELAXED;
4158 10 : continue;
4159 : }
4160 44 : if ((mask & OMP_CLAUSE_MEMORDER)
4161 45 : && (m = gfc_match_dupl_memorder ((c->memorder
4162 18 : == OMP_MEMORDER_UNSET),
4163 : "release")) != MATCH_NO)
4164 : {
4165 18 : if (m == MATCH_ERROR)
4166 1 : goto error;
4167 17 : c->memorder = OMP_MEMORDER_RELEASE;
4168 17 : continue;
4169 : }
4170 : break;
4171 3036 : case 's':
4172 3129 : if ((mask & OMP_CLAUSE_SAFELEN)
4173 3036 : && (m = gfc_match_dupl_check (!c->safelen_expr, "safelen",
4174 : true, &c->safelen_expr))
4175 : != MATCH_NO)
4176 : {
4177 93 : if (m == MATCH_ERROR)
4178 0 : goto error;
4179 93 : continue;
4180 : }
4181 2943 : if ((mask & OMP_CLAUSE_SCHEDULE)
4182 2943 : && (m = gfc_match_dupl_check (c->sched_kind == OMP_SCHED_NONE,
4183 : "schedule", true)) != MATCH_NO)
4184 : {
4185 809 : if (m == MATCH_ERROR)
4186 0 : goto error;
4187 809 : int nmodifiers = 0;
4188 809 : locus old_loc2 = gfc_current_locus;
4189 827 : do
4190 : {
4191 818 : if (gfc_match ("simd") == MATCH_YES)
4192 : {
4193 18 : c->sched_simd = true;
4194 18 : nmodifiers++;
4195 : }
4196 800 : else if (gfc_match ("monotonic") == MATCH_YES)
4197 : {
4198 30 : c->sched_monotonic = true;
4199 30 : nmodifiers++;
4200 : }
4201 770 : else if (gfc_match ("nonmonotonic") == MATCH_YES)
4202 : {
4203 35 : c->sched_nonmonotonic = true;
4204 35 : nmodifiers++;
4205 : }
4206 : else
4207 : {
4208 735 : if (nmodifiers)
4209 0 : gfc_current_locus = old_loc2;
4210 : break;
4211 : }
4212 92 : if (nmodifiers == 1
4213 83 : && gfc_match (" , ") == MATCH_YES)
4214 9 : continue;
4215 74 : else if (gfc_match (" : ") == MATCH_YES)
4216 : break;
4217 0 : gfc_current_locus = old_loc2;
4218 0 : break;
4219 : }
4220 : while (1);
4221 809 : if (gfc_match ("static") == MATCH_YES)
4222 425 : c->sched_kind = OMP_SCHED_STATIC;
4223 384 : else if (gfc_match ("dynamic") == MATCH_YES)
4224 164 : c->sched_kind = OMP_SCHED_DYNAMIC;
4225 220 : else if (gfc_match ("guided") == MATCH_YES)
4226 127 : c->sched_kind = OMP_SCHED_GUIDED;
4227 93 : else if (gfc_match ("runtime") == MATCH_YES)
4228 85 : c->sched_kind = OMP_SCHED_RUNTIME;
4229 8 : else if (gfc_match ("auto") == MATCH_YES)
4230 8 : c->sched_kind = OMP_SCHED_AUTO;
4231 809 : if (c->sched_kind != OMP_SCHED_NONE)
4232 : {
4233 809 : m = MATCH_NO;
4234 809 : if (c->sched_kind != OMP_SCHED_RUNTIME
4235 809 : && c->sched_kind != OMP_SCHED_AUTO)
4236 716 : m = gfc_match (" , %e )", &c->chunk_size);
4237 716 : if (m != MATCH_YES)
4238 299 : m = gfc_match_char (')');
4239 299 : if (m != MATCH_YES)
4240 0 : c->sched_kind = OMP_SCHED_NONE;
4241 : }
4242 809 : if (c->sched_kind != OMP_SCHED_NONE)
4243 809 : continue;
4244 : else
4245 0 : gfc_current_locus = old_loc;
4246 : }
4247 2317 : if ((mask & OMP_CLAUSE_SELF)
4248 335 : && !(mask & OMP_CLAUSE_HOST) /* OpenACC compute construct */
4249 2374 : && (m = gfc_match_dupl_check (!c->self_expr, "self"))
4250 : != MATCH_NO)
4251 : {
4252 186 : if (m == MATCH_ERROR)
4253 3 : goto error;
4254 183 : m = gfc_match (" ( %e )", &c->self_expr);
4255 183 : if (m == MATCH_ERROR)
4256 : {
4257 0 : gfc_current_locus = old_loc;
4258 0 : break;
4259 : }
4260 183 : else if (m == MATCH_NO)
4261 9 : c->self_expr = gfc_get_logical_expr (gfc_default_logical_kind,
4262 : NULL, true);
4263 183 : continue;
4264 : }
4265 2042 : if ((mask & OMP_CLAUSE_SELF)
4266 149 : && (mask & OMP_CLAUSE_HOST) /* OpenACC 'update' directive */
4267 95 : && gfc_match ("self ( ") == MATCH_YES
4268 2043 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4269 : OMP_MAP_FORCE_FROM, true,
4270 : /* allow_derived = */ true))
4271 94 : continue;
4272 2202 : if ((mask & OMP_CLAUSE_SEQ)
4273 1854 : && (m = gfc_match_dupl_check (!c->seq, "seq")) != MATCH_NO)
4274 : {
4275 348 : if (m == MATCH_ERROR)
4276 0 : goto error;
4277 348 : c->seq = true;
4278 348 : continue;
4279 : }
4280 1647 : if ((mask & OMP_CLAUSE_MEMORDER)
4281 1647 : && (m = gfc_match_dupl_memorder ((c->memorder
4282 141 : == OMP_MEMORDER_UNSET),
4283 : "seq_cst")) != MATCH_NO)
4284 : {
4285 141 : if (m == MATCH_ERROR)
4286 0 : goto error;
4287 141 : c->memorder = OMP_MEMORDER_SEQ_CST;
4288 141 : continue;
4289 : }
4290 2340 : if ((mask & OMP_CLAUSE_SHARED)
4291 1365 : && gfc_match_omp_variable_list ("shared (",
4292 : &c->lists[OMP_LIST_SHARED],
4293 : true) == MATCH_YES)
4294 975 : continue;
4295 508 : if ((mask & OMP_CLAUSE_SIMDLEN)
4296 390 : && (m = gfc_match_dupl_check (!c->simdlen_expr, "simdlen", true,
4297 : &c->simdlen_expr)) != MATCH_NO)
4298 : {
4299 118 : if (m == MATCH_ERROR)
4300 0 : goto error;
4301 118 : continue;
4302 : }
4303 294 : if ((mask & OMP_CLAUSE_SIMD)
4304 272 : && (m = gfc_match_dupl_check (!c->simd, "simd")) != MATCH_NO)
4305 : {
4306 22 : if (m == MATCH_ERROR)
4307 0 : goto error;
4308 22 : c->simd = true;
4309 22 : continue;
4310 : }
4311 289 : if ((mask & OMP_CLAUSE_SEVERITY)
4312 250 : && (m = gfc_match_dupl_check (!c->severity, "severity", true))
4313 : != MATCH_NO)
4314 : {
4315 45 : if (m == MATCH_ERROR)
4316 2 : goto error;
4317 43 : if (gfc_match ("fatal )") == MATCH_YES)
4318 10 : c->severity = OMP_SEVERITY_FATAL;
4319 33 : else if (gfc_match ("warning )") == MATCH_YES)
4320 29 : c->severity = OMP_SEVERITY_WARNING;
4321 : else
4322 : {
4323 4 : gfc_error ("Expected FATAL or WARNING in SEVERITY clause "
4324 : "at %C");
4325 4 : goto error;
4326 : }
4327 39 : continue;
4328 : }
4329 205 : if ((mask & OMP_CLAUSE_SIZES)
4330 205 : && ((m = gfc_match_dupl_check (!c->sizes_list, "sizes"))
4331 : != MATCH_NO))
4332 : {
4333 203 : if (m == MATCH_ERROR)
4334 0 : goto error;
4335 203 : m = match_omp_oacc_expr_list (" (", &c->sizes_list, false, true);
4336 203 : if (m == MATCH_ERROR)
4337 7 : goto error;
4338 196 : if (m == MATCH_YES)
4339 195 : continue;
4340 1 : gfc_error ("Expected %<(%> after %qs at %C", "sizes");
4341 1 : goto error;
4342 : }
4343 : break;
4344 1203 : case 't':
4345 1268 : if ((mask & OMP_CLAUSE_TASK_REDUCTION)
4346 1203 : && gfc_match_omp_clause_reduction (pc, c, openacc,
4347 : allow_derived) == MATCH_YES)
4348 65 : continue;
4349 1210 : if ((mask & OMP_CLAUSE_THREAD_LIMIT)
4350 1138 : && (m = gfc_match_dupl_check (!c->thread_limit, "thread_limit",
4351 : true, &c->thread_limit))
4352 : != MATCH_NO)
4353 : {
4354 72 : if (m == MATCH_ERROR)
4355 0 : goto error;
4356 72 : continue;
4357 : }
4358 1079 : if ((mask & OMP_CLAUSE_THREADS)
4359 1066 : && (m = gfc_match_dupl_check (!c->threads, "threads"))
4360 : != MATCH_NO)
4361 : {
4362 13 : if (m == MATCH_ERROR)
4363 0 : goto error;
4364 13 : c->threads = true;
4365 13 : continue;
4366 : }
4367 1250 : if ((mask & OMP_CLAUSE_TILE)
4368 221 : && !c->tile_list
4369 1274 : && match_omp_oacc_expr_list ("tile (", &c->tile_list,
4370 : true, false) == MATCH_YES)
4371 197 : continue;
4372 856 : if ((mask & OMP_CLAUSE_TO) && (mask & OMP_CLAUSE_LINK))
4373 : {
4374 : /* Declare target: 'to' is an alias for 'enter';
4375 : 'to' is deprecated since 5.2. */
4376 116 : m = gfc_match_omp_to_link ("to (", &c->lists[OMP_LIST_TO]);
4377 116 : if (m == MATCH_ERROR)
4378 0 : goto error;
4379 116 : if (m == MATCH_YES)
4380 : {
4381 116 : gfc_warning (OPT_Wdeprecated_openmp,
4382 : "%<to%> clause with %<declare target%> at %L "
4383 : "deprecated since OpenMP 5.2, use %<enter%>",
4384 : &old_loc);
4385 116 : continue;
4386 : }
4387 : }
4388 1456 : else if ((mask & OMP_CLAUSE_TO)
4389 740 : && gfc_match_motion_var_list ("to (", &c->lists[OMP_LIST_TO],
4390 : &head) == MATCH_YES)
4391 716 : continue;
4392 : break;
4393 1516 : case 'u':
4394 1574 : if ((mask & OMP_CLAUSE_UNIFORM)
4395 1516 : && gfc_match_omp_variable_list ("uniform (",
4396 : &c->lists[OMP_LIST_UNIFORM],
4397 : false) == MATCH_YES)
4398 58 : continue;
4399 1599 : if ((mask & OMP_CLAUSE_UNTIED)
4400 1458 : && (m = gfc_match_dupl_check (!c->untied, "untied")) != MATCH_NO)
4401 : {
4402 141 : if (m == MATCH_ERROR)
4403 0 : goto error;
4404 141 : c->untied = true;
4405 141 : continue;
4406 : }
4407 1561 : if ((mask & OMP_CLAUSE_ATOMIC)
4408 1317 : && (m = gfc_match_dupl_atomic ((c->atomic_op
4409 : == GFC_OMP_ATOMIC_UNSET),
4410 : "update")) != MATCH_NO)
4411 : {
4412 245 : if (m == MATCH_ERROR)
4413 1 : goto error;
4414 244 : c->atomic_op = GFC_OMP_ATOMIC_UPDATE;
4415 244 : continue;
4416 : }
4417 1094 : if ((mask & OMP_CLAUSE_USE)
4418 1072 : && gfc_match_omp_variable_list ("use (",
4419 : &c->lists[OMP_LIST_USE],
4420 : true) == MATCH_YES)
4421 22 : continue;
4422 1110 : if ((mask & OMP_CLAUSE_USE_DEVICE)
4423 1050 : && gfc_match_omp_variable_list ("use_device (",
4424 : &c->lists[OMP_LIST_USE_DEVICE],
4425 : true) == MATCH_YES)
4426 60 : continue;
4427 1153 : if ((mask & OMP_CLAUSE_USE_DEVICE_PTR)
4428 1918 : && gfc_match_omp_variable_list
4429 928 : ("use_device_ptr (",
4430 : &c->lists[OMP_LIST_USE_DEVICE_PTR], false) == MATCH_YES)
4431 163 : continue;
4432 1592 : if ((mask & OMP_CLAUSE_USE_DEVICE_ADDR)
4433 1592 : && gfc_match_omp_variable_list
4434 765 : ("use_device_addr (", &c->lists[OMP_LIST_USE_DEVICE_ADDR],
4435 : false, NULL, NULL, true) == MATCH_YES)
4436 765 : continue;
4437 114 : if ((mask & OMP_CLAUSE_USES_ALLOCATORS)
4438 62 : && (gfc_match ("uses_allocators ( ") == MATCH_YES))
4439 : {
4440 56 : if (gfc_match_omp_clause_uses_allocators (c) != MATCH_YES)
4441 4 : goto error;
4442 52 : continue;
4443 : }
4444 : break;
4445 1570 : case 'v':
4446 : /* VECTOR_LENGTH must be matched before VECTOR, because the latter
4447 : doesn't unconditionally match '('. */
4448 2139 : if ((mask & OMP_CLAUSE_VECTOR_LENGTH)
4449 1570 : && (m = gfc_match_dupl_check (!c->vector_length_expr,
4450 : "vector_length", true,
4451 : &c->vector_length_expr))
4452 : != MATCH_NO)
4453 : {
4454 573 : if (m == MATCH_ERROR)
4455 4 : goto error;
4456 569 : continue;
4457 : }
4458 1989 : if ((mask & OMP_CLAUSE_VECTOR)
4459 997 : && (m = gfc_match_dupl_check (!c->vector, "vector")) != MATCH_NO)
4460 : {
4461 995 : if (m == MATCH_ERROR)
4462 0 : goto error;
4463 995 : c->vector = true;
4464 995 : m = match_oacc_clause_gwv (c, GOMP_DIM_VECTOR);
4465 995 : if (m == MATCH_ERROR)
4466 3 : goto error;
4467 992 : continue;
4468 : }
4469 : break;
4470 1482 : case 'w':
4471 1482 : if ((mask & OMP_CLAUSE_WAIT)
4472 1482 : && gfc_match ("wait") == MATCH_YES)
4473 : {
4474 192 : m = match_omp_oacc_expr_list (" (", &c->wait_list, false, false);
4475 192 : if (m == MATCH_ERROR)
4476 9 : goto error;
4477 183 : else if (m == MATCH_NO)
4478 : {
4479 47 : gfc_expr *expr
4480 47 : = gfc_get_constant_expr (BT_INTEGER,
4481 : gfc_default_integer_kind,
4482 : &gfc_current_locus);
4483 47 : mpz_set_si (expr->value.integer, GOMP_ASYNC_NOVAL);
4484 47 : gfc_expr_list **expr_list = &c->wait_list;
4485 56 : while (*expr_list)
4486 9 : expr_list = &(*expr_list)->next;
4487 47 : *expr_list = gfc_get_expr_list ();
4488 47 : (*expr_list)->expr = expr;
4489 47 : needs_space = true;
4490 : }
4491 183 : continue;
4492 183 : }
4493 1303 : if ((mask & OMP_CLAUSE_WEAK)
4494 1290 : && (m = gfc_match_dupl_check (!c->weak, "weak"))
4495 : != MATCH_NO)
4496 : {
4497 14 : if (m == MATCH_ERROR)
4498 1 : goto error;
4499 13 : c->weak = true;
4500 13 : continue;
4501 : }
4502 2137 : if ((mask & OMP_CLAUSE_WORKER)
4503 1276 : && (m = gfc_match_dupl_check (!c->worker, "worker")) != MATCH_NO)
4504 : {
4505 864 : if (m == MATCH_ERROR)
4506 0 : goto error;
4507 864 : c->worker = true;
4508 864 : m = match_oacc_clause_gwv (c, GOMP_DIM_WORKER);
4509 864 : if (m == MATCH_ERROR)
4510 3 : goto error;
4511 861 : continue;
4512 : }
4513 824 : if ((mask & OMP_CLAUSE_ATOMIC)
4514 412 : && (m = gfc_match_dupl_atomic ((c->atomic_op
4515 : == GFC_OMP_ATOMIC_UNSET),
4516 : "write")) != MATCH_NO)
4517 : {
4518 412 : if (m == MATCH_ERROR)
4519 0 : goto error;
4520 412 : c->atomic_op = GFC_OMP_ATOMIC_WRITE;
4521 412 : continue;
4522 : }
4523 : break;
4524 : }
4525 : break;
4526 45461 : }
4527 :
4528 34124 : end:
4529 33870 : if (error || gfc_match_omp_eos () != MATCH_YES)
4530 : {
4531 521 : if (!gfc_error_flag_test ())
4532 137 : gfc_error ("Failed to match clause at %C");
4533 521 : gfc_free_omp_clauses (c);
4534 521 : return MATCH_ERROR;
4535 : }
4536 :
4537 33603 : *cp = c;
4538 33603 : return MATCH_YES;
4539 :
4540 254 : error:
4541 254 : error = true;
4542 254 : goto end;
4543 : }
4544 :
4545 :
4546 : #define OACC_PARALLEL_CLAUSES \
4547 : (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_NUM_GANGS \
4548 : | OMP_CLAUSE_NUM_WORKERS | OMP_CLAUSE_VECTOR_LENGTH | OMP_CLAUSE_REDUCTION \
4549 : | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT \
4550 : | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT \
4551 : | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE \
4552 : | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH \
4553 : | OMP_CLAUSE_SELF)
4554 : #define OACC_KERNELS_CLAUSES \
4555 : (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_NUM_GANGS \
4556 : | OMP_CLAUSE_NUM_WORKERS | OMP_CLAUSE_VECTOR_LENGTH | OMP_CLAUSE_DEVICEPTR \
4557 : | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT \
4558 : | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT \
4559 : | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH \
4560 : | OMP_CLAUSE_SELF)
4561 : #define OACC_SERIAL_CLAUSES \
4562 : (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_REDUCTION \
4563 : | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT \
4564 : | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT \
4565 : | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE \
4566 : | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH \
4567 : | OMP_CLAUSE_SELF)
4568 : #define OACC_DATA_CLAUSES \
4569 : (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_COPY \
4570 : | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_CREATE \
4571 : | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT | OMP_CLAUSE_ATTACH \
4572 : | OMP_CLAUSE_DEFAULT)
4573 : #define OACC_LOOP_CLAUSES \
4574 : (omp_mask (OMP_CLAUSE_COLLAPSE) | OMP_CLAUSE_GANG | OMP_CLAUSE_WORKER \
4575 : | OMP_CLAUSE_VECTOR | OMP_CLAUSE_SEQ | OMP_CLAUSE_INDEPENDENT \
4576 : | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_AUTO \
4577 : | OMP_CLAUSE_TILE)
4578 : #define OACC_PARALLEL_LOOP_CLAUSES \
4579 : (OACC_LOOP_CLAUSES | OACC_PARALLEL_CLAUSES)
4580 : #define OACC_KERNELS_LOOP_CLAUSES \
4581 : (OACC_LOOP_CLAUSES | OACC_KERNELS_CLAUSES)
4582 : #define OACC_SERIAL_LOOP_CLAUSES \
4583 : (OACC_LOOP_CLAUSES | OACC_SERIAL_CLAUSES)
4584 : #define OACC_HOST_DATA_CLAUSES \
4585 : (omp_mask (OMP_CLAUSE_USE_DEVICE) \
4586 : | OMP_CLAUSE_IF \
4587 : | OMP_CLAUSE_IF_PRESENT)
4588 : #define OACC_DECLARE_CLAUSES \
4589 : (omp_mask (OMP_CLAUSE_COPY) | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT \
4590 : | OMP_CLAUSE_CREATE | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_DEVICE_RESIDENT \
4591 : | OMP_CLAUSE_PRESENT \
4592 : | OMP_CLAUSE_LINK)
4593 : #define OACC_UPDATE_CLAUSES \
4594 : (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_HOST \
4595 : | OMP_CLAUSE_DEVICE | OMP_CLAUSE_WAIT | OMP_CLAUSE_IF_PRESENT \
4596 : | OMP_CLAUSE_SELF)
4597 : #define OACC_ENTER_DATA_CLAUSES \
4598 : (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_WAIT \
4599 : | OMP_CLAUSE_COPYIN | OMP_CLAUSE_CREATE | OMP_CLAUSE_ATTACH)
4600 : #define OACC_EXIT_DATA_CLAUSES \
4601 : (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_WAIT \
4602 : | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_DELETE | OMP_CLAUSE_FINALIZE \
4603 : | OMP_CLAUSE_DETACH)
4604 : #define OACC_WAIT_CLAUSES \
4605 : omp_mask (OMP_CLAUSE_ASYNC) | OMP_CLAUSE_IF
4606 : #define OACC_ROUTINE_CLAUSES \
4607 : (omp_mask (OMP_CLAUSE_GANG) | OMP_CLAUSE_WORKER | OMP_CLAUSE_VECTOR \
4608 : | OMP_CLAUSE_SEQ \
4609 : | OMP_CLAUSE_NOHOST)
4610 :
4611 :
4612 : static match
4613 11804 : match_acc (gfc_exec_op op, const omp_mask mask)
4614 : {
4615 11804 : gfc_omp_clauses *c;
4616 11804 : if (gfc_match_omp_clauses (&c, mask, false, false, true) != MATCH_YES)
4617 : return MATCH_ERROR;
4618 11599 : new_st.op = op;
4619 11599 : new_st.ext.omp_clauses = c;
4620 11599 : return MATCH_YES;
4621 : }
4622 :
4623 : match
4624 1378 : gfc_match_oacc_parallel_loop (void)
4625 : {
4626 1378 : return match_acc (EXEC_OACC_PARALLEL_LOOP, OACC_PARALLEL_LOOP_CLAUSES);
4627 : }
4628 :
4629 :
4630 : match
4631 2974 : gfc_match_oacc_parallel (void)
4632 : {
4633 2974 : return match_acc (EXEC_OACC_PARALLEL, OACC_PARALLEL_CLAUSES);
4634 : }
4635 :
4636 :
4637 : match
4638 129 : gfc_match_oacc_kernels_loop (void)
4639 : {
4640 129 : return match_acc (EXEC_OACC_KERNELS_LOOP, OACC_KERNELS_LOOP_CLAUSES);
4641 : }
4642 :
4643 :
4644 : match
4645 906 : gfc_match_oacc_kernels (void)
4646 : {
4647 906 : return match_acc (EXEC_OACC_KERNELS, OACC_KERNELS_CLAUSES);
4648 : }
4649 :
4650 :
4651 : match
4652 230 : gfc_match_oacc_serial_loop (void)
4653 : {
4654 230 : return match_acc (EXEC_OACC_SERIAL_LOOP, OACC_SERIAL_LOOP_CLAUSES);
4655 : }
4656 :
4657 :
4658 : match
4659 359 : gfc_match_oacc_serial (void)
4660 : {
4661 359 : return match_acc (EXEC_OACC_SERIAL, OACC_SERIAL_CLAUSES);
4662 : }
4663 :
4664 :
4665 : match
4666 689 : gfc_match_oacc_data (void)
4667 : {
4668 689 : return match_acc (EXEC_OACC_DATA, OACC_DATA_CLAUSES);
4669 : }
4670 :
4671 :
4672 : match
4673 65 : gfc_match_oacc_host_data (void)
4674 : {
4675 65 : return match_acc (EXEC_OACC_HOST_DATA, OACC_HOST_DATA_CLAUSES);
4676 : }
4677 :
4678 :
4679 : match
4680 3585 : gfc_match_oacc_loop (void)
4681 : {
4682 3585 : return match_acc (EXEC_OACC_LOOP, OACC_LOOP_CLAUSES);
4683 : }
4684 :
4685 :
4686 : match
4687 178 : gfc_match_oacc_declare (void)
4688 : {
4689 178 : gfc_omp_clauses *c;
4690 178 : gfc_omp_namelist *n;
4691 178 : gfc_namespace *ns = gfc_current_ns;
4692 178 : gfc_oacc_declare *new_oc;
4693 178 : bool module_var = false;
4694 178 : locus where = gfc_current_locus;
4695 :
4696 178 : if (gfc_match_omp_clauses (&c, OACC_DECLARE_CLAUSES, false, false, true)
4697 : != MATCH_YES)
4698 : return MATCH_ERROR;
4699 :
4700 262 : for (n = c->lists[OMP_LIST_DEVICE_RESIDENT]; n != NULL; n = n->next)
4701 90 : n->sym->attr.oacc_declare_device_resident = 1;
4702 :
4703 192 : for (n = c->lists[OMP_LIST_LINK]; n != NULL; n = n->next)
4704 20 : n->sym->attr.oacc_declare_link = 1;
4705 :
4706 318 : for (n = c->lists[OMP_LIST_MAP]; n != NULL; n = n->next)
4707 : {
4708 156 : gfc_symbol *s = n->sym;
4709 :
4710 156 : if (gfc_current_ns->proc_name
4711 156 : && gfc_current_ns->proc_name->attr.flavor == FL_MODULE)
4712 : {
4713 52 : if (n->u.map.op != OMP_MAP_ALLOC && n->u.map.op != OMP_MAP_TO)
4714 : {
4715 6 : gfc_error ("Invalid clause in module with !$ACC DECLARE at %L",
4716 : &where);
4717 6 : return MATCH_ERROR;
4718 : }
4719 :
4720 : module_var = true;
4721 : }
4722 :
4723 150 : if (s->attr.use_assoc)
4724 : {
4725 0 : gfc_error ("Variable is USE-associated with !$ACC DECLARE at %L",
4726 : &where);
4727 0 : return MATCH_ERROR;
4728 : }
4729 :
4730 150 : if ((s->result == s && s->ns->contained != gfc_current_ns)
4731 150 : || ((s->attr.flavor == FL_UNKNOWN || s->attr.flavor == FL_VARIABLE)
4732 135 : && s->ns != gfc_current_ns))
4733 : {
4734 2 : gfc_error ("Variable %qs shall be declared in the same scoping unit "
4735 : "as !$ACC DECLARE at %L", s->name, &where);
4736 2 : return MATCH_ERROR;
4737 : }
4738 :
4739 148 : if ((s->attr.dimension || s->attr.codimension)
4740 76 : && s->attr.dummy && s->as->type != AS_EXPLICIT)
4741 : {
4742 2 : gfc_error ("Assumed-size dummy array with !$ACC DECLARE at %L",
4743 : &where);
4744 2 : return MATCH_ERROR;
4745 : }
4746 :
4747 146 : switch (n->u.map.op)
4748 : {
4749 49 : case OMP_MAP_FORCE_ALLOC:
4750 49 : case OMP_MAP_ALLOC:
4751 49 : s->attr.oacc_declare_create = 1;
4752 49 : break;
4753 :
4754 63 : case OMP_MAP_FORCE_TO:
4755 63 : case OMP_MAP_TO:
4756 63 : s->attr.oacc_declare_copyin = 1;
4757 63 : break;
4758 :
4759 1 : case OMP_MAP_FORCE_DEVICEPTR:
4760 1 : s->attr.oacc_declare_deviceptr = 1;
4761 1 : break;
4762 :
4763 : default:
4764 : break;
4765 : }
4766 : }
4767 :
4768 162 : new_oc = gfc_get_oacc_declare ();
4769 162 : new_oc->next = ns->oacc_declare;
4770 162 : new_oc->module_var = module_var;
4771 162 : new_oc->clauses = c;
4772 162 : new_oc->loc = gfc_current_locus;
4773 162 : ns->oacc_declare = new_oc;
4774 :
4775 162 : return MATCH_YES;
4776 : }
4777 :
4778 :
4779 : match
4780 760 : gfc_match_oacc_update (void)
4781 : {
4782 760 : gfc_omp_clauses *c;
4783 760 : locus here = gfc_current_locus;
4784 :
4785 760 : if (gfc_match_omp_clauses (&c, OACC_UPDATE_CLAUSES, false, false, true)
4786 : != MATCH_YES)
4787 : return MATCH_ERROR;
4788 :
4789 756 : if (!c->lists[OMP_LIST_MAP])
4790 : {
4791 1 : gfc_error ("%<acc update%> must contain at least one "
4792 : "%<device%> or %<host%> or %<self%> clause at %L", &here);
4793 1 : return MATCH_ERROR;
4794 : }
4795 :
4796 755 : new_st.op = EXEC_OACC_UPDATE;
4797 755 : new_st.ext.omp_clauses = c;
4798 755 : return MATCH_YES;
4799 : }
4800 :
4801 :
4802 : match
4803 877 : gfc_match_oacc_enter_data (void)
4804 : {
4805 877 : return match_acc (EXEC_OACC_ENTER_DATA, OACC_ENTER_DATA_CLAUSES);
4806 : }
4807 :
4808 :
4809 : match
4810 612 : gfc_match_oacc_exit_data (void)
4811 : {
4812 612 : return match_acc (EXEC_OACC_EXIT_DATA, OACC_EXIT_DATA_CLAUSES);
4813 : }
4814 :
4815 :
4816 : match
4817 203 : gfc_match_oacc_wait (void)
4818 : {
4819 203 : gfc_omp_clauses *c = gfc_get_omp_clauses ();
4820 203 : gfc_expr_list *wait_list = NULL, *el;
4821 203 : bool space = true;
4822 203 : match m;
4823 :
4824 203 : m = match_omp_oacc_expr_list (" (", &wait_list, true, false);
4825 203 : if (m == MATCH_ERROR)
4826 : return m;
4827 197 : else if (m == MATCH_YES)
4828 126 : space = false;
4829 :
4830 197 : if (gfc_match_omp_clauses (&c, OACC_WAIT_CLAUSES, space, space, true)
4831 : == MATCH_ERROR)
4832 : return MATCH_ERROR;
4833 :
4834 184 : if (wait_list)
4835 261 : for (el = wait_list; el; el = el->next)
4836 : {
4837 140 : if (el->expr == NULL)
4838 : {
4839 2 : gfc_error ("Invalid argument to !$ACC WAIT at %C");
4840 2 : return MATCH_ERROR;
4841 : }
4842 :
4843 138 : if (!gfc_resolve_expr (el->expr)
4844 138 : || el->expr->ts.type != BT_INTEGER || el->expr->rank != 0)
4845 : {
4846 3 : gfc_error ("WAIT clause at %L requires a scalar INTEGER expression",
4847 3 : &el->expr->where);
4848 :
4849 3 : return MATCH_ERROR;
4850 : }
4851 : }
4852 179 : c->wait_list = wait_list;
4853 179 : new_st.op = EXEC_OACC_WAIT;
4854 179 : new_st.ext.omp_clauses = c;
4855 179 : return MATCH_YES;
4856 : }
4857 :
4858 :
4859 : match
4860 97 : gfc_match_oacc_cache (void)
4861 : {
4862 97 : bool readonly = false;
4863 97 : gfc_omp_clauses *c = gfc_get_omp_clauses ();
4864 : /* The OpenACC cache directive explicitly only allows "array elements or
4865 : subarrays", which we're currently not checking here. Either check this
4866 : after the call of gfc_match_omp_variable_list, or add something like a
4867 : only_sections variant next to its allow_sections parameter. */
4868 97 : match m = gfc_match (" ( ");
4869 97 : if (m != MATCH_YES)
4870 : {
4871 0 : gfc_free_omp_clauses(c);
4872 0 : return m;
4873 : }
4874 :
4875 97 : if (gfc_match ("readonly : ") == MATCH_YES)
4876 8 : readonly = true;
4877 :
4878 97 : gfc_omp_namelist **head = NULL;
4879 97 : m = gfc_match_omp_variable_list ("", &c->lists[OMP_LIST_CACHE], true,
4880 : NULL, &head, true);
4881 97 : if (m != MATCH_YES)
4882 : {
4883 2 : gfc_free_omp_clauses(c);
4884 2 : return m;
4885 : }
4886 :
4887 95 : if (readonly)
4888 24 : for (gfc_omp_namelist *n = *head; n; n = n->next)
4889 16 : n->u.map.readonly = true;
4890 :
4891 95 : if (gfc_current_state() != COMP_DO
4892 56 : && gfc_current_state() != COMP_DO_CONCURRENT)
4893 : {
4894 2 : gfc_error ("ACC CACHE directive must be inside of loop %C");
4895 2 : gfc_free_omp_clauses(c);
4896 2 : return MATCH_ERROR;
4897 : }
4898 :
4899 93 : new_st.op = EXEC_OACC_CACHE;
4900 93 : new_st.ext.omp_clauses = c;
4901 93 : return MATCH_YES;
4902 : }
4903 :
4904 : /* Determine the OpenACC 'routine' directive's level of parallelism. */
4905 :
4906 : static oacc_routine_lop
4907 734 : gfc_oacc_routine_lop (gfc_omp_clauses *clauses)
4908 : {
4909 734 : oacc_routine_lop ret = OACC_ROUTINE_LOP_SEQ;
4910 :
4911 734 : if (clauses)
4912 : {
4913 584 : unsigned n_lop_clauses = 0;
4914 :
4915 584 : if (clauses->gang)
4916 : {
4917 164 : ++n_lop_clauses;
4918 164 : ret = OACC_ROUTINE_LOP_GANG;
4919 : }
4920 584 : if (clauses->worker)
4921 : {
4922 114 : ++n_lop_clauses;
4923 114 : ret = OACC_ROUTINE_LOP_WORKER;
4924 : }
4925 584 : if (clauses->vector)
4926 : {
4927 116 : ++n_lop_clauses;
4928 116 : ret = OACC_ROUTINE_LOP_VECTOR;
4929 : }
4930 584 : if (clauses->seq)
4931 : {
4932 206 : ++n_lop_clauses;
4933 206 : ret = OACC_ROUTINE_LOP_SEQ;
4934 : }
4935 :
4936 584 : if (n_lop_clauses > 1)
4937 47 : ret = OACC_ROUTINE_LOP_ERROR;
4938 : }
4939 :
4940 734 : return ret;
4941 : }
4942 :
4943 : match
4944 698 : gfc_match_oacc_routine (void)
4945 : {
4946 698 : locus old_loc;
4947 698 : match m;
4948 698 : gfc_intrinsic_sym *isym = NULL;
4949 698 : gfc_symbol *sym = NULL;
4950 698 : gfc_omp_clauses *c = NULL;
4951 698 : gfc_oacc_routine_name *n = NULL;
4952 698 : oacc_routine_lop lop = OACC_ROUTINE_LOP_NONE;
4953 698 : bool nohost;
4954 :
4955 698 : old_loc = gfc_current_locus;
4956 :
4957 698 : m = gfc_match (" (");
4958 :
4959 698 : if (gfc_current_ns->proc_name
4960 696 : && gfc_current_ns->proc_name->attr.if_source == IFSRC_IFBODY
4961 90 : && m == MATCH_YES)
4962 : {
4963 3 : gfc_error ("Only the !$ACC ROUTINE form without "
4964 : "list is allowed in interface block at %C");
4965 3 : goto cleanup;
4966 : }
4967 :
4968 608 : if (m == MATCH_YES)
4969 : {
4970 295 : char buffer[GFC_MAX_SYMBOL_LEN + 1];
4971 :
4972 295 : m = gfc_match_name (buffer);
4973 295 : if (m == MATCH_YES)
4974 : {
4975 294 : gfc_symtree *st = NULL;
4976 :
4977 : /* First look for an intrinsic symbol. */
4978 294 : isym = gfc_find_function (buffer);
4979 294 : if (!isym)
4980 294 : isym = gfc_find_subroutine (buffer);
4981 : /* If no intrinsic symbol found, search the current namespace. */
4982 294 : if (!isym)
4983 276 : st = gfc_find_symtree (gfc_current_ns->sym_root, buffer);
4984 276 : if (st)
4985 : {
4986 270 : sym = st->n.sym;
4987 : /* If the name in a 'routine' directive refers to the containing
4988 : subroutine or function, then make sure that we'll later handle
4989 : this accordingly. */
4990 270 : if (gfc_current_ns->proc_name != NULL
4991 270 : && strcmp (sym->name, gfc_current_ns->proc_name->name) == 0)
4992 294 : sym = NULL;
4993 : }
4994 :
4995 294 : if (isym == NULL && st == NULL)
4996 : {
4997 6 : gfc_error ("Invalid NAME %qs in !$ACC ROUTINE ( NAME ) at %C",
4998 : buffer);
4999 6 : gfc_current_locus = old_loc;
5000 9 : return MATCH_ERROR;
5001 : }
5002 : }
5003 : else
5004 : {
5005 1 : gfc_error ("Syntax error in !$ACC ROUTINE ( NAME ) at %C");
5006 1 : gfc_current_locus = old_loc;
5007 1 : return MATCH_ERROR;
5008 : }
5009 :
5010 288 : if (gfc_match_char (')') != MATCH_YES)
5011 : {
5012 2 : gfc_error ("Syntax error in !$ACC ROUTINE ( NAME ) at %C, expecting"
5013 : " %<)%> after NAME");
5014 2 : gfc_current_locus = old_loc;
5015 2 : return MATCH_ERROR;
5016 : }
5017 : }
5018 :
5019 686 : if (gfc_match_omp_eos () != MATCH_YES
5020 686 : && (gfc_match_omp_clauses (&c, OACC_ROUTINE_CLAUSES, false, false, true)
5021 : != MATCH_YES))
5022 : return MATCH_ERROR;
5023 :
5024 683 : lop = gfc_oacc_routine_lop (c);
5025 683 : if (lop == OACC_ROUTINE_LOP_ERROR)
5026 : {
5027 47 : gfc_error ("Multiple loop axes specified for routine at %C");
5028 47 : goto cleanup;
5029 : }
5030 636 : nohost = c ? c->nohost : false;
5031 :
5032 636 : if (isym != NULL)
5033 : {
5034 : /* Diagnose any OpenACC 'routine' directive that doesn't match the
5035 : (implicit) one with a 'seq' clause. */
5036 16 : if (c && (c->gang || c->worker || c->vector))
5037 : {
5038 10 : gfc_error ("Intrinsic symbol specified in !$ACC ROUTINE ( NAME )"
5039 : " at %C marked with incompatible GANG, WORKER, or VECTOR"
5040 : " clause");
5041 10 : goto cleanup;
5042 : }
5043 : /* ..., and no 'nohost' clause. */
5044 6 : if (nohost)
5045 : {
5046 2 : gfc_error ("Intrinsic symbol specified in !$ACC ROUTINE ( NAME )"
5047 : " at %C marked with incompatible NOHOST clause");
5048 2 : goto cleanup;
5049 : }
5050 : }
5051 620 : else if (sym != NULL)
5052 : {
5053 151 : bool add = true;
5054 :
5055 : /* For a repeated OpenACC 'routine' directive, diagnose if it doesn't
5056 : match the first one. */
5057 151 : for (gfc_oacc_routine_name *n_p = gfc_current_ns->oacc_routine_names;
5058 346 : n_p;
5059 195 : n_p = n_p->next)
5060 235 : if (n_p->sym == sym)
5061 : {
5062 51 : add = false;
5063 51 : bool nohost_p = n_p->clauses ? n_p->clauses->nohost : false;
5064 51 : if (lop != gfc_oacc_routine_lop (n_p->clauses)
5065 51 : || nohost != nohost_p)
5066 : {
5067 40 : gfc_error ("!$ACC ROUTINE already applied at %C");
5068 40 : goto cleanup;
5069 : }
5070 : }
5071 :
5072 111 : if (add)
5073 : {
5074 100 : sym->attr.oacc_routine_lop = lop;
5075 100 : sym->attr.oacc_routine_nohost = nohost;
5076 :
5077 100 : n = gfc_get_oacc_routine_name ();
5078 100 : n->sym = sym;
5079 100 : n->clauses = c;
5080 100 : n->next = gfc_current_ns->oacc_routine_names;
5081 100 : n->loc = old_loc;
5082 100 : gfc_current_ns->oacc_routine_names = n;
5083 : }
5084 : }
5085 469 : else if (gfc_current_ns->proc_name)
5086 : {
5087 : /* For a repeated OpenACC 'routine' directive, diagnose if it doesn't
5088 : match the first one. */
5089 468 : oacc_routine_lop lop_p = gfc_current_ns->proc_name->attr.oacc_routine_lop;
5090 468 : bool nohost_p = gfc_current_ns->proc_name->attr.oacc_routine_nohost;
5091 468 : if (lop_p != OACC_ROUTINE_LOP_NONE
5092 86 : && (lop != lop_p
5093 86 : || nohost != nohost_p))
5094 : {
5095 56 : gfc_error ("!$ACC ROUTINE already applied at %C");
5096 56 : goto cleanup;
5097 : }
5098 :
5099 412 : if (!gfc_add_omp_declare_target (&gfc_current_ns->proc_name->attr,
5100 : gfc_current_ns->proc_name->name,
5101 : &old_loc))
5102 1 : goto cleanup;
5103 411 : gfc_current_ns->proc_name->attr.oacc_routine_lop = lop;
5104 411 : gfc_current_ns->proc_name->attr.oacc_routine_nohost = nohost;
5105 : }
5106 : else
5107 : /* Something has gone wrong, possibly a syntax error. */
5108 1 : goto cleanup;
5109 :
5110 526 : if (gfc_pure (NULL) && c && (c->gang || c->worker || c->vector))
5111 : {
5112 6 : gfc_error ("!$ACC ROUTINE with GANG, WORKER, or VECTOR clause is not "
5113 : "permitted in PURE procedure at %C");
5114 6 : goto cleanup;
5115 : }
5116 :
5117 :
5118 520 : if (n)
5119 100 : n->clauses = c;
5120 420 : else if (gfc_current_ns->oacc_routine)
5121 0 : gfc_current_ns->oacc_routine_clauses = c;
5122 :
5123 520 : new_st.op = EXEC_OACC_ROUTINE;
5124 520 : new_st.ext.omp_clauses = c;
5125 520 : return MATCH_YES;
5126 :
5127 166 : cleanup:
5128 166 : gfc_current_locus = old_loc;
5129 166 : return MATCH_ERROR;
5130 : }
5131 :
5132 :
5133 : #define OMP_PARALLEL_CLAUSES \
5134 : (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
5135 : | OMP_CLAUSE_SHARED | OMP_CLAUSE_COPYIN | OMP_CLAUSE_REDUCTION \
5136 : | OMP_CLAUSE_IF | OMP_CLAUSE_NUM_THREADS | OMP_CLAUSE_DEFAULT \
5137 : | OMP_CLAUSE_PROC_BIND | OMP_CLAUSE_ALLOCATE)
5138 : #define OMP_DECLARE_SIMD_CLAUSES \
5139 : (omp_mask (OMP_CLAUSE_SIMDLEN) | OMP_CLAUSE_LINEAR \
5140 : | OMP_CLAUSE_UNIFORM | OMP_CLAUSE_ALIGNED | OMP_CLAUSE_INBRANCH \
5141 : | OMP_CLAUSE_NOTINBRANCH)
5142 : #define OMP_DO_CLAUSES \
5143 : (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
5144 : | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION \
5145 : | OMP_CLAUSE_SCHEDULE | OMP_CLAUSE_ORDERED | OMP_CLAUSE_COLLAPSE \
5146 : | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ORDER | OMP_CLAUSE_ALLOCATE \
5147 : | OMP_CLAUSE_NOWAIT)
5148 : #define OMP_LOOP_CLAUSES \
5149 : (omp_mask (OMP_CLAUSE_BIND) | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_ORDER \
5150 : | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION)
5151 :
5152 : #define OMP_SCOPE_CLAUSES \
5153 : (omp_mask (OMP_CLAUSE_PRIVATE) |OMP_CLAUSE_FIRSTPRIVATE \
5154 : | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT)
5155 : #define OMP_SECTIONS_CLAUSES \
5156 : (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
5157 : | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION \
5158 : | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT)
5159 : #define OMP_SIMD_CLAUSES \
5160 : (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_LASTPRIVATE \
5161 : | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_SAFELEN \
5162 : | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ALIGNED | OMP_CLAUSE_SIMDLEN \
5163 : | OMP_CLAUSE_IF | OMP_CLAUSE_ORDER | OMP_CLAUSE_NOTEMPORAL)
5164 : #define OMP_TASK_CLAUSES \
5165 : (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
5166 : | OMP_CLAUSE_SHARED | OMP_CLAUSE_IF | OMP_CLAUSE_DEFAULT \
5167 : | OMP_CLAUSE_UNTIED | OMP_CLAUSE_FINAL | OMP_CLAUSE_MERGEABLE \
5168 : | OMP_CLAUSE_DEPEND | OMP_CLAUSE_PRIORITY | OMP_CLAUSE_IN_REDUCTION \
5169 : | OMP_CLAUSE_DETACH | OMP_CLAUSE_AFFINITY | OMP_CLAUSE_ALLOCATE)
5170 : #define OMP_TASKLOOP_CLAUSES \
5171 : (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
5172 : | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_IF \
5173 : | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_UNTIED | OMP_CLAUSE_FINAL \
5174 : | OMP_CLAUSE_MERGEABLE | OMP_CLAUSE_PRIORITY | OMP_CLAUSE_GRAINSIZE \
5175 : | OMP_CLAUSE_NUM_TASKS | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_NOGROUP \
5176 : | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_IN_REDUCTION | OMP_CLAUSE_ALLOCATE)
5177 : #define OMP_TASKGROUP_CLAUSES \
5178 : (omp_mask (OMP_CLAUSE_TASK_REDUCTION) | OMP_CLAUSE_ALLOCATE)
5179 : #define OMP_TARGET_CLAUSES \
5180 : (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF \
5181 : | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_PRIVATE \
5182 : | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_DEFAULTMAP \
5183 : | OMP_CLAUSE_IS_DEVICE_PTR | OMP_CLAUSE_IN_REDUCTION \
5184 : | OMP_CLAUSE_THREAD_LIMIT | OMP_CLAUSE_ALLOCATE \
5185 : | OMP_CLAUSE_HAS_DEVICE_ADDR | OMP_CLAUSE_USES_ALLOCATORS \
5186 : | OMP_CLAUSE_DYN_GROUPPRIVATE | OMP_CLAUSE_DEVICE_TYPE)
5187 : #define OMP_TARGET_DATA_CLAUSES \
5188 : (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF \
5189 : | OMP_CLAUSE_USE_DEVICE_PTR | OMP_CLAUSE_USE_DEVICE_ADDR)
5190 : #define OMP_TARGET_ENTER_DATA_CLAUSES \
5191 : (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF \
5192 : | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT)
5193 : #define OMP_TARGET_EXIT_DATA_CLAUSES \
5194 : (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF \
5195 : | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT)
5196 : #define OMP_TARGET_UPDATE_CLAUSES \
5197 : (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_IF | OMP_CLAUSE_TO \
5198 : | OMP_CLAUSE_FROM | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT)
5199 : #define OMP_TEAMS_CLAUSES \
5200 : (omp_mask (OMP_CLAUSE_NUM_TEAMS) | OMP_CLAUSE_THREAD_LIMIT \
5201 : | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE \
5202 : | OMP_CLAUSE_SHARED | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_ALLOCATE)
5203 : #define OMP_DISTRIBUTE_CLAUSES \
5204 : (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
5205 : | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_DIST_SCHEDULE \
5206 : | OMP_CLAUSE_ORDER | OMP_CLAUSE_ALLOCATE)
5207 : #define OMP_SINGLE_CLAUSES \
5208 : (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
5209 : | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_COPYPRIVATE)
5210 : #define OMP_ORDERED_CLAUSES \
5211 : (omp_mask (OMP_CLAUSE_THREADS) | OMP_CLAUSE_SIMD)
5212 : #define OMP_DECLARE_TARGET_CLAUSES \
5213 : (omp_mask (OMP_CLAUSE_ENTER) | OMP_CLAUSE_LINK | OMP_CLAUSE_DEVICE_TYPE \
5214 : | OMP_CLAUSE_TO | OMP_CLAUSE_INDIRECT | OMP_CLAUSE_LOCAL)
5215 : #define OMP_ATOMIC_CLAUSES \
5216 : (omp_mask (OMP_CLAUSE_ATOMIC) | OMP_CLAUSE_CAPTURE | OMP_CLAUSE_HINT \
5217 : | OMP_CLAUSE_MEMORDER | OMP_CLAUSE_COMPARE | OMP_CLAUSE_FAIL \
5218 : | OMP_CLAUSE_WEAK)
5219 : #define OMP_MASKED_CLAUSES \
5220 : (omp_mask (OMP_CLAUSE_FILTER))
5221 : #define OMP_ERROR_CLAUSES \
5222 : (omp_mask (OMP_CLAUSE_AT) | OMP_CLAUSE_MESSAGE | OMP_CLAUSE_SEVERITY)
5223 : #define OMP_WORKSHARE_CLAUSES \
5224 : omp_mask (OMP_CLAUSE_NOWAIT)
5225 : #define OMP_UNROLL_CLAUSES \
5226 : (omp_mask (OMP_CLAUSE_FULL) | OMP_CLAUSE_PARTIAL)
5227 : #define OMP_TILE_CLAUSES \
5228 : (omp_mask (OMP_CLAUSE_SIZES))
5229 : #define OMP_ALLOCATORS_CLAUSES \
5230 : omp_mask (OMP_CLAUSE_ALLOCATE)
5231 : #define OMP_INTEROP_CLAUSES \
5232 : (omp_mask (OMP_CLAUSE_DEPEND) | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_DEVICE \
5233 : | OMP_CLAUSE_INIT | OMP_CLAUSE_DESTROY | OMP_CLAUSE_USE)
5234 : #define OMP_DISPATCH_CLAUSES \
5235 : (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOVARIANTS \
5236 : | OMP_CLAUSE_NOCONTEXT | OMP_CLAUSE_IS_DEVICE_PTR | OMP_CLAUSE_NOWAIT \
5237 : | OMP_CLAUSE_HAS_DEVICE_ADDR | OMP_CLAUSE_INTEROP)
5238 :
5239 :
5240 : static match
5241 16800 : match_omp (gfc_exec_op op, const omp_mask mask)
5242 : {
5243 16800 : gfc_omp_clauses *c;
5244 16800 : if (gfc_match_omp_clauses (&c, mask, true, true, false,
5245 : op == EXEC_OMP_TARGET) != MATCH_YES)
5246 : return MATCH_ERROR;
5247 16552 : new_st.op = op;
5248 16552 : new_st.ext.omp_clauses = c;
5249 16552 : return MATCH_YES;
5250 : }
5251 :
5252 : /* Handles both declarative and (deprecated) executable ALLOCATE directive;
5253 : accepts optional list (for executable) and common blocks.
5254 : If no variables have been provided, the single omp namelist has sym == NULL.
5255 :
5256 : Note that the executable ALLOCATE directive permits structure elements only
5257 : in OpenMP 5.0 and 5.1 but not longer in 5.2. See also the comment on the
5258 : 'omp allocators' directive below. The accidental change was reverted for
5259 : OpenMP TR12, permitting them again. See also gfc_match_omp_allocators.
5260 :
5261 : Hence, structure elements are rejected for now, also to make resolving
5262 : OMP_LIST_ALLOCATE simpler (check for duplicates, same symbol in
5263 : Fortran allocate stmt). TODO: Permit structure elements. */
5264 :
5265 : match
5266 274 : gfc_match_omp_allocate (void)
5267 : {
5268 274 : match m;
5269 274 : bool first = true;
5270 274 : gfc_omp_namelist *vars = NULL;
5271 274 : gfc_expr *align = NULL;
5272 274 : gfc_expr *allocator = NULL;
5273 274 : locus loc = gfc_current_locus;
5274 :
5275 274 : m = gfc_match_omp_variable_list (" (", &vars, true, NULL, NULL, true, true,
5276 : NULL, true);
5277 :
5278 274 : if (m == MATCH_ERROR)
5279 : return m;
5280 :
5281 502 : while (true)
5282 : {
5283 502 : gfc_gobble_whitespace ();
5284 502 : if (gfc_match_omp_eos () == MATCH_YES)
5285 : break;
5286 234 : if (!first)
5287 28 : gfc_match (", ");
5288 234 : first = false;
5289 234 : if ((m = gfc_match_dupl_check (!align, "align", true, &align))
5290 : != MATCH_NO)
5291 : {
5292 62 : if (m == MATCH_ERROR)
5293 1 : goto error;
5294 61 : continue;
5295 : }
5296 172 : if ((m = gfc_match_dupl_check (!allocator, "allocator",
5297 : true, &allocator)) != MATCH_NO)
5298 : {
5299 171 : if (m == MATCH_ERROR)
5300 1 : goto error;
5301 170 : continue;
5302 : }
5303 1 : gfc_error ("Expected ALIGN or ALLOCATOR clause at %C");
5304 1 : return MATCH_ERROR;
5305 : }
5306 541 : for (gfc_omp_namelist *n = vars; n; n = n->next)
5307 276 : if (n->expr)
5308 : {
5309 3 : if ((n->expr->ref && n->expr->ref->type == REF_COMPONENT)
5310 3 : || (n->expr->ref->next && n->expr->ref->type == REF_COMPONENT))
5311 1 : gfc_error ("Sorry, structure-element list item at %L in ALLOCATE "
5312 : "directive is not yet supported", &n->expr->where);
5313 : else
5314 2 : gfc_error ("Unexpected expression as list item at %L in ALLOCATE "
5315 : "directive", &n->expr->where);
5316 :
5317 3 : gfc_free_omp_namelist (vars, OMP_LIST_ALLOCATE);
5318 3 : goto error;
5319 : }
5320 :
5321 265 : new_st.op = EXEC_OMP_ALLOCATE;
5322 265 : new_st.ext.omp_clauses = gfc_get_omp_clauses ();
5323 265 : if (vars == NULL)
5324 : {
5325 27 : vars = gfc_get_omp_namelist ();
5326 27 : vars->where = loc;
5327 27 : vars->u.align = align;
5328 27 : vars->u2.allocator = allocator;
5329 27 : new_st.ext.omp_clauses->lists[OMP_LIST_ALLOCATE] = vars;
5330 : }
5331 : else
5332 : {
5333 238 : new_st.ext.omp_clauses->lists[OMP_LIST_ALLOCATE] = vars;
5334 511 : for (; vars; vars = vars->next)
5335 : {
5336 273 : vars->u.align = (align) ? gfc_copy_expr (align) : NULL;
5337 273 : vars->u2.allocator = allocator;
5338 : }
5339 238 : gfc_free_expr (align);
5340 : }
5341 : return MATCH_YES;
5342 :
5343 5 : error:
5344 5 : gfc_free_expr (align);
5345 5 : gfc_free_expr (allocator);
5346 5 : return MATCH_ERROR;
5347 : }
5348 :
5349 : /* In line with OpenMP 5.2 derived-type components are rejected.
5350 : See also comment before gfc_match_omp_allocate. */
5351 :
5352 : match
5353 26 : gfc_match_omp_allocators (void)
5354 : {
5355 26 : return match_omp (EXEC_OMP_ALLOCATORS, OMP_ALLOCATORS_CLAUSES);
5356 : }
5357 :
5358 :
5359 : match
5360 22 : gfc_match_omp_assume (void)
5361 : {
5362 22 : gfc_omp_clauses *c;
5363 22 : locus loc = gfc_current_locus;
5364 22 : if ((gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_ASSUMPTIONS))
5365 : != MATCH_YES)
5366 22 : || (omp_verify_merge_absent_contains (ST_OMP_ASSUME, c->assume, NULL,
5367 : &loc) != MATCH_YES))
5368 6 : return MATCH_ERROR;
5369 16 : new_st.op = EXEC_OMP_ASSUME;
5370 16 : new_st.ext.omp_clauses = c;
5371 16 : return MATCH_YES;
5372 : }
5373 :
5374 :
5375 : match
5376 28 : gfc_match_omp_assumes (void)
5377 : {
5378 28 : gfc_omp_clauses *c;
5379 28 : locus loc = gfc_current_locus;
5380 28 : if (!gfc_current_ns->proc_name
5381 27 : || (gfc_current_ns->proc_name->attr.flavor != FL_MODULE
5382 23 : && !gfc_current_ns->proc_name->attr.subroutine
5383 10 : && !gfc_current_ns->proc_name->attr.function))
5384 : {
5385 2 : gfc_error ("!$OMP ASSUMES at %C must be in the specification part of a "
5386 : "subprogram or module");
5387 2 : return MATCH_ERROR;
5388 : }
5389 26 : if ((gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_ASSUMPTIONS))
5390 : != MATCH_YES)
5391 50 : || (omp_verify_merge_absent_contains (ST_OMP_ASSUMES, c->assume,
5392 24 : gfc_current_ns->omp_assumes, &loc)
5393 : != MATCH_YES))
5394 5 : return MATCH_ERROR;
5395 21 : if (gfc_current_ns->omp_assumes == NULL)
5396 : {
5397 19 : gfc_current_ns->omp_assumes = c->assume;
5398 19 : c->assume = NULL;
5399 : }
5400 2 : else if (gfc_current_ns->omp_assumes && c->assume)
5401 : {
5402 2 : gfc_current_ns->omp_assumes->no_openmp |= c->assume->no_openmp;
5403 2 : gfc_current_ns->omp_assumes->no_openmp_routines
5404 2 : |= c->assume->no_openmp_routines;
5405 2 : gfc_current_ns->omp_assumes->no_openmp_constructs
5406 2 : |= c->assume->no_openmp_constructs;
5407 2 : gfc_current_ns->omp_assumes->no_parallelism |= c->assume->no_parallelism;
5408 2 : if (gfc_current_ns->omp_assumes->holds && c->assume->holds)
5409 : {
5410 : gfc_expr_list *el = gfc_current_ns->omp_assumes->holds;
5411 1 : for ( ; el->next ; el = el->next)
5412 : ;
5413 1 : el->next = c->assume->holds;
5414 1 : }
5415 1 : else if (c->assume->holds)
5416 0 : gfc_current_ns->omp_assumes->holds = c->assume->holds;
5417 2 : c->assume->holds = NULL;
5418 : }
5419 21 : gfc_free_omp_clauses (c);
5420 21 : return MATCH_YES;
5421 : }
5422 :
5423 :
5424 : match
5425 162 : gfc_match_omp_critical (void)
5426 : {
5427 162 : char n[GFC_MAX_SYMBOL_LEN+1];
5428 162 : gfc_omp_clauses *c = NULL;
5429 :
5430 162 : if (gfc_match (" ( %n )", n) != MATCH_YES)
5431 115 : n[0] = '\0';
5432 :
5433 162 : if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_HINT),
5434 162 : /* first = */ n[0] == '\0') != MATCH_YES)
5435 : return MATCH_ERROR;
5436 :
5437 160 : new_st.op = EXEC_OMP_CRITICAL;
5438 160 : new_st.ext.omp_clauses = c;
5439 160 : if (n[0])
5440 47 : c->critical_name = xstrdup (n);
5441 : return MATCH_YES;
5442 : }
5443 :
5444 :
5445 : match
5446 160 : gfc_match_omp_end_critical (void)
5447 : {
5448 160 : char n[GFC_MAX_SYMBOL_LEN+1];
5449 :
5450 160 : if (gfc_match (" ( %n )", n) != MATCH_YES)
5451 113 : n[0] = '\0';
5452 160 : if (gfc_match_omp_eos () != MATCH_YES)
5453 : {
5454 1 : gfc_error ("Unexpected junk after $OMP CRITICAL statement at %C");
5455 1 : return MATCH_ERROR;
5456 : }
5457 :
5458 159 : new_st.op = EXEC_OMP_END_CRITICAL;
5459 159 : new_st.ext.omp_name = n[0] ? xstrdup (n) : NULL;
5460 159 : return MATCH_YES;
5461 : }
5462 :
5463 : /* depobj(depobj) depend(dep-type:loc)|destroy|update(dep-type)
5464 : dep-type = in/out/inout/mutexinoutset/depobj/source/sink
5465 : depend: !source, !sink
5466 : update: !source, !sink, !depobj
5467 : locator = exactly one list item .*/
5468 : match
5469 125 : gfc_match_omp_depobj (void)
5470 : {
5471 125 : gfc_omp_clauses *c = NULL;
5472 125 : gfc_expr *depobj;
5473 :
5474 125 : if (gfc_match (" ( %v ) ", &depobj) != MATCH_YES)
5475 : {
5476 2 : gfc_error ("Expected %<( depobj )%> at %C");
5477 2 : return MATCH_ERROR;
5478 : }
5479 123 : if (gfc_match ("update ( ") == MATCH_YES)
5480 : {
5481 12 : c = gfc_get_omp_clauses ();
5482 12 : if (gfc_match ("inoutset )") == MATCH_YES)
5483 2 : c->depobj_update = OMP_DEPEND_INOUTSET;
5484 10 : else if (gfc_match ("inout )") == MATCH_YES)
5485 1 : c->depobj_update = OMP_DEPEND_INOUT;
5486 9 : else if (gfc_match ("in )") == MATCH_YES)
5487 2 : c->depobj_update = OMP_DEPEND_IN;
5488 7 : else if (gfc_match ("out )") == MATCH_YES)
5489 2 : c->depobj_update = OMP_DEPEND_OUT;
5490 5 : else if (gfc_match ("mutexinoutset )") == MATCH_YES)
5491 2 : c->depobj_update = OMP_DEPEND_MUTEXINOUTSET;
5492 : else
5493 : {
5494 3 : gfc_error ("Expected IN, OUT, INOUT, INOUTSET or MUTEXINOUTSET "
5495 : "followed by %<)%> at %C");
5496 3 : goto error;
5497 : }
5498 : }
5499 111 : else if (gfc_match ("destroy ") == MATCH_YES)
5500 : {
5501 16 : gfc_expr *destroyobj = NULL;
5502 16 : c = gfc_get_omp_clauses ();
5503 16 : c->destroy = true;
5504 :
5505 16 : if (gfc_match (" ( %v ) ", &destroyobj) == MATCH_YES)
5506 : {
5507 3 : if (destroyobj->symtree != depobj->symtree)
5508 2 : gfc_warning (OPT_Wopenmp, "The same depend object should be used as"
5509 : " DEPOBJ argument at %L and as DESTROY argument at %L",
5510 : &depobj->where, &destroyobj->where);
5511 3 : gfc_free_expr (destroyobj);
5512 : }
5513 : }
5514 95 : else if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_DEPEND), true, false)
5515 : != MATCH_YES)
5516 2 : goto error;
5517 :
5518 118 : if (c->depobj_update == OMP_DEPEND_UNSET && !c->destroy)
5519 : {
5520 93 : if (!c->doacross_source && !c->lists[OMP_LIST_DEPEND])
5521 : {
5522 1 : gfc_error ("Expected DEPEND, UPDATE, or DESTROY clause at %C");
5523 1 : goto error;
5524 : }
5525 92 : if (c->lists[OMP_LIST_DEPEND]->u.depend_doacross_op == OMP_DEPEND_DEPOBJ)
5526 : {
5527 1 : gfc_error ("DEPEND clause at %L of OMP DEPOBJ construct shall not "
5528 : "have dependence-type DEPOBJ",
5529 : c->lists[OMP_LIST_DEPEND]
5530 : ? &c->lists[OMP_LIST_DEPEND]->where : &gfc_current_locus);
5531 1 : goto error;
5532 : }
5533 91 : if (c->lists[OMP_LIST_DEPEND]->next)
5534 : {
5535 1 : gfc_error ("DEPEND clause at %L of OMP DEPOBJ construct shall have "
5536 : "only a single locator",
5537 : &c->lists[OMP_LIST_DEPEND]->next->where);
5538 1 : goto error;
5539 : }
5540 : }
5541 :
5542 115 : c->depobj = depobj;
5543 115 : new_st.op = EXEC_OMP_DEPOBJ;
5544 115 : new_st.ext.omp_clauses = c;
5545 115 : return MATCH_YES;
5546 :
5547 8 : error:
5548 8 : gfc_free_expr (depobj);
5549 8 : gfc_free_omp_clauses (c);
5550 8 : return MATCH_ERROR;
5551 : }
5552 :
5553 : match
5554 160 : gfc_match_omp_dispatch (void)
5555 : {
5556 160 : return match_omp (EXEC_OMP_DISPATCH, OMP_DISPATCH_CLAUSES);
5557 : }
5558 :
5559 : match
5560 57 : gfc_match_omp_distribute (void)
5561 : {
5562 57 : return match_omp (EXEC_OMP_DISTRIBUTE, OMP_DISTRIBUTE_CLAUSES);
5563 : }
5564 :
5565 :
5566 : match
5567 44 : gfc_match_omp_distribute_parallel_do (void)
5568 : {
5569 44 : return match_omp (EXEC_OMP_DISTRIBUTE_PARALLEL_DO,
5570 44 : (OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
5571 44 : | OMP_DO_CLAUSES)
5572 44 : & ~(omp_mask (OMP_CLAUSE_ORDERED)
5573 44 : | OMP_CLAUSE_LINEAR | OMP_CLAUSE_NOWAIT));
5574 : }
5575 :
5576 :
5577 : match
5578 34 : gfc_match_omp_distribute_parallel_do_simd (void)
5579 : {
5580 34 : return match_omp (EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD,
5581 34 : (OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
5582 34 : | OMP_DO_CLAUSES | OMP_SIMD_CLAUSES)
5583 34 : & ~(omp_mask (OMP_CLAUSE_ORDERED) | OMP_CLAUSE_NOWAIT));
5584 : }
5585 :
5586 :
5587 : match
5588 52 : gfc_match_omp_distribute_simd (void)
5589 : {
5590 52 : return match_omp (EXEC_OMP_DISTRIBUTE_SIMD,
5591 52 : OMP_DISTRIBUTE_CLAUSES | OMP_SIMD_CLAUSES);
5592 : }
5593 :
5594 :
5595 : match
5596 1252 : gfc_match_omp_do (void)
5597 : {
5598 1252 : return match_omp (EXEC_OMP_DO, OMP_DO_CLAUSES);
5599 : }
5600 :
5601 :
5602 : match
5603 137 : gfc_match_omp_do_simd (void)
5604 : {
5605 137 : return match_omp (EXEC_OMP_DO_SIMD, OMP_DO_CLAUSES | OMP_SIMD_CLAUSES);
5606 : }
5607 :
5608 :
5609 : match
5610 70 : gfc_match_omp_loop (void)
5611 : {
5612 70 : return match_omp (EXEC_OMP_LOOP, OMP_LOOP_CLAUSES);
5613 : }
5614 :
5615 :
5616 : match
5617 35 : gfc_match_omp_teams_loop (void)
5618 : {
5619 35 : return match_omp (EXEC_OMP_TEAMS_LOOP, OMP_TEAMS_CLAUSES | OMP_LOOP_CLAUSES);
5620 : }
5621 :
5622 :
5623 : match
5624 18 : gfc_match_omp_target_teams_loop (void)
5625 : {
5626 18 : return match_omp (EXEC_OMP_TARGET_TEAMS_LOOP,
5627 18 : OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES | OMP_LOOP_CLAUSES);
5628 : }
5629 :
5630 :
5631 : match
5632 31 : gfc_match_omp_parallel_loop (void)
5633 : {
5634 31 : return match_omp (EXEC_OMP_PARALLEL_LOOP,
5635 31 : OMP_PARALLEL_CLAUSES | OMP_LOOP_CLAUSES);
5636 : }
5637 :
5638 :
5639 : match
5640 16 : gfc_match_omp_target_parallel_loop (void)
5641 : {
5642 16 : return match_omp (EXEC_OMP_TARGET_PARALLEL_LOOP,
5643 16 : (OMP_TARGET_CLAUSES | OMP_PARALLEL_CLAUSES
5644 16 : | OMP_LOOP_CLAUSES));
5645 : }
5646 :
5647 :
5648 : match
5649 101 : gfc_match_omp_error (void)
5650 : {
5651 101 : locus loc = gfc_current_locus;
5652 101 : match m = match_omp (EXEC_OMP_ERROR, OMP_ERROR_CLAUSES);
5653 101 : if (m != MATCH_YES)
5654 : return m;
5655 :
5656 82 : gfc_omp_clauses *c = new_st.ext.omp_clauses;
5657 82 : if (c->severity == OMP_SEVERITY_UNSET)
5658 45 : c->severity = OMP_SEVERITY_FATAL;
5659 82 : if (new_st.ext.omp_clauses->at == OMP_AT_EXECUTION)
5660 : return MATCH_YES;
5661 37 : if (c->message
5662 37 : && (!gfc_resolve_expr (c->message)
5663 16 : || c->message->ts.type != BT_CHARACTER
5664 14 : || c->message->ts.kind != gfc_default_character_kind
5665 13 : || c->message->rank != 0))
5666 : {
5667 4 : gfc_error ("MESSAGE clause at %L requires a scalar default-kind "
5668 : "CHARACTER expression",
5669 4 : &new_st.ext.omp_clauses->message->where);
5670 4 : return MATCH_ERROR;
5671 : }
5672 33 : if (c->message && !gfc_is_constant_expr (c->message))
5673 : {
5674 2 : gfc_error ("Constant character expression required in MESSAGE clause "
5675 2 : "at %L", &new_st.ext.omp_clauses->message->where);
5676 2 : return MATCH_ERROR;
5677 : }
5678 31 : if (c->message)
5679 : {
5680 10 : const char *msg = G_("$OMP ERROR encountered at %L: %s");
5681 10 : gcc_assert (c->message->expr_type == EXPR_CONSTANT);
5682 10 : gfc_charlen_t slen = c->message->value.character.length;
5683 10 : int i = gfc_validate_kind (BT_CHARACTER, gfc_default_character_kind,
5684 : false);
5685 10 : size_t size = slen * gfc_character_kinds[i].bit_size / 8;
5686 10 : unsigned char *s = XCNEWVAR (unsigned char, size + 1);
5687 10 : gfc_encode_character (gfc_default_character_kind, slen,
5688 10 : c->message->value.character.string,
5689 : (unsigned char *) s, size);
5690 10 : s[size] = '\0';
5691 10 : if (c->severity == OMP_SEVERITY_WARNING)
5692 6 : gfc_warning_now (0, msg, &loc, s);
5693 : else
5694 4 : gfc_error_now (msg, &loc, s);
5695 10 : free (s);
5696 : }
5697 : else
5698 : {
5699 21 : const char *msg = G_("$OMP ERROR encountered at %L");
5700 21 : if (c->severity == OMP_SEVERITY_WARNING)
5701 7 : gfc_warning_now (0, msg, &loc);
5702 : else
5703 14 : gfc_error_now (msg, &loc);
5704 : }
5705 : return MATCH_YES;
5706 : }
5707 :
5708 : match
5709 86 : gfc_match_omp_flush (void)
5710 : {
5711 86 : gfc_omp_namelist *list = NULL;
5712 86 : gfc_omp_clauses *c = NULL;
5713 86 : gfc_gobble_whitespace ();
5714 86 : enum gfc_omp_memorder mo = OMP_MEMORDER_UNSET;
5715 86 : if (gfc_match_omp_eos () == MATCH_NO && gfc_peek_ascii_char () != '(')
5716 : {
5717 14 : if (gfc_match ("seq_cst") == MATCH_YES)
5718 : mo = OMP_MEMORDER_SEQ_CST;
5719 11 : else if (gfc_match ("acq_rel") == MATCH_YES)
5720 : mo = OMP_MEMORDER_ACQ_REL;
5721 8 : else if (gfc_match ("release") == MATCH_YES)
5722 : mo = OMP_MEMORDER_RELEASE;
5723 5 : else if (gfc_match ("acquire") == MATCH_YES)
5724 : mo = OMP_MEMORDER_ACQUIRE;
5725 : else
5726 : {
5727 2 : gfc_error ("Expected SEQ_CST, AQC_REL, RELEASE, or ACQUIRE at %C");
5728 2 : return MATCH_ERROR;
5729 : }
5730 12 : c = gfc_get_omp_clauses ();
5731 12 : c->memorder = mo;
5732 : }
5733 84 : gfc_match_omp_variable_list (" (", &list, true);
5734 84 : if (list && mo != OMP_MEMORDER_UNSET)
5735 : {
5736 4 : gfc_error ("List specified together with memory order clause in FLUSH "
5737 : "directive at %C");
5738 4 : gfc_free_omp_namelist (list, OMP_LIST_NONE);
5739 4 : gfc_free_omp_clauses (c);
5740 4 : return MATCH_ERROR;
5741 : }
5742 80 : if (gfc_match_omp_eos () != MATCH_YES)
5743 : {
5744 0 : gfc_error ("Unexpected junk after $OMP FLUSH statement at %C");
5745 0 : gfc_free_omp_namelist (list, OMP_LIST_NONE);
5746 0 : gfc_free_omp_clauses (c);
5747 0 : return MATCH_ERROR;
5748 : }
5749 80 : new_st.op = EXEC_OMP_FLUSH;
5750 80 : new_st.ext.omp_namelist = list;
5751 80 : new_st.ext.omp_clauses = c;
5752 80 : return MATCH_YES;
5753 : }
5754 :
5755 :
5756 : match
5757 188 : gfc_match_omp_declare_simd (void)
5758 : {
5759 188 : locus where = gfc_current_locus;
5760 188 : gfc_symbol *proc_name;
5761 188 : gfc_omp_clauses *c;
5762 188 : gfc_omp_declare_simd *ods;
5763 188 : bool needs_space = false;
5764 :
5765 188 : switch (gfc_match (" ( "))
5766 : {
5767 144 : case MATCH_YES:
5768 144 : if (gfc_match_symbol (&proc_name, /* host assoc = */ true) != MATCH_YES
5769 144 : || gfc_match (" ) ") != MATCH_YES)
5770 0 : return MATCH_ERROR;
5771 : break;
5772 44 : case MATCH_NO: proc_name = NULL; needs_space = true; break;
5773 : case MATCH_ERROR: return MATCH_ERROR;
5774 : }
5775 :
5776 188 : if (gfc_match_omp_clauses (&c, OMP_DECLARE_SIMD_CLAUSES, true,
5777 : needs_space) != MATCH_YES)
5778 : return MATCH_ERROR;
5779 :
5780 183 : if (gfc_current_ns->is_block_data)
5781 : {
5782 1 : gfc_free_omp_clauses (c);
5783 1 : return MATCH_YES;
5784 : }
5785 :
5786 182 : ods = gfc_get_omp_declare_simd ();
5787 182 : ods->where = where;
5788 182 : ods->proc_name = proc_name;
5789 182 : ods->clauses = c;
5790 182 : ods->next = gfc_current_ns->omp_declare_simd;
5791 182 : gfc_current_ns->omp_declare_simd = ods;
5792 182 : return MATCH_YES;
5793 : }
5794 :
5795 :
5796 : static bool
5797 877 : match_udr_expr (gfc_symtree *omp_sym1, gfc_symtree *omp_sym2)
5798 : {
5799 877 : match m;
5800 877 : locus old_loc = gfc_current_locus;
5801 877 : char sname[GFC_MAX_SYMBOL_LEN + 1];
5802 877 : gfc_symbol *sym;
5803 877 : gfc_namespace *ns = gfc_current_ns;
5804 877 : gfc_expr *lvalue = NULL, *rvalue = NULL;
5805 877 : gfc_symtree *st;
5806 877 : gfc_actual_arglist *arglist;
5807 :
5808 877 : m = gfc_match (" %v =", &lvalue);
5809 877 : if (m != MATCH_YES)
5810 200 : gfc_current_locus = old_loc;
5811 : else
5812 : {
5813 677 : m = gfc_match (" %e )", &rvalue);
5814 677 : if (m == MATCH_YES)
5815 : {
5816 675 : ns->code = gfc_get_code (EXEC_ASSIGN);
5817 675 : ns->code->expr1 = lvalue;
5818 675 : ns->code->expr2 = rvalue;
5819 675 : ns->code->loc = old_loc;
5820 675 : return true;
5821 : }
5822 :
5823 2 : gfc_current_locus = old_loc;
5824 2 : gfc_free_expr (lvalue);
5825 : }
5826 :
5827 202 : m = gfc_match (" %n", sname);
5828 202 : if (m != MATCH_YES)
5829 : return false;
5830 :
5831 202 : if (strcmp (sname, omp_sym1->name) == 0
5832 200 : || strcmp (sname, omp_sym2->name) == 0)
5833 : return false;
5834 :
5835 200 : gfc_current_ns = ns->parent;
5836 200 : if (gfc_get_ha_sym_tree (sname, &st))
5837 : return false;
5838 :
5839 200 : sym = st->n.sym;
5840 200 : if (sym->attr.flavor != FL_PROCEDURE
5841 72 : && sym->attr.flavor != FL_UNKNOWN)
5842 : return false;
5843 :
5844 199 : if (!sym->attr.generic
5845 189 : && !sym->attr.subroutine
5846 71 : && !sym->attr.function)
5847 : {
5848 71 : if (!(sym->attr.external && !sym->attr.referenced))
5849 : {
5850 : /* ...create a symbol in this scope... */
5851 71 : if (sym->ns != gfc_current_ns
5852 71 : && gfc_get_sym_tree (sname, NULL, &st, false) == 1)
5853 : return false;
5854 :
5855 71 : if (sym != st->n.sym)
5856 71 : sym = st->n.sym;
5857 : }
5858 :
5859 : /* ...and then to try to make the symbol into a subroutine. */
5860 71 : if (!gfc_add_subroutine (&sym->attr, sym->name, NULL))
5861 : return false;
5862 : }
5863 :
5864 199 : gfc_set_sym_referenced (sym);
5865 199 : gfc_gobble_whitespace ();
5866 199 : if (gfc_peek_ascii_char () != '(')
5867 : return false;
5868 :
5869 195 : gfc_current_ns = ns;
5870 195 : m = gfc_match_actual_arglist (1, &arglist);
5871 195 : if (m != MATCH_YES)
5872 : return false;
5873 :
5874 195 : if (gfc_match_char (')') != MATCH_YES)
5875 : return false;
5876 :
5877 195 : ns->code = gfc_get_code (EXEC_CALL);
5878 195 : ns->code->symtree = st;
5879 195 : ns->code->ext.actual = arglist;
5880 195 : ns->code->loc = old_loc;
5881 195 : return true;
5882 : }
5883 :
5884 : static bool
5885 1156 : gfc_omp_udr_predef (gfc_omp_reduction_op rop, const char *name,
5886 : gfc_typespec *ts, const char **n)
5887 : {
5888 1156 : if (!gfc_numeric_ts (ts) && ts->type != BT_LOGICAL)
5889 : return false;
5890 :
5891 648 : switch (rop)
5892 : {
5893 21 : case OMP_REDUCTION_PLUS:
5894 21 : case OMP_REDUCTION_MINUS:
5895 21 : case OMP_REDUCTION_TIMES:
5896 21 : return ts->type != BT_LOGICAL;
5897 8 : case OMP_REDUCTION_AND:
5898 8 : case OMP_REDUCTION_OR:
5899 8 : case OMP_REDUCTION_EQV:
5900 8 : case OMP_REDUCTION_NEQV:
5901 8 : return ts->type == BT_LOGICAL;
5902 618 : case OMP_REDUCTION_USER:
5903 618 : if (name[0] != '.' && (ts->type == BT_INTEGER || ts->type == BT_REAL))
5904 : {
5905 546 : gfc_symbol *sym;
5906 :
5907 546 : gfc_find_symbol (name, NULL, 1, &sym);
5908 546 : if (sym != NULL)
5909 : {
5910 93 : if (sym->attr.intrinsic)
5911 0 : *n = sym->name;
5912 93 : else if ((sym->attr.flavor != FL_UNKNOWN
5913 81 : && sym->attr.flavor != FL_PROCEDURE)
5914 69 : || sym->attr.external
5915 54 : || sym->attr.generic
5916 54 : || sym->attr.entry
5917 54 : || sym->attr.result
5918 54 : || sym->attr.dummy
5919 54 : || sym->attr.subroutine
5920 50 : || sym->attr.pointer
5921 50 : || sym->attr.target
5922 50 : || sym->attr.cray_pointer
5923 50 : || sym->attr.cray_pointee
5924 50 : || (sym->attr.proc != PROC_UNKNOWN
5925 0 : && sym->attr.proc != PROC_INTRINSIC)
5926 50 : || sym->attr.if_source != IFSRC_UNKNOWN
5927 50 : || sym == sym->ns->proc_name)
5928 43 : *n = NULL;
5929 : else
5930 50 : *n = sym->name;
5931 : }
5932 : else
5933 453 : *n = name;
5934 546 : if (*n
5935 503 : && (strcmp (*n, "max") == 0 || strcmp (*n, "min") == 0))
5936 54 : return true;
5937 510 : else if (*n
5938 467 : && ts->type == BT_INTEGER
5939 383 : && (strcmp (*n, "iand") == 0
5940 377 : || strcmp (*n, "ior") == 0
5941 371 : || strcmp (*n, "ieor") == 0))
5942 : return true;
5943 : }
5944 : break;
5945 : default:
5946 : break;
5947 : }
5948 : return false;
5949 : }
5950 :
5951 : gfc_omp_udr *
5952 639 : gfc_omp_udr_find (gfc_symtree *st, gfc_typespec *ts)
5953 : {
5954 639 : gfc_omp_udr *omp_udr;
5955 :
5956 639 : if (st == NULL)
5957 : return NULL;
5958 :
5959 250 : for (omp_udr = st->n.omp_udr; omp_udr; omp_udr = omp_udr->next)
5960 154 : if (omp_udr->ts.type == ts->type
5961 89 : || ((omp_udr->ts.type == BT_DERIVED || omp_udr->ts.type == BT_CLASS)
5962 0 : && (ts->type == BT_DERIVED || ts->type == BT_CLASS)))
5963 : {
5964 65 : if (omp_udr->ts.type == BT_DERIVED || omp_udr->ts.type == BT_CLASS)
5965 : {
5966 12 : if (strcmp (omp_udr->ts.u.derived->name, ts->u.derived->name) == 0)
5967 : return omp_udr;
5968 : }
5969 53 : else if (omp_udr->ts.kind == ts->kind)
5970 : {
5971 19 : if (omp_udr->ts.type == BT_CHARACTER)
5972 : {
5973 17 : if (omp_udr->ts.u.cl->length == NULL
5974 15 : || ts->u.cl->length == NULL)
5975 : return omp_udr;
5976 15 : if (omp_udr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
5977 : return omp_udr;
5978 15 : if (ts->u.cl->length->expr_type != EXPR_CONSTANT)
5979 : return omp_udr;
5980 15 : if (omp_udr->ts.u.cl->length->ts.type != BT_INTEGER)
5981 : return omp_udr;
5982 15 : if (ts->u.cl->length->ts.type != BT_INTEGER)
5983 : return omp_udr;
5984 15 : if (gfc_compare_expr (omp_udr->ts.u.cl->length,
5985 : ts->u.cl->length, INTRINSIC_EQ) != 0)
5986 15 : continue;
5987 : }
5988 2 : return omp_udr;
5989 : }
5990 : }
5991 : return NULL;
5992 : }
5993 :
5994 : match
5995 532 : gfc_match_omp_declare_reduction (void)
5996 : {
5997 532 : match m;
5998 532 : gfc_intrinsic_op op;
5999 532 : char name[GFC_MAX_SYMBOL_LEN + 3];
6000 532 : auto_vec<gfc_typespec, 5> tss;
6001 532 : gfc_typespec ts;
6002 532 : unsigned int i;
6003 532 : gfc_symtree *st;
6004 532 : locus where = gfc_current_locus;
6005 532 : locus end_loc = gfc_current_locus;
6006 532 : bool end_loc_set = false;
6007 532 : gfc_omp_reduction_op rop = OMP_REDUCTION_NONE;
6008 :
6009 532 : if (gfc_match_char ('(') != MATCH_YES)
6010 : return MATCH_ERROR;
6011 :
6012 530 : m = gfc_match (" %o : ", &op);
6013 530 : if (m == MATCH_ERROR)
6014 : return MATCH_ERROR;
6015 530 : if (m == MATCH_YES)
6016 : {
6017 117 : snprintf (name, sizeof name, "operator %s", gfc_op2string (op));
6018 117 : rop = (gfc_omp_reduction_op) op;
6019 : }
6020 : else
6021 : {
6022 413 : m = gfc_match_defined_op_name (name + 1, 1);
6023 413 : if (m == MATCH_ERROR)
6024 : return MATCH_ERROR;
6025 413 : if (m == MATCH_YES)
6026 : {
6027 41 : name[0] = '.';
6028 41 : strcat (name, ".");
6029 41 : if (gfc_match (" : ") != MATCH_YES)
6030 : return MATCH_ERROR;
6031 : }
6032 : else
6033 : {
6034 372 : if (gfc_match (" %n : ", name) != MATCH_YES)
6035 : return MATCH_ERROR;
6036 : }
6037 : rop = OMP_REDUCTION_USER;
6038 : }
6039 :
6040 529 : m = gfc_match_type_spec (&ts);
6041 529 : if (m != MATCH_YES)
6042 : return MATCH_ERROR;
6043 : /* Treat len=: the same as len=*. */
6044 528 : if (ts.type == BT_CHARACTER)
6045 61 : ts.deferred = false;
6046 528 : tss.safe_push (ts);
6047 :
6048 1093 : while (gfc_match_char (',') == MATCH_YES)
6049 : {
6050 37 : m = gfc_match_type_spec (&ts);
6051 37 : if (m != MATCH_YES)
6052 : return MATCH_ERROR;
6053 37 : tss.safe_push (ts);
6054 : }
6055 528 : if (gfc_match_char (':') != MATCH_YES)
6056 : return MATCH_ERROR;
6057 :
6058 527 : st = gfc_find_symtree (gfc_current_ns->omp_udr_root, name);
6059 1084 : for (i = 0; i < tss.length (); i++)
6060 : {
6061 564 : gfc_symtree *omp_out, *omp_in;
6062 564 : gfc_symtree *omp_priv = NULL, *omp_orig = NULL;
6063 564 : gfc_namespace *combiner_ns, *initializer_ns = NULL;
6064 564 : gfc_omp_udr *prev_udr, *omp_udr;
6065 564 : const char *predef_name = NULL;
6066 :
6067 564 : omp_udr = gfc_get_omp_udr ();
6068 564 : omp_udr->name = gfc_get_string ("%s", name);
6069 564 : omp_udr->rop = rop;
6070 564 : omp_udr->ts = tss[i];
6071 564 : omp_udr->where = where;
6072 :
6073 564 : gfc_current_ns = combiner_ns = gfc_get_namespace (gfc_current_ns, 1);
6074 564 : combiner_ns->proc_name = combiner_ns->parent->proc_name;
6075 :
6076 564 : gfc_get_sym_tree ("omp_out", combiner_ns, &omp_out, false);
6077 564 : gfc_get_sym_tree ("omp_in", combiner_ns, &omp_in, false);
6078 564 : combiner_ns->omp_udr_ns = 1;
6079 564 : omp_out->n.sym->ts = tss[i];
6080 564 : omp_in->n.sym->ts = tss[i];
6081 564 : omp_out->n.sym->attr.omp_udr_artificial_var = 1;
6082 564 : omp_in->n.sym->attr.omp_udr_artificial_var = 1;
6083 564 : omp_out->n.sym->attr.flavor = FL_VARIABLE;
6084 564 : omp_in->n.sym->attr.flavor = FL_VARIABLE;
6085 564 : gfc_commit_symbols ();
6086 564 : omp_udr->combiner_ns = combiner_ns;
6087 564 : omp_udr->omp_out = omp_out->n.sym;
6088 564 : omp_udr->omp_in = omp_in->n.sym;
6089 :
6090 564 : locus old_loc = gfc_current_locus;
6091 :
6092 564 : if (!match_udr_expr (omp_out, omp_in))
6093 : {
6094 4 : syntax:
6095 7 : gfc_current_locus = old_loc;
6096 7 : gfc_current_ns = combiner_ns->parent;
6097 7 : gfc_undo_symbols ();
6098 7 : gfc_free_omp_udr (omp_udr);
6099 7 : return MATCH_ERROR;
6100 : }
6101 :
6102 560 : if (gfc_match (" initializer ( ") == MATCH_YES)
6103 : {
6104 313 : gfc_current_ns = combiner_ns->parent;
6105 313 : initializer_ns = gfc_get_namespace (gfc_current_ns, 1);
6106 313 : gfc_current_ns = initializer_ns;
6107 313 : initializer_ns->proc_name = initializer_ns->parent->proc_name;
6108 :
6109 313 : gfc_get_sym_tree ("omp_priv", initializer_ns, &omp_priv, false);
6110 313 : gfc_get_sym_tree ("omp_orig", initializer_ns, &omp_orig, false);
6111 313 : initializer_ns->omp_udr_ns = 1;
6112 313 : omp_priv->n.sym->ts = tss[i];
6113 313 : omp_orig->n.sym->ts = tss[i];
6114 313 : omp_priv->n.sym->attr.omp_udr_artificial_var = 1;
6115 313 : omp_orig->n.sym->attr.omp_udr_artificial_var = 1;
6116 313 : omp_priv->n.sym->attr.flavor = FL_VARIABLE;
6117 313 : omp_orig->n.sym->attr.flavor = FL_VARIABLE;
6118 313 : gfc_commit_symbols ();
6119 313 : omp_udr->initializer_ns = initializer_ns;
6120 313 : omp_udr->omp_priv = omp_priv->n.sym;
6121 313 : omp_udr->omp_orig = omp_orig->n.sym;
6122 :
6123 313 : if (!match_udr_expr (omp_priv, omp_orig))
6124 3 : goto syntax;
6125 : }
6126 :
6127 557 : gfc_current_ns = combiner_ns->parent;
6128 557 : if (!end_loc_set)
6129 : {
6130 520 : end_loc_set = true;
6131 520 : end_loc = gfc_current_locus;
6132 : }
6133 557 : gfc_current_locus = old_loc;
6134 :
6135 557 : prev_udr = gfc_omp_udr_find (st, &tss[i]);
6136 557 : if (gfc_omp_udr_predef (rop, name, &tss[i], &predef_name)
6137 : /* Don't error on !$omp declare reduction (min : integer : ...)
6138 : just yet, there could be integer :: min afterwards,
6139 : making it valid. When the UDR is resolved, we'll get
6140 : to it again. */
6141 557 : && (rop != OMP_REDUCTION_USER || name[0] == '.'))
6142 : {
6143 29 : if (predef_name)
6144 0 : gfc_error_now ("Redefinition of predefined %s "
6145 : "!$OMP DECLARE REDUCTION at %L",
6146 : predef_name, &where);
6147 : else
6148 29 : gfc_error_now ("Redefinition of predefined "
6149 : "!$OMP DECLARE REDUCTION at %L", &where);
6150 : }
6151 528 : else if (prev_udr)
6152 : {
6153 6 : gfc_error_now ("Redefinition of !$OMP DECLARE REDUCTION at %L",
6154 : &where);
6155 6 : gfc_error_now ("Previous !$OMP DECLARE REDUCTION at %L",
6156 : &prev_udr->where);
6157 : }
6158 522 : else if (st)
6159 : {
6160 96 : omp_udr->next = st->n.omp_udr;
6161 96 : st->n.omp_udr = omp_udr;
6162 : }
6163 : else
6164 : {
6165 426 : st = gfc_new_symtree (&gfc_current_ns->omp_udr_root, name);
6166 426 : st->n.omp_udr = omp_udr;
6167 : }
6168 : }
6169 :
6170 520 : if (end_loc_set)
6171 : {
6172 520 : gfc_current_locus = end_loc;
6173 520 : if (gfc_match_omp_eos () != MATCH_YES)
6174 : {
6175 1 : gfc_error ("Unexpected junk after !$OMP DECLARE REDUCTION at %C");
6176 1 : gfc_current_locus = where;
6177 1 : return MATCH_ERROR;
6178 : }
6179 :
6180 : return MATCH_YES;
6181 : }
6182 0 : gfc_clear_error ();
6183 0 : return MATCH_ERROR;
6184 532 : }
6185 :
6186 :
6187 : match
6188 471 : gfc_match_omp_declare_target (void)
6189 : {
6190 471 : locus old_loc;
6191 471 : match m;
6192 471 : gfc_omp_clauses *c = NULL;
6193 471 : enum gfc_omp_list_type list;
6194 471 : gfc_omp_namelist *n;
6195 471 : gfc_symbol *s;
6196 :
6197 471 : old_loc = gfc_current_locus;
6198 :
6199 471 : if (gfc_current_ns->proc_name
6200 471 : && gfc_match_omp_eos () == MATCH_YES)
6201 : {
6202 138 : if (!gfc_add_omp_declare_target (&gfc_current_ns->proc_name->attr,
6203 138 : gfc_current_ns->proc_name->name,
6204 : &old_loc))
6205 0 : goto cleanup;
6206 : return MATCH_YES;
6207 : }
6208 :
6209 333 : if (gfc_current_ns->proc_name
6210 333 : && gfc_current_ns->proc_name->attr.if_source == IFSRC_IFBODY)
6211 : {
6212 2 : gfc_error ("Only the !$OMP DECLARE TARGET form without "
6213 : "clauses is allowed in interface block at %C");
6214 2 : goto cleanup;
6215 : }
6216 :
6217 331 : m = gfc_match (" (");
6218 331 : if (m == MATCH_YES)
6219 : {
6220 85 : c = gfc_get_omp_clauses ();
6221 85 : gfc_current_locus = old_loc;
6222 85 : m = gfc_match_omp_to_link (" (", &c->lists[OMP_LIST_ENTER]);
6223 85 : if (m != MATCH_YES)
6224 0 : goto syntax;
6225 85 : if (gfc_match_omp_eos () != MATCH_YES)
6226 : {
6227 0 : gfc_error ("Unexpected junk after !$OMP DECLARE TARGET at %C");
6228 0 : goto cleanup;
6229 : }
6230 : }
6231 246 : else if (gfc_match_omp_clauses (&c, OMP_DECLARE_TARGET_CLAUSES) != MATCH_YES)
6232 : return MATCH_ERROR;
6233 :
6234 325 : gfc_buffer_error (false);
6235 :
6236 325 : static const enum gfc_omp_list_type to_enter_link_lists[]
6237 : = { OMP_LIST_TO, OMP_LIST_ENTER, OMP_LIST_LINK, OMP_LIST_LOCAL };
6238 1625 : for (size_t listn = 0; listn < ARRAY_SIZE (to_enter_link_lists)
6239 1625 : && (list = to_enter_link_lists[listn], true); ++listn)
6240 1844 : for (n = c->lists[list]; n; n = n->next)
6241 544 : if (n->sym)
6242 503 : n->sym->mark = 0;
6243 41 : else if (n->u.common->head)
6244 41 : n->u.common->head->mark = 0;
6245 :
6246 325 : if (c->device_type == OMP_DEVICE_TYPE_UNSET)
6247 257 : c->device_type = OMP_DEVICE_TYPE_ANY;
6248 1300 : for (size_t listn = 0; listn < ARRAY_SIZE (to_enter_link_lists)
6249 1625 : && (list = to_enter_link_lists[listn], true); ++listn)
6250 1844 : for (n = c->lists[list]; n; n = n->next)
6251 544 : if (n->sym)
6252 : {
6253 503 : if (n->sym->attr.in_common)
6254 1 : gfc_error_now ("OMP DECLARE TARGET variable at %L is an "
6255 : "element of a COMMON block", &n->where);
6256 502 : else if (n->sym->attr.omp_groupprivate && list != OMP_LIST_LOCAL)
6257 12 : gfc_error_now ("List item %qs at %L not appear in the %qs clause "
6258 : "as it was previously specified in a GROUPPRIVATE "
6259 : "directive", n->sym->name, &n->where,
6260 : list == OMP_LIST_LINK
6261 5 : ? "link" : list == OMP_LIST_TO ? "to" : "enter");
6262 495 : else if (n->sym->mark)
6263 9 : gfc_error_now ("Variable at %L mentioned multiple times in "
6264 : "clauses of the same OMP DECLARE TARGET directive",
6265 : &n->where);
6266 486 : else if ((n->sym->attr.omp_declare_target_link
6267 481 : || n->sym->attr.omp_declare_target_local)
6268 : && list != OMP_LIST_LINK
6269 7 : && list != OMP_LIST_LOCAL)
6270 1 : gfc_error_now ("OMP DECLARE TARGET variable at %L previously "
6271 : "mentioned in %s clause and later in %s clause",
6272 : &n->where,
6273 : n->sym->attr.omp_declare_target_link ? "LINK"
6274 : : "LOCAL",
6275 : list == OMP_LIST_TO ? "TO" : "ENTER");
6276 485 : else if (n->sym->attr.omp_declare_target
6277 14 : && (list == OMP_LIST_LINK || list == OMP_LIST_LOCAL))
6278 1 : gfc_error_now ("OMP DECLARE TARGET variable at %L previously "
6279 : "mentioned in TO or ENTER clause and later in "
6280 : "%s clause", &n->where,
6281 : list == OMP_LIST_LINK ? "LINK" : "LOCAL");
6282 : else
6283 : {
6284 484 : if (list == OMP_LIST_TO || list == OMP_LIST_ENTER)
6285 445 : gfc_add_omp_declare_target (&n->sym->attr, n->sym->name,
6286 : &n->sym->declared_at);
6287 484 : if (list == OMP_LIST_LINK)
6288 30 : gfc_add_omp_declare_target_link (&n->sym->attr, n->sym->name,
6289 30 : &n->sym->declared_at);
6290 484 : if (list == OMP_LIST_LOCAL)
6291 9 : gfc_add_omp_declare_target_local (&n->sym->attr, n->sym->name,
6292 9 : &n->sym->declared_at);
6293 : }
6294 503 : if (n->sym->attr.omp_device_type != OMP_DEVICE_TYPE_UNSET
6295 36 : && n->sym->attr.omp_device_type != c->device_type)
6296 : {
6297 12 : const char *dt = "any";
6298 12 : if (n->sym->attr.omp_device_type == OMP_DEVICE_TYPE_NOHOST)
6299 : dt = "nohost";
6300 8 : else if (n->sym->attr.omp_device_type == OMP_DEVICE_TYPE_HOST)
6301 4 : dt = "host";
6302 12 : if (n->sym->attr.omp_groupprivate)
6303 1 : gfc_error_now ("List item %qs at %L set in previous OMP "
6304 : "GROUPPRIVATE directive to the different "
6305 : "DEVICE_TYPE %qs", n->sym->name, &n->where, dt);
6306 : else
6307 11 : gfc_error_now ("List item %qs at %L set in previous OMP "
6308 : "DECLARE TARGET directive to the different "
6309 : "DEVICE_TYPE %qs", n->sym->name, &n->where, dt);
6310 : }
6311 503 : n->sym->attr.omp_device_type = c->device_type;
6312 503 : if (c->indirect && c->device_type != OMP_DEVICE_TYPE_ANY)
6313 : {
6314 1 : gfc_error_now ("DEVICE_TYPE must be ANY when used with INDIRECT "
6315 : "at %L", &n->where);
6316 1 : c->indirect = 0;
6317 : }
6318 503 : n->sym->attr.omp_declare_target_indirect = c->indirect;
6319 503 : if (list == OMP_LIST_LINK && c->device_type == OMP_DEVICE_TYPE_NOHOST)
6320 3 : gfc_error_now ("List item %qs at %L set with NOHOST specified may "
6321 : "not appear in a LINK clause", n->sym->name,
6322 : &n->where);
6323 503 : n->sym->mark = 1;
6324 : }
6325 : else /* common block */
6326 : {
6327 41 : if (n->u.common->omp_groupprivate && list != OMP_LIST_LOCAL)
6328 7 : gfc_error_now ("Common block %</%s/%> at %L not appear in the %qs "
6329 : "clause as it was previously specified in a "
6330 : "GROUPPRIVATE directive",
6331 7 : n->u.common->name, &n->where,
6332 : list == OMP_LIST_LINK
6333 5 : ? "link" : list == OMP_LIST_TO ? "to" : "enter");
6334 34 : else if (n->u.common->head && n->u.common->head->mark)
6335 4 : gfc_error_now ("Common block %</%s/%> at %L mentioned multiple "
6336 : "times in clauses of the same OMP DECLARE TARGET "
6337 4 : "directive", n->u.common->name, &n->where);
6338 30 : else if ((n->u.common->omp_declare_target_link
6339 26 : || n->u.common->omp_declare_target_local)
6340 : && list != OMP_LIST_LINK
6341 6 : && list != OMP_LIST_LOCAL)
6342 2 : gfc_error_now ("Common block %</%s/%> at %L previously mentioned "
6343 : "in %s clause and later in %s clause",
6344 1 : n->u.common->name, &n->where,
6345 : n->u.common->omp_declare_target_link ? "LINK"
6346 : : "LOCAL",
6347 : list == OMP_LIST_TO ? "TO" : "ENTER");
6348 29 : else if (n->u.common->omp_declare_target
6349 4 : && (list == OMP_LIST_LINK || list == OMP_LIST_LOCAL))
6350 1 : gfc_error_now ("Common block %</%s/%> at %L previously mentioned "
6351 : "in TO or ENTER clause and later in %s clause",
6352 1 : n->u.common->name, &n->where,
6353 : list == OMP_LIST_LINK ? "LINK" : "LOCAL");
6354 41 : if (n->u.common->omp_device_type != OMP_DEVICE_TYPE_UNSET
6355 21 : && n->u.common->omp_device_type != c->device_type)
6356 : {
6357 1 : const char *dt = "any";
6358 1 : if (n->u.common->omp_device_type == OMP_DEVICE_TYPE_NOHOST)
6359 : dt = "nohost";
6360 0 : else if (n->u.common->omp_device_type == OMP_DEVICE_TYPE_HOST)
6361 0 : dt = "host";
6362 1 : if (n->u.common->omp_groupprivate)
6363 1 : gfc_error_now ("Common block %</%s/%> at %L set in previous OMP "
6364 : "GROUPPRIVATE directive to the different "
6365 1 : "DEVICE_TYPE %qs", n->u.common->name, &n->where,
6366 : dt);
6367 : else
6368 0 : gfc_error_now ("Common block %</%s/%> at %L set in previous OMP "
6369 : "DECLARE TARGET directive to the different "
6370 0 : "DEVICE_TYPE %qs", n->u.common->name, &n->where,
6371 : dt);
6372 : }
6373 41 : n->u.common->omp_device_type = c->device_type;
6374 :
6375 41 : if (c->indirect && c->device_type != OMP_DEVICE_TYPE_ANY)
6376 : {
6377 0 : gfc_error_now ("DEVICE_TYPE must be ANY when used with INDIRECT "
6378 : "at %L", &n->where);
6379 0 : c->indirect = 0;
6380 : }
6381 41 : if (list == OMP_LIST_LINK && c->device_type == OMP_DEVICE_TYPE_NOHOST)
6382 1 : gfc_error_now ("Common block %</%s/%> at %L set with NOHOST "
6383 : "specified may not appear in a LINK clause",
6384 1 : n->u.common->name, &n->where);
6385 :
6386 41 : if (list == OMP_LIST_TO || list == OMP_LIST_ENTER)
6387 21 : n->u.common->omp_declare_target = 1;
6388 41 : if (list == OMP_LIST_LINK)
6389 15 : n->u.common->omp_declare_target_link = 1;
6390 41 : if (list == OMP_LIST_LOCAL)
6391 5 : n->u.common->omp_declare_target_local = 1;
6392 :
6393 110 : for (s = n->u.common->head; s; s = s->common_next)
6394 : {
6395 69 : s->mark = 1;
6396 69 : if (list == OMP_LIST_TO || list == OMP_LIST_ENTER)
6397 33 : gfc_add_omp_declare_target (&s->attr, s->name, &n->where);
6398 69 : if (list == OMP_LIST_LINK)
6399 31 : gfc_add_omp_declare_target_link (&s->attr, s->name, &n->where);
6400 69 : if (list == OMP_LIST_LOCAL)
6401 5 : gfc_add_omp_declare_target_local (&s->attr, s->name, &n->where);
6402 69 : s->attr.omp_device_type = c->device_type;
6403 69 : s->attr.omp_declare_target_indirect = c->indirect;
6404 : }
6405 : }
6406 325 : if ((c->device_type || c->indirect)
6407 325 : && !c->lists[OMP_LIST_ENTER]
6408 151 : && !c->lists[OMP_LIST_TO]
6409 47 : && !c->lists[OMP_LIST_LINK]
6410 10 : && !c->lists[OMP_LIST_LOCAL])
6411 2 : gfc_warning_now (OPT_Wopenmp,
6412 : "OMP DECLARE TARGET directive at %L with only "
6413 : "DEVICE_TYPE or INDIRECT clauses is ignored",
6414 : &old_loc);
6415 :
6416 325 : gfc_buffer_error (true);
6417 :
6418 325 : if (c)
6419 325 : gfc_free_omp_clauses (c);
6420 325 : return MATCH_YES;
6421 :
6422 0 : syntax:
6423 0 : gfc_error ("Syntax error in !$OMP DECLARE TARGET list at %C");
6424 :
6425 2 : cleanup:
6426 2 : gfc_current_locus = old_loc;
6427 2 : if (c)
6428 0 : gfc_free_omp_clauses (c);
6429 : return MATCH_ERROR;
6430 : }
6431 :
6432 : /* Skip over and ignore trait-property-extensions.
6433 :
6434 : trait-property-extension :
6435 : trait-property-name
6436 : identifier (trait-property-extension[, trait-property-extension[, ...]])
6437 : constant integer expression
6438 : */
6439 :
6440 : static match gfc_ignore_trait_property_extension_list (void);
6441 :
6442 : static match
6443 7 : gfc_ignore_trait_property_extension (void)
6444 : {
6445 7 : char buf[GFC_MAX_SYMBOL_LEN + 1];
6446 7 : gfc_expr *expr;
6447 :
6448 : /* Identifier form of trait-property name, possibly followed by
6449 : a list of (recursive) trait-property-extensions. */
6450 7 : if (gfc_match_name (buf) == MATCH_YES)
6451 : {
6452 0 : if (gfc_match (" (") == MATCH_YES)
6453 0 : return gfc_ignore_trait_property_extension_list ();
6454 : return MATCH_YES;
6455 : }
6456 :
6457 : /* Literal constant. */
6458 7 : if (gfc_match_literal_constant (&expr, 0) == MATCH_YES)
6459 : return MATCH_YES;
6460 :
6461 : /* FIXME: constant integer expressions. */
6462 0 : gfc_error ("Expected trait-property-extension at %C");
6463 0 : return MATCH_ERROR;
6464 : }
6465 :
6466 : static match
6467 5 : gfc_ignore_trait_property_extension_list (void)
6468 : {
6469 9 : while (1)
6470 : {
6471 7 : if (gfc_ignore_trait_property_extension () != MATCH_YES)
6472 : return MATCH_ERROR;
6473 7 : if (gfc_match (" ,") == MATCH_YES)
6474 2 : continue;
6475 5 : if (gfc_match (" )") == MATCH_YES)
6476 : return MATCH_YES;
6477 0 : gfc_error ("expected %<)%> at %C");
6478 0 : return MATCH_ERROR;
6479 : }
6480 : }
6481 :
6482 :
6483 : match
6484 110 : gfc_match_omp_interop (void)
6485 : {
6486 110 : return match_omp (EXEC_OMP_INTEROP, OMP_INTEROP_CLAUSES);
6487 : }
6488 :
6489 :
6490 : /* OpenMP 5.0:
6491 :
6492 : trait-selector:
6493 : trait-selector-name[([trait-score:]trait-property[,trait-property[,...]])]
6494 :
6495 : trait-score:
6496 : score(score-expression) */
6497 :
6498 : static match
6499 637 : gfc_match_omp_context_selector (gfc_omp_set_selector *oss)
6500 : {
6501 775 : do
6502 : {
6503 775 : char selector[GFC_MAX_SYMBOL_LEN + 1];
6504 :
6505 775 : if (gfc_match_name (selector) != MATCH_YES)
6506 : {
6507 2 : gfc_error ("expected trait selector name at %C");
6508 39 : return MATCH_ERROR;
6509 : }
6510 :
6511 773 : gfc_omp_selector *os = gfc_get_omp_selector ();
6512 773 : if (oss->code == OMP_TRAIT_SET_CONSTRUCT
6513 335 : && !strcmp (selector, "do"))
6514 48 : os->code = OMP_TRAIT_CONSTRUCT_FOR;
6515 725 : else if (oss->code == OMP_TRAIT_SET_CONSTRUCT
6516 287 : && !strcmp (selector, "for"))
6517 1 : os->code = OMP_TRAIT_INVALID;
6518 : else
6519 724 : os->code = omp_lookup_ts_code (oss->code, selector);
6520 773 : os->next = oss->trait_selectors;
6521 773 : oss->trait_selectors = os;
6522 :
6523 773 : if (os->code == OMP_TRAIT_INVALID)
6524 : {
6525 18 : gfc_warning (OPT_Wopenmp,
6526 : "unknown selector %qs for context selector set %qs "
6527 : "at %C",
6528 18 : selector, omp_tss_map[oss->code]);
6529 18 : if (gfc_match (" (") == MATCH_YES
6530 18 : && gfc_ignore_trait_property_extension_list () != MATCH_YES)
6531 : return MATCH_ERROR;
6532 18 : if (gfc_match (" ,") == MATCH_YES)
6533 1 : continue;
6534 598 : break;
6535 : }
6536 :
6537 755 : enum omp_tp_type property_kind = omp_ts_map[os->code].tp_type;
6538 755 : bool allow_score = omp_ts_map[os->code].allow_score;
6539 :
6540 755 : if (gfc_match (" (") == MATCH_YES)
6541 : {
6542 431 : if (property_kind == OMP_TRAIT_PROPERTY_NONE)
6543 : {
6544 6 : gfc_error ("selector %qs does not accept any properties at %C",
6545 : selector);
6546 6 : return MATCH_ERROR;
6547 : }
6548 :
6549 425 : if (gfc_match (" score") == MATCH_YES)
6550 : {
6551 63 : if (!allow_score)
6552 : {
6553 10 : gfc_error ("%<score%> cannot be specified in traits "
6554 : "in the %qs trait-selector-set at %C",
6555 10 : omp_tss_map[oss->code]);
6556 10 : return MATCH_ERROR;
6557 : }
6558 53 : if (gfc_match (" (") != MATCH_YES)
6559 : {
6560 0 : gfc_error ("expected %<(%> at %C");
6561 0 : return MATCH_ERROR;
6562 : }
6563 53 : if (gfc_match_expr (&os->score) != MATCH_YES)
6564 : return MATCH_ERROR;
6565 :
6566 52 : if (gfc_match (" )") != MATCH_YES)
6567 : {
6568 0 : gfc_error ("expected %<)%> at %C");
6569 0 : return MATCH_ERROR;
6570 : }
6571 :
6572 52 : if (gfc_match (" :") != MATCH_YES)
6573 : {
6574 0 : gfc_error ("expected : at %C");
6575 0 : return MATCH_ERROR;
6576 : }
6577 : }
6578 :
6579 414 : gfc_omp_trait_property *otp = gfc_get_omp_trait_property ();
6580 414 : otp->property_kind = property_kind;
6581 414 : otp->next = os->properties;
6582 414 : os->properties = otp;
6583 :
6584 414 : switch (property_kind)
6585 : {
6586 25 : case OMP_TRAIT_PROPERTY_ID:
6587 25 : {
6588 25 : char buf[GFC_MAX_SYMBOL_LEN + 1];
6589 25 : if (gfc_match_name (buf) == MATCH_YES)
6590 : {
6591 24 : otp->name = XNEWVEC (char, strlen (buf) + 1);
6592 24 : strcpy (otp->name, buf);
6593 : }
6594 : else
6595 : {
6596 1 : gfc_error ("expected identifier at %C");
6597 1 : free (otp);
6598 1 : os->properties = nullptr;
6599 1 : return MATCH_ERROR;
6600 : }
6601 : }
6602 24 : break;
6603 290 : case OMP_TRAIT_PROPERTY_NAME_LIST:
6604 343 : do
6605 : {
6606 290 : char buf[GFC_MAX_SYMBOL_LEN + 1];
6607 290 : if (gfc_match_name (buf) == MATCH_YES)
6608 : {
6609 170 : otp->name = XNEWVEC (char, strlen (buf) + 1);
6610 170 : strcpy (otp->name, buf);
6611 170 : otp->is_name = true;
6612 : }
6613 120 : else if (gfc_match_literal_constant (&otp->expr, 0)
6614 : != MATCH_YES
6615 120 : || otp->expr->ts.type != BT_CHARACTER)
6616 : {
6617 5 : gfc_error ("expected identifier or string literal "
6618 : "at %C");
6619 5 : free (otp);
6620 5 : os->properties = nullptr;
6621 5 : return MATCH_ERROR;
6622 : }
6623 :
6624 285 : if (gfc_match (" ,") == MATCH_YES)
6625 : {
6626 53 : otp = gfc_get_omp_trait_property ();
6627 53 : otp->property_kind = property_kind;
6628 53 : otp->next = os->properties;
6629 53 : os->properties = otp;
6630 : }
6631 : else
6632 : break;
6633 53 : }
6634 : while (1);
6635 232 : break;
6636 137 : case OMP_TRAIT_PROPERTY_DEV_NUM_EXPR:
6637 137 : case OMP_TRAIT_PROPERTY_BOOL_EXPR:
6638 137 : if (gfc_match_expr (&otp->expr) != MATCH_YES)
6639 : {
6640 3 : gfc_error ("expected expression at %C");
6641 3 : free (otp);
6642 3 : os->properties = nullptr;
6643 3 : return MATCH_ERROR;
6644 : }
6645 : break;
6646 15 : case OMP_TRAIT_PROPERTY_CLAUSE_LIST:
6647 15 : {
6648 15 : if (os->code == OMP_TRAIT_CONSTRUCT_SIMD)
6649 : {
6650 15 : gfc_matching_omp_context_selector = true;
6651 15 : if (gfc_match_omp_clauses (&otp->clauses,
6652 15 : OMP_DECLARE_SIMD_CLAUSES,
6653 : true, false, false)
6654 : != MATCH_YES)
6655 : {
6656 1 : gfc_matching_omp_context_selector = false;
6657 1 : gfc_error ("expected simd clause at %C");
6658 1 : return MATCH_ERROR;
6659 : }
6660 14 : gfc_matching_omp_context_selector = false;
6661 : }
6662 0 : else if (os->code == OMP_TRAIT_IMPLEMENTATION_REQUIRES)
6663 : {
6664 : /* FIXME: The "requires" selector was added in OpenMP 5.1.
6665 : Currently only the now-deprecated syntax
6666 : from OpenMP 5.0 is supported.
6667 : TODO: When implementing, update modules.cc as well. */
6668 0 : sorry_at (gfc_get_location (&gfc_current_locus),
6669 : "%<requires%> selector is not supported yet");
6670 0 : return MATCH_ERROR;
6671 : }
6672 : else
6673 0 : gcc_unreachable ();
6674 14 : break;
6675 : }
6676 0 : default:
6677 0 : gcc_unreachable ();
6678 : }
6679 :
6680 404 : if (gfc_match (" )") != MATCH_YES)
6681 : {
6682 2 : gfc_error ("expected %<)%> at %C");
6683 2 : return MATCH_ERROR;
6684 : }
6685 : }
6686 324 : else if (property_kind != OMP_TRAIT_PROPERTY_NONE
6687 324 : && property_kind != OMP_TRAIT_PROPERTY_CLAUSE_LIST
6688 8 : && property_kind != OMP_TRAIT_PROPERTY_EXTENSION)
6689 : {
6690 8 : if (gfc_match (" (") != MATCH_YES)
6691 : {
6692 8 : gfc_error ("expected %<(%> at %C");
6693 8 : return MATCH_ERROR;
6694 : }
6695 : }
6696 :
6697 718 : if (gfc_match (" ,") != MATCH_YES)
6698 : break;
6699 : }
6700 : while (1);
6701 :
6702 598 : return MATCH_YES;
6703 : }
6704 :
6705 : /* OpenMP 5.0:
6706 :
6707 : trait-set-selector[,trait-set-selector[,...]]
6708 :
6709 : trait-set-selector:
6710 : trait-set-selector-name = { trait-selector[, trait-selector[, ...]] }
6711 :
6712 : trait-set-selector-name:
6713 : constructor
6714 : device
6715 : implementation
6716 : user */
6717 :
6718 : static match
6719 577 : gfc_match_omp_context_selector_specification (gfc_omp_set_selector **oss_head)
6720 : {
6721 713 : do
6722 : {
6723 645 : match m;
6724 645 : char buf[GFC_MAX_SYMBOL_LEN + 1];
6725 645 : enum omp_tss_code set = OMP_TRAIT_SET_INVALID;
6726 :
6727 645 : m = gfc_match_name (buf);
6728 645 : if (m == MATCH_YES)
6729 643 : set = omp_lookup_tss_code (buf);
6730 :
6731 643 : if (set == OMP_TRAIT_SET_INVALID)
6732 : {
6733 5 : gfc_error ("expected context selector set name at %C");
6734 47 : return MATCH_ERROR;
6735 : }
6736 :
6737 640 : m = gfc_match (" =");
6738 640 : if (m != MATCH_YES)
6739 : {
6740 1 : gfc_error ("expected %<=%> at %C");
6741 1 : return MATCH_ERROR;
6742 : }
6743 :
6744 639 : m = gfc_match (" {");
6745 639 : if (m != MATCH_YES)
6746 : {
6747 2 : gfc_error ("expected %<{%> at %C");
6748 2 : return MATCH_ERROR;
6749 : }
6750 :
6751 637 : gfc_omp_set_selector *oss = gfc_get_omp_set_selector ();
6752 637 : oss->next = *oss_head;
6753 637 : oss->code = set;
6754 637 : *oss_head = oss;
6755 :
6756 637 : if (gfc_match_omp_context_selector (oss) != MATCH_YES)
6757 : return MATCH_ERROR;
6758 :
6759 598 : m = gfc_match (" }");
6760 598 : if (m != MATCH_YES)
6761 : {
6762 0 : gfc_error ("expected %<}%> at %C");
6763 0 : return MATCH_ERROR;
6764 : }
6765 :
6766 598 : m = gfc_match (" ,");
6767 598 : if (m != MATCH_YES)
6768 : break;
6769 68 : }
6770 : while (1);
6771 :
6772 530 : return MATCH_YES;
6773 : }
6774 :
6775 :
6776 : match
6777 419 : gfc_match_omp_declare_variant (void)
6778 : {
6779 419 : char buf[GFC_MAX_SYMBOL_LEN + 1];
6780 :
6781 419 : if (gfc_match (" (") != MATCH_YES)
6782 : {
6783 2 : gfc_error ("expected %<(%> at %C");
6784 2 : return MATCH_ERROR;
6785 : }
6786 :
6787 417 : gfc_symtree *base_proc_st, *variant_proc_st;
6788 417 : if (gfc_match_name (buf) != MATCH_YES)
6789 : {
6790 2 : gfc_error ("expected name at %C");
6791 2 : return MATCH_ERROR;
6792 : }
6793 :
6794 415 : if (gfc_get_ha_sym_tree (buf, &base_proc_st))
6795 : return MATCH_ERROR;
6796 :
6797 415 : if (gfc_match (" :") == MATCH_YES)
6798 : {
6799 16 : if (gfc_match_name (buf) != MATCH_YES)
6800 : {
6801 0 : gfc_error ("expected variant name at %C");
6802 0 : return MATCH_ERROR;
6803 : }
6804 :
6805 16 : if (gfc_get_ha_sym_tree (buf, &variant_proc_st))
6806 : return MATCH_ERROR;
6807 : }
6808 : else
6809 : {
6810 : /* Base procedure not specified. */
6811 399 : variant_proc_st = base_proc_st;
6812 399 : base_proc_st = NULL;
6813 : }
6814 :
6815 415 : gfc_omp_declare_variant *odv;
6816 415 : odv = gfc_get_omp_declare_variant ();
6817 415 : odv->where = gfc_current_locus;
6818 415 : odv->variant_proc_symtree = variant_proc_st;
6819 415 : odv->adjust_args_list = NULL;
6820 415 : odv->base_proc_symtree = base_proc_st;
6821 415 : odv->next = NULL;
6822 415 : odv->error_p = false;
6823 :
6824 : /* Add the new declare variant to the end of the list. */
6825 415 : gfc_omp_declare_variant **prev_next = &gfc_current_ns->omp_declare_variant;
6826 555 : while (*prev_next)
6827 140 : prev_next = &((*prev_next)->next);
6828 415 : *prev_next = odv;
6829 :
6830 415 : if (gfc_match (" )") != MATCH_YES)
6831 : {
6832 1 : gfc_error ("expected %<)%> at %C");
6833 1 : return MATCH_ERROR;
6834 : }
6835 :
6836 414 : bool has_match = false, has_adjust_args = false, has_append_args = false;
6837 414 : bool error_p = false;
6838 414 : locus adjust_args_loc;
6839 414 : locus append_args_loc;
6840 :
6841 414 : gfc_gobble_whitespace ();
6842 414 : gfc_match_char (',');
6843 632 : for (;;)
6844 : {
6845 523 : gfc_gobble_whitespace ();
6846 :
6847 523 : enum clause
6848 : {
6849 : clause_match,
6850 : clause_adjust_args,
6851 : clause_append_args
6852 : } ccode;
6853 :
6854 523 : if (gfc_match ("match") == MATCH_YES)
6855 : ccode = clause_match;
6856 119 : else if (gfc_match ("adjust_args") == MATCH_YES)
6857 : {
6858 517 : ccode = clause_adjust_args;
6859 : adjust_args_loc = gfc_current_locus;
6860 : }
6861 38 : else if (gfc_match ("append_args") == MATCH_YES)
6862 : {
6863 517 : ccode = clause_append_args;
6864 : append_args_loc = gfc_current_locus;
6865 : }
6866 : else
6867 : {
6868 : error_p = true;
6869 : break;
6870 : }
6871 :
6872 517 : if (gfc_match (" ( ") != MATCH_YES)
6873 : {
6874 1 : gfc_error ("expected %<(%> at %C");
6875 1 : return MATCH_ERROR;
6876 : }
6877 :
6878 516 : if (ccode == clause_match)
6879 : {
6880 403 : if (has_match)
6881 : {
6882 1 : gfc_error ("%qs clause at %L specified more than once",
6883 : "match", &gfc_current_locus);
6884 1 : return MATCH_ERROR;
6885 : }
6886 402 : has_match = true;
6887 402 : if (gfc_match_omp_context_selector_specification (&odv->set_selectors)
6888 : != MATCH_YES)
6889 : return MATCH_ERROR;
6890 362 : if (gfc_match (" )") != MATCH_YES)
6891 : {
6892 0 : gfc_error ("expected %<)%> at %C");
6893 0 : return MATCH_ERROR;
6894 : }
6895 : }
6896 113 : else if (ccode == clause_adjust_args)
6897 : {
6898 81 : has_adjust_args = true;
6899 81 : bool need_device_ptr_p = false;
6900 81 : bool need_device_addr_p = false;
6901 81 : if (gfc_match ("nothing ") == MATCH_YES)
6902 : ;
6903 58 : else if (gfc_match ("need_device_ptr ") == MATCH_YES)
6904 : need_device_ptr_p = true;
6905 9 : else if (gfc_match ("need_device_addr ") == MATCH_YES)
6906 : need_device_addr_p = true;
6907 : else
6908 : {
6909 2 : gfc_error ("expected %<nothing%>, %<need_device_ptr%> or "
6910 : "%<need_device_addr%> at %C");
6911 2 : return MATCH_ERROR;
6912 : }
6913 79 : if (gfc_match (": ") != MATCH_YES)
6914 : {
6915 1 : gfc_error ("expected %<:%> at %C");
6916 1 : return MATCH_ERROR;
6917 : }
6918 : gfc_omp_namelist *tail = NULL;
6919 : bool need_range = false, have_range = false;
6920 125 : while (true)
6921 : {
6922 125 : gfc_omp_namelist *p = gfc_get_omp_namelist ();
6923 125 : p->where = gfc_current_locus;
6924 125 : p->u.adj_args.need_ptr = need_device_ptr_p;
6925 125 : p->u.adj_args.need_addr = need_device_addr_p;
6926 125 : if (tail)
6927 : {
6928 47 : tail->next = p;
6929 47 : tail = tail->next;
6930 : }
6931 : else
6932 : {
6933 78 : gfc_omp_namelist **q = &odv->adjust_args_list;
6934 78 : if (*q)
6935 : {
6936 50 : for (; (*q)->next; q = &(*q)->next)
6937 : ;
6938 28 : (*q)->next = p;
6939 : }
6940 : else
6941 50 : *q = p;
6942 : tail = p;
6943 : }
6944 125 : if (gfc_match (": ") == MATCH_YES)
6945 : {
6946 2 : if (have_range)
6947 : {
6948 0 : gfc_error ("unexpected %<:%> at %C");
6949 2 : return MATCH_ERROR;
6950 : }
6951 2 : p->u.adj_args.range_start = have_range = true;
6952 2 : need_range = false;
6953 49 : continue;
6954 : }
6955 123 : if (have_range && gfc_match (", ") == MATCH_YES)
6956 : {
6957 1 : have_range = false;
6958 1 : continue;
6959 : }
6960 122 : if (have_range && gfc_match (") ") == MATCH_YES)
6961 : break;
6962 121 : locus saved_loc = gfc_current_locus;
6963 :
6964 : /* Without ranges, only arg names or integer literals permitted;
6965 : handle literals here as gfc_match_expr simplifies the expr. */
6966 121 : if (gfc_match_literal_constant (&p->expr, true) == MATCH_YES)
6967 : {
6968 17 : gfc_gobble_whitespace ();
6969 17 : char c = gfc_peek_ascii_char ();
6970 17 : if (c != ')' && c != ',' && c != ':')
6971 : {
6972 1 : gfc_free_expr (p->expr);
6973 1 : p->expr = NULL;
6974 1 : gfc_current_locus = saved_loc;
6975 : }
6976 : }
6977 121 : if (!p->expr && gfc_match ("omp_num_args") == MATCH_YES)
6978 : {
6979 6 : if (!have_range)
6980 3 : p->u.adj_args.range_start = need_range = true;
6981 : else
6982 : need_range = false;
6983 :
6984 6 : locus saved_loc2 = gfc_current_locus;
6985 6 : gfc_gobble_whitespace ();
6986 6 : char c = gfc_peek_ascii_char ();
6987 6 : if (c == '+' || c == '-')
6988 : {
6989 5 : if (gfc_match ("+ %e", &p->expr) == MATCH_YES)
6990 1 : p->u.adj_args.omp_num_args_plus = true;
6991 4 : else if (gfc_match ("- %e", &p->expr) == MATCH_YES)
6992 4 : p->u.adj_args.omp_num_args_minus = true;
6993 0 : else if (!gfc_error_check ())
6994 : {
6995 0 : gfc_error ("expected constant integer expression "
6996 : "at %C");
6997 0 : p->u.adj_args.error_p = true;
6998 0 : return MATCH_ERROR;
6999 : }
7000 5 : p->where = gfc_get_location_range (&saved_loc, 1,
7001 : &saved_loc, 1,
7002 : &gfc_current_locus);
7003 : }
7004 : else
7005 : {
7006 1 : p->where = gfc_get_location_range (&saved_loc, 1,
7007 : &saved_loc, 1,
7008 : &saved_loc2);
7009 1 : p->u.adj_args.omp_num_args_plus = true;
7010 : }
7011 : }
7012 115 : else if (!p->expr)
7013 : {
7014 99 : match m = gfc_match_expr (&p->expr);
7015 99 : if (m != MATCH_YES)
7016 : {
7017 1 : gfc_error ("expected dummy parameter name, "
7018 : "%<omp_num_args%> or constant positive integer"
7019 : " at %C");
7020 1 : p->u.adj_args.error_p = true;
7021 1 : return MATCH_ERROR;
7022 : }
7023 98 : if (p->expr->expr_type == EXPR_CONSTANT && !have_range)
7024 98 : need_range = true; /* Constant expr but not literal. */
7025 98 : p->where = p->expr->where;
7026 : }
7027 : else
7028 16 : p->where = p->expr->where;
7029 120 : gfc_gobble_whitespace ();
7030 120 : match m = gfc_match (": ");
7031 120 : if (need_range && m != MATCH_YES)
7032 : {
7033 1 : gfc_error ("expected %<:%> at %C");
7034 1 : return MATCH_ERROR;
7035 : }
7036 119 : if (m == MATCH_YES)
7037 : {
7038 6 : p->u.adj_args.range_start = have_range = true;
7039 6 : need_range = false;
7040 6 : continue;
7041 : }
7042 113 : need_range = have_range = false;
7043 113 : if (gfc_match (", ") == MATCH_YES)
7044 38 : continue;
7045 75 : if (gfc_match (") ") == MATCH_YES)
7046 : break;
7047 : }
7048 : }
7049 32 : else if (ccode == clause_append_args)
7050 : {
7051 32 : if (has_append_args)
7052 : {
7053 1 : gfc_error ("%qs clause at %L specified more than once",
7054 : "append_args", &gfc_current_locus);
7055 1 : return MATCH_ERROR;
7056 : }
7057 56 : has_append_args = true;
7058 : gfc_omp_namelist *append_args_last = NULL;
7059 81 : do
7060 : {
7061 56 : gfc_gobble_whitespace ();
7062 56 : if (gfc_match ("interop ") != MATCH_YES)
7063 : {
7064 0 : gfc_error ("expected %<interop%> at %C");
7065 3 : return MATCH_ERROR;
7066 : }
7067 56 : if (gfc_match ("( ") != MATCH_YES)
7068 : {
7069 0 : gfc_error ("expected %<(%> at %C");
7070 0 : return MATCH_ERROR;
7071 : }
7072 :
7073 56 : bool target, targetsync;
7074 56 : char *type_str = NULL;
7075 56 : int type_str_len;
7076 56 : locus loc = gfc_current_locus;
7077 56 : if (gfc_parser_omp_clause_init_modifiers (target, targetsync,
7078 : &type_str, type_str_len,
7079 : false) == MATCH_ERROR)
7080 : return MATCH_ERROR;
7081 :
7082 54 : gfc_omp_namelist *n = gfc_get_omp_namelist();
7083 54 : n->where = loc;
7084 54 : n->u.init.target = target;
7085 54 : n->u.init.targetsync = targetsync;
7086 54 : n->u.init.len = type_str_len;
7087 54 : n->u2.init_interop = type_str;
7088 54 : if (odv->append_args_list)
7089 : {
7090 25 : append_args_last->next = n;
7091 25 : append_args_last = n;
7092 : }
7093 : else
7094 29 : append_args_last = odv->append_args_list = n;
7095 :
7096 54 : gfc_gobble_whitespace ();
7097 54 : if (gfc_match_char (',') == MATCH_YES)
7098 25 : continue;
7099 29 : if (gfc_match_char (')') == MATCH_YES)
7100 : break;
7101 1 : gfc_error ("Expected %<,%> or %<)%> at %C");
7102 1 : return MATCH_ERROR;
7103 : }
7104 : while (true);
7105 : }
7106 466 : gfc_gobble_whitespace ();
7107 466 : if (gfc_match_omp_eos () == MATCH_YES)
7108 : break;
7109 109 : gfc_match_char (',');
7110 109 : }
7111 :
7112 363 : if (error_p || (!has_match && !has_adjust_args && !has_append_args))
7113 : {
7114 6 : gfc_error ("expected %<match%>, %<adjust_args%> or %<append_args%> at %C");
7115 6 : return MATCH_ERROR;
7116 : }
7117 :
7118 357 : if (!has_match)
7119 : {
7120 3 : gfc_error ("expected %<match%> clause at %C");
7121 3 : return MATCH_ERROR;
7122 : }
7123 :
7124 : return MATCH_YES;
7125 : }
7126 :
7127 :
7128 : static match
7129 160 : match_omp_metadirective (bool begin_p)
7130 : {
7131 160 : locus old_loc = gfc_current_locus;
7132 160 : gfc_omp_variant *variants_head;
7133 160 : gfc_omp_variant **next_variant = &variants_head;
7134 160 : bool default_seen = false;
7135 :
7136 : /* Parse the context selectors. */
7137 656 : for (;;)
7138 : {
7139 408 : bool default_p = false;
7140 408 : gfc_omp_set_selector *selectors = NULL;
7141 :
7142 408 : gfc_gobble_whitespace ();
7143 408 : if (gfc_match_eos () == MATCH_YES)
7144 : break;
7145 266 : gfc_match_char (',');
7146 266 : gfc_gobble_whitespace ();
7147 :
7148 266 : locus variant_locus = gfc_current_locus;
7149 :
7150 266 : if (gfc_match ("default ( ") == MATCH_YES)
7151 : {
7152 82 : default_p = true;
7153 82 : gfc_warning (OPT_Wdeprecated_openmp,
7154 : "%<default%> clause with metadirective at %L "
7155 : "deprecated since OpenMP 5.2", &variant_locus);
7156 : }
7157 184 : else if (gfc_match ("otherwise ( ") == MATCH_YES)
7158 : default_p = true;
7159 177 : else if (gfc_match ("when ( ") != MATCH_YES)
7160 : {
7161 1 : gfc_error ("expected %<when%>, %<otherwise%>, or %<default%> at %C");
7162 1 : gfc_current_locus = old_loc;
7163 18 : return MATCH_ERROR;
7164 : }
7165 89 : if (default_p && default_seen)
7166 : {
7167 3 : gfc_error ("too many %<otherwise%> or %<default%> clauses "
7168 : "in %<metadirective%> at %C");
7169 3 : gfc_current_locus = old_loc;
7170 3 : return MATCH_ERROR;
7171 : }
7172 262 : else if (default_seen)
7173 : {
7174 1 : gfc_error ("%<otherwise%> or %<default%> clause "
7175 : "must appear last in %<metadirective%> at %C");
7176 1 : gfc_current_locus = old_loc;
7177 1 : return MATCH_ERROR;
7178 : }
7179 :
7180 261 : if (!default_p)
7181 : {
7182 175 : if (gfc_match_omp_context_selector_specification (&selectors)
7183 : != MATCH_YES)
7184 : return MATCH_ERROR;
7185 :
7186 168 : if (gfc_match (" : ") != MATCH_YES)
7187 : {
7188 1 : gfc_error ("expected %<:%> at %C");
7189 1 : gfc_current_locus = old_loc;
7190 1 : return MATCH_ERROR;
7191 : }
7192 :
7193 167 : gfc_commit_symbols ();
7194 : }
7195 :
7196 253 : gfc_matching_omp_context_selector = true;
7197 253 : gfc_statement directive = match_omp_directive ();
7198 253 : gfc_matching_omp_context_selector = false;
7199 :
7200 253 : if (is_omp_declarative_stmt (directive))
7201 0 : sorry_at (gfc_get_location (&gfc_current_locus),
7202 : "declarative directive variants are not supported");
7203 :
7204 253 : if (gfc_error_flag_test ())
7205 : {
7206 2 : gfc_current_locus = old_loc;
7207 2 : return MATCH_ERROR;
7208 : }
7209 :
7210 251 : if (gfc_match (" )") != MATCH_YES)
7211 : {
7212 0 : gfc_error ("Expected %<)%> at %C");
7213 0 : gfc_current_locus = old_loc;
7214 0 : return MATCH_ERROR;
7215 : }
7216 :
7217 251 : gfc_commit_symbols ();
7218 :
7219 251 : if (begin_p
7220 251 : && directive != ST_NONE
7221 251 : && gfc_omp_end_stmt (directive) == ST_NONE)
7222 : {
7223 3 : gfc_error ("variant directive used in OMP BEGIN METADIRECTIVE "
7224 : "at %C must have a corresponding end directive");
7225 3 : gfc_current_locus = old_loc;
7226 3 : return MATCH_ERROR;
7227 : }
7228 :
7229 248 : if (default_p)
7230 : default_seen = true;
7231 :
7232 248 : gfc_omp_variant *omv = gfc_get_omp_variant ();
7233 248 : omv->selectors = selectors;
7234 248 : omv->stmt = directive;
7235 248 : omv->where = variant_locus;
7236 :
7237 248 : if (directive == ST_NONE)
7238 : {
7239 : /* The directive was a 'nothing' directive. */
7240 15 : omv->code = gfc_get_code (EXEC_CONTINUE);
7241 15 : omv->code->ext.omp_clauses = NULL;
7242 : }
7243 : else
7244 : {
7245 233 : omv->code = gfc_get_code (new_st.op);
7246 233 : omv->code->ext.omp_clauses = new_st.ext.omp_clauses;
7247 : /* Prevent the OpenMP clauses from being freed via NEW_ST. */
7248 233 : new_st.ext.omp_clauses = NULL;
7249 : }
7250 :
7251 248 : *next_variant = omv;
7252 248 : next_variant = &omv->next;
7253 248 : }
7254 :
7255 142 : if (gfc_match_omp_eos () != MATCH_YES)
7256 : {
7257 0 : gfc_error ("Unexpected junk after OMP METADIRECTIVE at %C");
7258 0 : gfc_current_locus = old_loc;
7259 0 : return MATCH_ERROR;
7260 : }
7261 :
7262 : /* Add a 'default (nothing)' clause if no default is explicitly given. */
7263 142 : if (!default_seen)
7264 : {
7265 65 : gfc_omp_variant *omv = gfc_get_omp_variant ();
7266 65 : omv->stmt = ST_NONE;
7267 65 : omv->code = gfc_get_code (EXEC_CONTINUE);
7268 65 : omv->code->ext.omp_clauses = NULL;
7269 65 : omv->where = old_loc;
7270 65 : omv->selectors = NULL;
7271 :
7272 65 : *next_variant = omv;
7273 65 : next_variant = &omv->next;
7274 : }
7275 :
7276 142 : new_st.op = EXEC_OMP_METADIRECTIVE;
7277 142 : new_st.ext.omp_variants = variants_head;
7278 :
7279 142 : return MATCH_YES;
7280 : }
7281 :
7282 : match
7283 43 : gfc_match_omp_begin_metadirective (void)
7284 : {
7285 43 : return match_omp_metadirective (true);
7286 : }
7287 :
7288 : match
7289 117 : gfc_match_omp_metadirective (void)
7290 : {
7291 117 : return match_omp_metadirective (false);
7292 : }
7293 :
7294 : /* Match 'omp threadprivate' or 'omp groupprivate'. */
7295 : static match
7296 259 : gfc_match_omp_thread_group_private (bool is_groupprivate)
7297 : {
7298 259 : locus old_loc;
7299 259 : char n[GFC_MAX_SYMBOL_LEN+1];
7300 259 : gfc_symbol *sym;
7301 259 : match m;
7302 259 : gfc_symtree *st;
7303 259 : struct sym_loc_t { gfc_symbol *sym; gfc_common_head *com; locus loc; };
7304 259 : auto_vec<sym_loc_t> syms;
7305 :
7306 259 : old_loc = gfc_current_locus;
7307 :
7308 259 : m = gfc_match (" ( ");
7309 259 : if (m != MATCH_YES)
7310 : return m;
7311 :
7312 369 : for (;;)
7313 : {
7314 314 : locus sym_loc = gfc_current_locus;
7315 314 : m = gfc_match_symbol (&sym, 0);
7316 314 : switch (m)
7317 : {
7318 209 : case MATCH_YES:
7319 209 : if (sym->attr.in_common)
7320 0 : gfc_error_now ("%qs variable at %L is an element of a COMMON block",
7321 : is_groupprivate ? "groupprivate" : "threadprivate",
7322 : &sym_loc);
7323 209 : else if (!is_groupprivate
7324 209 : && !gfc_add_threadprivate (&sym->attr, sym->name, &sym_loc))
7325 16 : goto cleanup;
7326 207 : else if (is_groupprivate)
7327 : {
7328 30 : if (!gfc_add_omp_groupprivate (&sym->attr, sym->name, &sym_loc))
7329 4 : goto cleanup;
7330 26 : syms.safe_push ({sym, nullptr, sym_loc});
7331 : }
7332 203 : goto next_item;
7333 : case MATCH_NO:
7334 : break;
7335 0 : case MATCH_ERROR:
7336 0 : goto cleanup;
7337 : }
7338 :
7339 105 : m = gfc_match (" / %n /", n);
7340 105 : if (m == MATCH_ERROR)
7341 0 : goto cleanup;
7342 105 : if (m == MATCH_NO || n[0] == '\0')
7343 0 : goto syntax;
7344 :
7345 105 : st = gfc_find_symtree (gfc_current_ns->common_root, n);
7346 105 : if (st == NULL)
7347 : {
7348 2 : gfc_error ("COMMON block /%s/ not found at %L", n, &sym_loc);
7349 2 : goto cleanup;
7350 : }
7351 103 : syms.safe_push ({nullptr, st->n.common, sym_loc});
7352 103 : if (is_groupprivate)
7353 30 : st->n.common->omp_groupprivate = 1;
7354 : else
7355 73 : st->n.common->threadprivate = 1;
7356 236 : for (sym = st->n.common->head; sym; sym = sym->common_next)
7357 141 : if (!is_groupprivate
7358 141 : && !gfc_add_threadprivate (&sym->attr, sym->name, &sym_loc))
7359 3 : goto cleanup;
7360 138 : else if (is_groupprivate
7361 138 : && !gfc_add_omp_groupprivate (&sym->attr, sym->name, &sym_loc))
7362 5 : goto cleanup;
7363 :
7364 95 : next_item:
7365 298 : if (gfc_match_char (')') == MATCH_YES)
7366 : break;
7367 55 : if (gfc_match_char (',') != MATCH_YES)
7368 0 : goto syntax;
7369 55 : }
7370 :
7371 243 : if (is_groupprivate)
7372 : {
7373 39 : gfc_omp_clauses *c;
7374 39 : m = gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_DEVICE_TYPE));
7375 39 : if (m == MATCH_ERROR)
7376 0 : return MATCH_ERROR;
7377 :
7378 39 : if (c->device_type == OMP_DEVICE_TYPE_UNSET)
7379 19 : c->device_type = OMP_DEVICE_TYPE_ANY;
7380 :
7381 86 : for (size_t i = 0; i < syms.length (); i++)
7382 47 : if (syms[i].sym)
7383 : {
7384 24 : sym_loc_t &n = syms[i];
7385 24 : if (n.sym->attr.in_common)
7386 0 : gfc_error_now ("Variable %qs at %L is an element of a COMMON "
7387 : "block", n.sym->name, &n.loc);
7388 24 : else if (n.sym->attr.omp_declare_target
7389 23 : || n.sym->attr.omp_declare_target_link)
7390 2 : gfc_error_now ("List item %qs at %L implies OMP DECLARE TARGET "
7391 : "with the LOCAL clause, but it has been specified"
7392 : " with a different clause before",
7393 : n.sym->name, &n.loc);
7394 24 : if (n.sym->attr.omp_device_type != OMP_DEVICE_TYPE_UNSET
7395 5 : && n.sym->attr.omp_device_type != c->device_type)
7396 : {
7397 2 : const char *dt = "any";
7398 2 : if (n.sym->attr.omp_device_type == OMP_DEVICE_TYPE_HOST)
7399 : dt = "host";
7400 0 : else if (n.sym->attr.omp_device_type == OMP_DEVICE_TYPE_NOHOST)
7401 0 : dt = "nohost";
7402 2 : gfc_error_now ("List item %qs at %L set in previous OMP DECLARE "
7403 : "TARGET directive to the different DEVICE_TYPE %qs",
7404 : n.sym->name, &n.loc, dt);
7405 : }
7406 24 : gfc_add_omp_declare_target_local (&n.sym->attr, n.sym->name,
7407 : &n.loc);
7408 24 : n.sym->attr.omp_device_type = c->device_type;
7409 : }
7410 : else /* Common block. */
7411 : {
7412 23 : sym_loc_t &n = syms[i];
7413 23 : if (n.com->omp_declare_target
7414 22 : || n.com->omp_declare_target_link)
7415 2 : gfc_error_now ("List item %</%s/%> at %L implies OMP DECLARE "
7416 : "TARGET with the LOCAL clause, but it has been "
7417 : "specified with a different clause before",
7418 2 : n.com->name, &n.loc);
7419 23 : if (n.com->omp_device_type != OMP_DEVICE_TYPE_UNSET
7420 5 : && n.com->omp_device_type != c->device_type)
7421 : {
7422 2 : const char *dt = "any";
7423 2 : if (n.com->omp_device_type == OMP_DEVICE_TYPE_HOST)
7424 : dt = "host";
7425 0 : else if (n.com->omp_device_type == OMP_DEVICE_TYPE_NOHOST)
7426 0 : dt = "nohost";
7427 2 : gfc_error_now ("List item %qs at %L set in previous OMP DECLARE"
7428 : " TARGET directive to the different DEVICE_TYPE "
7429 2 : "%qs", n.com->name, &n.loc, dt);
7430 : }
7431 23 : n.com->omp_declare_target_local = 1;
7432 23 : n.com->omp_device_type = c->device_type;
7433 46 : for (gfc_symbol *s = n.com->head; s; s = s->common_next)
7434 : {
7435 23 : gfc_add_omp_declare_target_local (&s->attr, s->name, &n.loc);
7436 23 : s->attr.omp_device_type = c->device_type;
7437 : }
7438 : }
7439 39 : free (c);
7440 : }
7441 :
7442 243 : if (gfc_match_omp_eos () != MATCH_YES)
7443 : {
7444 0 : gfc_error ("Unexpected junk after OMP %s at %C",
7445 : is_groupprivate ? "GROUPPRIVATE" : "THREADPRIVATE");
7446 0 : goto cleanup;
7447 : }
7448 :
7449 : return MATCH_YES;
7450 :
7451 0 : syntax:
7452 0 : gfc_error ("Syntax error in !$OMP %s list at %C",
7453 : is_groupprivate ? "GROUPPRIVATE" : "THREADPRIVATE");
7454 :
7455 16 : cleanup:
7456 16 : gfc_current_locus = old_loc;
7457 16 : return MATCH_ERROR;
7458 259 : }
7459 :
7460 :
7461 : match
7462 48 : gfc_match_omp_groupprivate (void)
7463 : {
7464 48 : return gfc_match_omp_thread_group_private (true);
7465 : }
7466 :
7467 :
7468 : match
7469 211 : gfc_match_omp_threadprivate (void)
7470 : {
7471 211 : return gfc_match_omp_thread_group_private (false);
7472 : }
7473 :
7474 :
7475 : match
7476 2145 : gfc_match_omp_parallel (void)
7477 : {
7478 2145 : return match_omp (EXEC_OMP_PARALLEL, OMP_PARALLEL_CLAUSES);
7479 : }
7480 :
7481 :
7482 : match
7483 1199 : gfc_match_omp_parallel_do (void)
7484 : {
7485 1199 : return match_omp (EXEC_OMP_PARALLEL_DO,
7486 1199 : (OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES)
7487 1199 : & ~(omp_mask (OMP_CLAUSE_NOWAIT)));
7488 : }
7489 :
7490 :
7491 : match
7492 298 : gfc_match_omp_parallel_do_simd (void)
7493 : {
7494 298 : return match_omp (EXEC_OMP_PARALLEL_DO_SIMD,
7495 298 : (OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES | OMP_SIMD_CLAUSES)
7496 298 : & ~(omp_mask (OMP_CLAUSE_NOWAIT)));
7497 : }
7498 :
7499 :
7500 : match
7501 14 : gfc_match_omp_parallel_masked (void)
7502 : {
7503 14 : return match_omp (EXEC_OMP_PARALLEL_MASKED,
7504 14 : OMP_PARALLEL_CLAUSES | OMP_MASKED_CLAUSES);
7505 : }
7506 :
7507 : match
7508 10 : gfc_match_omp_parallel_masked_taskloop (void)
7509 : {
7510 10 : return match_omp (EXEC_OMP_PARALLEL_MASKED_TASKLOOP,
7511 10 : (OMP_PARALLEL_CLAUSES | OMP_MASKED_CLAUSES
7512 10 : | OMP_TASKLOOP_CLAUSES)
7513 10 : & ~(omp_mask (OMP_CLAUSE_IN_REDUCTION)));
7514 : }
7515 :
7516 : match
7517 13 : gfc_match_omp_parallel_masked_taskloop_simd (void)
7518 : {
7519 13 : return match_omp (EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD,
7520 13 : (OMP_PARALLEL_CLAUSES | OMP_MASKED_CLAUSES
7521 13 : | OMP_TASKLOOP_CLAUSES | OMP_SIMD_CLAUSES)
7522 13 : & ~(omp_mask (OMP_CLAUSE_IN_REDUCTION)));
7523 : }
7524 :
7525 : match
7526 14 : gfc_match_omp_parallel_master (void)
7527 : {
7528 14 : gfc_warning (OPT_Wdeprecated_openmp,
7529 : "%<master%> construct at %C deprecated since OpenMP 5.1, use "
7530 : "%<masked%>");
7531 14 : return match_omp (EXEC_OMP_PARALLEL_MASTER, OMP_PARALLEL_CLAUSES);
7532 : }
7533 :
7534 : match
7535 15 : gfc_match_omp_parallel_master_taskloop (void)
7536 : {
7537 15 : gfc_warning (OPT_Wdeprecated_openmp,
7538 : "%<master%> construct at %C deprecated since OpenMP 5.1, "
7539 : "use %<masked%>");
7540 15 : return match_omp (EXEC_OMP_PARALLEL_MASTER_TASKLOOP,
7541 15 : (OMP_PARALLEL_CLAUSES | OMP_TASKLOOP_CLAUSES)
7542 15 : & ~(omp_mask (OMP_CLAUSE_IN_REDUCTION)));
7543 : }
7544 :
7545 : match
7546 21 : gfc_match_omp_parallel_master_taskloop_simd (void)
7547 : {
7548 21 : gfc_warning (OPT_Wdeprecated_openmp,
7549 : "%<master%> construct at %C deprecated since OpenMP 5.1, "
7550 : "use %<masked%>");
7551 21 : return match_omp (EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD,
7552 21 : (OMP_PARALLEL_CLAUSES | OMP_TASKLOOP_CLAUSES
7553 21 : | OMP_SIMD_CLAUSES)
7554 21 : & ~(omp_mask (OMP_CLAUSE_IN_REDUCTION)));
7555 : }
7556 :
7557 : match
7558 59 : gfc_match_omp_parallel_sections (void)
7559 : {
7560 59 : return match_omp (EXEC_OMP_PARALLEL_SECTIONS,
7561 59 : (OMP_PARALLEL_CLAUSES | OMP_SECTIONS_CLAUSES)
7562 59 : & ~(omp_mask (OMP_CLAUSE_NOWAIT)));
7563 : }
7564 :
7565 :
7566 : match
7567 56 : gfc_match_omp_parallel_workshare (void)
7568 : {
7569 56 : return match_omp (EXEC_OMP_PARALLEL_WORKSHARE, OMP_PARALLEL_CLAUSES);
7570 : }
7571 :
7572 : void
7573 48975 : gfc_check_omp_requires (gfc_namespace *ns, int ref_omp_requires)
7574 : {
7575 48975 : const char *msg = G_("Program unit at %L has OpenMP device "
7576 : "constructs/routines but does not set !$OMP REQUIRES %s "
7577 : "but other program units do");
7578 48975 : if (ns->omp_target_seen
7579 1211 : && (ns->omp_requires & OMP_REQ_TARGET_MASK)
7580 1211 : != (ref_omp_requires & OMP_REQ_TARGET_MASK))
7581 : {
7582 6 : gcc_assert (ns->proc_name);
7583 6 : if ((ref_omp_requires & OMP_REQ_REVERSE_OFFLOAD)
7584 5 : && !(ns->omp_requires & OMP_REQ_REVERSE_OFFLOAD))
7585 4 : gfc_error (msg, &ns->proc_name->declared_at, "REVERSE_OFFLOAD");
7586 6 : if ((ref_omp_requires & OMP_REQ_UNIFIED_ADDRESS)
7587 1 : && !(ns->omp_requires & OMP_REQ_UNIFIED_ADDRESS))
7588 1 : gfc_error (msg, &ns->proc_name->declared_at, "UNIFIED_ADDRESS");
7589 6 : if ((ref_omp_requires & OMP_REQ_UNIFIED_SHARED_MEMORY)
7590 4 : && !(ns->omp_requires & OMP_REQ_UNIFIED_SHARED_MEMORY))
7591 2 : gfc_error (msg, &ns->proc_name->declared_at, "UNIFIED_SHARED_MEMORY");
7592 6 : if ((ref_omp_requires & OMP_REQ_SELF_MAPS)
7593 1 : && !(ns->omp_requires & OMP_REQ_UNIFIED_SHARED_MEMORY))
7594 1 : gfc_error (msg, &ns->proc_name->declared_at, "SELF_MAPS");
7595 : }
7596 48975 : }
7597 :
7598 : bool
7599 120 : gfc_omp_requires_add_clause (gfc_omp_requires_kind clause,
7600 : const char *clause_name, locus *loc,
7601 : const char *module_name)
7602 : {
7603 120 : gfc_namespace *prog_unit = gfc_current_ns;
7604 144 : while (prog_unit->parent)
7605 : {
7606 25 : if (gfc_state_stack->previous
7607 25 : && gfc_state_stack->previous->state == COMP_INTERFACE)
7608 : break;
7609 : prog_unit = prog_unit->parent;
7610 : }
7611 :
7612 : /* Requires added after use. */
7613 120 : if (prog_unit->omp_target_seen
7614 24 : && (clause & OMP_REQ_TARGET_MASK)
7615 24 : && !(prog_unit->omp_requires & clause))
7616 : {
7617 0 : if (module_name)
7618 0 : gfc_error ("!$OMP REQUIRES clause %qs specified via module %qs use "
7619 : "at %L comes after using a device construct/routine",
7620 : clause_name, module_name, loc);
7621 : else
7622 0 : gfc_error ("!$OMP REQUIRES clause %qs specified at %L comes after "
7623 : "using a device construct/routine", clause_name, loc);
7624 0 : return false;
7625 : }
7626 :
7627 : /* Overriding atomic_default_mem_order clause value. */
7628 120 : if ((clause & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
7629 34 : && (prog_unit->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
7630 6 : && (prog_unit->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
7631 6 : != (int) clause)
7632 : {
7633 3 : const char *other;
7634 3 : switch (prog_unit->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
7635 : {
7636 : case OMP_REQ_ATOMIC_MEM_ORDER_SEQ_CST: other = "seq_cst"; break;
7637 0 : case OMP_REQ_ATOMIC_MEM_ORDER_ACQ_REL: other = "acq_rel"; break;
7638 1 : case OMP_REQ_ATOMIC_MEM_ORDER_ACQUIRE: other = "acquire"; break;
7639 1 : case OMP_REQ_ATOMIC_MEM_ORDER_RELAXED: other = "relaxed"; break;
7640 0 : case OMP_REQ_ATOMIC_MEM_ORDER_RELEASE: other = "release"; break;
7641 0 : default: gcc_unreachable ();
7642 : }
7643 :
7644 3 : if (module_name)
7645 0 : gfc_error ("!$OMP REQUIRES clause %<atomic_default_mem_order(%s)%> "
7646 : "specified via module %qs use at %L overrides a previous "
7647 : "%<atomic_default_mem_order(%s)%> (which might be through "
7648 : "using a module)", clause_name, module_name, loc, other);
7649 : else
7650 3 : gfc_error ("!$OMP REQUIRES clause %<atomic_default_mem_order(%s)%> "
7651 : "specified at %L overrides a previous "
7652 : "%<atomic_default_mem_order(%s)%> (which might be through "
7653 : "using a module)", clause_name, loc, other);
7654 3 : return false;
7655 : }
7656 :
7657 : /* Requires via module not at program-unit level and not repeating clause. */
7658 117 : if (prog_unit != gfc_current_ns && !(prog_unit->omp_requires & clause))
7659 : {
7660 0 : if (clause & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
7661 0 : gfc_error ("!$OMP REQUIRES clause %<atomic_default_mem_order(%s)%> "
7662 : "specified via module %qs use at %L but same clause is "
7663 : "not specified for the program unit", clause_name,
7664 : module_name, loc);
7665 : else
7666 0 : gfc_error ("!$OMP REQUIRES clause %qs specified via module %qs use at "
7667 : "%L but same clause is not specified for the program unit",
7668 : clause_name, module_name, loc);
7669 0 : return false;
7670 : }
7671 :
7672 117 : if (!gfc_state_stack->previous
7673 109 : || gfc_state_stack->previous->state != COMP_INTERFACE)
7674 116 : prog_unit->omp_requires |= clause;
7675 : return true;
7676 : }
7677 :
7678 : match
7679 92 : gfc_match_omp_requires (void)
7680 : {
7681 92 : static const char *clauses[] = {"reverse_offload",
7682 : "unified_address",
7683 : "unified_shared_memory",
7684 : "self_maps",
7685 : "dynamic_allocators",
7686 : "atomic_default"};
7687 92 : const char *clause = NULL;
7688 92 : int requires_clauses = 0;
7689 92 : bool first = true;
7690 92 : locus old_loc;
7691 :
7692 92 : if (gfc_current_ns->parent
7693 7 : && (!gfc_state_stack->previous
7694 7 : || gfc_state_stack->previous->state != COMP_INTERFACE))
7695 : {
7696 6 : gfc_error ("!$OMP REQUIRES at %C must appear in the specification part "
7697 : "of a program unit");
7698 6 : return MATCH_ERROR;
7699 : }
7700 :
7701 258 : while (true)
7702 : {
7703 172 : old_loc = gfc_current_locus;
7704 172 : gfc_omp_requires_kind requires_clause;
7705 86 : if ((first || gfc_match_char (',') != MATCH_YES)
7706 172 : && (first && gfc_match_space () != MATCH_YES))
7707 0 : goto error;
7708 172 : first = false;
7709 172 : gfc_gobble_whitespace ();
7710 172 : old_loc = gfc_current_locus;
7711 :
7712 172 : if (gfc_match_omp_eos () != MATCH_NO)
7713 : break;
7714 97 : if (gfc_match (clauses[0]) == MATCH_YES)
7715 : {
7716 34 : clause = clauses[0];
7717 34 : requires_clause = OMP_REQ_REVERSE_OFFLOAD;
7718 34 : if (requires_clauses & OMP_REQ_REVERSE_OFFLOAD)
7719 1 : goto duplicate_clause;
7720 : }
7721 63 : else if (gfc_match (clauses[1]) == MATCH_YES)
7722 : {
7723 9 : clause = clauses[1];
7724 9 : requires_clause = OMP_REQ_UNIFIED_ADDRESS;
7725 9 : if (requires_clauses & OMP_REQ_UNIFIED_ADDRESS)
7726 1 : goto duplicate_clause;
7727 : }
7728 54 : else if (gfc_match (clauses[2]) == MATCH_YES)
7729 : {
7730 14 : clause = clauses[2];
7731 14 : requires_clause = OMP_REQ_UNIFIED_SHARED_MEMORY;
7732 14 : if (requires_clauses & OMP_REQ_UNIFIED_SHARED_MEMORY)
7733 1 : goto duplicate_clause;
7734 : }
7735 40 : else if (gfc_match (clauses[3]) == MATCH_YES)
7736 : {
7737 1 : clause = clauses[3];
7738 1 : requires_clause = OMP_REQ_SELF_MAPS;
7739 1 : if (requires_clauses & OMP_REQ_SELF_MAPS)
7740 0 : goto duplicate_clause;
7741 : }
7742 39 : else if (gfc_match (clauses[4]) == MATCH_YES)
7743 : {
7744 7 : clause = clauses[4];
7745 7 : requires_clause = OMP_REQ_DYNAMIC_ALLOCATORS;
7746 7 : if (requires_clauses & OMP_REQ_DYNAMIC_ALLOCATORS)
7747 1 : goto duplicate_clause;
7748 : }
7749 32 : else if (gfc_match ("atomic_default_mem_order (") == MATCH_YES)
7750 : {
7751 31 : clause = clauses[5];
7752 31 : if (requires_clauses & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
7753 1 : goto duplicate_clause;
7754 30 : if (gfc_match (" seq_cst )") == MATCH_YES)
7755 : {
7756 : clause = "seq_cst";
7757 : requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_SEQ_CST;
7758 : }
7759 18 : else if (gfc_match (" acq_rel )") == MATCH_YES)
7760 : {
7761 : clause = "acq_rel";
7762 : requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_ACQ_REL;
7763 : }
7764 12 : else if (gfc_match (" acquire )") == MATCH_YES)
7765 : {
7766 : clause = "acquire";
7767 : requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_ACQUIRE;
7768 : }
7769 9 : else if (gfc_match (" relaxed )") == MATCH_YES)
7770 : {
7771 : clause = "relaxed";
7772 : requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_RELAXED;
7773 : }
7774 5 : else if (gfc_match (" release )") == MATCH_YES)
7775 : {
7776 : clause = "release";
7777 : requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_RELEASE;
7778 : }
7779 : else
7780 : {
7781 2 : gfc_error ("Expected ACQ_REL, ACQUIRE, RELAXED, RELEASE or "
7782 : "SEQ_CST for ATOMIC_DEFAULT_MEM_ORDER clause at %C");
7783 2 : goto error;
7784 : }
7785 : }
7786 : else
7787 1 : goto error;
7788 :
7789 89 : if (!gfc_omp_requires_add_clause (requires_clause, clause, &old_loc, NULL))
7790 3 : goto error;
7791 86 : requires_clauses |= requires_clause;
7792 86 : }
7793 :
7794 75 : if (requires_clauses == 0)
7795 : {
7796 1 : if (!gfc_error_flag_test ())
7797 1 : gfc_error ("Clause expected at %C");
7798 1 : goto error;
7799 : }
7800 : return MATCH_YES;
7801 :
7802 5 : duplicate_clause:
7803 5 : gfc_error ("%qs clause at %L specified more than once", clause, &old_loc);
7804 12 : error:
7805 12 : if (!gfc_error_flag_test ())
7806 1 : gfc_error ("Expected UNIFIED_ADDRESS, UNIFIED_SHARED_MEMORY, SELF_MAPS, "
7807 : "DYNAMIC_ALLOCATORS, REVERSE_OFFLOAD, or "
7808 : "ATOMIC_DEFAULT_MEM_ORDER clause at %L", &old_loc);
7809 : return MATCH_ERROR;
7810 : }
7811 :
7812 :
7813 : match
7814 51 : gfc_match_omp_scan (void)
7815 : {
7816 51 : bool incl;
7817 51 : gfc_omp_clauses *c = gfc_get_omp_clauses ();
7818 51 : gfc_gobble_whitespace ();
7819 51 : if ((incl = (gfc_match ("inclusive") == MATCH_YES))
7820 51 : || gfc_match ("exclusive") == MATCH_YES)
7821 : {
7822 70 : if (gfc_match_omp_variable_list (" (", &c->lists[incl ? OMP_LIST_SCAN_IN
7823 : : OMP_LIST_SCAN_EX],
7824 : false) != MATCH_YES)
7825 : {
7826 0 : gfc_free_omp_clauses (c);
7827 0 : return MATCH_ERROR;
7828 : }
7829 : }
7830 : else
7831 : {
7832 1 : gfc_error ("Expected INCLUSIVE or EXCLUSIVE clause at %C");
7833 1 : gfc_free_omp_clauses (c);
7834 1 : return MATCH_ERROR;
7835 : }
7836 50 : if (gfc_match_omp_eos () != MATCH_YES)
7837 : {
7838 1 : gfc_error ("Unexpected junk after !$OMP SCAN at %C");
7839 1 : gfc_free_omp_clauses (c);
7840 1 : return MATCH_ERROR;
7841 : }
7842 :
7843 49 : new_st.op = EXEC_OMP_SCAN;
7844 49 : new_st.ext.omp_clauses = c;
7845 49 : return MATCH_YES;
7846 : }
7847 :
7848 :
7849 : match
7850 58 : gfc_match_omp_scope (void)
7851 : {
7852 58 : return match_omp (EXEC_OMP_SCOPE, OMP_SCOPE_CLAUSES);
7853 : }
7854 :
7855 :
7856 : match
7857 82 : gfc_match_omp_sections (void)
7858 : {
7859 82 : return match_omp (EXEC_OMP_SECTIONS, OMP_SECTIONS_CLAUSES);
7860 : }
7861 :
7862 :
7863 : match
7864 782 : gfc_match_omp_simd (void)
7865 : {
7866 782 : return match_omp (EXEC_OMP_SIMD, OMP_SIMD_CLAUSES);
7867 : }
7868 :
7869 :
7870 : match
7871 570 : gfc_match_omp_single (void)
7872 : {
7873 570 : return match_omp (EXEC_OMP_SINGLE, OMP_SINGLE_CLAUSES);
7874 : }
7875 :
7876 :
7877 : match
7878 1985 : gfc_match_omp_target (void)
7879 : {
7880 1985 : return match_omp (EXEC_OMP_TARGET, OMP_TARGET_CLAUSES);
7881 : }
7882 :
7883 :
7884 : match
7885 1398 : gfc_match_omp_target_data (void)
7886 : {
7887 1398 : return match_omp (EXEC_OMP_TARGET_DATA, OMP_TARGET_DATA_CLAUSES);
7888 : }
7889 :
7890 :
7891 : match
7892 408 : gfc_match_omp_target_enter_data (void)
7893 : {
7894 408 : return match_omp (EXEC_OMP_TARGET_ENTER_DATA, OMP_TARGET_ENTER_DATA_CLAUSES);
7895 : }
7896 :
7897 :
7898 : match
7899 322 : gfc_match_omp_target_exit_data (void)
7900 : {
7901 322 : return match_omp (EXEC_OMP_TARGET_EXIT_DATA, OMP_TARGET_EXIT_DATA_CLAUSES);
7902 : }
7903 :
7904 :
7905 : match
7906 25 : gfc_match_omp_target_parallel (void)
7907 : {
7908 25 : return match_omp (EXEC_OMP_TARGET_PARALLEL,
7909 25 : (OMP_TARGET_CLAUSES | OMP_PARALLEL_CLAUSES)
7910 25 : & ~(omp_mask (OMP_CLAUSE_COPYIN)));
7911 : }
7912 :
7913 :
7914 : match
7915 81 : gfc_match_omp_target_parallel_do (void)
7916 : {
7917 81 : return match_omp (EXEC_OMP_TARGET_PARALLEL_DO,
7918 81 : (OMP_TARGET_CLAUSES | OMP_PARALLEL_CLAUSES
7919 81 : | OMP_DO_CLAUSES) & ~(omp_mask (OMP_CLAUSE_COPYIN)));
7920 : }
7921 :
7922 :
7923 : match
7924 19 : gfc_match_omp_target_parallel_do_simd (void)
7925 : {
7926 19 : return match_omp (EXEC_OMP_TARGET_PARALLEL_DO_SIMD,
7927 19 : (OMP_TARGET_CLAUSES | OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES
7928 19 : | OMP_SIMD_CLAUSES) & ~(omp_mask (OMP_CLAUSE_COPYIN)));
7929 : }
7930 :
7931 :
7932 : match
7933 34 : gfc_match_omp_target_simd (void)
7934 : {
7935 34 : return match_omp (EXEC_OMP_TARGET_SIMD,
7936 34 : OMP_TARGET_CLAUSES | OMP_SIMD_CLAUSES);
7937 : }
7938 :
7939 :
7940 : match
7941 72 : gfc_match_omp_target_teams (void)
7942 : {
7943 72 : return match_omp (EXEC_OMP_TARGET_TEAMS,
7944 72 : OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES);
7945 : }
7946 :
7947 :
7948 : match
7949 19 : gfc_match_omp_target_teams_distribute (void)
7950 : {
7951 19 : return match_omp (EXEC_OMP_TARGET_TEAMS_DISTRIBUTE,
7952 19 : OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES
7953 19 : | OMP_DISTRIBUTE_CLAUSES);
7954 : }
7955 :
7956 :
7957 : match
7958 64 : gfc_match_omp_target_teams_distribute_parallel_do (void)
7959 : {
7960 64 : return match_omp (EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO,
7961 64 : (OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES
7962 64 : | OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
7963 64 : | OMP_DO_CLAUSES)
7964 64 : & ~(omp_mask (OMP_CLAUSE_ORDERED))
7965 64 : & ~(omp_mask (OMP_CLAUSE_LINEAR)));
7966 : }
7967 :
7968 :
7969 : match
7970 35 : gfc_match_omp_target_teams_distribute_parallel_do_simd (void)
7971 : {
7972 35 : return match_omp (EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD,
7973 35 : (OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES
7974 35 : | OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
7975 35 : | OMP_DO_CLAUSES | OMP_SIMD_CLAUSES)
7976 35 : & ~(omp_mask (OMP_CLAUSE_ORDERED)));
7977 : }
7978 :
7979 :
7980 : match
7981 21 : gfc_match_omp_target_teams_distribute_simd (void)
7982 : {
7983 21 : return match_omp (EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD,
7984 21 : OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES
7985 21 : | OMP_DISTRIBUTE_CLAUSES | OMP_SIMD_CLAUSES);
7986 : }
7987 :
7988 :
7989 : match
7990 1704 : gfc_match_omp_target_update (void)
7991 : {
7992 1704 : return match_omp (EXEC_OMP_TARGET_UPDATE, OMP_TARGET_UPDATE_CLAUSES);
7993 : }
7994 :
7995 :
7996 : match
7997 1182 : gfc_match_omp_task (void)
7998 : {
7999 1182 : return match_omp (EXEC_OMP_TASK, OMP_TASK_CLAUSES);
8000 : }
8001 :
8002 :
8003 : match
8004 72 : gfc_match_omp_taskloop (void)
8005 : {
8006 72 : return match_omp (EXEC_OMP_TASKLOOP, OMP_TASKLOOP_CLAUSES);
8007 : }
8008 :
8009 :
8010 : match
8011 40 : gfc_match_omp_taskloop_simd (void)
8012 : {
8013 40 : return match_omp (EXEC_OMP_TASKLOOP_SIMD,
8014 40 : OMP_TASKLOOP_CLAUSES | OMP_SIMD_CLAUSES);
8015 : }
8016 :
8017 :
8018 : match
8019 147 : gfc_match_omp_taskwait (void)
8020 : {
8021 147 : if (gfc_match_omp_eos () == MATCH_YES)
8022 : {
8023 133 : new_st.op = EXEC_OMP_TASKWAIT;
8024 133 : new_st.ext.omp_clauses = NULL;
8025 133 : return MATCH_YES;
8026 : }
8027 14 : return match_omp (EXEC_OMP_TASKWAIT,
8028 14 : omp_mask (OMP_CLAUSE_DEPEND) | OMP_CLAUSE_NOWAIT);
8029 : }
8030 :
8031 :
8032 : match
8033 10 : gfc_match_omp_taskyield (void)
8034 : {
8035 10 : if (gfc_match_omp_eos () != MATCH_YES)
8036 : {
8037 0 : gfc_error ("Unexpected junk after TASKYIELD clause at %C");
8038 0 : return MATCH_ERROR;
8039 : }
8040 10 : new_st.op = EXEC_OMP_TASKYIELD;
8041 10 : new_st.ext.omp_clauses = NULL;
8042 10 : return MATCH_YES;
8043 : }
8044 :
8045 :
8046 : match
8047 150 : gfc_match_omp_teams (void)
8048 : {
8049 150 : return match_omp (EXEC_OMP_TEAMS, OMP_TEAMS_CLAUSES);
8050 : }
8051 :
8052 :
8053 : match
8054 22 : gfc_match_omp_teams_distribute (void)
8055 : {
8056 22 : return match_omp (EXEC_OMP_TEAMS_DISTRIBUTE,
8057 22 : OMP_TEAMS_CLAUSES | OMP_DISTRIBUTE_CLAUSES);
8058 : }
8059 :
8060 :
8061 : match
8062 39 : gfc_match_omp_teams_distribute_parallel_do (void)
8063 : {
8064 39 : return match_omp (EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO,
8065 39 : (OMP_TEAMS_CLAUSES | OMP_DISTRIBUTE_CLAUSES
8066 39 : | OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES)
8067 39 : & ~(omp_mask (OMP_CLAUSE_ORDERED)
8068 39 : | OMP_CLAUSE_LINEAR | OMP_CLAUSE_NOWAIT));
8069 : }
8070 :
8071 :
8072 : match
8073 62 : gfc_match_omp_teams_distribute_parallel_do_simd (void)
8074 : {
8075 62 : return match_omp (EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD,
8076 62 : (OMP_TEAMS_CLAUSES | OMP_DISTRIBUTE_CLAUSES
8077 62 : | OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES
8078 62 : | OMP_SIMD_CLAUSES)
8079 62 : & ~(omp_mask (OMP_CLAUSE_ORDERED) | OMP_CLAUSE_NOWAIT));
8080 : }
8081 :
8082 :
8083 : match
8084 44 : gfc_match_omp_teams_distribute_simd (void)
8085 : {
8086 44 : return match_omp (EXEC_OMP_TEAMS_DISTRIBUTE_SIMD,
8087 44 : OMP_TEAMS_CLAUSES | OMP_DISTRIBUTE_CLAUSES
8088 44 : | OMP_SIMD_CLAUSES);
8089 : }
8090 :
8091 : match
8092 203 : gfc_match_omp_tile (void)
8093 : {
8094 203 : return match_omp (EXEC_OMP_TILE, OMP_TILE_CLAUSES);
8095 : }
8096 :
8097 : match
8098 415 : gfc_match_omp_unroll (void)
8099 : {
8100 415 : return match_omp (EXEC_OMP_UNROLL, OMP_UNROLL_CLAUSES);
8101 : }
8102 :
8103 : match
8104 39 : gfc_match_omp_workshare (void)
8105 : {
8106 39 : return match_omp (EXEC_OMP_WORKSHARE, OMP_WORKSHARE_CLAUSES);
8107 : }
8108 :
8109 :
8110 : match
8111 49 : gfc_match_omp_masked (void)
8112 : {
8113 49 : return match_omp (EXEC_OMP_MASKED, OMP_MASKED_CLAUSES);
8114 : }
8115 :
8116 : match
8117 10 : gfc_match_omp_masked_taskloop (void)
8118 : {
8119 10 : return match_omp (EXEC_OMP_MASKED_TASKLOOP,
8120 10 : OMP_MASKED_CLAUSES | OMP_TASKLOOP_CLAUSES);
8121 : }
8122 :
8123 : match
8124 16 : gfc_match_omp_masked_taskloop_simd (void)
8125 : {
8126 16 : return match_omp (EXEC_OMP_MASKED_TASKLOOP_SIMD,
8127 16 : (OMP_MASKED_CLAUSES | OMP_TASKLOOP_CLAUSES
8128 16 : | OMP_SIMD_CLAUSES));
8129 : }
8130 :
8131 : match
8132 111 : gfc_match_omp_master (void)
8133 : {
8134 111 : gfc_warning (OPT_Wdeprecated_openmp,
8135 : "%<master%> construct at %C deprecated since OpenMP 5.1, "
8136 : "use %<masked%>");
8137 111 : if (gfc_match_omp_eos () != MATCH_YES)
8138 : {
8139 1 : gfc_error ("Unexpected junk after $OMP MASTER statement at %C");
8140 1 : return MATCH_ERROR;
8141 : }
8142 110 : new_st.op = EXEC_OMP_MASTER;
8143 110 : new_st.ext.omp_clauses = NULL;
8144 110 : return MATCH_YES;
8145 : }
8146 :
8147 : match
8148 16 : gfc_match_omp_master_taskloop (void)
8149 : {
8150 16 : gfc_warning (OPT_Wdeprecated_openmp,
8151 : "%<master%> construct at %C deprecated since OpenMP 5.1, "
8152 : "use %<masked%>");
8153 16 : return match_omp (EXEC_OMP_MASTER_TASKLOOP, OMP_TASKLOOP_CLAUSES);
8154 : }
8155 :
8156 : match
8157 21 : gfc_match_omp_master_taskloop_simd (void)
8158 : {
8159 21 : gfc_warning (OPT_Wdeprecated_openmp,
8160 : "%<master%> construct at %C deprecated since OpenMP 5.1, use "
8161 : "%<masked%>");
8162 21 : return match_omp (EXEC_OMP_MASTER_TASKLOOP_SIMD,
8163 21 : OMP_TASKLOOP_CLAUSES | OMP_SIMD_CLAUSES);
8164 : }
8165 :
8166 : match
8167 235 : gfc_match_omp_ordered (void)
8168 : {
8169 235 : return match_omp (EXEC_OMP_ORDERED, OMP_ORDERED_CLAUSES);
8170 : }
8171 :
8172 : match
8173 24 : gfc_match_omp_nothing (void)
8174 : {
8175 24 : if (gfc_match_omp_eos () != MATCH_YES)
8176 : {
8177 1 : gfc_error ("Unexpected junk after $OMP NOTHING statement at %C");
8178 1 : return MATCH_ERROR;
8179 : }
8180 : /* Will use ST_NONE; therefore, no EXEC_OMP_ is needed. */
8181 : return MATCH_YES;
8182 : }
8183 :
8184 : match
8185 317 : gfc_match_omp_ordered_depend (void)
8186 : {
8187 317 : return match_omp (EXEC_OMP_ORDERED, omp_mask (OMP_CLAUSE_DOACROSS));
8188 : }
8189 :
8190 :
8191 : /* omp atomic [clause-list]
8192 : - atomic-clause: read | write | update
8193 : - capture
8194 : - memory-order-clause: seq_cst | acq_rel | release | acquire | relaxed
8195 : - hint(hint-expr)
8196 : - OpenMP 5.1: compare | fail (seq_cst | acquire | relaxed ) | weak
8197 : */
8198 :
8199 : match
8200 2171 : gfc_match_omp_atomic (void)
8201 : {
8202 2171 : gfc_omp_clauses *c;
8203 2171 : locus loc = gfc_current_locus;
8204 :
8205 2171 : if (gfc_match_omp_clauses (&c, OMP_ATOMIC_CLAUSES, true, true) != MATCH_YES)
8206 : return MATCH_ERROR;
8207 :
8208 2153 : if (c->atomic_op == GFC_OMP_ATOMIC_UNSET)
8209 1011 : c->atomic_op = GFC_OMP_ATOMIC_UPDATE;
8210 :
8211 2153 : if (c->capture && c->atomic_op != GFC_OMP_ATOMIC_UPDATE)
8212 3 : gfc_error ("!$OMP ATOMIC at %L with %s clause is incompatible with "
8213 : "READ or WRITE", &loc, "CAPTURE");
8214 2153 : if (c->compare && c->atomic_op != GFC_OMP_ATOMIC_UPDATE)
8215 3 : gfc_error ("!$OMP ATOMIC at %L with %s clause is incompatible with "
8216 : "READ or WRITE", &loc, "COMPARE");
8217 2153 : if (c->fail != OMP_MEMORDER_UNSET && c->atomic_op != GFC_OMP_ATOMIC_UPDATE)
8218 2 : gfc_error ("!$OMP ATOMIC at %L with %s clause is incompatible with "
8219 : "READ or WRITE", &loc, "FAIL");
8220 2153 : if (c->weak && !c->compare)
8221 : {
8222 5 : gfc_error ("!$OMP ATOMIC at %L with %s clause requires %s clause", &loc,
8223 : "WEAK", "COMPARE");
8224 5 : c->weak = false;
8225 : }
8226 :
8227 2153 : if (c->memorder == OMP_MEMORDER_UNSET)
8228 : {
8229 1969 : gfc_namespace *prog_unit = gfc_current_ns;
8230 2525 : while (prog_unit->parent)
8231 : prog_unit = prog_unit->parent;
8232 1969 : switch (prog_unit->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
8233 : {
8234 1936 : case 0:
8235 1936 : case OMP_REQ_ATOMIC_MEM_ORDER_RELAXED:
8236 1936 : c->memorder = OMP_MEMORDER_RELAXED;
8237 1936 : break;
8238 7 : case OMP_REQ_ATOMIC_MEM_ORDER_SEQ_CST:
8239 7 : c->memorder = OMP_MEMORDER_SEQ_CST;
8240 7 : break;
8241 16 : case OMP_REQ_ATOMIC_MEM_ORDER_ACQ_REL:
8242 16 : if (c->capture)
8243 5 : c->memorder = OMP_MEMORDER_ACQ_REL;
8244 11 : else if (c->atomic_op == GFC_OMP_ATOMIC_READ)
8245 3 : c->memorder = OMP_MEMORDER_ACQUIRE;
8246 : else
8247 8 : c->memorder = OMP_MEMORDER_RELEASE;
8248 : break;
8249 5 : case OMP_REQ_ATOMIC_MEM_ORDER_ACQUIRE:
8250 5 : if (c->atomic_op == GFC_OMP_ATOMIC_WRITE)
8251 : {
8252 1 : gfc_error ("!$OMP ATOMIC WRITE at %L incompatible with "
8253 : "ACQUIRES clause implicitly provided by a "
8254 : "REQUIRES directive", &loc);
8255 1 : c->memorder = OMP_MEMORDER_SEQ_CST;
8256 : }
8257 : else
8258 4 : c->memorder = OMP_MEMORDER_ACQUIRE;
8259 : break;
8260 5 : case OMP_REQ_ATOMIC_MEM_ORDER_RELEASE:
8261 5 : if (c->atomic_op == GFC_OMP_ATOMIC_READ)
8262 : {
8263 1 : gfc_error ("!$OMP ATOMIC READ at %L incompatible with "
8264 : "RELEASE clause implicitly provided by a "
8265 : "REQUIRES directive", &loc);
8266 1 : c->memorder = OMP_MEMORDER_SEQ_CST;
8267 : }
8268 : else
8269 4 : c->memorder = OMP_MEMORDER_RELEASE;
8270 : break;
8271 0 : default:
8272 0 : gcc_unreachable ();
8273 : }
8274 : }
8275 : else
8276 184 : switch (c->atomic_op)
8277 : {
8278 29 : case GFC_OMP_ATOMIC_READ:
8279 29 : if (c->memorder == OMP_MEMORDER_RELEASE)
8280 : {
8281 1 : gfc_error ("!$OMP ATOMIC READ at %L incompatible with "
8282 : "RELEASE clause", &loc);
8283 1 : c->memorder = OMP_MEMORDER_SEQ_CST;
8284 : }
8285 28 : else if (c->memorder == OMP_MEMORDER_ACQ_REL)
8286 1 : c->memorder = OMP_MEMORDER_ACQUIRE;
8287 : break;
8288 35 : case GFC_OMP_ATOMIC_WRITE:
8289 35 : if (c->memorder == OMP_MEMORDER_ACQUIRE)
8290 : {
8291 1 : gfc_error ("!$OMP ATOMIC WRITE at %L incompatible with "
8292 : "ACQUIRE clause", &loc);
8293 1 : c->memorder = OMP_MEMORDER_SEQ_CST;
8294 : }
8295 34 : else if (c->memorder == OMP_MEMORDER_ACQ_REL)
8296 1 : c->memorder = OMP_MEMORDER_RELEASE;
8297 : break;
8298 : default:
8299 : break;
8300 : }
8301 2153 : gfc_error_check ();
8302 2153 : new_st.ext.omp_clauses = c;
8303 2153 : new_st.op = EXEC_OMP_ATOMIC;
8304 2153 : return MATCH_YES;
8305 : }
8306 :
8307 :
8308 : /* acc atomic [ read | write | update | capture] */
8309 :
8310 : match
8311 552 : gfc_match_oacc_atomic (void)
8312 : {
8313 552 : gfc_omp_clauses *c = gfc_get_omp_clauses ();
8314 552 : c->atomic_op = GFC_OMP_ATOMIC_UPDATE;
8315 552 : c->memorder = OMP_MEMORDER_RELAXED;
8316 552 : gfc_gobble_whitespace ();
8317 552 : if (gfc_match ("update") == MATCH_YES)
8318 : ;
8319 373 : else if (gfc_match ("read") == MATCH_YES)
8320 17 : c->atomic_op = GFC_OMP_ATOMIC_READ;
8321 356 : else if (gfc_match ("write") == MATCH_YES)
8322 13 : c->atomic_op = GFC_OMP_ATOMIC_WRITE;
8323 343 : else if (gfc_match ("capture") == MATCH_YES)
8324 319 : c->capture = true;
8325 552 : gfc_gobble_whitespace ();
8326 552 : if (gfc_match_omp_eos () != MATCH_YES)
8327 : {
8328 9 : gfc_error ("Unexpected junk after !$ACC ATOMIC statement at %C");
8329 9 : gfc_free_omp_clauses (c);
8330 9 : return MATCH_ERROR;
8331 : }
8332 543 : new_st.ext.omp_clauses = c;
8333 543 : new_st.op = EXEC_OACC_ATOMIC;
8334 543 : return MATCH_YES;
8335 : }
8336 :
8337 :
8338 : match
8339 614 : gfc_match_omp_barrier (void)
8340 : {
8341 614 : if (gfc_match_omp_eos () != MATCH_YES)
8342 : {
8343 0 : gfc_error ("Unexpected junk after $OMP BARRIER statement at %C");
8344 0 : return MATCH_ERROR;
8345 : }
8346 614 : new_st.op = EXEC_OMP_BARRIER;
8347 614 : new_st.ext.omp_clauses = NULL;
8348 614 : return MATCH_YES;
8349 : }
8350 :
8351 :
8352 : match
8353 188 : gfc_match_omp_taskgroup (void)
8354 : {
8355 188 : return match_omp (EXEC_OMP_TASKGROUP, OMP_TASKGROUP_CLAUSES);
8356 : }
8357 :
8358 :
8359 : static enum gfc_omp_cancel_kind
8360 494 : gfc_match_omp_cancel_kind (void)
8361 : {
8362 494 : if (gfc_match_space () != MATCH_YES)
8363 : return OMP_CANCEL_UNKNOWN;
8364 492 : if (gfc_match ("parallel") == MATCH_YES)
8365 : return OMP_CANCEL_PARALLEL;
8366 352 : if (gfc_match ("sections") == MATCH_YES)
8367 : return OMP_CANCEL_SECTIONS;
8368 253 : if (gfc_match ("do") == MATCH_YES)
8369 : return OMP_CANCEL_DO;
8370 123 : if (gfc_match ("taskgroup") == MATCH_YES)
8371 : return OMP_CANCEL_TASKGROUP;
8372 : return OMP_CANCEL_UNKNOWN;
8373 : }
8374 :
8375 :
8376 : match
8377 321 : gfc_match_omp_cancel (void)
8378 : {
8379 321 : gfc_omp_clauses *c;
8380 321 : enum gfc_omp_cancel_kind kind = gfc_match_omp_cancel_kind ();
8381 321 : if (kind == OMP_CANCEL_UNKNOWN)
8382 : return MATCH_ERROR;
8383 319 : if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_IF), false) != MATCH_YES)
8384 : return MATCH_ERROR;
8385 316 : c->cancel = kind;
8386 316 : new_st.op = EXEC_OMP_CANCEL;
8387 316 : new_st.ext.omp_clauses = c;
8388 316 : return MATCH_YES;
8389 : }
8390 :
8391 :
8392 : match
8393 173 : gfc_match_omp_cancellation_point (void)
8394 : {
8395 173 : gfc_omp_clauses *c;
8396 173 : enum gfc_omp_cancel_kind kind = gfc_match_omp_cancel_kind ();
8397 173 : if (kind == OMP_CANCEL_UNKNOWN)
8398 : {
8399 2 : gfc_error ("Expected construct-type PARALLEL, SECTIONS, DO or TASKGROUP "
8400 : "in $OMP CANCELLATION POINT statement at %C");
8401 2 : return MATCH_ERROR;
8402 : }
8403 171 : if (gfc_match_omp_eos () != MATCH_YES)
8404 : {
8405 0 : gfc_error ("Unexpected junk after $OMP CANCELLATION POINT statement "
8406 : "at %C");
8407 0 : return MATCH_ERROR;
8408 : }
8409 171 : c = gfc_get_omp_clauses ();
8410 171 : c->cancel = kind;
8411 171 : new_st.op = EXEC_OMP_CANCELLATION_POINT;
8412 171 : new_st.ext.omp_clauses = c;
8413 171 : return MATCH_YES;
8414 : }
8415 :
8416 :
8417 : match
8418 2495 : gfc_match_omp_end_nowait (void)
8419 : {
8420 2495 : bool nowait = false;
8421 2495 : if (gfc_match ("% nowait") == MATCH_YES)
8422 258 : nowait = true;
8423 2495 : if (gfc_match_omp_eos () != MATCH_YES)
8424 : {
8425 4 : if (nowait)
8426 3 : gfc_error ("Unexpected junk after NOWAIT clause at %C");
8427 : else
8428 1 : gfc_error ("Unexpected junk at %C");
8429 4 : return MATCH_ERROR;
8430 : }
8431 2491 : new_st.op = EXEC_OMP_END_NOWAIT;
8432 2491 : new_st.ext.omp_bool = nowait;
8433 2491 : return MATCH_YES;
8434 : }
8435 :
8436 :
8437 : match
8438 566 : gfc_match_omp_end_single (void)
8439 : {
8440 566 : gfc_omp_clauses *c;
8441 566 : if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_COPYPRIVATE)
8442 : | OMP_CLAUSE_NOWAIT) != MATCH_YES)
8443 : return MATCH_ERROR;
8444 566 : new_st.op = EXEC_OMP_END_SINGLE;
8445 566 : new_st.ext.omp_clauses = c;
8446 566 : return MATCH_YES;
8447 : }
8448 :
8449 :
8450 : static bool
8451 37071 : oacc_is_loop (gfc_code *code)
8452 : {
8453 37071 : return code->op == EXEC_OACC_PARALLEL_LOOP
8454 : || code->op == EXEC_OACC_KERNELS_LOOP
8455 20016 : || code->op == EXEC_OACC_SERIAL_LOOP
8456 13457 : || code->op == EXEC_OACC_LOOP;
8457 : }
8458 :
8459 : static void
8460 5725 : resolve_scalar_int_expr (gfc_expr *expr, const char *clause)
8461 : {
8462 5725 : if (!gfc_resolve_expr (expr)
8463 5725 : || expr->ts.type != BT_INTEGER
8464 11379 : || expr->rank != 0)
8465 89 : gfc_error ("%s clause at %L requires a scalar INTEGER expression",
8466 : clause, &expr->where);
8467 5725 : }
8468 :
8469 : static void
8470 3940 : resolve_positive_int_expr (gfc_expr *expr, const char *clause)
8471 : {
8472 3940 : resolve_scalar_int_expr (expr, clause);
8473 3940 : if (expr->expr_type == EXPR_CONSTANT
8474 3519 : && expr->ts.type == BT_INTEGER
8475 3486 : && mpz_sgn (expr->value.integer) <= 0)
8476 54 : gfc_warning ((flag_openmp || flag_openmp_simd) ? OPT_Wopenmp : 0,
8477 : "INTEGER expression of %s clause at %L must be positive",
8478 : clause, &expr->where);
8479 3940 : }
8480 :
8481 : static void
8482 86 : resolve_nonnegative_int_expr (gfc_expr *expr, const char *clause)
8483 : {
8484 86 : resolve_scalar_int_expr (expr, clause);
8485 86 : if (expr->expr_type == EXPR_CONSTANT
8486 13 : && expr->ts.type == BT_INTEGER
8487 11 : && mpz_sgn (expr->value.integer) < 0)
8488 6 : gfc_warning ((flag_openmp || flag_openmp_simd) ? OPT_Wopenmp : 0,
8489 : "INTEGER expression of %s clause at %L must be non-negative",
8490 : clause, &expr->where);
8491 86 : }
8492 :
8493 : /* Emits error when symbol is pointer, cray pointer or cray pointee
8494 : of derived of polymorphic type. */
8495 :
8496 : static void
8497 98 : check_symbol_not_pointer (gfc_symbol *sym, locus loc, const char *name)
8498 : {
8499 98 : if (sym->ts.type == BT_DERIVED && sym->attr.cray_pointer)
8500 0 : gfc_error ("Cray pointer object %qs of derived type in %s clause at %L",
8501 : sym->name, name, &loc);
8502 98 : if (sym->ts.type == BT_DERIVED && sym->attr.cray_pointee)
8503 0 : gfc_error ("Cray pointee object %qs of derived type in %s clause at %L",
8504 : sym->name, name, &loc);
8505 :
8506 98 : if ((sym->ts.type == BT_ASSUMED && sym->attr.pointer)
8507 98 : || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
8508 0 : && CLASS_DATA (sym)->attr.pointer))
8509 0 : gfc_error ("POINTER object %qs of polymorphic type in %s clause at %L",
8510 : sym->name, name, &loc);
8511 98 : if ((sym->ts.type == BT_ASSUMED && sym->attr.cray_pointer)
8512 98 : || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
8513 0 : && CLASS_DATA (sym)->attr.cray_pointer))
8514 0 : gfc_error ("Cray pointer object %qs of polymorphic type in %s clause at %L",
8515 : sym->name, name, &loc);
8516 98 : if ((sym->ts.type == BT_ASSUMED && sym->attr.cray_pointee)
8517 98 : || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
8518 0 : && CLASS_DATA (sym)->attr.cray_pointee))
8519 0 : gfc_error ("Cray pointee object %qs of polymorphic type in %s clause at %L",
8520 : sym->name, name, &loc);
8521 98 : }
8522 :
8523 : /* Emits error when symbol represents assumed size/rank array. */
8524 :
8525 : static void
8526 14844 : check_array_not_assumed (gfc_symbol *sym, locus loc, const char *name)
8527 : {
8528 14844 : if (sym->as && sym->as->type == AS_ASSUMED_SIZE)
8529 13 : gfc_error ("Assumed size array %qs in %s clause at %L",
8530 : sym->name, name, &loc);
8531 14844 : if (sym->as && sym->as->type == AS_ASSUMED_RANK)
8532 11 : gfc_error ("Assumed rank array %qs in %s clause at %L",
8533 : sym->name, name, &loc);
8534 14844 : }
8535 :
8536 : static void
8537 5850 : resolve_oacc_data_clauses (gfc_symbol *sym, locus loc, const char *name)
8538 : {
8539 0 : check_array_not_assumed (sym, loc, name);
8540 0 : }
8541 :
8542 : static void
8543 65 : resolve_oacc_deviceptr_clause (gfc_symbol *sym, locus loc, const char *name)
8544 : {
8545 65 : if (sym->attr.pointer
8546 64 : || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
8547 0 : && CLASS_DATA (sym)->attr.class_pointer))
8548 1 : gfc_error ("POINTER object %qs in %s clause at %L",
8549 : sym->name, name, &loc);
8550 65 : if (sym->attr.cray_pointer
8551 63 : || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
8552 0 : && CLASS_DATA (sym)->attr.cray_pointer))
8553 2 : gfc_error ("Cray pointer object %qs in %s clause at %L",
8554 : sym->name, name, &loc);
8555 65 : if (sym->attr.cray_pointee
8556 63 : || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
8557 0 : && CLASS_DATA (sym)->attr.cray_pointee))
8558 2 : gfc_error ("Cray pointee object %qs in %s clause at %L",
8559 : sym->name, name, &loc);
8560 65 : if (sym->attr.allocatable
8561 64 : || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
8562 0 : && CLASS_DATA (sym)->attr.allocatable))
8563 1 : gfc_error ("ALLOCATABLE object %qs in %s clause at %L",
8564 : sym->name, name, &loc);
8565 65 : if (sym->attr.value)
8566 1 : gfc_error ("VALUE object %qs in %s clause at %L",
8567 : sym->name, name, &loc);
8568 65 : check_array_not_assumed (sym, loc, name);
8569 65 : }
8570 :
8571 :
8572 : struct resolve_omp_udr_callback_data
8573 : {
8574 : gfc_symbol *sym1, *sym2;
8575 : };
8576 :
8577 :
8578 : static int
8579 1413 : resolve_omp_udr_callback (gfc_expr **e, int *, void *data)
8580 : {
8581 1413 : struct resolve_omp_udr_callback_data *rcd
8582 : = (struct resolve_omp_udr_callback_data *) data;
8583 1413 : if ((*e)->expr_type == EXPR_VARIABLE
8584 801 : && ((*e)->symtree->n.sym == rcd->sym1
8585 255 : || (*e)->symtree->n.sym == rcd->sym2))
8586 : {
8587 801 : gfc_ref *ref = gfc_get_ref ();
8588 801 : ref->type = REF_ARRAY;
8589 801 : ref->u.ar.where = (*e)->where;
8590 801 : ref->u.ar.as = (*e)->symtree->n.sym->as;
8591 801 : ref->u.ar.type = AR_FULL;
8592 801 : ref->u.ar.dimen = 0;
8593 801 : ref->next = (*e)->ref;
8594 801 : (*e)->ref = ref;
8595 : }
8596 1413 : return 0;
8597 : }
8598 :
8599 :
8600 : static int
8601 2990 : resolve_omp_udr_callback2 (gfc_expr **e, int *, void *)
8602 : {
8603 2990 : if ((*e)->expr_type == EXPR_FUNCTION
8604 360 : && (*e)->value.function.isym == NULL)
8605 : {
8606 174 : gfc_symbol *sym = (*e)->symtree->n.sym;
8607 174 : if (!sym->attr.intrinsic
8608 174 : && sym->attr.if_source == IFSRC_UNKNOWN)
8609 4 : gfc_error ("Implicitly declared function %s used in "
8610 : "!$OMP DECLARE REDUCTION at %L", sym->name, &(*e)->where);
8611 : }
8612 2990 : return 0;
8613 : }
8614 :
8615 :
8616 : static gfc_code *
8617 797 : resolve_omp_udr_clause (gfc_omp_namelist *n, gfc_namespace *ns,
8618 : gfc_symbol *sym1, gfc_symbol *sym2)
8619 : {
8620 797 : gfc_code *copy;
8621 797 : gfc_symbol sym1_copy, sym2_copy;
8622 :
8623 797 : if (ns->code->op == EXEC_ASSIGN)
8624 : {
8625 625 : copy = gfc_get_code (EXEC_ASSIGN);
8626 625 : copy->expr1 = gfc_copy_expr (ns->code->expr1);
8627 625 : copy->expr2 = gfc_copy_expr (ns->code->expr2);
8628 : }
8629 : else
8630 : {
8631 172 : copy = gfc_get_code (EXEC_CALL);
8632 172 : copy->symtree = ns->code->symtree;
8633 172 : copy->ext.actual = gfc_copy_actual_arglist (ns->code->ext.actual);
8634 : }
8635 797 : copy->loc = ns->code->loc;
8636 797 : sym1_copy = *sym1;
8637 797 : sym2_copy = *sym2;
8638 797 : *sym1 = *n->sym;
8639 797 : *sym2 = *n->sym;
8640 797 : sym1->name = sym1_copy.name;
8641 797 : sym2->name = sym2_copy.name;
8642 797 : ns->proc_name = ns->parent->proc_name;
8643 797 : if (n->sym->attr.dimension)
8644 : {
8645 348 : struct resolve_omp_udr_callback_data rcd;
8646 348 : rcd.sym1 = sym1;
8647 348 : rcd.sym2 = sym2;
8648 348 : gfc_code_walker (©, gfc_dummy_code_callback,
8649 : resolve_omp_udr_callback, &rcd);
8650 : }
8651 797 : gfc_resolve_code (copy, gfc_current_ns);
8652 797 : if (copy->op == EXEC_CALL && copy->resolved_isym == NULL)
8653 : {
8654 172 : gfc_symbol *sym = copy->resolved_sym;
8655 172 : if (sym
8656 170 : && !sym->attr.intrinsic
8657 170 : && sym->attr.if_source == IFSRC_UNKNOWN)
8658 4 : gfc_error ("Implicitly declared subroutine %s used in "
8659 : "!$OMP DECLARE REDUCTION at %L", sym->name,
8660 : ©->loc);
8661 : }
8662 797 : gfc_code_walker (©, gfc_dummy_code_callback,
8663 : resolve_omp_udr_callback2, NULL);
8664 797 : *sym1 = sym1_copy;
8665 797 : *sym2 = sym2_copy;
8666 797 : return copy;
8667 : }
8668 :
8669 : /* Assume that a constant expression in the range 1 (omp_default_mem_alloc)
8670 : to GOMP_OMP_PREDEF_ALLOC_MAX, or GOMP_OMPX_PREDEF_ALLOC_MIN to
8671 : GOMP_OMPX_PREDEF_ALLOC_MAX is fine. The original symbol name is already
8672 : lost during matching via gfc_match_expr. */
8673 : static bool
8674 130 : is_predefined_allocator (gfc_expr *expr)
8675 : {
8676 130 : return (gfc_resolve_expr (expr)
8677 129 : && expr->rank == 0
8678 124 : && expr->ts.type == BT_INTEGER
8679 119 : && expr->ts.kind == gfc_c_intptr_kind
8680 114 : && expr->expr_type == EXPR_CONSTANT
8681 239 : && ((mpz_sgn (expr->value.integer) > 0
8682 107 : && mpz_cmp_si (expr->value.integer,
8683 : GOMP_OMP_PREDEF_ALLOC_MAX) <= 0)
8684 4 : || (mpz_cmp_si (expr->value.integer,
8685 : GOMP_OMPX_PREDEF_ALLOC_MIN) >= 0
8686 1 : && mpz_cmp_si (expr->value.integer,
8687 130 : GOMP_OMPX_PREDEF_ALLOC_MAX) <= 0)));
8688 : }
8689 :
8690 : /* Resolve declarative ALLOCATE statement. Note: Common block vars only appear
8691 : as /block/ not individual, which is ensured during parsing. */
8692 :
8693 : void
8694 62 : gfc_resolve_omp_allocate (gfc_namespace *ns, gfc_omp_namelist *list)
8695 : {
8696 278 : for (gfc_omp_namelist *n = list; n; n = n->next)
8697 : {
8698 216 : if (n->sym->attr.result || n->sym->result == n->sym)
8699 : {
8700 1 : gfc_error ("Unexpected function-result variable %qs at %L in "
8701 : "declarative !$OMP ALLOCATE", n->sym->name, &n->where);
8702 31 : continue;
8703 : }
8704 215 : if (ns->omp_allocate->sym->attr.proc_pointer)
8705 : {
8706 0 : gfc_error ("Procedure pointer %qs not supported with !$OMP "
8707 : "ALLOCATE at %L", n->sym->name, &n->where);
8708 0 : continue;
8709 : }
8710 215 : if (n->sym->attr.flavor != FL_VARIABLE)
8711 : {
8712 3 : gfc_error ("Argument %qs at %L to declarative !$OMP ALLOCATE "
8713 : "directive must be a variable", n->sym->name,
8714 : &n->where);
8715 3 : continue;
8716 : }
8717 212 : if (ns != n->sym->ns || n->sym->attr.use_assoc || n->sym->attr.imported)
8718 : {
8719 8 : gfc_error ("Argument %qs at %L to declarative !$OMP ALLOCATE shall be"
8720 : " in the same scope as the variable declaration",
8721 : n->sym->name, &n->where);
8722 8 : continue;
8723 : }
8724 204 : if (n->sym->attr.dummy)
8725 : {
8726 3 : gfc_error ("Unexpected dummy argument %qs as argument at %L to "
8727 : "declarative !$OMP ALLOCATE", n->sym->name, &n->where);
8728 3 : continue;
8729 : }
8730 201 : if (n->sym->attr.codimension)
8731 : {
8732 0 : gfc_error ("Unexpected coarray argument %qs as argument at %L to "
8733 : "declarative !$OMP ALLOCATE", n->sym->name, &n->where);
8734 0 : continue;
8735 : }
8736 201 : if (n->sym->attr.omp_allocate)
8737 : {
8738 5 : if (n->sym->attr.in_common)
8739 : {
8740 1 : gfc_error ("Duplicated common block %</%s/%> in !$OMP ALLOCATE "
8741 1 : "at %L", n->sym->common_head->name, &n->where);
8742 3 : while (n->next && n->next->sym
8743 3 : && n->sym->common_head == n->next->sym->common_head)
8744 : n = n->next;
8745 : }
8746 : else
8747 4 : gfc_error ("Duplicated variable %qs in !$OMP ALLOCATE at %L",
8748 : n->sym->name, &n->where);
8749 5 : continue;
8750 : }
8751 : /* For 'equivalence(a,b)', a 'union_type {<type> a,b} equiv.0' is created
8752 : with a value expression for 'a' as 'equiv.0.a' (likewise for b); while
8753 : this can be handled, EQUIVALENCE is marked as obsolescent since Fortran
8754 : 2018 and also not widely used. However, it could be supported,
8755 : if needed. */
8756 196 : if (n->sym->attr.in_equivalence)
8757 : {
8758 2 : gfc_error ("Sorry, EQUIVALENCE object %qs not supported with !$OMP "
8759 : "ALLOCATE at %L", n->sym->name, &n->where);
8760 2 : continue;
8761 : }
8762 : /* Similar for Cray pointer/pointee - they could be implemented but as
8763 : common vendor extension but nowadays rarely used and requiring
8764 : -fcray-pointer, there is no need to support them. */
8765 194 : if (n->sym->attr.cray_pointer || n->sym->attr.cray_pointee)
8766 : {
8767 2 : gfc_error ("Sorry, Cray pointers and pointees such as %qs are not "
8768 : "supported with !$OMP ALLOCATE at %L",
8769 : n->sym->name, &n->where);
8770 2 : continue;
8771 : }
8772 192 : n->sym->attr.omp_allocate = 1;
8773 192 : if ((n->sym->ts.type == BT_CLASS && n->sym->attr.class_ok
8774 0 : && CLASS_DATA (n->sym)->attr.allocatable)
8775 192 : || (n->sym->ts.type != BT_CLASS && n->sym->attr.allocatable))
8776 1 : gfc_error ("Unexpected allocatable variable %qs at %L in declarative "
8777 : "!$OMP ALLOCATE directive", n->sym->name, &n->where);
8778 191 : else if ((n->sym->ts.type == BT_CLASS && n->sym->attr.class_ok
8779 0 : && CLASS_DATA (n->sym)->attr.class_pointer)
8780 191 : || (n->sym->ts.type != BT_CLASS && n->sym->attr.pointer))
8781 1 : gfc_error ("Unexpected pointer variable %qs at %L in declarative "
8782 : "!$OMP ALLOCATE directive", n->sym->name, &n->where);
8783 192 : HOST_WIDE_INT alignment = 0;
8784 198 : if (n->u.align
8785 192 : && (!gfc_resolve_expr (n->u.align)
8786 27 : || n->u.align->ts.type != BT_INTEGER
8787 26 : || n->u.align->rank != 0
8788 24 : || n->u.align->expr_type != EXPR_CONSTANT
8789 23 : || gfc_extract_hwi (n->u.align, &alignment)
8790 23 : || !pow2p_hwi (alignment)))
8791 : {
8792 6 : gfc_error ("ALIGN requires a scalar positive constant integer "
8793 : "alignment expression at %L that is a power of two",
8794 6 : &n->u.align->where);
8795 6 : while (n->sym->attr.in_common && n->next && n->next->sym
8796 6 : && n->sym->common_head == n->next->sym->common_head)
8797 : n = n->next;
8798 6 : continue;
8799 : }
8800 186 : if (n->sym->attr.in_common || n->sym->attr.save || n->sym->ns->save_all
8801 63 : || (n->sym->ns->proc_name
8802 63 : && (n->sym->ns->proc_name->attr.flavor == FL_PROGRAM
8803 : || n->sym->ns->proc_name->attr.flavor == FL_MODULE
8804 : || n->sym->ns->proc_name->attr.flavor == FL_BLOCK_DATA)))
8805 : {
8806 131 : bool com = n->sym->attr.in_common;
8807 131 : if (!n->u2.allocator)
8808 1 : gfc_error ("An ALLOCATOR clause is required as the list item "
8809 : "%<%s%s%s%> at %L has the SAVE attribute", com ? "/" : "",
8810 0 : com ? n->sym->common_head->name : n->sym->name,
8811 : com ? "/" : "", &n->where);
8812 130 : else if (!is_predefined_allocator (n->u2.allocator))
8813 24 : gfc_error ("Predefined allocator required in ALLOCATOR clause at %L"
8814 : " as the list item %<%s%s%s%> at %L has the SAVE attribute",
8815 24 : &n->u2.allocator->where, com ? "/" : "",
8816 24 : com ? n->sym->common_head->name : n->sym->name,
8817 : com ? "/" : "", &n->where);
8818 : /* Only local static variables might use omp_cgroup_mem_alloc (6),
8819 : omp_pteam_mem_alloc (7), or omp_thread_mem_alloc (8). */
8820 106 : else if ((!ns->proc_name
8821 98 : || ns->proc_name->attr.flavor == FL_PROGRAM
8822 : || ns->proc_name->attr.flavor == FL_BLOCK_DATA
8823 : || ns->proc_name->attr.flavor == FL_MODULE
8824 54 : || com)
8825 74 : && mpz_cmp_si (n->u2.allocator->value.integer,
8826 : 6 /* cgroup */) >= 0
8827 24 : && mpz_cmp_si (n->u2.allocator->value.integer,
8828 : 8 /* thread */) <= 0)
8829 : {
8830 24 : const char *alloc_name[] = {"omp_cgroup_mem_alloc",
8831 : "omp_pteam_mem_alloc",
8832 : "omp_thread_mem_alloc" };
8833 24 : gfc_error ("Predefined allocator %qs in ALLOCATOR clause at %L, "
8834 : "used for list item %<%s%s%s%> at %L, may only be used"
8835 : " for local static variables",
8836 24 : alloc_name[mpz_get_ui (n->u2.allocator->value.integer)
8837 24 : - 6 /* cgroup */], &n->u2.allocator->where,
8838 : com ? "/" : "",
8839 24 : com ? n->sym->common_head->name : n->sym->name,
8840 : com ? "/" : "", &n->where);
8841 : }
8842 67 : while (n->sym->attr.in_common && n->next && n->next->sym
8843 186 : && n->sym->common_head == n->next->sym->common_head)
8844 : n = n->next;
8845 : }
8846 55 : else if (n->u2.allocator
8847 55 : && (!gfc_resolve_expr (n->u2.allocator)
8848 20 : || n->u2.allocator->ts.type != BT_INTEGER
8849 19 : || n->u2.allocator->rank != 0
8850 18 : || n->u2.allocator->ts.kind != gfc_c_intptr_kind))
8851 3 : gfc_error ("Expected integer expression of the "
8852 : "%<omp_allocator_handle_kind%> kind at %L",
8853 3 : &n->u2.allocator->where);
8854 : }
8855 62 : }
8856 :
8857 : /* Resolve ASSUME's and ASSUMES' assumption clauses. Note that absent/contains
8858 : is handled during parse time in omp_verify_merge_absent_contains. */
8859 :
8860 : void
8861 29 : gfc_resolve_omp_assumptions (gfc_omp_assumptions *assume)
8862 : {
8863 46 : for (gfc_expr_list *el = assume->holds; el; el = el->next)
8864 17 : if (!gfc_resolve_expr (el->expr)
8865 17 : || el->expr->ts.type != BT_LOGICAL
8866 32 : || el->expr->rank != 0)
8867 4 : gfc_error ("HOLDS expression at %L must be a scalar logical expression",
8868 4 : &el->expr->where);
8869 29 : }
8870 :
8871 :
8872 : /* OpenMP directive resolving routines. */
8873 :
8874 : static void
8875 32198 : resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
8876 : gfc_namespace *ns, bool openacc = false)
8877 : {
8878 32198 : gfc_omp_namelist *n, *last;
8879 32198 : gfc_expr_list *el;
8880 32198 : enum gfc_omp_list_type list;
8881 32198 : int ifc;
8882 32198 : bool if_without_mod = false;
8883 32198 : gfc_omp_linear_op linear_op = OMP_LINEAR_DEFAULT;
8884 32198 : static const char *clause_names[]
8885 : = { "PRIVATE", "FIRSTPRIVATE", "LASTPRIVATE", "COPYPRIVATE", "SHARED",
8886 : "COPYIN", "UNIFORM", "AFFINITY", "ALIGNED", "LINEAR", "DEPEND", "MAP",
8887 : "TO", "FROM", "INCLUSIVE", "EXCLUSIVE",
8888 : "REDUCTION", "REDUCTION" /*inscan*/, "REDUCTION" /*task*/,
8889 : "IN_REDUCTION", "TASK_REDUCTION",
8890 : "DEVICE_RESIDENT", "LINK", "LOCAL", "USE_DEVICE",
8891 : "CACHE", "IS_DEVICE_PTR", "USE_DEVICE_PTR", "USE_DEVICE_ADDR",
8892 : "NONTEMPORAL", "ALLOCATE", "HAS_DEVICE_ADDR", "ENTER",
8893 : "USES_ALLOCATORS", "INIT", "USE", "DESTROY", "INTEROP", "ADJUST_ARGS" };
8894 32198 : STATIC_ASSERT (ARRAY_SIZE (clause_names) == OMP_LIST_NUM);
8895 :
8896 32198 : if (omp_clauses == NULL)
8897 : return;
8898 :
8899 32198 : if (ns == NULL)
8900 31777 : ns = gfc_current_ns;
8901 :
8902 32198 : if (omp_clauses->orderedc && omp_clauses->orderedc < omp_clauses->collapse)
8903 0 : gfc_error ("ORDERED clause parameter is less than COLLAPSE at %L",
8904 : &code->loc);
8905 32198 : if (omp_clauses->order_concurrent && omp_clauses->ordered)
8906 4 : gfc_error ("ORDER clause must not be used together with ORDERED at %L",
8907 : &code->loc);
8908 32198 : if (omp_clauses->if_expr)
8909 : {
8910 1184 : gfc_expr *expr = omp_clauses->if_expr;
8911 1184 : if (!gfc_resolve_expr (expr)
8912 1184 : || expr->ts.type != BT_LOGICAL || expr->rank != 0)
8913 16 : gfc_error ("IF clause at %L requires a scalar LOGICAL expression",
8914 : &expr->where);
8915 : if_without_mod = true;
8916 : }
8917 354178 : for (ifc = 0; ifc < OMP_IF_LAST; ifc++)
8918 321980 : if (omp_clauses->if_exprs[ifc])
8919 : {
8920 137 : gfc_expr *expr = omp_clauses->if_exprs[ifc];
8921 137 : bool ok = true;
8922 137 : if (!gfc_resolve_expr (expr)
8923 137 : || expr->ts.type != BT_LOGICAL || expr->rank != 0)
8924 0 : gfc_error ("IF clause at %L requires a scalar LOGICAL expression",
8925 : &expr->where);
8926 137 : else if (if_without_mod)
8927 : {
8928 1 : gfc_error ("IF clause without modifier at %L used together with "
8929 : "IF clauses with modifiers",
8930 1 : &omp_clauses->if_expr->where);
8931 1 : if_without_mod = false;
8932 : }
8933 : else
8934 136 : switch (code->op)
8935 : {
8936 13 : case EXEC_OMP_CANCEL:
8937 13 : ok = ifc == OMP_IF_CANCEL;
8938 13 : break;
8939 :
8940 16 : case EXEC_OMP_PARALLEL:
8941 16 : case EXEC_OMP_PARALLEL_DO:
8942 16 : case EXEC_OMP_PARALLEL_LOOP:
8943 16 : case EXEC_OMP_PARALLEL_MASKED:
8944 16 : case EXEC_OMP_PARALLEL_MASTER:
8945 16 : case EXEC_OMP_PARALLEL_SECTIONS:
8946 16 : case EXEC_OMP_PARALLEL_WORKSHARE:
8947 16 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
8948 16 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
8949 16 : ok = ifc == OMP_IF_PARALLEL;
8950 16 : break;
8951 :
8952 28 : case EXEC_OMP_PARALLEL_DO_SIMD:
8953 28 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
8954 28 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
8955 28 : ok = ifc == OMP_IF_PARALLEL || ifc == OMP_IF_SIMD;
8956 28 : break;
8957 :
8958 8 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
8959 8 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
8960 8 : ok = ifc == OMP_IF_PARALLEL || ifc == OMP_IF_TASKLOOP;
8961 8 : break;
8962 :
8963 12 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
8964 12 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
8965 12 : ok = (ifc == OMP_IF_PARALLEL
8966 12 : || ifc == OMP_IF_TASKLOOP
8967 : || ifc == OMP_IF_SIMD);
8968 : break;
8969 :
8970 0 : case EXEC_OMP_SIMD:
8971 0 : case EXEC_OMP_DO_SIMD:
8972 0 : case EXEC_OMP_DISTRIBUTE_SIMD:
8973 0 : case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
8974 0 : ok = ifc == OMP_IF_SIMD;
8975 0 : break;
8976 :
8977 1 : case EXEC_OMP_TASK:
8978 1 : ok = ifc == OMP_IF_TASK;
8979 1 : break;
8980 :
8981 5 : case EXEC_OMP_TASKLOOP:
8982 5 : case EXEC_OMP_MASKED_TASKLOOP:
8983 5 : case EXEC_OMP_MASTER_TASKLOOP:
8984 5 : ok = ifc == OMP_IF_TASKLOOP;
8985 5 : break;
8986 :
8987 20 : case EXEC_OMP_TASKLOOP_SIMD:
8988 20 : case EXEC_OMP_MASKED_TASKLOOP_SIMD:
8989 20 : case EXEC_OMP_MASTER_TASKLOOP_SIMD:
8990 20 : ok = ifc == OMP_IF_TASKLOOP || ifc == OMP_IF_SIMD;
8991 20 : break;
8992 :
8993 5 : case EXEC_OMP_TARGET:
8994 5 : case EXEC_OMP_TARGET_TEAMS:
8995 5 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
8996 5 : case EXEC_OMP_TARGET_TEAMS_LOOP:
8997 5 : ok = ifc == OMP_IF_TARGET;
8998 5 : break;
8999 :
9000 4 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
9001 4 : case EXEC_OMP_TARGET_SIMD:
9002 4 : ok = ifc == OMP_IF_TARGET || ifc == OMP_IF_SIMD;
9003 4 : break;
9004 :
9005 1 : case EXEC_OMP_TARGET_DATA:
9006 1 : ok = ifc == OMP_IF_TARGET_DATA;
9007 1 : break;
9008 :
9009 1 : case EXEC_OMP_TARGET_UPDATE:
9010 1 : ok = ifc == OMP_IF_TARGET_UPDATE;
9011 1 : break;
9012 :
9013 1 : case EXEC_OMP_TARGET_ENTER_DATA:
9014 1 : ok = ifc == OMP_IF_TARGET_ENTER_DATA;
9015 1 : break;
9016 :
9017 1 : case EXEC_OMP_TARGET_EXIT_DATA:
9018 1 : ok = ifc == OMP_IF_TARGET_EXIT_DATA;
9019 1 : break;
9020 :
9021 10 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
9022 10 : case EXEC_OMP_TARGET_PARALLEL:
9023 10 : case EXEC_OMP_TARGET_PARALLEL_DO:
9024 10 : case EXEC_OMP_TARGET_PARALLEL_LOOP:
9025 10 : ok = ifc == OMP_IF_TARGET || ifc == OMP_IF_PARALLEL;
9026 10 : break;
9027 :
9028 10 : case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
9029 10 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
9030 10 : ok = (ifc == OMP_IF_TARGET
9031 10 : || ifc == OMP_IF_PARALLEL
9032 : || ifc == OMP_IF_SIMD);
9033 : break;
9034 :
9035 : default:
9036 : ok = false;
9037 : break;
9038 : }
9039 115 : if (!ok)
9040 : {
9041 2 : static const char *ifs[] = {
9042 : "CANCEL",
9043 : "PARALLEL",
9044 : "SIMD",
9045 : "TASK",
9046 : "TASKLOOP",
9047 : "TARGET",
9048 : "TARGET DATA",
9049 : "TARGET UPDATE",
9050 : "TARGET ENTER DATA",
9051 : "TARGET EXIT DATA"
9052 : };
9053 2 : gfc_error ("IF clause modifier %s at %L not appropriate for "
9054 : "the current OpenMP construct", ifs[ifc], &expr->where);
9055 : }
9056 : }
9057 :
9058 32198 : if (omp_clauses->self_expr)
9059 : {
9060 177 : gfc_expr *expr = omp_clauses->self_expr;
9061 177 : if (!gfc_resolve_expr (expr)
9062 177 : || expr->ts.type != BT_LOGICAL || expr->rank != 0)
9063 6 : gfc_error ("SELF clause at %L requires a scalar LOGICAL expression",
9064 : &expr->where);
9065 : }
9066 :
9067 32198 : if (omp_clauses->final_expr)
9068 : {
9069 64 : gfc_expr *expr = omp_clauses->final_expr;
9070 64 : if (!gfc_resolve_expr (expr)
9071 64 : || expr->ts.type != BT_LOGICAL || expr->rank != 0)
9072 0 : gfc_error ("FINAL clause at %L requires a scalar LOGICAL expression",
9073 : &expr->where);
9074 : }
9075 32198 : if (omp_clauses->novariants)
9076 : {
9077 9 : gfc_expr *expr = omp_clauses->novariants;
9078 18 : if (!gfc_resolve_expr (expr) || expr->ts.type != BT_LOGICAL
9079 17 : || expr->rank != 0)
9080 1 : gfc_error (
9081 : "NOVARIANTS clause at %L requires a scalar LOGICAL expression",
9082 : &expr->where);
9083 32198 : if_without_mod = true;
9084 : }
9085 32198 : if (omp_clauses->nocontext)
9086 : {
9087 12 : gfc_expr *expr = omp_clauses->nocontext;
9088 24 : if (!gfc_resolve_expr (expr) || expr->ts.type != BT_LOGICAL
9089 23 : || expr->rank != 0)
9090 1 : gfc_error (
9091 : "NOCONTEXT clause at %L requires a scalar LOGICAL expression",
9092 : &expr->where);
9093 32198 : if_without_mod = true;
9094 : }
9095 32198 : if (omp_clauses->num_threads)
9096 962 : resolve_positive_int_expr (omp_clauses->num_threads, "NUM_THREADS");
9097 32198 : if (omp_clauses->dyn_groupprivate)
9098 10 : resolve_nonnegative_int_expr (omp_clauses->dyn_groupprivate,
9099 : "DYN_GROUPPRIVATE");
9100 32198 : if (omp_clauses->chunk_size)
9101 : {
9102 510 : gfc_expr *expr = omp_clauses->chunk_size;
9103 510 : if (!gfc_resolve_expr (expr)
9104 510 : || expr->ts.type != BT_INTEGER || expr->rank != 0)
9105 0 : gfc_error ("SCHEDULE clause's chunk_size at %L requires "
9106 : "a scalar INTEGER expression", &expr->where);
9107 510 : else if (expr->expr_type == EXPR_CONSTANT
9108 : && expr->ts.type == BT_INTEGER
9109 485 : && mpz_sgn (expr->value.integer) <= 0)
9110 2 : gfc_warning (OPT_Wopenmp, "INTEGER expression of SCHEDULE clause's "
9111 : "chunk_size at %L must be positive", &expr->where);
9112 : }
9113 32198 : if (omp_clauses->sched_kind != OMP_SCHED_NONE
9114 891 : && omp_clauses->sched_nonmonotonic)
9115 : {
9116 34 : if (omp_clauses->sched_monotonic)
9117 2 : gfc_error ("Both MONOTONIC and NONMONOTONIC schedule modifiers "
9118 : "specified at %L", &code->loc);
9119 32 : else if (omp_clauses->ordered)
9120 4 : gfc_error ("NONMONOTONIC schedule modifier specified with ORDERED "
9121 : "clause at %L", &code->loc);
9122 : }
9123 :
9124 32198 : if (omp_clauses->depobj
9125 32198 : && (!gfc_resolve_expr (omp_clauses->depobj)
9126 115 : || omp_clauses->depobj->ts.type != BT_INTEGER
9127 114 : || omp_clauses->depobj->ts.kind != 2 * gfc_index_integer_kind
9128 113 : || omp_clauses->depobj->rank != 0))
9129 4 : gfc_error ("DEPOBJ in DEPOBJ construct at %L shall be a scalar integer "
9130 4 : "of OMP_DEPEND_KIND kind", &omp_clauses->depobj->where);
9131 :
9132 : /* Check that no symbol appears on multiple clauses, except that
9133 : a symbol can appear on both firstprivate and lastprivate. */
9134 1287920 : for (list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
9135 1255722 : list = gfc_omp_list_type (list + 1))
9136 1300720 : for (n = omp_clauses->lists[list]; n; n = n->next)
9137 : {
9138 44998 : if (!n->sym) /* omp_all_memory. */
9139 47 : continue;
9140 44951 : n->sym->mark = 0;
9141 44951 : n->sym->comp_mark = 0;
9142 44951 : n->sym->data_mark = 0;
9143 44951 : n->sym->dev_mark = 0;
9144 44951 : n->sym->gen_mark = 0;
9145 44951 : n->sym->reduc_mark = 0;
9146 44951 : if (n->sym->attr.flavor == FL_VARIABLE
9147 274 : || n->sym->attr.proc_pointer
9148 233 : || (!code && (!n->sym->attr.dummy || n->sym->ns != ns)))
9149 : {
9150 44718 : if (!code && (!n->sym->attr.dummy || n->sym->ns != ns))
9151 0 : gfc_error ("Variable %qs is not a dummy argument at %L",
9152 : n->sym->name, &n->where);
9153 44718 : continue;
9154 : }
9155 233 : if (n->sym->attr.flavor == FL_PROCEDURE
9156 153 : && n->sym->result == n->sym
9157 138 : && n->sym->attr.function)
9158 : {
9159 138 : if (ns->proc_name == n->sym
9160 44 : || (ns->parent && ns->parent->proc_name == n->sym))
9161 101 : continue;
9162 37 : if (ns->proc_name->attr.entry_master)
9163 : {
9164 32 : gfc_entry_list *el = ns->entries;
9165 51 : for (; el; el = el->next)
9166 51 : if (el->sym == n->sym)
9167 : break;
9168 32 : if (el)
9169 32 : continue;
9170 : }
9171 5 : if (ns->parent
9172 3 : && ns->parent->proc_name->attr.entry_master)
9173 : {
9174 2 : gfc_entry_list *el = ns->parent->entries;
9175 3 : for (; el; el = el->next)
9176 3 : if (el->sym == n->sym)
9177 : break;
9178 2 : if (el)
9179 2 : continue;
9180 : }
9181 : }
9182 98 : if (list == OMP_LIST_MAP
9183 18 : && n->sym->attr.flavor == FL_PARAMETER)
9184 : {
9185 : /* OpenACC since 3.4 permits for Fortran named constants, but
9186 : permits removing then as optimization is not needed and such
9187 : ignore them. Likewise below for FIRSTPRIVATE. */
9188 12 : if (openacc)
9189 10 : gfc_warning (OPT_Wsurprising, "Clause for object %qs at %L is "
9190 : "ignored as parameters need not be copied",
9191 : n->sym->name, &n->where);
9192 : else
9193 2 : gfc_error ("Object %qs is not a variable at %L; parameters"
9194 : " cannot be and need not be mapped", n->sym->name,
9195 : &n->where);
9196 : }
9197 86 : else if (openacc && n->sym->attr.flavor == FL_PARAMETER)
9198 9 : gfc_warning (OPT_Wsurprising, "Clause for object %qs at %L is ignored"
9199 : " as it is a parameter", n->sym->name, &n->where);
9200 77 : else if (list != OMP_LIST_USES_ALLOCATORS)
9201 30 : gfc_error ("Object %qs is not a variable at %L", n->sym->name,
9202 : &n->where);
9203 : }
9204 32198 : if (omp_clauses->lists[OMP_LIST_REDUCTION_INSCAN])
9205 : {
9206 69 : locus *loc = &omp_clauses->lists[OMP_LIST_REDUCTION_INSCAN]->where;
9207 69 : if (code->op != EXEC_OMP_DO
9208 : && code->op != EXEC_OMP_SIMD
9209 : && code->op != EXEC_OMP_DO_SIMD
9210 : && code->op != EXEC_OMP_PARALLEL_DO
9211 : && code->op != EXEC_OMP_PARALLEL_DO_SIMD)
9212 23 : gfc_error ("%<inscan%> REDUCTION clause on construct other than DO, "
9213 : "SIMD, DO SIMD, PARALLEL DO, PARALLEL DO SIMD at %L",
9214 : loc);
9215 69 : if (omp_clauses->ordered)
9216 2 : gfc_error ("ORDERED clause specified together with %<inscan%> "
9217 : "REDUCTION clause at %L", loc);
9218 69 : if (omp_clauses->sched_kind != OMP_SCHED_NONE)
9219 3 : gfc_error ("SCHEDULE clause specified together with %<inscan%> "
9220 : "REDUCTION clause at %L", loc);
9221 : }
9222 :
9223 1287920 : for (list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
9224 1255722 : list = gfc_omp_list_type (list + 1))
9225 1255722 : if (list != OMP_LIST_FIRSTPRIVATE
9226 1255722 : && list != OMP_LIST_LASTPRIVATE
9227 1255722 : && list != OMP_LIST_ALIGNED
9228 1159128 : && list != OMP_LIST_DEPEND
9229 1159128 : && list != OMP_LIST_FROM
9230 1094732 : && list != OMP_LIST_TO
9231 1094732 : && list != OMP_LIST_INTEROP
9232 1030336 : && (list != OMP_LIST_REDUCTION || !openacc)
9233 1017711 : && list != OMP_LIST_ALLOCATE)
9234 1019685 : for (n = omp_clauses->lists[list]; n; n = n->next)
9235 : {
9236 34172 : bool component_ref_p = false;
9237 :
9238 : /* Allow multiple components of the same (e.g. derived-type)
9239 : variable here. Duplicate components are detected elsewhere. */
9240 34172 : if (n->expr && n->expr->expr_type == EXPR_VARIABLE)
9241 15390 : for (gfc_ref *ref = n->expr->ref; ref; ref = ref->next)
9242 9385 : if (ref->type == REF_COMPONENT)
9243 3134 : component_ref_p = true;
9244 34172 : if ((list == OMP_LIST_IS_DEVICE_PTR
9245 34172 : || list == OMP_LIST_HAS_DEVICE_ADDR)
9246 313 : && !component_ref_p)
9247 : {
9248 313 : if (n->sym->gen_mark
9249 311 : || n->sym->dev_mark
9250 310 : || n->sym->reduc_mark
9251 310 : || n->sym->mark)
9252 5 : gfc_error ("Symbol %qs present on multiple clauses at %L",
9253 : n->sym->name, &n->where);
9254 : else
9255 308 : n->sym->dev_mark = 1;
9256 : }
9257 33859 : else if ((list == OMP_LIST_USE_DEVICE_PTR
9258 33859 : || list == OMP_LIST_USE_DEVICE_ADDR
9259 33859 : || list == OMP_LIST_PRIVATE
9260 : || list == OMP_LIST_SHARED)
9261 12851 : && !component_ref_p)
9262 : {
9263 12851 : if (n->sym->gen_mark || n->sym->dev_mark || n->sym->reduc_mark)
9264 13 : gfc_error ("Symbol %qs present on multiple clauses at %L",
9265 : n->sym->name, &n->where);
9266 : else
9267 : {
9268 12838 : n->sym->gen_mark = 1;
9269 : /* Set both generic and device bits if we have
9270 : use_device_*(x) or shared(x). This allows us to diagnose
9271 : "map(x) private(x)" below. */
9272 12838 : if (list != OMP_LIST_PRIVATE)
9273 3456 : n->sym->dev_mark = 1;
9274 : }
9275 : }
9276 21008 : else if ((list == OMP_LIST_REDUCTION
9277 21008 : || list == OMP_LIST_REDUCTION_TASK
9278 18551 : || list == OMP_LIST_REDUCTION_INSCAN
9279 18551 : || list == OMP_LIST_IN_REDUCTION
9280 18338 : || list == OMP_LIST_TASK_REDUCTION)
9281 2670 : && !component_ref_p)
9282 : {
9283 : /* Attempts to mix reduction types are diagnosed below. */
9284 2670 : if (n->sym->gen_mark || n->sym->dev_mark)
9285 2 : gfc_error ("Symbol %qs present on multiple clauses at %L",
9286 : n->sym->name, &n->where);
9287 2670 : n->sym->reduc_mark = 1;
9288 : }
9289 18338 : else if ((!component_ref_p && n->sym->comp_mark)
9290 2451 : || (component_ref_p && n->sym->mark))
9291 : {
9292 28 : if (openacc)
9293 3 : gfc_error ("Symbol %qs has mixed component and non-component "
9294 3 : "accesses at %L", n->sym->name, &n->where);
9295 : }
9296 18310 : else if (n->sym->mark)
9297 89 : gfc_error ("Symbol %qs present on multiple clauses at %L",
9298 : n->sym->name, &n->where);
9299 : else
9300 : {
9301 18221 : if (component_ref_p)
9302 2424 : n->sym->comp_mark = 1;
9303 : else
9304 15797 : n->sym->mark = 1;
9305 : }
9306 : }
9307 :
9308 32198 : if (code
9309 31980 : && code->op == EXEC_OMP_INTEROP
9310 63 : && omp_clauses->lists[OMP_LIST_DEPEND])
9311 : {
9312 12 : if (!omp_clauses->lists[OMP_LIST_INIT]
9313 5 : && !omp_clauses->lists[OMP_LIST_USE]
9314 1 : && !omp_clauses->lists[OMP_LIST_DESTROY])
9315 : {
9316 1 : gfc_error ("DEPEND clause at %L requires action clause with "
9317 : "%<targetsync%> interop-type",
9318 : &omp_clauses->lists[OMP_LIST_DEPEND]->where);
9319 : }
9320 22 : for (n = omp_clauses->lists[OMP_LIST_INIT]; n; n = n->next)
9321 12 : if (!n->u.init.targetsync)
9322 : {
9323 2 : gfc_error ("DEPEND clause at %L requires %<targetsync%> "
9324 : "interop-type, lacking it for %qs at %L",
9325 2 : &omp_clauses->lists[OMP_LIST_DEPEND]->where,
9326 2 : n->sym->name, &n->where);
9327 2 : break;
9328 : }
9329 : }
9330 31980 : if (code && (code->op == EXEC_OMP_INTEROP || code->op == EXEC_OMP_DISPATCH))
9331 1085 : for (list = OMP_LIST_INIT; list <= OMP_LIST_INTEROP;
9332 868 : list = gfc_omp_list_type (list + 1))
9333 1123 : for (n = omp_clauses->lists[list]; n; n = n->next)
9334 : {
9335 255 : if (n->sym->ts.type != BT_INTEGER
9336 252 : || n->sym->ts.kind != gfc_index_integer_kind
9337 248 : || n->sym->attr.dimension
9338 243 : || n->sym->attr.flavor != FL_VARIABLE)
9339 16 : gfc_error ("%qs at %L in %qs clause must be a scalar integer "
9340 : "variable of %<omp_interop_kind%> kind", n->sym->name,
9341 : &n->where, clause_names[list]);
9342 255 : if (list != OMP_LIST_USE && list != OMP_LIST_INTEROP
9343 109 : && n->sym->attr.intent == INTENT_IN)
9344 2 : gfc_error ("%qs at %L in %qs clause must be definable",
9345 : n->sym->name, &n->where, clause_names[list]);
9346 : }
9347 :
9348 : /* Detect specifically the case where we have "map(x) private(x)" and raise
9349 : an error. If we have "...simd" combined directives though, the "private"
9350 : applies to the simd part, so this is permitted though. */
9351 41588 : for (n = omp_clauses->lists[OMP_LIST_PRIVATE]; n; n = n->next)
9352 9390 : if (n->sym->mark
9353 6 : && n->sym->gen_mark
9354 6 : && !n->sym->dev_mark
9355 6 : && !n->sym->reduc_mark
9356 5 : && code->op != EXEC_OMP_TARGET_SIMD
9357 : && code->op != EXEC_OMP_TARGET_PARALLEL_DO_SIMD
9358 : && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD
9359 : && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD)
9360 1 : gfc_error ("Symbol %qs present on multiple clauses at %L",
9361 : n->sym->name, &n->where);
9362 :
9363 : gcc_assert (OMP_LIST_LASTPRIVATE == OMP_LIST_FIRSTPRIVATE + 1);
9364 96594 : for (list = OMP_LIST_FIRSTPRIVATE; list <= OMP_LIST_LASTPRIVATE;
9365 64396 : list = gfc_omp_list_type (list + 1))
9366 68557 : for (n = omp_clauses->lists[list]; n; n = n->next)
9367 4161 : if (n->sym->data_mark || n->sym->gen_mark || n->sym->dev_mark)
9368 : {
9369 9 : gfc_error ("Symbol %qs present on multiple clauses at %L",
9370 : n->sym->name, &n->where);
9371 9 : n->sym->data_mark = n->sym->gen_mark = n->sym->dev_mark = 0;
9372 : }
9373 4152 : else if (n->sym->mark
9374 18 : && code->op != EXEC_OMP_TARGET_TEAMS
9375 : && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE
9376 : && code->op != EXEC_OMP_TARGET_TEAMS_LOOP
9377 : && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD
9378 : && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO
9379 : && code->op != EXEC_OMP_TARGET_PARALLEL
9380 : && code->op != EXEC_OMP_TARGET_PARALLEL_DO
9381 : && code->op != EXEC_OMP_TARGET_PARALLEL_LOOP
9382 : && code->op != EXEC_OMP_TARGET_PARALLEL_DO_SIMD
9383 : && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD)
9384 7 : gfc_error ("Symbol %qs present on both data and map clauses "
9385 : "at %L", n->sym->name, &n->where);
9386 :
9387 34053 : for (n = omp_clauses->lists[OMP_LIST_FIRSTPRIVATE]; n; n = n->next)
9388 : {
9389 1855 : if (n->sym->data_mark || n->sym->gen_mark || n->sym->dev_mark)
9390 7 : gfc_error ("Symbol %qs present on multiple clauses at %L",
9391 : n->sym->name, &n->where);
9392 : else
9393 1848 : n->sym->data_mark = 1;
9394 : }
9395 34504 : for (n = omp_clauses->lists[OMP_LIST_LASTPRIVATE]; n; n = n->next)
9396 2306 : n->sym->data_mark = 0;
9397 :
9398 34504 : for (n = omp_clauses->lists[OMP_LIST_LASTPRIVATE]; n; n = n->next)
9399 : {
9400 2306 : if (n->sym->data_mark || n->sym->gen_mark || n->sym->dev_mark)
9401 0 : gfc_error ("Symbol %qs present on multiple clauses at %L",
9402 : n->sym->name, &n->where);
9403 : else
9404 2306 : n->sym->data_mark = 1;
9405 : }
9406 :
9407 32348 : for (n = omp_clauses->lists[OMP_LIST_ALIGNED]; n; n = n->next)
9408 150 : n->sym->mark = 0;
9409 :
9410 32348 : for (n = omp_clauses->lists[OMP_LIST_ALIGNED]; n; n = n->next)
9411 : {
9412 150 : if (n->sym->mark)
9413 0 : gfc_error ("Symbol %qs present on multiple clauses at %L",
9414 : n->sym->name, &n->where);
9415 : else
9416 150 : n->sym->mark = 1;
9417 : }
9418 :
9419 32198 : if (omp_clauses->lists[OMP_LIST_ALLOCATE])
9420 : {
9421 791 : for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; n = n->next)
9422 : {
9423 513 : if (n->u2.allocator
9424 513 : && (!gfc_resolve_expr (n->u2.allocator)
9425 288 : || n->u2.allocator->ts.type != BT_INTEGER
9426 286 : || n->u2.allocator->rank != 0
9427 285 : || n->u2.allocator->ts.kind != gfc_c_intptr_kind))
9428 : {
9429 8 : gfc_error ("Expected integer expression of the "
9430 : "%<omp_allocator_handle_kind%> kind at %L",
9431 8 : &n->u2.allocator->where);
9432 28 : break;
9433 : }
9434 505 : if (!n->u.align)
9435 397 : continue;
9436 108 : HOST_WIDE_INT alignment = 0;
9437 108 : if (!gfc_resolve_expr (n->u.align)
9438 108 : || n->u.align->ts.type != BT_INTEGER
9439 105 : || n->u.align->rank != 0
9440 102 : || n->u.align->expr_type != EXPR_CONSTANT
9441 99 : || gfc_extract_hwi (n->u.align, &alignment)
9442 99 : || alignment <= 0
9443 207 : || !pow2p_hwi (alignment))
9444 : {
9445 12 : gfc_error ("ALIGN requires a scalar positive constant integer "
9446 : "alignment expression at %L that is a power of two",
9447 12 : &n->u.align->where);
9448 12 : break;
9449 : }
9450 : }
9451 :
9452 : /* Check for 2 things here.
9453 : 1. There is no duplication of variable in allocate clause.
9454 : 2. Variable in allocate clause are also present in some
9455 : privatization clase (non-composite case). */
9456 811 : for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; n = n->next)
9457 513 : if (n->sym)
9458 487 : n->sym->mark = 0;
9459 :
9460 : gfc_omp_namelist *prev = NULL;
9461 811 : for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; )
9462 : {
9463 513 : if (n->sym == NULL)
9464 : {
9465 26 : n = n->next;
9466 26 : continue;
9467 : }
9468 487 : if (n->sym->mark == 1)
9469 : {
9470 3 : gfc_warning (OPT_Wopenmp, "%qs appears more than once in "
9471 : "%<allocate%> at %L" , n->sym->name, &n->where);
9472 : /* We have already seen this variable so it is a duplicate.
9473 : Remove it. */
9474 3 : if (prev != NULL && prev->next == n)
9475 : {
9476 3 : prev->next = n->next;
9477 3 : n->next = NULL;
9478 3 : gfc_free_omp_namelist (n, OMP_LIST_ALLOCATE);
9479 3 : n = prev->next;
9480 : }
9481 3 : continue;
9482 : }
9483 484 : n->sym->mark = 1;
9484 484 : prev = n;
9485 484 : n = n->next;
9486 : }
9487 :
9488 : /* Non-composite constructs. */
9489 298 : if (code && code->op < EXEC_OMP_DO_SIMD)
9490 : {
9491 4760 : for (list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
9492 4641 : list = gfc_omp_list_type (list + 1))
9493 4641 : switch (list)
9494 : {
9495 1071 : case OMP_LIST_PRIVATE:
9496 1071 : case OMP_LIST_FIRSTPRIVATE:
9497 1071 : case OMP_LIST_LASTPRIVATE:
9498 1071 : case OMP_LIST_REDUCTION:
9499 1071 : case OMP_LIST_REDUCTION_INSCAN:
9500 1071 : case OMP_LIST_REDUCTION_TASK:
9501 1071 : case OMP_LIST_IN_REDUCTION:
9502 1071 : case OMP_LIST_TASK_REDUCTION:
9503 1071 : case OMP_LIST_LINEAR:
9504 1370 : for (n = omp_clauses->lists[list]; n; n = n->next)
9505 299 : n->sym->mark = 0;
9506 : break;
9507 : default:
9508 : break;
9509 : }
9510 :
9511 410 : for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; n = n->next)
9512 291 : if (n->sym->mark == 1)
9513 4 : gfc_error ("%qs specified in %<allocate%> clause at %L but not "
9514 : "in an explicit privatization clause",
9515 : n->sym->name, &n->where);
9516 : }
9517 : if (code
9518 298 : && (code->op == EXEC_OMP_ALLOCATORS || code->op == EXEC_OMP_ALLOCATE)
9519 73 : && code->block
9520 72 : && code->block->next
9521 71 : && code->block->next->op == EXEC_ALLOCATE)
9522 : {
9523 68 : if (code->op == EXEC_OMP_ALLOCATE)
9524 49 : gfc_warning (OPT_Wdeprecated_openmp,
9525 : "The use of one or more %<allocate%> directives with "
9526 : "an associated %<allocate%> statement at %L is "
9527 : "deprecated since OpenMP 5.2, use an %<allocators%> "
9528 : "directive", &code->loc);
9529 68 : gfc_alloc *a;
9530 68 : gfc_omp_namelist *n_null = NULL;
9531 68 : bool missing_allocator = false;
9532 68 : gfc_symbol *missing_allocator_sym = NULL;
9533 161 : for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; n = n->next)
9534 : {
9535 93 : if (n->u2.allocator == NULL)
9536 : {
9537 77 : if (!missing_allocator_sym)
9538 59 : missing_allocator_sym = n->sym;
9539 : missing_allocator = true;
9540 : }
9541 93 : if (n->sym == NULL)
9542 : {
9543 26 : n_null = n;
9544 26 : continue;
9545 : }
9546 67 : if (n->sym->attr.codimension)
9547 2 : gfc_error ("Unexpected coarray %qs in %<allocate%> at %L",
9548 : n->sym->name, &n->where);
9549 103 : for (a = code->block->next->ext.alloc.list; a; a = a->next)
9550 101 : if (a->expr->expr_type == EXPR_VARIABLE
9551 101 : && a->expr->symtree->n.sym == n->sym)
9552 : {
9553 65 : gfc_ref *ref;
9554 82 : for (ref = a->expr->ref; ref; ref = ref->next)
9555 17 : if (ref->type == REF_COMPONENT)
9556 : break;
9557 : if (ref == NULL)
9558 : break;
9559 : }
9560 67 : if (a == NULL)
9561 2 : gfc_error ("%qs specified in %<allocate%> at %L but not "
9562 : "in the associated ALLOCATE statement",
9563 2 : n->sym->name, &n->where);
9564 : }
9565 : /* If there is an ALLOCATE directive without list argument, a
9566 : namelist with its allocator/align clauses and n->sym = NULL is
9567 : created during parsing; here, we add all not otherwise specified
9568 : items from the Fortran allocate to that list.
9569 : For an ALLOCATORS directive, not listed items use the normal
9570 : Fortran way.
9571 : The behavior of an ALLOCATE directive that does not list all
9572 : arguments but there is no directive without list argument is not
9573 : well specified. Thus, we reject such code below. In OpenMP 5.2
9574 : the executable ALLOCATE directive is deprecated and in 6.0
9575 : deleted such that no spec clarification is to be expected. */
9576 125 : for (a = code->block->next->ext.alloc.list; a; a = a->next)
9577 89 : if (a->expr->expr_type == EXPR_VARIABLE)
9578 : {
9579 154 : for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; n = n->next)
9580 122 : if (a->expr->symtree->n.sym == n->sym)
9581 : {
9582 57 : gfc_ref *ref;
9583 72 : for (ref = a->expr->ref; ref; ref = ref->next)
9584 15 : if (ref->type == REF_COMPONENT)
9585 : break;
9586 : if (ref == NULL)
9587 : break;
9588 : }
9589 89 : if (n == NULL && n_null == NULL)
9590 : {
9591 : /* OK for ALLOCATORS but for ALLOCATE: Unspecified whether
9592 : that should use the default allocator of OpenMP or the
9593 : Fortran allocator. Thus, just reject it. */
9594 7 : if (code->op == EXEC_OMP_ALLOCATE)
9595 1 : gfc_error ("%qs listed in %<allocate%> statement at %L "
9596 : "but it is neither explicitly in listed in "
9597 : "the %<!$OMP ALLOCATE%> directive nor exists"
9598 : " a directive without argument list",
9599 1 : a->expr->symtree->n.sym->name,
9600 : &a->expr->where);
9601 : break;
9602 : }
9603 82 : if (n == NULL)
9604 : {
9605 25 : if (a->expr->symtree->n.sym->attr.codimension)
9606 1 : gfc_error ("Unexpected coarray %qs in %<allocate%> at "
9607 : "%L, implicitly listed in %<!$OMP ALLOCATE%>"
9608 : " at %L", a->expr->symtree->n.sym->name,
9609 : &a->expr->where, &n_null->where);
9610 : break;
9611 : }
9612 : }
9613 68 : gfc_namespace *prog_unit = ns;
9614 87 : while (prog_unit->parent)
9615 : prog_unit = prog_unit->parent;
9616 : gfc_namespace *fn_ns = ns;
9617 72 : while (fn_ns)
9618 : {
9619 70 : if (ns->proc_name
9620 70 : && (ns->proc_name->attr.subroutine
9621 6 : || ns->proc_name->attr.function))
9622 : break;
9623 4 : fn_ns = fn_ns->parent;
9624 : }
9625 68 : if (missing_allocator
9626 58 : && !(prog_unit->omp_requires & OMP_REQ_DYNAMIC_ALLOCATORS)
9627 58 : && ((fn_ns && fn_ns->proc_name->attr.omp_declare_target)
9628 55 : || omp_clauses->contained_in_target_construct))
9629 : {
9630 6 : if (code->op == EXEC_OMP_ALLOCATORS)
9631 2 : gfc_error ("ALLOCATORS directive at %L inside a target region "
9632 : "must specify an ALLOCATOR modifier for %qs",
9633 : &code->loc, missing_allocator_sym->name);
9634 4 : else if (missing_allocator_sym)
9635 2 : gfc_error ("ALLOCATE directive at %L inside a target region "
9636 : "must specify an ALLOCATOR clause for %qs",
9637 : &code->loc, missing_allocator_sym->name);
9638 : else
9639 2 : gfc_error ("ALLOCATE directive at %L inside a target region "
9640 : "must specify an ALLOCATOR clause", &code->loc);
9641 : }
9642 :
9643 : }
9644 : }
9645 :
9646 : /* OpenACC reductions. */
9647 32198 : if (openacc)
9648 : {
9649 14761 : for (n = omp_clauses->lists[OMP_LIST_REDUCTION]; n; n = n->next)
9650 2136 : n->sym->mark = 0;
9651 :
9652 14761 : for (n = omp_clauses->lists[OMP_LIST_REDUCTION]; n; n = n->next)
9653 : {
9654 2136 : if (n->sym->mark)
9655 0 : gfc_error ("Symbol %qs present on multiple clauses at %L",
9656 : n->sym->name, &n->where);
9657 : else
9658 2136 : n->sym->mark = 1;
9659 :
9660 : /* OpenACC does not support reductions on arrays. */
9661 2136 : if (n->sym->as)
9662 71 : gfc_error ("Array %qs is not permitted in reduction at %L",
9663 : n->sym->name, &n->where);
9664 : }
9665 : }
9666 :
9667 32952 : for (n = omp_clauses->lists[OMP_LIST_TO]; n; n = n->next)
9668 754 : n->sym->mark = 0;
9669 33229 : for (n = omp_clauses->lists[OMP_LIST_FROM]; n; n = n->next)
9670 1031 : if (n->expr == NULL)
9671 1015 : n->sym->mark = 1;
9672 32952 : for (n = omp_clauses->lists[OMP_LIST_TO]; n; n = n->next)
9673 : {
9674 754 : if (n->expr == NULL && n->sym->mark)
9675 0 : gfc_error ("Symbol %qs present on both FROM and TO clauses at %L",
9676 : n->sym->name, &n->where);
9677 : else
9678 754 : n->sym->mark = 1;
9679 : }
9680 :
9681 : bool has_inscan = false, has_notinscan = false;
9682 1287920 : for (enum gfc_omp_list_type list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
9683 1255722 : list = gfc_omp_list_type (list + 1))
9684 1255722 : if ((n = omp_clauses->lists[list]) != NULL)
9685 : {
9686 28895 : const char *name = clause_names[list];
9687 :
9688 28895 : switch (list)
9689 : {
9690 : case OMP_LIST_COPYIN:
9691 267 : for (; n != NULL; n = n->next)
9692 : {
9693 170 : if (!n->sym->attr.threadprivate)
9694 0 : gfc_error ("Non-THREADPRIVATE object %qs in COPYIN clause"
9695 : " at %L", n->sym->name, &n->where);
9696 : }
9697 : break;
9698 83 : case OMP_LIST_COPYPRIVATE:
9699 83 : if (omp_clauses->nowait)
9700 6 : gfc_error ("NOWAIT clause must not be used with COPYPRIVATE "
9701 : "clause at %L", &n->where);
9702 376 : for (; n != NULL; n = n->next)
9703 : {
9704 293 : if (n->sym->as && n->sym->as->type == AS_ASSUMED_SIZE)
9705 0 : gfc_error ("Assumed size array %qs in COPYPRIVATE clause "
9706 : "at %L", n->sym->name, &n->where);
9707 293 : if (n->sym->attr.pointer && n->sym->attr.intent == INTENT_IN)
9708 1 : gfc_error ("INTENT(IN) POINTER %qs in COPYPRIVATE clause "
9709 : "at %L", n->sym->name, &n->where);
9710 : }
9711 : break;
9712 : case OMP_LIST_SHARED:
9713 2604 : for (; n != NULL; n = n->next)
9714 : {
9715 1642 : if (n->sym->attr.threadprivate)
9716 0 : gfc_error ("THREADPRIVATE object %qs in SHARED clause at "
9717 : "%L", n->sym->name, &n->where);
9718 1642 : if (n->sym->attr.cray_pointee)
9719 1 : gfc_error ("Cray pointee %qs in SHARED clause at %L",
9720 : n->sym->name, &n->where);
9721 1642 : if (n->sym->attr.associate_var)
9722 8 : gfc_error ("Associate name %qs in SHARED clause at %L",
9723 8 : n->sym->attr.select_type_temporary
9724 4 : ? n->sym->assoc->target->symtree->n.sym->name
9725 : : n->sym->name, &n->where);
9726 1642 : if (omp_clauses->detach
9727 1 : && n->sym == omp_clauses->detach->symtree->n.sym)
9728 1 : gfc_error ("DETACH event handle %qs in SHARED clause at %L",
9729 : n->sym->name, &n->where);
9730 : }
9731 : break;
9732 : case OMP_LIST_ALIGNED:
9733 256 : for (; n != NULL; n = n->next)
9734 : {
9735 150 : if (!n->sym->attr.pointer
9736 45 : && !n->sym->attr.allocatable
9737 30 : && !n->sym->attr.cray_pointer
9738 18 : && (n->sym->ts.type != BT_DERIVED
9739 18 : || (n->sym->ts.u.derived->from_intmod
9740 : != INTMOD_ISO_C_BINDING)
9741 18 : || (n->sym->ts.u.derived->intmod_sym_id
9742 : != ISOCBINDING_PTR)))
9743 0 : gfc_error ("%qs in ALIGNED clause must be POINTER, "
9744 : "ALLOCATABLE, Cray pointer or C_PTR at %L",
9745 : n->sym->name, &n->where);
9746 150 : else if (n->expr)
9747 : {
9748 147 : if (!gfc_resolve_expr (n->expr)
9749 147 : || n->expr->ts.type != BT_INTEGER
9750 146 : || n->expr->rank != 0
9751 146 : || n->expr->expr_type != EXPR_CONSTANT
9752 292 : || mpz_sgn (n->expr->value.integer) <= 0)
9753 4 : gfc_error ("%qs in ALIGNED clause at %L requires a scalar"
9754 : " positive constant integer alignment "
9755 4 : "expression", n->sym->name, &n->where);
9756 : }
9757 : }
9758 : break;
9759 : case OMP_LIST_AFFINITY:
9760 : case OMP_LIST_DEPEND:
9761 : case OMP_LIST_MAP:
9762 : case OMP_LIST_TO:
9763 : case OMP_LIST_FROM:
9764 : case OMP_LIST_CACHE:
9765 32098 : for (; n != NULL; n = n->next)
9766 : {
9767 20197 : if ((list == OMP_LIST_DEPEND || list == OMP_LIST_AFFINITY)
9768 1998 : && n->u2.ns && !n->u2.ns->resolved)
9769 : {
9770 56 : n->u2.ns->resolved = 1;
9771 56 : for (gfc_symbol *sym = n->u2.ns->omp_affinity_iterators;
9772 116 : sym; sym = sym->tlink)
9773 : {
9774 60 : gfc_constructor *c;
9775 60 : c = gfc_constructor_first (sym->value->value.constructor);
9776 60 : if (!gfc_resolve_expr (c->expr)
9777 60 : || c->expr->ts.type != BT_INTEGER
9778 118 : || c->expr->rank != 0)
9779 2 : gfc_error ("Scalar integer expression for range begin"
9780 2 : " expected at %L", &c->expr->where);
9781 60 : c = gfc_constructor_next (c);
9782 60 : if (!gfc_resolve_expr (c->expr)
9783 60 : || c->expr->ts.type != BT_INTEGER
9784 118 : || c->expr->rank != 0)
9785 2 : gfc_error ("Scalar integer expression for range end "
9786 2 : "expected at %L", &c->expr->where);
9787 60 : c = gfc_constructor_next (c);
9788 60 : if (c && (!gfc_resolve_expr (c->expr)
9789 16 : || c->expr->ts.type != BT_INTEGER
9790 14 : || c->expr->rank != 0))
9791 2 : gfc_error ("Scalar integer expression for range step "
9792 2 : "expected at %L", &c->expr->where);
9793 58 : else if (c
9794 14 : && c->expr->expr_type == EXPR_CONSTANT
9795 12 : && mpz_cmp_si (c->expr->value.integer, 0) == 0)
9796 2 : gfc_error ("Nonzero range step expected at %L",
9797 : &c->expr->where);
9798 : }
9799 : }
9800 :
9801 1998 : if (list == OMP_LIST_DEPEND)
9802 : {
9803 3196 : if (n->u.depend_doacross_op == OMP_DEPEND_SINK_FIRST
9804 : || n->u.depend_doacross_op == OMP_DOACROSS_SINK_FIRST
9805 1963 : || n->u.depend_doacross_op == OMP_DOACROSS_SINK)
9806 : {
9807 1233 : if (omp_clauses->doacross_source)
9808 : {
9809 0 : gfc_error ("Dependence-type SINK used together with"
9810 : " SOURCE on the same construct at %L",
9811 : &n->where);
9812 0 : omp_clauses->doacross_source = false;
9813 : }
9814 1233 : else if (n->expr)
9815 : {
9816 571 : if (!gfc_resolve_expr (n->expr)
9817 571 : || n->expr->ts.type != BT_INTEGER
9818 1142 : || n->expr->rank != 0)
9819 0 : gfc_error ("SINK addend not a constant integer "
9820 : "at %L", &n->where);
9821 : }
9822 1233 : if (n->sym == NULL
9823 4 : && (n->expr == NULL
9824 3 : || mpz_cmp_si (n->expr->value.integer, -1) != 0))
9825 2 : gfc_error ("omp_cur_iteration at %L requires %<-1%> "
9826 : "as logical offset", &n->where);
9827 1233 : continue;
9828 : }
9829 730 : else if (n->u.depend_doacross_op == OMP_DEPEND_DEPOBJ
9830 38 : && !n->expr
9831 22 : && (n->sym->ts.type != BT_INTEGER
9832 22 : || n->sym->ts.kind
9833 22 : != 2 * gfc_index_integer_kind
9834 22 : || n->sym->attr.dimension))
9835 0 : gfc_error ("Locator %qs at %L in DEPEND clause of depobj "
9836 : "type shall be a scalar integer of "
9837 : "OMP_DEPEND_KIND kind", n->sym->name,
9838 : &n->where);
9839 730 : else if (n->u.depend_doacross_op == OMP_DEPEND_DEPOBJ
9840 38 : && n->expr
9841 746 : && (!gfc_resolve_expr (n->expr)
9842 16 : || n->expr->ts.type != BT_INTEGER
9843 16 : || n->expr->ts.kind
9844 16 : != 2 * gfc_index_integer_kind
9845 16 : || n->expr->rank != 0))
9846 0 : gfc_error ("Locator at %L in DEPEND clause of depobj "
9847 : "type shall be a scalar integer of "
9848 0 : "OMP_DEPEND_KIND kind", &n->expr->where);
9849 : }
9850 18964 : gfc_ref *lastref = NULL, *lastslice = NULL;
9851 18964 : bool resolved = false;
9852 18964 : if (n->expr)
9853 : {
9854 6257 : lastref = n->expr->ref;
9855 6257 : resolved = gfc_resolve_expr (n->expr);
9856 :
9857 : /* Look through component refs to find last array
9858 : reference. */
9859 6257 : if (resolved)
9860 : {
9861 15894 : for (gfc_ref *ref = n->expr->ref; ref; ref = ref->next)
9862 9655 : if (ref->type == REF_COMPONENT
9863 : || ref->type == REF_SUBSTRING
9864 9655 : || ref->type == REF_INQUIRY)
9865 : lastref = ref;
9866 6473 : else if (ref->type == REF_ARRAY)
9867 : {
9868 13636 : for (int i = 0; i < ref->u.ar.dimen; i++)
9869 7163 : if (ref->u.ar.dimen_type[i] == DIMEN_RANGE)
9870 6009 : lastslice = ref;
9871 :
9872 : lastref = ref;
9873 : }
9874 :
9875 : /* The "!$acc cache" directive allows rectangular
9876 : subarrays to be specified, with some restrictions
9877 : on the form of bounds (not implemented).
9878 : Only raise an error here if we're really sure the
9879 : array isn't contiguous. An expression such as
9880 : arr(-n:n,-n:n) could be contiguous even if it looks
9881 : like it may not be. */
9882 6239 : if (code->op != EXEC_OACC_UPDATE
9883 5457 : && list != OMP_LIST_CACHE
9884 5457 : && list != OMP_LIST_DEPEND
9885 5135 : && !gfc_is_simply_contiguous (n->expr, false, true)
9886 1407 : && gfc_is_not_contiguous (n->expr)
9887 6252 : && !(lastslice
9888 13 : && (lastslice->next
9889 3 : || lastslice->type != REF_ARRAY)))
9890 3 : gfc_error ("Array is not contiguous at %L",
9891 : &n->where);
9892 : }
9893 : }
9894 18964 : if (list == OMP_LIST_MAP
9895 16313 : && (n->sym->attr.omp_groupprivate
9896 16312 : || n->sym->attr.omp_declare_target_local))
9897 2 : gfc_error ("%qs argument to MAP clause at %L must not be a "
9898 : "device-local variable, including GROUPPRIVATE",
9899 : n->sym->name, &n->where);
9900 18964 : if (openacc
9901 18964 : && list == OMP_LIST_MAP
9902 9571 : && (n->u.map.op == OMP_MAP_ATTACH
9903 9501 : || n->u.map.op == OMP_MAP_DETACH))
9904 : {
9905 117 : symbol_attribute attr;
9906 117 : if (n->expr)
9907 99 : attr = gfc_expr_attr (n->expr);
9908 : else
9909 18 : attr = n->sym->attr;
9910 117 : if (!attr.pointer && !attr.allocatable)
9911 7 : gfc_error ("%qs clause argument must be ALLOCATABLE or "
9912 : "a POINTER at %L",
9913 7 : (n->u.map.op == OMP_MAP_ATTACH) ? "attach"
9914 : : "detach", &n->where);
9915 : }
9916 18964 : if (lastref
9917 12719 : || (n->expr
9918 12 : && (!resolved || n->expr->expr_type != EXPR_VARIABLE)))
9919 : {
9920 6257 : if (!lastslice
9921 6257 : && lastref
9922 898 : && lastref->type == REF_SUBSTRING)
9923 11 : gfc_error ("Unexpected substring reference in %s clause "
9924 : "at %L", name, &n->where);
9925 6246 : else if (!lastslice
9926 : && lastref
9927 887 : && lastref->type == REF_INQUIRY)
9928 : {
9929 12 : gcc_assert (lastref->u.i == INQUIRY_RE
9930 : || lastref->u.i == INQUIRY_IM);
9931 12 : gfc_error ("Unexpected complex-parts designator "
9932 : "reference in %s clause at %L",
9933 : name, &n->where);
9934 : }
9935 6234 : else if (!resolved
9936 6216 : || n->expr->expr_type != EXPR_VARIABLE
9937 6204 : || (lastslice
9938 5347 : && (lastslice->next
9939 5331 : || lastslice->type != REF_ARRAY)))
9940 46 : gfc_error ("%qs in %s clause at %L is not a proper "
9941 46 : "array section", n->sym->name, name,
9942 : &n->where);
9943 : else if (lastslice)
9944 : {
9945 : int i;
9946 : gfc_array_ref *ar = &lastslice->u.ar;
9947 11337 : for (i = 0; i < ar->dimen; i++)
9948 6007 : if (ar->stride[i] && code->op != EXEC_OACC_UPDATE)
9949 : {
9950 1 : gfc_error ("Stride should not be specified for "
9951 : "array section in %s clause at %L",
9952 : name, &n->where);
9953 1 : break;
9954 : }
9955 6006 : else if (ar->dimen_type[i] != DIMEN_ELEMENT
9956 6006 : && ar->dimen_type[i] != DIMEN_RANGE)
9957 : {
9958 0 : gfc_error ("%qs in %s clause at %L is not a "
9959 : "proper array section",
9960 0 : n->sym->name, name, &n->where);
9961 0 : break;
9962 : }
9963 6006 : else if ((list == OMP_LIST_DEPEND
9964 : || list == OMP_LIST_AFFINITY)
9965 161 : && ar->start[i]
9966 133 : && ar->start[i]->expr_type == EXPR_CONSTANT
9967 97 : && ar->end[i]
9968 72 : && ar->end[i]->expr_type == EXPR_CONSTANT
9969 72 : && mpz_cmp (ar->start[i]->value.integer,
9970 72 : ar->end[i]->value.integer) > 0)
9971 : {
9972 0 : gfc_error ("%qs in %s clause at %L is a "
9973 : "zero size array section",
9974 0 : n->sym->name,
9975 : list == OMP_LIST_DEPEND
9976 : ? "DEPEND" : "AFFINITY", &n->where);
9977 0 : break;
9978 : }
9979 : }
9980 : }
9981 12707 : else if (openacc)
9982 : {
9983 5915 : if (list == OMP_LIST_MAP
9984 5900 : && n->u.map.op == OMP_MAP_FORCE_DEVICEPTR)
9985 65 : resolve_oacc_deviceptr_clause (n->sym, n->where, name);
9986 : else
9987 5850 : resolve_oacc_data_clauses (n->sym, n->where, name);
9988 : }
9989 6792 : else if (list != OMP_LIST_DEPEND
9990 6299 : && n->sym->as
9991 3013 : && n->sym->as->type == AS_ASSUMED_SIZE)
9992 5 : gfc_error ("Assumed size array %qs in %s clause at %L",
9993 : n->sym->name, name, &n->where);
9994 18964 : if (list == OMP_LIST_MAP && !openacc)
9995 6742 : switch (code->op)
9996 : {
9997 5618 : case EXEC_OMP_TARGET:
9998 5618 : case EXEC_OMP_TARGET_PARALLEL:
9999 5618 : case EXEC_OMP_TARGET_PARALLEL_DO:
10000 5618 : case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
10001 5618 : case EXEC_OMP_TARGET_PARALLEL_LOOP:
10002 5618 : case EXEC_OMP_TARGET_SIMD:
10003 5618 : case EXEC_OMP_TARGET_TEAMS:
10004 5618 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
10005 5618 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
10006 5618 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
10007 5618 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
10008 5618 : case EXEC_OMP_TARGET_TEAMS_LOOP:
10009 5618 : case EXEC_OMP_TARGET_DATA:
10010 5618 : switch (n->u.map.op)
10011 : {
10012 : case OMP_MAP_TO:
10013 : case OMP_MAP_ALWAYS_TO:
10014 : case OMP_MAP_PRESENT_TO:
10015 : case OMP_MAP_ALWAYS_PRESENT_TO:
10016 : case OMP_MAP_FROM:
10017 : case OMP_MAP_ALWAYS_FROM:
10018 : case OMP_MAP_PRESENT_FROM:
10019 : case OMP_MAP_ALWAYS_PRESENT_FROM:
10020 : case OMP_MAP_TOFROM:
10021 : case OMP_MAP_ALWAYS_TOFROM:
10022 : case OMP_MAP_PRESENT_TOFROM:
10023 : case OMP_MAP_ALWAYS_PRESENT_TOFROM:
10024 : case OMP_MAP_ALLOC:
10025 : case OMP_MAP_PRESENT_ALLOC:
10026 : break;
10027 2 : default:
10028 2 : gfc_error ("TARGET%s with map-type other than TO, "
10029 : "FROM, TOFROM, or ALLOC on MAP clause "
10030 : "at %L",
10031 : code->op == EXEC_OMP_TARGET_DATA
10032 : ? " DATA" : "", &n->where);
10033 2 : break;
10034 : }
10035 : break;
10036 625 : case EXEC_OMP_TARGET_ENTER_DATA:
10037 625 : switch (n->u.map.op)
10038 : {
10039 : case OMP_MAP_TO:
10040 : case OMP_MAP_ALWAYS_TO:
10041 : case OMP_MAP_PRESENT_TO:
10042 : case OMP_MAP_ALWAYS_PRESENT_TO:
10043 : case OMP_MAP_ALLOC:
10044 : case OMP_MAP_PRESENT_ALLOC:
10045 : break;
10046 176 : case OMP_MAP_TOFROM:
10047 176 : n->u.map.op = OMP_MAP_TO;
10048 176 : break;
10049 3 : case OMP_MAP_ALWAYS_TOFROM:
10050 3 : n->u.map.op = OMP_MAP_ALWAYS_TO;
10051 3 : break;
10052 2 : case OMP_MAP_PRESENT_TOFROM:
10053 2 : n->u.map.op = OMP_MAP_PRESENT_TO;
10054 2 : break;
10055 2 : case OMP_MAP_ALWAYS_PRESENT_TOFROM:
10056 2 : n->u.map.op = OMP_MAP_ALWAYS_PRESENT_TO;
10057 2 : break;
10058 2 : default:
10059 2 : gfc_error ("TARGET ENTER DATA with map-type other "
10060 : "than TO, TOFROM or ALLOC on MAP clause "
10061 : "at %L", &n->where);
10062 2 : break;
10063 : }
10064 : break;
10065 499 : case EXEC_OMP_TARGET_EXIT_DATA:
10066 499 : switch (n->u.map.op)
10067 : {
10068 : case OMP_MAP_FROM:
10069 : case OMP_MAP_ALWAYS_FROM:
10070 : case OMP_MAP_PRESENT_FROM:
10071 : case OMP_MAP_ALWAYS_PRESENT_FROM:
10072 : case OMP_MAP_RELEASE:
10073 : case OMP_MAP_DELETE:
10074 : break;
10075 132 : case OMP_MAP_TOFROM:
10076 132 : n->u.map.op = OMP_MAP_FROM;
10077 132 : break;
10078 1 : case OMP_MAP_ALWAYS_TOFROM:
10079 1 : n->u.map.op = OMP_MAP_ALWAYS_FROM;
10080 1 : break;
10081 0 : case OMP_MAP_PRESENT_TOFROM:
10082 0 : n->u.map.op = OMP_MAP_PRESENT_FROM;
10083 0 : break;
10084 0 : case OMP_MAP_ALWAYS_PRESENT_TOFROM:
10085 0 : n->u.map.op = OMP_MAP_ALWAYS_PRESENT_FROM;
10086 0 : break;
10087 2 : default:
10088 2 : gfc_error ("TARGET EXIT DATA with map-type other "
10089 : "than FROM, TOFROM, RELEASE, or DELETE on "
10090 : "MAP clause at %L", &n->where);
10091 2 : break;
10092 : }
10093 : break;
10094 : default:
10095 : break;
10096 : }
10097 : }
10098 :
10099 11901 : if (list != OMP_LIST_DEPEND)
10100 29288 : for (n = omp_clauses->lists[list]; n != NULL; n = n->next)
10101 : {
10102 18234 : n->sym->attr.referenced = 1;
10103 18234 : if (n->sym->attr.threadprivate)
10104 1 : gfc_error ("THREADPRIVATE object %qs in %s clause at %L",
10105 : n->sym->name, name, &n->where);
10106 18234 : if (n->sym->attr.cray_pointee)
10107 14 : gfc_error ("Cray pointee %qs in %s clause at %L",
10108 : n->sym->name, name, &n->where);
10109 : }
10110 : break;
10111 : case OMP_LIST_IS_DEVICE_PTR:
10112 : last = NULL;
10113 377 : for (n = omp_clauses->lists[list]; n != NULL; )
10114 : {
10115 257 : if ((n->sym->ts.type != BT_DERIVED
10116 71 : || !n->sym->ts.u.derived->ts.is_iso_c
10117 71 : || (n->sym->ts.u.derived->intmod_sym_id
10118 : != ISOCBINDING_PTR))
10119 187 : && code->op == EXEC_OMP_DISPATCH)
10120 : /* Non-TARGET (i.e. DISPATCH) requires a C_PTR. */
10121 3 : gfc_error ("List item %qs in %s clause at %L must be of "
10122 : "TYPE(C_PTR)", n->sym->name, name, &n->where);
10123 254 : else if (n->sym->ts.type != BT_DERIVED
10124 70 : || !n->sym->ts.u.derived->ts.is_iso_c
10125 70 : || (n->sym->ts.u.derived->intmod_sym_id
10126 : != ISOCBINDING_PTR))
10127 : {
10128 : /* For TARGET, non-C_PTR are deprecated and handled as
10129 : has_device_addr. */
10130 184 : gfc_warning (OPT_Wdeprecated_openmp,
10131 : "Non-C_PTR type argument at %L is deprecated, "
10132 : "use HAS_DEVICE_ADDR", &n->where);
10133 184 : gfc_omp_namelist *n2 = n;
10134 184 : n = n->next;
10135 184 : if (last)
10136 0 : last->next = n;
10137 : else
10138 184 : omp_clauses->lists[list] = n;
10139 184 : n2->next = omp_clauses->lists[OMP_LIST_HAS_DEVICE_ADDR];
10140 184 : omp_clauses->lists[OMP_LIST_HAS_DEVICE_ADDR] = n2;
10141 184 : continue;
10142 184 : }
10143 73 : last = n;
10144 73 : n = n->next;
10145 : }
10146 : break;
10147 : case OMP_LIST_HAS_DEVICE_ADDR:
10148 : case OMP_LIST_USE_DEVICE_ADDR:
10149 : break;
10150 : case OMP_LIST_USE_DEVICE_PTR:
10151 : /* Non-C_PTR are deprecated and handled as use_device_ADDR. */
10152 : last = NULL;
10153 475 : for (n = omp_clauses->lists[list]; n != NULL; )
10154 : {
10155 312 : gfc_omp_namelist *n2 = n;
10156 312 : if (n->sym->ts.type != BT_DERIVED
10157 18 : || !n->sym->ts.u.derived->ts.is_iso_c)
10158 : {
10159 294 : gfc_warning (OPT_Wdeprecated_openmp,
10160 : "Non-C_PTR type argument at %L is "
10161 : "deprecated, use USE_DEVICE_ADDR", &n->where);
10162 294 : n = n->next;
10163 294 : if (last)
10164 0 : last->next = n;
10165 : else
10166 294 : omp_clauses->lists[list] = n;
10167 294 : n2->next = omp_clauses->lists[OMP_LIST_USE_DEVICE_ADDR];
10168 294 : omp_clauses->lists[OMP_LIST_USE_DEVICE_ADDR] = n2;
10169 294 : continue;
10170 : }
10171 18 : last = n;
10172 18 : n = n->next;
10173 : }
10174 : break;
10175 48 : case OMP_LIST_USES_ALLOCATORS:
10176 48 : {
10177 48 : if (n != NULL
10178 48 : && n->u.memspace_sym
10179 14 : && (n->u.memspace_sym->attr.flavor != FL_PARAMETER
10180 13 : || n->u.memspace_sym->ts.type != BT_INTEGER
10181 13 : || n->u.memspace_sym->ts.kind != gfc_c_intptr_kind
10182 13 : || n->u.memspace_sym->attr.dimension
10183 13 : || (!startswith (n->u.memspace_sym->name, "omp_")
10184 0 : && !startswith (n->u.memspace_sym->name, "ompx_"))
10185 13 : || !endswith (n->u.memspace_sym->name, "_mem_space")))
10186 2 : gfc_error ("Memspace %qs at %L in USES_ALLOCATORS must be "
10187 : "a predefined memory space",
10188 : n->u.memspace_sym->name, &n->where);
10189 144 : for (; n != NULL; n = n->next)
10190 : {
10191 102 : if (n->sym->ts.type != BT_INTEGER
10192 102 : || n->sym->ts.kind != gfc_c_intptr_kind
10193 101 : || n->sym->attr.dimension)
10194 2 : gfc_error ("Allocator %qs at %L in USES_ALLOCATORS must "
10195 : "be a scalar integer of kind "
10196 : "%<omp_allocator_handle_kind%>", n->sym->name,
10197 : &n->where);
10198 100 : else if (n->sym->attr.flavor != FL_VARIABLE
10199 47 : && strcmp (n->sym->name, "omp_null_allocator") != 0
10200 144 : && ((!startswith (n->sym->name, "omp_")
10201 1 : && !startswith (n->sym->name, "ompx_"))
10202 43 : || !endswith (n->sym->name, "_mem_alloc")))
10203 2 : gfc_error ("Allocator %qs at %L in USES_ALLOCATORS must "
10204 : "either a variable or a predefined allocator",
10205 : n->sym->name, &n->where);
10206 98 : else if ((n->u.memspace_sym || n->u2.traits_sym)
10207 47 : && n->sym->attr.flavor != FL_VARIABLE)
10208 3 : gfc_error ("A memory space or traits array may not be "
10209 : "specified for predefined allocator %qs at %L",
10210 : n->sym->name, &n->where);
10211 102 : if (n->u2.traits_sym
10212 41 : && (n->u2.traits_sym->attr.flavor != FL_PARAMETER
10213 39 : || !n->u2.traits_sym->attr.dimension
10214 37 : || n->u2.traits_sym->as->rank != 1
10215 37 : || n->u2.traits_sym->ts.type != BT_DERIVED
10216 35 : || strcmp (n->u2.traits_sym->ts.u.derived->name,
10217 : "omp_alloctrait") != 0))
10218 : {
10219 6 : gfc_error ("Traits array %qs in USES_ALLOCATORS %L must "
10220 : "be a one-dimensional named constant array of "
10221 : "type %<omp_alloctrait%>",
10222 : n->u2.traits_sym->name, &n->where);
10223 6 : break;
10224 : }
10225 : }
10226 : break;
10227 : }
10228 : default:
10229 34670 : for (; n != NULL; n = n->next)
10230 : {
10231 20309 : if (n->sym == NULL)
10232 : {
10233 26 : gcc_assert (code->op == EXEC_OMP_ALLOCATORS
10234 : || code->op == EXEC_OMP_ALLOCATE);
10235 26 : continue;
10236 : }
10237 20283 : bool bad = false;
10238 20283 : bool is_reduction = (list == OMP_LIST_REDUCTION
10239 : || list == OMP_LIST_REDUCTION_INSCAN
10240 : || list == OMP_LIST_REDUCTION_TASK
10241 : || list == OMP_LIST_IN_REDUCTION
10242 20283 : || list == OMP_LIST_TASK_REDUCTION);
10243 20283 : if (list == OMP_LIST_REDUCTION_INSCAN)
10244 : has_inscan = true;
10245 20211 : else if (is_reduction)
10246 4734 : has_notinscan = true;
10247 20283 : if (has_inscan && has_notinscan && is_reduction)
10248 : {
10249 3 : gfc_error ("%<inscan%> and non-%<inscan%> %<reduction%> "
10250 : "clauses on the same construct at %L",
10251 : &n->where);
10252 3 : break;
10253 : }
10254 20280 : if (n->sym->attr.threadprivate)
10255 1 : gfc_error ("THREADPRIVATE object %qs in %s clause at %L",
10256 : n->sym->name, name, &n->where);
10257 20280 : if (n->sym->attr.cray_pointee)
10258 14 : gfc_error ("Cray pointee %qs in %s clause at %L",
10259 : n->sym->name, name, &n->where);
10260 20280 : if (n->sym->attr.associate_var)
10261 22 : gfc_error ("Associate name %qs in %s clause at %L",
10262 22 : n->sym->attr.select_type_temporary
10263 4 : ? n->sym->assoc->target->symtree->n.sym->name
10264 : : n->sym->name, name, &n->where);
10265 20280 : if (list != OMP_LIST_PRIVATE && is_reduction)
10266 : {
10267 4803 : if (n->sym->attr.proc_pointer)
10268 1 : gfc_error ("Procedure pointer %qs in %s clause at %L",
10269 : n->sym->name, name, &n->where);
10270 4803 : if (n->sym->attr.pointer)
10271 3 : gfc_error ("POINTER object %qs in %s clause at %L",
10272 : n->sym->name, name, &n->where);
10273 4803 : if (n->sym->attr.cray_pointer)
10274 5 : gfc_error ("Cray pointer %qs in %s clause at %L",
10275 : n->sym->name, name, &n->where);
10276 : }
10277 20280 : if (code
10278 20280 : && (oacc_is_loop (code)
10279 : || code->op == EXEC_OACC_PARALLEL
10280 : || code->op == EXEC_OACC_SERIAL))
10281 8741 : check_array_not_assumed (n->sym, n->where, name);
10282 11539 : else if (list != OMP_LIST_UNIFORM
10283 11422 : && n->sym->as && n->sym->as->type == AS_ASSUMED_SIZE)
10284 2 : gfc_error ("Assumed size array %qs in %s clause at %L",
10285 : n->sym->name, name, &n->where);
10286 20280 : if (n->sym->attr.in_namelist && !is_reduction)
10287 0 : gfc_error ("Variable %qs in %s clause is used in "
10288 : "NAMELIST statement at %L",
10289 : n->sym->name, name, &n->where);
10290 20280 : if (n->sym->attr.pointer && n->sym->attr.intent == INTENT_IN)
10291 3 : switch (list)
10292 : {
10293 3 : case OMP_LIST_PRIVATE:
10294 3 : case OMP_LIST_LASTPRIVATE:
10295 3 : case OMP_LIST_LINEAR:
10296 : /* case OMP_LIST_REDUCTION: */
10297 3 : gfc_error ("INTENT(IN) POINTER %qs in %s clause at %L",
10298 : n->sym->name, name, &n->where);
10299 3 : break;
10300 : default:
10301 : break;
10302 : }
10303 20280 : if (omp_clauses->detach
10304 3 : && (list == OMP_LIST_PRIVATE
10305 : || list == OMP_LIST_FIRSTPRIVATE
10306 : || list == OMP_LIST_LASTPRIVATE)
10307 3 : && n->sym == omp_clauses->detach->symtree->n.sym)
10308 1 : gfc_error ("DETACH event handle %qs in %s clause at %L",
10309 : n->sym->name, name, &n->where);
10310 :
10311 20280 : if (!openacc
10312 20280 : && (list == OMP_LIST_PRIVATE
10313 20280 : || list == OMP_LIST_FIRSTPRIVATE)
10314 4640 : && ((n->sym->ts.type == BT_DERIVED
10315 158 : && n->sym->ts.u.derived->attr.alloc_comp)
10316 4530 : || n->sym->ts.type == BT_CLASS))
10317 170 : switch (code->op)
10318 : {
10319 8 : case EXEC_OMP_TARGET:
10320 8 : case EXEC_OMP_TARGET_PARALLEL:
10321 8 : case EXEC_OMP_TARGET_PARALLEL_DO:
10322 8 : case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
10323 8 : case EXEC_OMP_TARGET_PARALLEL_LOOP:
10324 8 : case EXEC_OMP_TARGET_SIMD:
10325 8 : case EXEC_OMP_TARGET_TEAMS:
10326 8 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
10327 8 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
10328 8 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
10329 8 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
10330 8 : case EXEC_OMP_TARGET_TEAMS_LOOP:
10331 8 : if (n->sym->ts.type == BT_DERIVED
10332 2 : && n->sym->ts.u.derived->attr.alloc_comp)
10333 3 : gfc_error ("Sorry, list item %qs at %L with allocatable"
10334 : " components is not yet supported in %s "
10335 : "clause", n->sym->name, &n->where,
10336 : list == OMP_LIST_PRIVATE ? "PRIVATE"
10337 : : "FIRSTPRIVATE");
10338 : else
10339 9 : gfc_error ("Polymorphic list item %qs at %L in %s "
10340 : "clause has unspecified behavior and "
10341 : "unsupported", n->sym->name, &n->where,
10342 : list == OMP_LIST_PRIVATE ? "PRIVATE"
10343 : : "FIRSTPRIVATE");
10344 : break;
10345 : default:
10346 : break;
10347 : }
10348 :
10349 20280 : switch (list)
10350 : {
10351 104 : case OMP_LIST_REDUCTION_TASK:
10352 104 : if (code
10353 104 : && (code->op == EXEC_OMP_LOOP
10354 : || code->op == EXEC_OMP_TASKLOOP
10355 : || code->op == EXEC_OMP_TASKLOOP_SIMD
10356 : || code->op == EXEC_OMP_MASKED_TASKLOOP
10357 : || code->op == EXEC_OMP_MASKED_TASKLOOP_SIMD
10358 : || code->op == EXEC_OMP_MASTER_TASKLOOP
10359 : || code->op == EXEC_OMP_MASTER_TASKLOOP_SIMD
10360 : || code->op == EXEC_OMP_PARALLEL_LOOP
10361 : || code->op == EXEC_OMP_PARALLEL_MASKED_TASKLOOP
10362 : || code->op == EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD
10363 : || code->op == EXEC_OMP_PARALLEL_MASTER_TASKLOOP
10364 : || code->op == EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD
10365 : || code->op == EXEC_OMP_TARGET_PARALLEL_LOOP
10366 : || code->op == EXEC_OMP_TARGET_TEAMS_LOOP
10367 : || code->op == EXEC_OMP_TEAMS
10368 : || code->op == EXEC_OMP_TEAMS_DISTRIBUTE
10369 : || code->op == EXEC_OMP_TEAMS_LOOP))
10370 : {
10371 17 : gfc_error ("Only DEFAULT permitted as reduction-"
10372 : "modifier in REDUCTION clause at %L",
10373 : &n->where);
10374 17 : break;
10375 : }
10376 4786 : gcc_fallthrough ();
10377 4786 : case OMP_LIST_REDUCTION:
10378 4786 : case OMP_LIST_IN_REDUCTION:
10379 4786 : case OMP_LIST_TASK_REDUCTION:
10380 4786 : case OMP_LIST_REDUCTION_INSCAN:
10381 4786 : switch (n->u.reduction_op)
10382 : {
10383 2652 : case OMP_REDUCTION_PLUS:
10384 2652 : case OMP_REDUCTION_TIMES:
10385 2652 : case OMP_REDUCTION_MINUS:
10386 2652 : if (!gfc_numeric_ts (&n->sym->ts))
10387 : bad = true;
10388 : break;
10389 1112 : case OMP_REDUCTION_AND:
10390 1112 : case OMP_REDUCTION_OR:
10391 1112 : case OMP_REDUCTION_EQV:
10392 1112 : case OMP_REDUCTION_NEQV:
10393 1112 : if (n->sym->ts.type != BT_LOGICAL)
10394 : bad = true;
10395 : break;
10396 480 : case OMP_REDUCTION_MAX:
10397 480 : case OMP_REDUCTION_MIN:
10398 480 : if (n->sym->ts.type != BT_INTEGER
10399 212 : && n->sym->ts.type != BT_REAL)
10400 : bad = true;
10401 : break;
10402 192 : case OMP_REDUCTION_IAND:
10403 192 : case OMP_REDUCTION_IOR:
10404 192 : case OMP_REDUCTION_IEOR:
10405 192 : if (n->sym->ts.type != BT_INTEGER)
10406 : bad = true;
10407 : break;
10408 : case OMP_REDUCTION_USER:
10409 : bad = true;
10410 : break;
10411 : default:
10412 : break;
10413 : }
10414 : if (!bad)
10415 4215 : n->u2.udr = NULL;
10416 : else
10417 : {
10418 571 : const char *udr_name = NULL;
10419 571 : if (n->u2.udr)
10420 : {
10421 467 : udr_name = n->u2.udr->udr->name;
10422 467 : n->u2.udr->udr
10423 934 : = gfc_find_omp_udr (NULL, udr_name,
10424 467 : &n->sym->ts);
10425 467 : if (n->u2.udr->udr == NULL)
10426 : {
10427 0 : free (n->u2.udr);
10428 0 : n->u2.udr = NULL;
10429 : }
10430 : }
10431 571 : if (n->u2.udr == NULL)
10432 : {
10433 104 : if (udr_name == NULL)
10434 104 : switch (n->u.reduction_op)
10435 : {
10436 50 : case OMP_REDUCTION_PLUS:
10437 50 : case OMP_REDUCTION_TIMES:
10438 50 : case OMP_REDUCTION_MINUS:
10439 50 : case OMP_REDUCTION_AND:
10440 50 : case OMP_REDUCTION_OR:
10441 50 : case OMP_REDUCTION_EQV:
10442 50 : case OMP_REDUCTION_NEQV:
10443 50 : udr_name = gfc_op2string ((gfc_intrinsic_op)
10444 : n->u.reduction_op);
10445 50 : break;
10446 : case OMP_REDUCTION_MAX:
10447 : udr_name = "max";
10448 : break;
10449 9 : case OMP_REDUCTION_MIN:
10450 9 : udr_name = "min";
10451 9 : break;
10452 12 : case OMP_REDUCTION_IAND:
10453 12 : udr_name = "iand";
10454 12 : break;
10455 12 : case OMP_REDUCTION_IOR:
10456 12 : udr_name = "ior";
10457 12 : break;
10458 9 : case OMP_REDUCTION_IEOR:
10459 9 : udr_name = "ieor";
10460 9 : break;
10461 0 : default:
10462 0 : gcc_unreachable ();
10463 : }
10464 104 : gfc_error ("!$OMP DECLARE REDUCTION %s not found "
10465 : "for type %s at %L", udr_name,
10466 104 : gfc_typename (&n->sym->ts), &n->where);
10467 : }
10468 : else
10469 : {
10470 467 : gfc_omp_udr *udr = n->u2.udr->udr;
10471 467 : n->u.reduction_op = OMP_REDUCTION_USER;
10472 467 : n->u2.udr->combiner
10473 934 : = resolve_omp_udr_clause (n, udr->combiner_ns,
10474 467 : udr->omp_out,
10475 467 : udr->omp_in);
10476 467 : if (udr->initializer_ns)
10477 330 : n->u2.udr->initializer
10478 330 : = resolve_omp_udr_clause (n,
10479 : udr->initializer_ns,
10480 330 : udr->omp_priv,
10481 330 : udr->omp_orig);
10482 : }
10483 : }
10484 : break;
10485 874 : case OMP_LIST_LINEAR:
10486 874 : if (code)
10487 : {
10488 727 : bool is_worksharing_for = false;
10489 727 : switch (code->op)
10490 : {
10491 54 : case EXEC_OMP_DO:
10492 54 : case EXEC_OMP_PARALLEL_DO:
10493 54 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
10494 54 : case EXEC_OMP_TARGET_PARALLEL_DO:
10495 54 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
10496 54 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
10497 54 : is_worksharing_for = true;
10498 54 : break;
10499 : default:
10500 : break;
10501 : }
10502 :
10503 54 : if (is_worksharing_for
10504 54 : && (n->sym->attr.dimension
10505 53 : || n->sym->attr.allocatable))
10506 : {
10507 1 : if (n->sym->attr.allocatable)
10508 0 : gfc_error ("Sorry, ALLOCATABLE object %qs in "
10509 : "LINEAR clause on worksharing-loop "
10510 : "construct at %L is not yet supported",
10511 : n->sym->name, &n->where);
10512 : else
10513 1 : gfc_error ("Sorry, array %qs in LINEAR clause "
10514 : "on worksharing-loop construct at %L "
10515 : "is not yet supported",
10516 : n->sym->name, &n->where);
10517 : break;
10518 : }
10519 : }
10520 :
10521 726 : if (code
10522 726 : && n->u.linear.op != OMP_LINEAR_DEFAULT
10523 23 : && n->u.linear.op != linear_op)
10524 : {
10525 23 : if (n->u.linear.old_modifier)
10526 : {
10527 9 : gfc_error ("LINEAR clause modifier used on DO or "
10528 : "SIMD construct at %L", &n->where);
10529 9 : linear_op = n->u.linear.op;
10530 : }
10531 14 : else if (n->u.linear.op != OMP_LINEAR_VAL)
10532 : {
10533 6 : gfc_error ("LINEAR clause modifier other than VAL "
10534 : "used on DO or SIMD construct at %L",
10535 : &n->where);
10536 6 : linear_op = n->u.linear.op;
10537 : }
10538 : }
10539 850 : else if (n->u.linear.op != OMP_LINEAR_REF
10540 800 : && n->sym->ts.type != BT_INTEGER)
10541 1 : gfc_error ("LINEAR variable %qs must be INTEGER "
10542 : "at %L", n->sym->name, &n->where);
10543 849 : else if ((n->u.linear.op == OMP_LINEAR_REF
10544 799 : || n->u.linear.op == OMP_LINEAR_UVAL)
10545 61 : && n->sym->attr.value)
10546 0 : gfc_error ("LINEAR dummy argument %qs with VALUE "
10547 : "attribute with %s modifier at %L",
10548 : n->sym->name,
10549 : n->u.linear.op == OMP_LINEAR_REF
10550 : ? "REF" : "UVAL", &n->where);
10551 849 : else if (n->expr)
10552 : {
10553 830 : gfc_expr *expr = n->expr;
10554 830 : if (!gfc_resolve_expr (expr)
10555 830 : || expr->ts.type != BT_INTEGER
10556 1660 : || expr->rank != 0)
10557 0 : gfc_error ("%qs in LINEAR clause at %L requires "
10558 : "a scalar integer linear-step expression",
10559 0 : n->sym->name, &n->where);
10560 830 : else if (!code && expr->expr_type != EXPR_CONSTANT)
10561 : {
10562 11 : if (expr->expr_type == EXPR_VARIABLE
10563 7 : && expr->symtree->n.sym->attr.dummy
10564 6 : && expr->symtree->n.sym->ns == ns)
10565 : {
10566 6 : gfc_omp_namelist *n2;
10567 6 : for (n2 = omp_clauses->lists[OMP_LIST_UNIFORM];
10568 6 : n2; n2 = n2->next)
10569 6 : if (n2->sym == expr->symtree->n.sym)
10570 : break;
10571 6 : if (n2)
10572 : break;
10573 : }
10574 5 : gfc_error ("%qs in LINEAR clause at %L requires "
10575 : "a constant integer linear-step "
10576 : "expression or dummy argument "
10577 : "specified in UNIFORM clause",
10578 5 : n->sym->name, &n->where);
10579 : }
10580 : }
10581 : break;
10582 : /* Workaround for PR middle-end/26316, nothing really needs
10583 : to be done here for OMP_LIST_PRIVATE. */
10584 9390 : case OMP_LIST_PRIVATE:
10585 9390 : gcc_assert (code && code->op != EXEC_NOP);
10586 : break;
10587 98 : case OMP_LIST_USE_DEVICE:
10588 98 : if (n->sym->attr.allocatable
10589 98 : || (n->sym->ts.type == BT_CLASS && CLASS_DATA (n->sym)
10590 0 : && CLASS_DATA (n->sym)->attr.allocatable))
10591 0 : gfc_error ("ALLOCATABLE object %qs in %s clause at %L",
10592 : n->sym->name, name, &n->where);
10593 98 : if (n->sym->ts.type == BT_CLASS
10594 0 : && CLASS_DATA (n->sym)
10595 0 : && CLASS_DATA (n->sym)->attr.class_pointer)
10596 0 : gfc_error ("POINTER object %qs of polymorphic type in "
10597 : "%s clause at %L", n->sym->name, name,
10598 : &n->where);
10599 98 : if (n->sym->attr.cray_pointer)
10600 2 : gfc_error ("Cray pointer object %qs in %s clause at %L",
10601 : n->sym->name, name, &n->where);
10602 96 : else if (n->sym->attr.cray_pointee)
10603 2 : gfc_error ("Cray pointee object %qs in %s clause at %L",
10604 : n->sym->name, name, &n->where);
10605 94 : else if (n->sym->attr.flavor == FL_VARIABLE
10606 93 : && !n->sym->as
10607 54 : && !n->sym->attr.pointer)
10608 13 : gfc_error ("%s clause variable %qs at %L is neither "
10609 : "a POINTER nor an array", name,
10610 : n->sym->name, &n->where);
10611 : /* FALLTHRU */
10612 98 : case OMP_LIST_DEVICE_RESIDENT:
10613 98 : check_symbol_not_pointer (n->sym, n->where, name);
10614 98 : check_array_not_assumed (n->sym, n->where, name);
10615 98 : break;
10616 : default:
10617 : break;
10618 : }
10619 : }
10620 : break;
10621 : }
10622 : }
10623 : /* OpenMP 5.1: use_device_ptr acts like use_device_addr, except for
10624 : type(c_ptr). */
10625 32198 : if (omp_clauses->lists[OMP_LIST_USE_DEVICE_PTR])
10626 : {
10627 9 : gfc_omp_namelist *n_prev, *n_next, *n_addr;
10628 9 : n_addr = omp_clauses->lists[OMP_LIST_USE_DEVICE_ADDR];
10629 28 : for (; n_addr && n_addr->next; n_addr = n_addr->next)
10630 : ;
10631 : n_prev = NULL;
10632 : n = omp_clauses->lists[OMP_LIST_USE_DEVICE_PTR];
10633 27 : while (n)
10634 : {
10635 18 : n_next = n->next;
10636 18 : if (n->sym->ts.type != BT_DERIVED
10637 18 : || n->sym->ts.u.derived->ts.f90_type != BT_VOID)
10638 : {
10639 0 : n->next = NULL;
10640 0 : if (n_addr)
10641 0 : n_addr->next = n;
10642 : else
10643 0 : omp_clauses->lists[OMP_LIST_USE_DEVICE_ADDR] = n;
10644 0 : n_addr = n;
10645 0 : if (n_prev)
10646 0 : n_prev->next = n_next;
10647 : else
10648 0 : omp_clauses->lists[OMP_LIST_USE_DEVICE_PTR] = n_next;
10649 : }
10650 : else
10651 : n_prev = n;
10652 : n = n_next;
10653 : }
10654 : }
10655 32198 : if (omp_clauses->safelen_expr)
10656 93 : resolve_positive_int_expr (omp_clauses->safelen_expr, "SAFELEN");
10657 32198 : if (omp_clauses->simdlen_expr)
10658 123 : resolve_positive_int_expr (omp_clauses->simdlen_expr, "SIMDLEN");
10659 32198 : if (omp_clauses->num_teams_lower)
10660 21 : resolve_positive_int_expr (omp_clauses->num_teams_lower, "NUM_TEAMS");
10661 32198 : if (omp_clauses->num_teams_upper)
10662 127 : resolve_positive_int_expr (omp_clauses->num_teams_upper, "NUM_TEAMS");
10663 32198 : if (omp_clauses->num_teams_lower
10664 21 : && omp_clauses->num_teams_lower->expr_type == EXPR_CONSTANT
10665 7 : && omp_clauses->num_teams_upper->expr_type == EXPR_CONSTANT
10666 7 : && mpz_cmp (omp_clauses->num_teams_lower->value.integer,
10667 7 : omp_clauses->num_teams_upper->value.integer) > 0)
10668 2 : gfc_warning (OPT_Wopenmp, "NUM_TEAMS lower bound at %L larger than upper "
10669 : "bound at %L", &omp_clauses->num_teams_lower->where,
10670 : &omp_clauses->num_teams_upper->where);
10671 32198 : if (omp_clauses->device)
10672 331 : resolve_scalar_int_expr (omp_clauses->device, "DEVICE");
10673 32198 : if (omp_clauses->filter)
10674 42 : resolve_nonnegative_int_expr (omp_clauses->filter, "FILTER");
10675 32198 : if (omp_clauses->hint)
10676 : {
10677 42 : resolve_scalar_int_expr (omp_clauses->hint, "HINT");
10678 42 : if (omp_clauses->hint->ts.type != BT_INTEGER
10679 40 : || omp_clauses->hint->expr_type != EXPR_CONSTANT
10680 38 : || mpz_sgn (omp_clauses->hint->value.integer) < 0)
10681 5 : gfc_error ("Value of HINT clause at %L shall be a valid "
10682 : "constant hint expression", &omp_clauses->hint->where);
10683 : }
10684 32198 : if (omp_clauses->priority)
10685 34 : resolve_nonnegative_int_expr (omp_clauses->priority, "PRIORITY");
10686 32198 : if (omp_clauses->dist_chunk_size)
10687 : {
10688 83 : gfc_expr *expr = omp_clauses->dist_chunk_size;
10689 83 : if (!gfc_resolve_expr (expr)
10690 83 : || expr->ts.type != BT_INTEGER || expr->rank != 0)
10691 0 : gfc_error ("DIST_SCHEDULE clause's chunk_size at %L requires "
10692 : "a scalar INTEGER expression", &expr->where);
10693 : }
10694 32198 : if (omp_clauses->thread_limit)
10695 72 : resolve_positive_int_expr (omp_clauses->thread_limit, "THREAD_LIMIT");
10696 32198 : if (omp_clauses->grainsize)
10697 34 : resolve_positive_int_expr (omp_clauses->grainsize, "GRAINSIZE");
10698 32198 : if (omp_clauses->num_tasks)
10699 26 : resolve_positive_int_expr (omp_clauses->num_tasks, "NUM_TASKS");
10700 32198 : if (omp_clauses->grainsize && omp_clauses->num_tasks)
10701 1 : gfc_error ("%<GRAINSIZE%> clause at %L must not be used together with "
10702 : "%<NUM_TASKS%> clause", &omp_clauses->grainsize->where);
10703 32198 : if (omp_clauses->lists[OMP_LIST_REDUCTION] && omp_clauses->nogroup)
10704 1 : gfc_error ("%<REDUCTION%> clause at %L must not be used together with "
10705 : "%<NOGROUP%> clause",
10706 : &omp_clauses->lists[OMP_LIST_REDUCTION]->where);
10707 32198 : if (omp_clauses->full && omp_clauses->partial)
10708 0 : gfc_error ("%<FULL%> clause at %C must not be used together with "
10709 : "%<PARTIAL%> clause");
10710 32198 : if (omp_clauses->async)
10711 610 : if (omp_clauses->async_expr)
10712 610 : resolve_scalar_int_expr (omp_clauses->async_expr, "ASYNC");
10713 32198 : if (omp_clauses->num_gangs_expr)
10714 682 : resolve_positive_int_expr (omp_clauses->num_gangs_expr, "NUM_GANGS");
10715 32198 : if (omp_clauses->num_workers_expr)
10716 599 : resolve_positive_int_expr (omp_clauses->num_workers_expr, "NUM_WORKERS");
10717 32198 : if (omp_clauses->vector_length_expr)
10718 569 : resolve_positive_int_expr (omp_clauses->vector_length_expr,
10719 : "VECTOR_LENGTH");
10720 32198 : if (omp_clauses->gang_num_expr)
10721 114 : resolve_positive_int_expr (omp_clauses->gang_num_expr, "GANG");
10722 32198 : if (omp_clauses->gang_static_expr)
10723 94 : resolve_positive_int_expr (omp_clauses->gang_static_expr, "GANG");
10724 32198 : if (omp_clauses->worker_expr)
10725 101 : resolve_positive_int_expr (omp_clauses->worker_expr, "WORKER");
10726 32198 : if (omp_clauses->vector_expr)
10727 132 : resolve_positive_int_expr (omp_clauses->vector_expr, "VECTOR");
10728 32537 : for (el = omp_clauses->wait_list; el; el = el->next)
10729 339 : resolve_scalar_int_expr (el->expr, "WAIT");
10730 32198 : if (omp_clauses->collapse && omp_clauses->tile_list)
10731 4 : gfc_error ("Incompatible use of TILE and COLLAPSE at %L", &code->loc);
10732 32198 : if (omp_clauses->message)
10733 : {
10734 45 : gfc_expr *expr = omp_clauses->message;
10735 45 : if (!gfc_resolve_expr (expr)
10736 45 : || expr->ts.kind != gfc_default_character_kind
10737 87 : || expr->ts.type != BT_CHARACTER || expr->rank != 0)
10738 4 : gfc_error ("MESSAGE clause at %L requires a scalar default-kind "
10739 : "CHARACTER expression", &expr->where);
10740 : }
10741 32198 : if (!openacc
10742 32198 : && code
10743 19355 : && omp_clauses->lists[OMP_LIST_MAP] == NULL
10744 15884 : && omp_clauses->lists[OMP_LIST_USE_DEVICE_PTR] == NULL
10745 15881 : && omp_clauses->lists[OMP_LIST_USE_DEVICE_ADDR] == NULL)
10746 : {
10747 15858 : const char *p = NULL;
10748 15858 : switch (code->op)
10749 : {
10750 1 : case EXEC_OMP_TARGET_ENTER_DATA: p = "TARGET ENTER DATA"; break;
10751 1 : case EXEC_OMP_TARGET_EXIT_DATA: p = "TARGET EXIT DATA"; break;
10752 : default: break;
10753 : }
10754 15858 : if (code->op == EXEC_OMP_TARGET_DATA)
10755 1 : gfc_error ("TARGET DATA must contain at least one MAP, USE_DEVICE_PTR, "
10756 : "or USE_DEVICE_ADDR clause at %L", &code->loc);
10757 15857 : else if (p)
10758 2 : gfc_error ("%s must contain at least one MAP clause at %L",
10759 : p, &code->loc);
10760 : }
10761 32198 : if (omp_clauses->sizes_list)
10762 : {
10763 : gfc_expr_list *el;
10764 572 : for (el = omp_clauses->sizes_list; el; el = el->next)
10765 : {
10766 377 : resolve_scalar_int_expr (el->expr, "SIZES");
10767 377 : if (el->expr->expr_type != EXPR_CONSTANT)
10768 1 : gfc_error ("SIZES requires constant expression at %L",
10769 : &el->expr->where);
10770 376 : else if (el->expr->expr_type == EXPR_CONSTANT
10771 376 : && el->expr->ts.type == BT_INTEGER
10772 376 : && mpz_sgn (el->expr->value.integer) <= 0)
10773 2 : gfc_error ("INTEGER expression of %s clause at %L must be "
10774 : "positive", "SIZES", &el->expr->where);
10775 : }
10776 : }
10777 :
10778 32198 : if (!openacc && omp_clauses->detach)
10779 : {
10780 125 : if (!gfc_resolve_expr (omp_clauses->detach)
10781 125 : || omp_clauses->detach->ts.type != BT_INTEGER
10782 124 : || omp_clauses->detach->ts.kind != gfc_c_intptr_kind
10783 248 : || omp_clauses->detach->rank != 0)
10784 3 : gfc_error ("%qs at %L should be a scalar of type "
10785 : "integer(kind=omp_event_handle_kind)",
10786 3 : omp_clauses->detach->symtree->n.sym->name,
10787 3 : &omp_clauses->detach->where);
10788 122 : else if (omp_clauses->detach->symtree->n.sym->attr.dimension > 0)
10789 1 : gfc_error ("The event handle at %L must not be an array element",
10790 : &omp_clauses->detach->where);
10791 121 : else if (omp_clauses->detach->symtree->n.sym->ts.type == BT_DERIVED
10792 120 : || omp_clauses->detach->symtree->n.sym->ts.type == BT_CLASS)
10793 1 : gfc_error ("The event handle at %L must not be part of "
10794 : "a derived type or class", &omp_clauses->detach->where);
10795 :
10796 125 : if (omp_clauses->mergeable)
10797 2 : gfc_error ("%<DETACH%> clause at %L must not be used together with "
10798 2 : "%<MERGEABLE%> clause", &omp_clauses->detach->where);
10799 : }
10800 :
10801 12625 : if (openacc
10802 12625 : && code->op == EXEC_OACC_HOST_DATA
10803 60 : && omp_clauses->lists[OMP_LIST_USE_DEVICE] == NULL)
10804 1 : gfc_error ("%<host_data%> construct at %L requires %<use_device%> clause",
10805 : &code->loc);
10806 :
10807 32198 : if (omp_clauses->assume)
10808 16 : gfc_resolve_omp_assumptions (omp_clauses->assume);
10809 : }
10810 :
10811 :
10812 : /* Return true if SYM is ever referenced in EXPR except in the SE node. */
10813 :
10814 : static bool
10815 4991 : expr_references_sym (gfc_expr *e, gfc_symbol *s, gfc_expr *se)
10816 : {
10817 6617 : gfc_actual_arglist *arg;
10818 6617 : if (e == NULL || e == se)
10819 : return false;
10820 5366 : switch (e->expr_type)
10821 : {
10822 3120 : case EXPR_CONSTANT:
10823 3120 : case EXPR_NULL:
10824 3120 : case EXPR_VARIABLE:
10825 3120 : case EXPR_STRUCTURE:
10826 3120 : case EXPR_ARRAY:
10827 3120 : if (e->symtree != NULL
10828 1152 : && e->symtree->n.sym == s)
10829 : return true;
10830 : return false;
10831 0 : case EXPR_SUBSTRING:
10832 0 : if (e->ref != NULL
10833 0 : && (expr_references_sym (e->ref->u.ss.start, s, se)
10834 0 : || expr_references_sym (e->ref->u.ss.end, s, se)))
10835 0 : return true;
10836 : return false;
10837 1735 : case EXPR_OP:
10838 1735 : if (expr_references_sym (e->value.op.op2, s, se))
10839 : return true;
10840 1626 : return expr_references_sym (e->value.op.op1, s, se);
10841 511 : case EXPR_FUNCTION:
10842 896 : for (arg = e->value.function.actual; arg; arg = arg->next)
10843 586 : if (expr_references_sym (arg->expr, s, se))
10844 : return true;
10845 : return false;
10846 0 : default:
10847 0 : gcc_unreachable ();
10848 : }
10849 : }
10850 :
10851 :
10852 : /* If EXPR is a conversion function that widens the type
10853 : if WIDENING is true or narrows the type if NARROW is true,
10854 : return the inner expression, otherwise return NULL. */
10855 :
10856 : static gfc_expr *
10857 5911 : is_conversion (gfc_expr *expr, bool narrowing, bool widening)
10858 : {
10859 5911 : gfc_typespec *ts1, *ts2;
10860 :
10861 5911 : if (expr->expr_type != EXPR_FUNCTION
10862 917 : || expr->value.function.isym == NULL
10863 894 : || expr->value.function.esym != NULL
10864 894 : || expr->value.function.isym->id != GFC_ISYM_CONVERSION
10865 388 : || (!narrowing && !widening))
10866 : return NULL;
10867 :
10868 388 : if (narrowing && widening)
10869 267 : return expr->value.function.actual->expr;
10870 :
10871 121 : if (widening)
10872 : {
10873 121 : ts1 = &expr->ts;
10874 121 : ts2 = &expr->value.function.actual->expr->ts;
10875 : }
10876 : else
10877 : {
10878 0 : ts1 = &expr->value.function.actual->expr->ts;
10879 0 : ts2 = &expr->ts;
10880 : }
10881 :
10882 121 : if (ts1->type > ts2->type
10883 49 : || (ts1->type == ts2->type && ts1->kind > ts2->kind))
10884 121 : return expr->value.function.actual->expr;
10885 :
10886 : return NULL;
10887 : }
10888 :
10889 : static bool
10890 6855 : is_scalar_intrinsic_expr (gfc_expr *expr, bool must_be_var, bool conv_ok)
10891 : {
10892 6855 : if (must_be_var
10893 4020 : && (expr->expr_type != EXPR_VARIABLE || !expr->symtree))
10894 : {
10895 37 : if (!conv_ok)
10896 : return false;
10897 37 : gfc_expr *conv = is_conversion (expr, true, true);
10898 37 : if (!conv)
10899 : return false;
10900 36 : if (conv->expr_type != EXPR_VARIABLE || !conv->symtree)
10901 : return false;
10902 : }
10903 6852 : return (expr->rank == 0
10904 6848 : && !gfc_is_coindexed (expr)
10905 13700 : && (expr->ts.type == BT_INTEGER
10906 : || expr->ts.type == BT_REAL
10907 : || expr->ts.type == BT_COMPLEX
10908 : || expr->ts.type == BT_LOGICAL));
10909 : }
10910 :
10911 : static void
10912 2697 : resolve_omp_atomic (gfc_code *code)
10913 : {
10914 2697 : gfc_code *atomic_code = code->block;
10915 2697 : gfc_symbol *var;
10916 2697 : gfc_expr *stmt_expr2, *capt_expr2;
10917 2697 : gfc_omp_atomic_op aop
10918 2697 : = (gfc_omp_atomic_op) (atomic_code->ext.omp_clauses->atomic_op
10919 : & GFC_OMP_ATOMIC_MASK);
10920 2697 : gfc_code *stmt = NULL, *capture_stmt = NULL, *tailing_stmt = NULL;
10921 2697 : gfc_expr *comp_cond = NULL;
10922 2697 : locus *loc = NULL;
10923 :
10924 2697 : code = code->block->next;
10925 : /* resolve_blocks asserts this is initially EXEC_ASSIGN or EXEC_IF
10926 : If it changed to EXEC_NOP, assume an error has been emitted already. */
10927 2697 : if (code->op == EXEC_NOP)
10928 : return;
10929 :
10930 2696 : if (atomic_code->ext.omp_clauses->compare
10931 156 : && atomic_code->ext.omp_clauses->capture)
10932 : {
10933 : /* Must be either "if (x == e) then; x = d; else; v = x; end if"
10934 : or "v = expr" followed/preceded by
10935 : "if (x == e) then; x = d; end if" or "if (x == e) x = d". */
10936 103 : gfc_code *next = code;
10937 103 : if (code->op == EXEC_ASSIGN)
10938 : {
10939 19 : capture_stmt = code;
10940 19 : next = code->next;
10941 : }
10942 103 : if (next->op == EXEC_IF
10943 103 : && next->block
10944 103 : && next->block->op == EXEC_IF
10945 103 : && next->block->next
10946 102 : && next->block->next->op == EXEC_ASSIGN)
10947 : {
10948 102 : comp_cond = next->block->expr1;
10949 102 : stmt = next->block->next;
10950 102 : if (stmt->next)
10951 : {
10952 0 : loc = &stmt->loc;
10953 0 : goto unexpected;
10954 : }
10955 : }
10956 1 : else if (capture_stmt)
10957 : {
10958 0 : gfc_error ("Expected IF at %L in atomic compare capture",
10959 : &next->loc);
10960 0 : return;
10961 : }
10962 103 : if (stmt && !capture_stmt && next->block->block)
10963 : {
10964 64 : if (next->block->block->expr1)
10965 : {
10966 0 : gfc_error ("Expected ELSE at %L in atomic compare capture",
10967 : &next->block->block->expr1->where);
10968 0 : return;
10969 : }
10970 64 : if (!code->block->block->next
10971 64 : || code->block->block->next->op != EXEC_ASSIGN)
10972 : {
10973 0 : loc = (code->block->block->next ? &code->block->block->next->loc
10974 : : &code->block->block->loc);
10975 0 : goto unexpected;
10976 : }
10977 64 : capture_stmt = code->block->block->next;
10978 64 : if (capture_stmt->next)
10979 : {
10980 0 : loc = &capture_stmt->next->loc;
10981 0 : goto unexpected;
10982 : }
10983 : }
10984 103 : if (stmt && !capture_stmt && next->next->op == EXEC_ASSIGN)
10985 : capture_stmt = next->next;
10986 84 : else if (!capture_stmt)
10987 : {
10988 1 : loc = &code->loc;
10989 1 : goto unexpected;
10990 : }
10991 : }
10992 2593 : else if (atomic_code->ext.omp_clauses->compare)
10993 : {
10994 : /* Must be: "if (x == e) then; x = d; end if" or "if (x == e) x = d". */
10995 53 : if (code->op == EXEC_IF
10996 53 : && code->block
10997 53 : && code->block->op == EXEC_IF
10998 53 : && code->block->next
10999 51 : && code->block->next->op == EXEC_ASSIGN)
11000 : {
11001 51 : comp_cond = code->block->expr1;
11002 51 : stmt = code->block->next;
11003 51 : if (stmt->next || code->block->block)
11004 : {
11005 0 : loc = stmt->next ? &stmt->next->loc : &code->block->block->loc;
11006 0 : goto unexpected;
11007 : }
11008 : }
11009 : else
11010 : {
11011 2 : loc = &code->loc;
11012 2 : goto unexpected;
11013 : }
11014 : }
11015 2540 : else if (atomic_code->ext.omp_clauses->capture)
11016 : {
11017 : /* Must be: "v = x" followed/preceded by "x = ...". */
11018 489 : if (code->op != EXEC_ASSIGN)
11019 0 : goto unexpected;
11020 489 : if (code->next->op != EXEC_ASSIGN)
11021 : {
11022 0 : loc = &code->next->loc;
11023 0 : goto unexpected;
11024 : }
11025 489 : gfc_expr *expr2, *expr2_next;
11026 489 : expr2 = is_conversion (code->expr2, true, true);
11027 489 : if (expr2 == NULL)
11028 447 : expr2 = code->expr2;
11029 489 : expr2_next = is_conversion (code->next->expr2, true, true);
11030 489 : if (expr2_next == NULL)
11031 478 : expr2_next = code->next->expr2;
11032 489 : if (code->expr1->expr_type == EXPR_VARIABLE
11033 489 : && code->next->expr1->expr_type == EXPR_VARIABLE
11034 489 : && expr2->expr_type == EXPR_VARIABLE
11035 243 : && expr2_next->expr_type == EXPR_VARIABLE)
11036 : {
11037 1 : if (code->expr1->symtree->n.sym == expr2_next->symtree->n.sym)
11038 : {
11039 : stmt = code;
11040 : capture_stmt = code->next;
11041 : }
11042 : else
11043 : {
11044 489 : capture_stmt = code;
11045 489 : stmt = code->next;
11046 : }
11047 : }
11048 488 : else if (expr2->expr_type == EXPR_VARIABLE)
11049 : {
11050 : capture_stmt = code;
11051 : stmt = code->next;
11052 : }
11053 : else
11054 : {
11055 247 : stmt = code;
11056 247 : capture_stmt = code->next;
11057 : }
11058 : /* Shall be NULL but can happen for invalid code. */
11059 489 : tailing_stmt = code->next->next;
11060 : }
11061 : else
11062 : {
11063 : /* x = ... */
11064 2051 : stmt = code;
11065 2051 : if (!atomic_code->ext.omp_clauses->compare && stmt->op != EXEC_ASSIGN)
11066 1 : goto unexpected;
11067 : /* Shall be NULL but can happen for invalid code. */
11068 2050 : tailing_stmt = code->next;
11069 : }
11070 :
11071 2692 : if (comp_cond)
11072 : {
11073 153 : if (comp_cond->expr_type != EXPR_OP
11074 153 : || (comp_cond->value.op.op != INTRINSIC_EQ
11075 : && comp_cond->value.op.op != INTRINSIC_EQ_OS
11076 : && comp_cond->value.op.op != INTRINSIC_EQV))
11077 : {
11078 0 : gfc_error ("Expected %<==%>, %<.EQ.%> or %<.EQV.%> atomic comparison "
11079 : "expression at %L", &comp_cond->where);
11080 0 : return;
11081 : }
11082 153 : if (!is_scalar_intrinsic_expr (comp_cond->value.op.op1, true, true))
11083 : {
11084 1 : gfc_error ("Expected scalar intrinsic variable at %L in atomic "
11085 1 : "comparison", &comp_cond->value.op.op1->where);
11086 1 : return;
11087 : }
11088 152 : if (!gfc_resolve_expr (comp_cond->value.op.op2))
11089 : return;
11090 152 : if (!is_scalar_intrinsic_expr (comp_cond->value.op.op2, false, false))
11091 : {
11092 0 : gfc_error ("Expected scalar intrinsic expression at %L in atomic "
11093 0 : "comparison", &comp_cond->value.op.op1->where);
11094 0 : return;
11095 : }
11096 : }
11097 :
11098 2691 : if (!is_scalar_intrinsic_expr (stmt->expr1, true, false))
11099 : {
11100 4 : gfc_error ("!$OMP ATOMIC statement must set a scalar variable of "
11101 4 : "intrinsic type at %L", &stmt->expr1->where);
11102 4 : return;
11103 : }
11104 :
11105 2687 : if (!gfc_resolve_expr (stmt->expr2))
11106 : return;
11107 2683 : if (!is_scalar_intrinsic_expr (stmt->expr2, false, false))
11108 : {
11109 0 : gfc_error ("!$OMP ATOMIC statement must assign an expression of "
11110 0 : "intrinsic type at %L", &stmt->expr2->where);
11111 0 : return;
11112 : }
11113 :
11114 2683 : if (gfc_expr_attr (stmt->expr1).allocatable)
11115 : {
11116 0 : gfc_error ("!$OMP ATOMIC with ALLOCATABLE variable at %L",
11117 0 : &stmt->expr1->where);
11118 0 : return;
11119 : }
11120 :
11121 : /* Should be diagnosed above already. */
11122 2683 : gcc_assert (tailing_stmt == NULL);
11123 :
11124 2683 : var = stmt->expr1->symtree->n.sym;
11125 2683 : stmt_expr2 = is_conversion (stmt->expr2, true, true);
11126 2683 : if (stmt_expr2 == NULL)
11127 2527 : stmt_expr2 = stmt->expr2;
11128 :
11129 2683 : switch (aop)
11130 : {
11131 503 : case GFC_OMP_ATOMIC_READ:
11132 503 : if (stmt_expr2->expr_type != EXPR_VARIABLE)
11133 0 : gfc_error ("!$OMP ATOMIC READ statement must read from a scalar "
11134 : "variable of intrinsic type at %L", &stmt_expr2->where);
11135 : return;
11136 421 : case GFC_OMP_ATOMIC_WRITE:
11137 421 : if (expr_references_sym (stmt_expr2, var, NULL))
11138 0 : gfc_error ("expr in !$OMP ATOMIC WRITE assignment var = expr "
11139 : "must be scalar and cannot reference var at %L",
11140 : &stmt_expr2->where);
11141 : return;
11142 1759 : default:
11143 1759 : break;
11144 : }
11145 :
11146 1759 : if (atomic_code->ext.omp_clauses->capture)
11147 : {
11148 588 : if (!is_scalar_intrinsic_expr (capture_stmt->expr1, true, false))
11149 : {
11150 0 : gfc_error ("!$OMP ATOMIC capture-statement must set a scalar "
11151 : "variable of intrinsic type at %L",
11152 0 : &capture_stmt->expr1->where);
11153 0 : return;
11154 : }
11155 :
11156 588 : if (!is_scalar_intrinsic_expr (capture_stmt->expr2, true, true))
11157 : {
11158 2 : gfc_error ("!$OMP ATOMIC capture-statement requires a scalar variable"
11159 2 : " of intrinsic type at %L", &capture_stmt->expr2->where);
11160 2 : return;
11161 : }
11162 586 : capt_expr2 = is_conversion (capture_stmt->expr2, true, true);
11163 586 : if (capt_expr2 == NULL)
11164 564 : capt_expr2 = capture_stmt->expr2;
11165 :
11166 586 : if (capt_expr2->symtree->n.sym != var)
11167 : {
11168 1 : gfc_error ("!$OMP ATOMIC CAPTURE capture statement reads from "
11169 : "different variable than update statement writes "
11170 : "into at %L", &capture_stmt->expr2->where);
11171 1 : return;
11172 : }
11173 : }
11174 :
11175 1756 : if (atomic_code->ext.omp_clauses->compare)
11176 : {
11177 149 : gfc_expr *var_expr;
11178 149 : if (comp_cond->value.op.op1->expr_type == EXPR_VARIABLE)
11179 : var_expr = comp_cond->value.op.op1;
11180 : else
11181 12 : var_expr = comp_cond->value.op.op1->value.function.actual->expr;
11182 149 : if (var_expr->symtree->n.sym != var)
11183 : {
11184 2 : gfc_error ("For !$OMP ATOMIC COMPARE, the first operand in comparison"
11185 : " at %L must be the variable %qs that the update statement"
11186 : " writes into at %L", &var_expr->where, var->name,
11187 2 : &stmt->expr1->where);
11188 2 : return;
11189 : }
11190 147 : if (stmt_expr2->rank != 0 || expr_references_sym (stmt_expr2, var, NULL))
11191 : {
11192 1 : gfc_error ("expr in !$OMP ATOMIC COMPARE assignment var = expr "
11193 : "must be scalar and cannot reference var at %L",
11194 : &stmt_expr2->where);
11195 1 : return;
11196 : }
11197 : }
11198 1607 : else if (atomic_code->ext.omp_clauses->capture
11199 1607 : && !expr_references_sym (stmt_expr2, var, NULL))
11200 22 : atomic_code->ext.omp_clauses->atomic_op
11201 22 : = (gfc_omp_atomic_op) (atomic_code->ext.omp_clauses->atomic_op
11202 : | GFC_OMP_ATOMIC_SWAP);
11203 1585 : else if (stmt_expr2->expr_type == EXPR_OP)
11204 : {
11205 1229 : gfc_expr *v = NULL, *e, *c;
11206 1229 : gfc_intrinsic_op op = stmt_expr2->value.op.op;
11207 1229 : gfc_intrinsic_op alt_op = INTRINSIC_NONE;
11208 :
11209 1229 : if (atomic_code->ext.omp_clauses->fail != OMP_MEMORDER_UNSET)
11210 3 : gfc_error ("!$OMP ATOMIC UPDATE at %L with FAIL clause requires either"
11211 : " the COMPARE clause or using the intrinsic MIN/MAX "
11212 : "procedure", &atomic_code->loc);
11213 1229 : switch (op)
11214 : {
11215 742 : case INTRINSIC_PLUS:
11216 742 : alt_op = INTRINSIC_MINUS;
11217 742 : break;
11218 94 : case INTRINSIC_TIMES:
11219 94 : alt_op = INTRINSIC_DIVIDE;
11220 94 : break;
11221 120 : case INTRINSIC_MINUS:
11222 120 : alt_op = INTRINSIC_PLUS;
11223 120 : break;
11224 94 : case INTRINSIC_DIVIDE:
11225 94 : alt_op = INTRINSIC_TIMES;
11226 94 : break;
11227 : case INTRINSIC_AND:
11228 : case INTRINSIC_OR:
11229 : break;
11230 43 : case INTRINSIC_EQV:
11231 43 : alt_op = INTRINSIC_NEQV;
11232 43 : break;
11233 43 : case INTRINSIC_NEQV:
11234 43 : alt_op = INTRINSIC_EQV;
11235 43 : break;
11236 1 : default:
11237 1 : gfc_error ("!$OMP ATOMIC assignment operator must be binary "
11238 : "+, *, -, /, .AND., .OR., .EQV. or .NEQV. at %L",
11239 : &stmt_expr2->where);
11240 1 : return;
11241 : }
11242 :
11243 : /* Check for var = var op expr resp. var = expr op var where
11244 : expr doesn't reference var and var op expr is mathematically
11245 : equivalent to var op (expr) resp. expr op var equivalent to
11246 : (expr) op var. We rely here on the fact that the matcher
11247 : for x op1 y op2 z where op1 and op2 have equal precedence
11248 : returns (x op1 y) op2 z. */
11249 1228 : e = stmt_expr2->value.op.op2;
11250 1228 : if (e->expr_type == EXPR_VARIABLE
11251 288 : && e->symtree != NULL
11252 288 : && e->symtree->n.sym == var)
11253 : v = e;
11254 999 : else if ((c = is_conversion (e, false, true)) != NULL
11255 48 : && c->expr_type == EXPR_VARIABLE
11256 48 : && c->symtree != NULL
11257 1047 : && c->symtree->n.sym == var)
11258 : v = c;
11259 : else
11260 : {
11261 951 : gfc_expr **p = NULL, **q;
11262 1049 : for (q = &stmt_expr2->value.op.op1; (e = *q) != NULL; )
11263 1049 : if (e->expr_type == EXPR_VARIABLE
11264 948 : && e->symtree != NULL
11265 948 : && e->symtree->n.sym == var)
11266 : {
11267 : v = e;
11268 : break;
11269 : }
11270 101 : else if ((c = is_conversion (e, false, true)) != NULL)
11271 60 : q = &e->value.function.actual->expr;
11272 41 : else if (e->expr_type != EXPR_OP
11273 41 : || (e->value.op.op != op
11274 15 : && e->value.op.op != alt_op)
11275 38 : || e->rank != 0)
11276 : break;
11277 : else
11278 : {
11279 38 : p = q;
11280 38 : q = &e->value.op.op1;
11281 : }
11282 :
11283 951 : if (v == NULL)
11284 : {
11285 3 : gfc_error ("!$OMP ATOMIC assignment must be var = var op expr "
11286 : "or var = expr op var at %L", &stmt_expr2->where);
11287 3 : return;
11288 : }
11289 :
11290 948 : if (p != NULL)
11291 : {
11292 38 : e = *p;
11293 38 : switch (e->value.op.op)
11294 : {
11295 8 : case INTRINSIC_MINUS:
11296 8 : case INTRINSIC_DIVIDE:
11297 8 : case INTRINSIC_EQV:
11298 8 : case INTRINSIC_NEQV:
11299 8 : gfc_error ("!$OMP ATOMIC var = var op expr not "
11300 : "mathematically equivalent to var = var op "
11301 : "(expr) at %L", &stmt_expr2->where);
11302 8 : break;
11303 : default:
11304 : break;
11305 : }
11306 :
11307 : /* Canonicalize into var = var op (expr). */
11308 38 : *p = e->value.op.op2;
11309 38 : e->value.op.op2 = stmt_expr2;
11310 38 : e->ts = stmt_expr2->ts;
11311 38 : if (stmt->expr2 == stmt_expr2)
11312 26 : stmt->expr2 = stmt_expr2 = e;
11313 : else
11314 12 : stmt->expr2->value.function.actual->expr = stmt_expr2 = e;
11315 :
11316 38 : if (!gfc_compare_types (&stmt_expr2->value.op.op1->ts,
11317 : &stmt_expr2->ts))
11318 : {
11319 24 : for (p = &stmt_expr2->value.op.op1; *p != v;
11320 12 : p = &(*p)->value.function.actual->expr)
11321 : ;
11322 12 : *p = NULL;
11323 12 : gfc_free_expr (stmt_expr2->value.op.op1);
11324 12 : stmt_expr2->value.op.op1 = v;
11325 12 : gfc_convert_type (v, &stmt_expr2->ts, 2);
11326 : }
11327 : }
11328 : }
11329 :
11330 1225 : if (e->rank != 0 || expr_references_sym (stmt->expr2, var, v))
11331 : {
11332 1 : gfc_error ("expr in !$OMP ATOMIC assignment var = var op expr "
11333 : "must be scalar and cannot reference var at %L",
11334 : &stmt_expr2->where);
11335 1 : return;
11336 : }
11337 : }
11338 356 : else if (stmt_expr2->expr_type == EXPR_FUNCTION
11339 355 : && stmt_expr2->value.function.isym != NULL
11340 355 : && stmt_expr2->value.function.esym == NULL
11341 355 : && stmt_expr2->value.function.actual != NULL
11342 355 : && stmt_expr2->value.function.actual->next != NULL)
11343 : {
11344 355 : gfc_actual_arglist *arg, *var_arg;
11345 :
11346 355 : switch (stmt_expr2->value.function.isym->id)
11347 : {
11348 : case GFC_ISYM_MIN:
11349 : case GFC_ISYM_MAX:
11350 : break;
11351 147 : case GFC_ISYM_IAND:
11352 147 : case GFC_ISYM_IOR:
11353 147 : case GFC_ISYM_IEOR:
11354 147 : if (stmt_expr2->value.function.actual->next->next != NULL)
11355 : {
11356 0 : gfc_error ("!$OMP ATOMIC assignment intrinsic IAND, IOR "
11357 : "or IEOR must have two arguments at %L",
11358 : &stmt_expr2->where);
11359 0 : return;
11360 : }
11361 : break;
11362 1 : default:
11363 1 : gfc_error ("!$OMP ATOMIC assignment intrinsic must be "
11364 : "MIN, MAX, IAND, IOR or IEOR at %L",
11365 : &stmt_expr2->where);
11366 1 : return;
11367 : }
11368 :
11369 : var_arg = NULL;
11370 1088 : for (arg = stmt_expr2->value.function.actual; arg; arg = arg->next)
11371 : {
11372 741 : gfc_expr *e = NULL;
11373 741 : if (arg == stmt_expr2->value.function.actual
11374 387 : || (var_arg == NULL && arg->next == NULL))
11375 : {
11376 527 : e = is_conversion (arg->expr, false, true);
11377 527 : if (!e)
11378 514 : e = arg->expr;
11379 527 : if (e->expr_type == EXPR_VARIABLE
11380 453 : && e->symtree != NULL
11381 453 : && e->symtree->n.sym == var)
11382 741 : var_arg = arg;
11383 : }
11384 741 : if ((!var_arg || !e) && expr_references_sym (arg->expr, var, NULL))
11385 : {
11386 7 : gfc_error ("!$OMP ATOMIC intrinsic arguments except one must "
11387 : "not reference %qs at %L",
11388 : var->name, &arg->expr->where);
11389 7 : return;
11390 : }
11391 734 : if (arg->expr->rank != 0)
11392 : {
11393 0 : gfc_error ("!$OMP ATOMIC intrinsic arguments must be scalar "
11394 : "at %L", &arg->expr->where);
11395 0 : return;
11396 : }
11397 : }
11398 :
11399 347 : if (var_arg == NULL)
11400 : {
11401 1 : gfc_error ("First or last !$OMP ATOMIC intrinsic argument must "
11402 : "be %qs at %L", var->name, &stmt_expr2->where);
11403 1 : return;
11404 : }
11405 :
11406 346 : if (var_arg != stmt_expr2->value.function.actual)
11407 : {
11408 : /* Canonicalize, so that var comes first. */
11409 172 : gcc_assert (var_arg->next == NULL);
11410 : for (arg = stmt_expr2->value.function.actual;
11411 185 : arg->next != var_arg; arg = arg->next)
11412 : ;
11413 172 : var_arg->next = stmt_expr2->value.function.actual;
11414 172 : stmt_expr2->value.function.actual = var_arg;
11415 172 : arg->next = NULL;
11416 : }
11417 : }
11418 : else
11419 1 : gfc_error ("!$OMP ATOMIC assignment must have an operator or "
11420 : "intrinsic on right hand side at %L", &stmt_expr2->where);
11421 : return;
11422 :
11423 4 : unexpected:
11424 4 : gfc_error ("unexpected !$OMP ATOMIC expression at %L",
11425 : loc ? loc : &code->loc);
11426 4 : return;
11427 : }
11428 :
11429 :
11430 : static struct fortran_omp_context
11431 : {
11432 : gfc_code *code;
11433 : hash_set<gfc_symbol *> *sharing_clauses;
11434 : hash_set<gfc_symbol *> *private_iterators;
11435 : struct fortran_omp_context *previous;
11436 : bool is_openmp;
11437 : } *omp_current_ctx;
11438 : static gfc_code *omp_current_do_code;
11439 : static int omp_current_do_collapse;
11440 :
11441 : /* Forward declaration for mutually recursive functions. */
11442 : static gfc_code *
11443 : find_nested_loop_in_block (gfc_code *block);
11444 :
11445 : /* Return the first nested DO loop in CHAIN, or NULL if there
11446 : isn't one. Does no error checking on intervening code. */
11447 :
11448 : static gfc_code *
11449 27482 : find_nested_loop_in_chain (gfc_code *chain)
11450 : {
11451 27482 : gfc_code *code;
11452 :
11453 27482 : if (!chain)
11454 : return NULL;
11455 :
11456 31643 : for (code = chain; code; code = code->next)
11457 31222 : switch (code->op)
11458 : {
11459 : case EXEC_DO:
11460 : case EXEC_OMP_TILE:
11461 : case EXEC_OMP_UNROLL:
11462 : return code;
11463 621 : case EXEC_BLOCK:
11464 621 : if (gfc_code *c = find_nested_loop_in_block (code))
11465 : return c;
11466 : break;
11467 : default:
11468 : break;
11469 : }
11470 : return NULL;
11471 : }
11472 :
11473 : /* Return the first nested DO loop in BLOCK, or NULL if there
11474 : isn't one. Does no error checking on intervening code. */
11475 : static gfc_code *
11476 939 : find_nested_loop_in_block (gfc_code *block)
11477 : {
11478 939 : gfc_namespace *ns;
11479 939 : gcc_assert (block->op == EXEC_BLOCK);
11480 939 : ns = block->ext.block.ns;
11481 939 : gcc_assert (ns);
11482 939 : return find_nested_loop_in_chain (ns->code);
11483 : }
11484 :
11485 : void
11486 5420 : gfc_resolve_omp_do_blocks (gfc_code *code, gfc_namespace *ns)
11487 : {
11488 5420 : if (code->block->next && code->block->next->op == EXEC_DO)
11489 : {
11490 5067 : int i;
11491 :
11492 5067 : omp_current_do_code = code->block->next;
11493 5067 : if (code->ext.omp_clauses->orderedc)
11494 142 : omp_current_do_collapse = code->ext.omp_clauses->orderedc;
11495 4925 : else if (code->ext.omp_clauses->collapse)
11496 1121 : omp_current_do_collapse = code->ext.omp_clauses->collapse;
11497 3804 : else if (code->ext.omp_clauses->sizes_list)
11498 175 : omp_current_do_collapse
11499 175 : = gfc_expr_list_len (code->ext.omp_clauses->sizes_list);
11500 : else
11501 3629 : omp_current_do_collapse = 1;
11502 5067 : if (code->ext.omp_clauses->lists[OMP_LIST_REDUCTION_INSCAN])
11503 : {
11504 : /* Checking that there is a matching EXEC_OMP_SCAN in the
11505 : innermost body cannot be deferred to resolve_omp_do because
11506 : we process directives nested in the loop before we get
11507 : there. */
11508 60 : locus *loc
11509 : = &code->ext.omp_clauses->lists[OMP_LIST_REDUCTION_INSCAN]->where;
11510 60 : gfc_code *c;
11511 :
11512 80 : for (i = 1, c = omp_current_do_code;
11513 80 : i < omp_current_do_collapse; i++)
11514 : {
11515 22 : c = find_nested_loop_in_chain (c->block->next);
11516 22 : if (!c || c->op != EXEC_DO || c->block == NULL)
11517 : break;
11518 : }
11519 :
11520 : /* Skip this if we don't have enough nested loops. That
11521 : problem will be diagnosed elsewhere. */
11522 60 : if (c && c->op == EXEC_DO)
11523 : {
11524 58 : gfc_code *block = c->block ? c->block->next : NULL;
11525 58 : if (block && block->op != EXEC_OMP_SCAN)
11526 54 : while (block && block->next
11527 54 : && block->next->op != EXEC_OMP_SCAN)
11528 : block = block->next;
11529 43 : if (!block
11530 46 : || (block->op != EXEC_OMP_SCAN
11531 43 : && (!block->next || block->next->op != EXEC_OMP_SCAN)))
11532 19 : gfc_error ("With INSCAN at %L, expected loop body with "
11533 : "!$OMP SCAN between two "
11534 : "structured block sequences", loc);
11535 : else
11536 : {
11537 39 : if (block->op == EXEC_OMP_SCAN)
11538 3 : gfc_warning (OPT_Wopenmp,
11539 : "!$OMP SCAN at %L with zero executable "
11540 : "statements in preceding structured block "
11541 : "sequence", &block->loc);
11542 39 : if ((block->op == EXEC_OMP_SCAN && !block->next)
11543 38 : || (block->next && block->next->op == EXEC_OMP_SCAN
11544 36 : && !block->next->next))
11545 3 : gfc_warning (OPT_Wopenmp,
11546 : "!$OMP SCAN at %L with zero executable "
11547 : "statements in succeeding structured block "
11548 : "sequence", block->op == EXEC_OMP_SCAN
11549 1 : ? &block->loc : &block->next->loc);
11550 : }
11551 58 : if (block && block->op != EXEC_OMP_SCAN)
11552 43 : block = block->next;
11553 46 : if (block && block->op == EXEC_OMP_SCAN)
11554 : /* Mark 'omp scan' as checked; flag will be unset later. */
11555 39 : block->ext.omp_clauses->if_present = true;
11556 : }
11557 : }
11558 : }
11559 5420 : gfc_resolve_blocks (code->block, ns);
11560 5420 : omp_current_do_collapse = 0;
11561 5420 : omp_current_do_code = NULL;
11562 5420 : }
11563 :
11564 :
11565 : void
11566 6031 : gfc_resolve_omp_parallel_blocks (gfc_code *code, gfc_namespace *ns)
11567 : {
11568 6031 : struct fortran_omp_context ctx;
11569 6031 : gfc_omp_clauses *omp_clauses = code->ext.omp_clauses;
11570 6031 : gfc_omp_namelist *n;
11571 :
11572 6031 : ctx.code = code;
11573 6031 : ctx.sharing_clauses = new hash_set<gfc_symbol *>;
11574 6031 : ctx.private_iterators = new hash_set<gfc_symbol *>;
11575 6031 : ctx.previous = omp_current_ctx;
11576 6031 : ctx.is_openmp = true;
11577 6031 : omp_current_ctx = &ctx;
11578 :
11579 241240 : for (enum gfc_omp_list_type list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
11580 235209 : list = gfc_omp_list_type (list + 1))
11581 235209 : switch (list)
11582 : {
11583 60310 : case OMP_LIST_SHARED:
11584 60310 : case OMP_LIST_PRIVATE:
11585 60310 : case OMP_LIST_FIRSTPRIVATE:
11586 60310 : case OMP_LIST_LASTPRIVATE:
11587 60310 : case OMP_LIST_REDUCTION:
11588 60310 : case OMP_LIST_REDUCTION_INSCAN:
11589 60310 : case OMP_LIST_REDUCTION_TASK:
11590 60310 : case OMP_LIST_IN_REDUCTION:
11591 60310 : case OMP_LIST_TASK_REDUCTION:
11592 60310 : case OMP_LIST_LINEAR:
11593 69267 : for (n = omp_clauses->lists[list]; n; n = n->next)
11594 8957 : ctx.sharing_clauses->add (n->sym);
11595 : break;
11596 : default:
11597 : break;
11598 : }
11599 :
11600 6031 : switch (code->op)
11601 : {
11602 2357 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
11603 2357 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
11604 2357 : case EXEC_OMP_MASKED_TASKLOOP:
11605 2357 : case EXEC_OMP_MASKED_TASKLOOP_SIMD:
11606 2357 : case EXEC_OMP_MASTER_TASKLOOP:
11607 2357 : case EXEC_OMP_MASTER_TASKLOOP_SIMD:
11608 2357 : case EXEC_OMP_PARALLEL_DO:
11609 2357 : case EXEC_OMP_PARALLEL_DO_SIMD:
11610 2357 : case EXEC_OMP_PARALLEL_LOOP:
11611 2357 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
11612 2357 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
11613 2357 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
11614 2357 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
11615 2357 : case EXEC_OMP_TARGET_PARALLEL_DO:
11616 2357 : case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
11617 2357 : case EXEC_OMP_TARGET_PARALLEL_LOOP:
11618 2357 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
11619 2357 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
11620 2357 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
11621 2357 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
11622 2357 : case EXEC_OMP_TARGET_TEAMS_LOOP:
11623 2357 : case EXEC_OMP_TASKLOOP:
11624 2357 : case EXEC_OMP_TASKLOOP_SIMD:
11625 2357 : case EXEC_OMP_TEAMS_DISTRIBUTE:
11626 2357 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
11627 2357 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
11628 2357 : case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
11629 2357 : case EXEC_OMP_TEAMS_LOOP:
11630 2357 : gfc_resolve_omp_do_blocks (code, ns);
11631 2357 : break;
11632 3674 : default:
11633 3674 : gfc_resolve_blocks (code->block, ns);
11634 : }
11635 :
11636 6031 : omp_current_ctx = ctx.previous;
11637 12062 : delete ctx.sharing_clauses;
11638 12062 : delete ctx.private_iterators;
11639 6031 : }
11640 :
11641 :
11642 : /* Save and clear openmp.cc private state. */
11643 :
11644 : void
11645 286164 : gfc_omp_save_and_clear_state (struct gfc_omp_saved_state *state)
11646 : {
11647 286164 : state->ptrs[0] = omp_current_ctx;
11648 286164 : state->ptrs[1] = omp_current_do_code;
11649 286164 : state->ints[0] = omp_current_do_collapse;
11650 286164 : omp_current_ctx = NULL;
11651 286164 : omp_current_do_code = NULL;
11652 286164 : omp_current_do_collapse = 0;
11653 286164 : }
11654 :
11655 :
11656 : /* Restore openmp.cc private state from the saved state. */
11657 :
11658 : void
11659 286163 : gfc_omp_restore_state (struct gfc_omp_saved_state *state)
11660 : {
11661 286163 : omp_current_ctx = (struct fortran_omp_context *) state->ptrs[0];
11662 286163 : omp_current_do_code = (gfc_code *) state->ptrs[1];
11663 286163 : omp_current_do_collapse = state->ints[0];
11664 286163 : }
11665 :
11666 :
11667 : /* Note a DO iterator variable. This is special in !$omp parallel
11668 : construct, where they are predetermined private. */
11669 :
11670 : void
11671 32821 : gfc_resolve_do_iterator (gfc_code *code, gfc_symbol *sym, bool add_clause)
11672 : {
11673 32821 : if (omp_current_ctx == NULL)
11674 : return;
11675 :
11676 13094 : int i = omp_current_do_collapse;
11677 13094 : gfc_code *c = omp_current_do_code;
11678 :
11679 13094 : if (sym->attr.threadprivate)
11680 : return;
11681 :
11682 : /* !$omp do and !$omp parallel do iteration variable is predetermined
11683 : private just in the !$omp do resp. !$omp parallel do construct,
11684 : with no implications for the outer parallel constructs. */
11685 :
11686 17929 : while (i-- >= 1 && c)
11687 : {
11688 9490 : if (code == c)
11689 : return;
11690 4835 : c = find_nested_loop_in_chain (c->block->next);
11691 4835 : if (c && (c->op == EXEC_OMP_TILE || c->op == EXEC_OMP_UNROLL))
11692 : return;
11693 : }
11694 :
11695 : /* An openacc context may represent a data clause. Abort if so. */
11696 8439 : if (!omp_current_ctx->is_openmp && !oacc_is_loop (omp_current_ctx->code))
11697 : return;
11698 :
11699 7461 : if (omp_current_ctx->sharing_clauses->contains (sym))
11700 : return;
11701 :
11702 6459 : if (! omp_current_ctx->private_iterators->add (sym) && add_clause)
11703 : {
11704 6272 : gfc_omp_clauses *omp_clauses = omp_current_ctx->code->ext.omp_clauses;
11705 6272 : gfc_omp_namelist *p;
11706 :
11707 6272 : p = gfc_get_omp_namelist ();
11708 6272 : p->sym = sym;
11709 6272 : p->where = omp_current_ctx->code->loc;
11710 6272 : p->next = omp_clauses->lists[OMP_LIST_PRIVATE];
11711 6272 : omp_clauses->lists[OMP_LIST_PRIVATE] = p;
11712 : }
11713 : }
11714 :
11715 : static void
11716 698 : handle_local_var (gfc_symbol *sym)
11717 : {
11718 698 : if (sym->attr.flavor != FL_VARIABLE
11719 178 : || sym->as != NULL
11720 137 : || (sym->ts.type != BT_INTEGER && sym->ts.type != BT_REAL))
11721 : return;
11722 71 : gfc_resolve_do_iterator (sym->ns->code, sym, false);
11723 : }
11724 :
11725 : void
11726 332159 : gfc_resolve_omp_local_vars (gfc_namespace *ns)
11727 : {
11728 332159 : if (omp_current_ctx)
11729 452 : gfc_traverse_ns (ns, handle_local_var);
11730 332159 : }
11731 :
11732 :
11733 : /* Error checking on intervening code uses a code walker. */
11734 :
11735 : struct icode_error_state
11736 : {
11737 : const char *name;
11738 : bool errorp;
11739 : gfc_code *nested;
11740 : gfc_code *next;
11741 : };
11742 :
11743 : static int
11744 944 : icode_code_error_callback (gfc_code **codep,
11745 : int *walk_subtrees ATTRIBUTE_UNUSED, void *opaque)
11746 : {
11747 944 : gfc_code *code = *codep;
11748 944 : icode_error_state *state = (icode_error_state *)opaque;
11749 :
11750 : /* gfc_code_walker walks down CODE's next chain as well as
11751 : walking things that are actually nested in CODE. We need to
11752 : special-case traversal of outer blocks, so stop immediately if we
11753 : are heading down such a next chain. */
11754 944 : if (code == state->next)
11755 : return 1;
11756 :
11757 647 : switch (code->op)
11758 : {
11759 1 : case EXEC_DO:
11760 1 : case EXEC_DO_WHILE:
11761 1 : case EXEC_DO_CONCURRENT:
11762 1 : gfc_error ("%s cannot contain loop in intervening code at %L",
11763 : state->name, &code->loc);
11764 1 : state->errorp = true;
11765 1 : break;
11766 0 : case EXEC_CYCLE:
11767 0 : case EXEC_EXIT:
11768 : /* Errors have already been diagnosed in match_exit_cycle. */
11769 0 : state->errorp = true;
11770 0 : break;
11771 : case EXEC_OMP_ASSUME:
11772 : case EXEC_OMP_METADIRECTIVE:
11773 : /* Per OpenMP 6.0, some non-executable directives are allowed in
11774 : intervening code. */
11775 : break;
11776 477 : case EXEC_CALL:
11777 : /* Per OpenMP 5.2, the "omp_" prefix is reserved, so we don't have to
11778 : consider the possibility that some locally-bound definition
11779 : overrides the runtime routine. */
11780 477 : if (code->resolved_sym
11781 477 : && omp_runtime_api_procname (code->resolved_sym->name))
11782 : {
11783 1 : gfc_error ("%s cannot contain OpenMP API call in intervening code "
11784 : "at %L",
11785 : state->name, &code->loc);
11786 1 : state->errorp = true;
11787 : }
11788 : break;
11789 168 : default:
11790 168 : if (code->op >= EXEC_OMP_FIRST_OPENMP_EXEC
11791 168 : && code->op <= EXEC_OMP_LAST_OPENMP_EXEC)
11792 : {
11793 2 : gfc_error ("%s cannot contain OpenMP directive in intervening code "
11794 : "at %L",
11795 : state->name, &code->loc);
11796 2 : state->errorp = true;
11797 : }
11798 : }
11799 : return 0;
11800 : }
11801 :
11802 : static int
11803 1081 : icode_expr_error_callback (gfc_expr **expr,
11804 : int *walk_subtrees ATTRIBUTE_UNUSED, void *opaque)
11805 : {
11806 1081 : icode_error_state *state = (icode_error_state *)opaque;
11807 :
11808 1081 : switch ((*expr)->expr_type)
11809 : {
11810 : /* As for EXPR_CALL with "omp_"-prefixed symbols. */
11811 2 : case EXPR_FUNCTION:
11812 2 : {
11813 2 : gfc_symbol *sym = (*expr)->value.function.esym;
11814 2 : if (sym && omp_runtime_api_procname (sym->name))
11815 : {
11816 1 : gfc_error ("%s cannot contain OpenMP API call in intervening code "
11817 : "at %L",
11818 1 : state->name, &((*expr)->where));
11819 1 : state->errorp = true;
11820 : }
11821 : }
11822 :
11823 : break;
11824 : default:
11825 : break;
11826 : }
11827 :
11828 : /* FIXME: The description of canonical loop form in the OpenMP standard
11829 : also says "array expressions" are not permitted in intervening code.
11830 : That term is not defined in either the OpenMP spec or the Fortran
11831 : standard, although the latter uses it informally to refer to any
11832 : expression that is not scalar-valued. It is also apparently not the
11833 : thing GCC internally calls EXPR_ARRAY. It seems the intent of the
11834 : OpenMP restriction is to disallow elemental operations/intrinsics
11835 : (including things that are not expressions, like assignment
11836 : statements) that generate implicit loops over array operands
11837 : (even if the result is a scalar), but even if the spec said
11838 : that there is no list of all the cases that would be forbidden.
11839 : This is OpenMP issue 3326. */
11840 :
11841 1081 : return 0;
11842 : }
11843 :
11844 : static void
11845 267 : diagnose_intervening_code_errors_1 (gfc_code *chain,
11846 : struct icode_error_state *state)
11847 : {
11848 267 : gfc_code *code;
11849 1080 : for (code = chain; code; code = code->next)
11850 : {
11851 813 : if (code == state->nested)
11852 : /* Do not walk the nested loop or its body, we are only
11853 : interested in intervening code. */
11854 : ;
11855 636 : else if (code->op == EXEC_BLOCK
11856 636 : && find_nested_loop_in_block (code) == state->nested)
11857 : /* This block contains the nested loop, recurse on its
11858 : statements. */
11859 : {
11860 90 : gfc_namespace* ns = code->ext.block.ns;
11861 90 : diagnose_intervening_code_errors_1 (ns->code, state);
11862 : }
11863 : else
11864 : /* Treat the whole statement as a unit. */
11865 : {
11866 546 : gfc_code *temp = state->next;
11867 546 : state->next = code->next;
11868 546 : gfc_code_walker (&code, icode_code_error_callback,
11869 : icode_expr_error_callback, state);
11870 546 : state->next = temp;
11871 : }
11872 : }
11873 267 : }
11874 :
11875 : /* Diagnose intervening code errors in BLOCK with nested loop NESTED.
11876 : NAME is the user-friendly name of the OMP directive, used for error
11877 : messages. Returns true if any error was found. */
11878 : static bool
11879 177 : diagnose_intervening_code_errors (gfc_code *chain, const char *name,
11880 : gfc_code *nested)
11881 : {
11882 177 : struct icode_error_state state;
11883 177 : state.name = name;
11884 177 : state.errorp = false;
11885 177 : state.nested = nested;
11886 177 : state.next = NULL;
11887 0 : diagnose_intervening_code_errors_1 (chain, &state);
11888 177 : return state.errorp;
11889 : }
11890 :
11891 : /* Helper function for restructure_intervening_code: wrap CHAIN in
11892 : a marker to indicate that it is a structured block sequence. That
11893 : information will be used later on (in omp-low.cc) for error checking. */
11894 : static gfc_code *
11895 461 : make_structured_block (gfc_code *chain)
11896 : {
11897 461 : gcc_assert (chain);
11898 461 : gfc_namespace *ns = gfc_build_block_ns (gfc_current_ns);
11899 461 : gfc_code *result = gfc_get_code (EXEC_BLOCK);
11900 461 : result->op = EXEC_BLOCK;
11901 461 : result->ext.block.ns = ns;
11902 461 : result->ext.block.assoc = NULL;
11903 461 : result->loc = chain->loc;
11904 461 : ns->omp_structured_block = 1;
11905 461 : ns->code = chain;
11906 461 : return result;
11907 : }
11908 :
11909 : /* Push intervening code surrounding a loop, including nested scopes,
11910 : into the body of the loop. CHAINP is the pointer to the head of
11911 : the next-chain to scan, OUTER_LOOP is the EXEC_DO for the next outer
11912 : loop level, and COLLAPSE is the number of nested loops we need to
11913 : process.
11914 : Note that CHAINP may point at outer_loop->block->next when we
11915 : are scanning the body of a loop, but if there is an intervening block
11916 : CHAINP points into the block's chain rather than its enclosing outer
11917 : loop. This is why OUTER_LOOP is passed separately. */
11918 : static gfc_code *
11919 7170 : restructure_intervening_code (gfc_code **chainp, gfc_code *outer_loop,
11920 : int count)
11921 : {
11922 7170 : gfc_code *code;
11923 7170 : gfc_code *head = *chainp;
11924 7170 : gfc_code *tail = NULL;
11925 7170 : gfc_code *innermost_loop = NULL;
11926 :
11927 7434 : for (code = *chainp; code; code = code->next, chainp = &(*chainp)->next)
11928 : {
11929 7434 : if (code->op == EXEC_DO)
11930 : {
11931 : /* Cut CODE free from its chain, leaving the ends dangling. */
11932 7086 : *chainp = NULL;
11933 7086 : tail = code->next;
11934 7086 : code->next = NULL;
11935 :
11936 7086 : if (count == 1)
11937 : innermost_loop = code;
11938 : else
11939 2090 : innermost_loop
11940 2090 : = restructure_intervening_code (&code->block->next,
11941 : code, count - 1);
11942 : break;
11943 : }
11944 348 : else if (code->op == EXEC_BLOCK
11945 348 : && find_nested_loop_in_block (code))
11946 : {
11947 84 : gfc_namespace *ns = code->ext.block.ns;
11948 :
11949 : /* Cut CODE free from its chain, leaving the ends dangling. */
11950 84 : *chainp = NULL;
11951 84 : tail = code->next;
11952 84 : code->next = NULL;
11953 :
11954 84 : innermost_loop
11955 84 : = restructure_intervening_code (&ns->code, outer_loop,
11956 : count);
11957 :
11958 : /* At this point we have already pulled out the nested loop and
11959 : pointed outer_loop at it, and moved the intervening code that
11960 : was previously in the block into the body of innermost_loop.
11961 : Now we want to move the BLOCK itself so it wraps the entire
11962 : current body of innermost_loop. */
11963 84 : ns->code = innermost_loop->block->next;
11964 84 : innermost_loop->block->next = code;
11965 84 : break;
11966 : }
11967 : }
11968 :
11969 2174 : gcc_assert (innermost_loop);
11970 :
11971 : /* Now we have split the intervening code into two parts:
11972 : head is the start of the part before the loop/block, terminating
11973 : at *chainp, and tail is the part after it. Mark each part as
11974 : a structured block sequence, and splice the two parts around the
11975 : existing body of the innermost loop. */
11976 7170 : if (head != code)
11977 : {
11978 222 : gfc_code *block = make_structured_block (head);
11979 222 : if (innermost_loop->block->next)
11980 221 : gfc_append_code (block, innermost_loop->block->next);
11981 222 : innermost_loop->block->next = block;
11982 : }
11983 7170 : if (tail)
11984 : {
11985 239 : gfc_code *block = make_structured_block (tail);
11986 239 : if (innermost_loop->block->next)
11987 237 : gfc_append_code (innermost_loop->block->next, block);
11988 : else
11989 2 : innermost_loop->block->next = block;
11990 : }
11991 :
11992 : /* For loops, finally splice CODE into OUTER_LOOP. We already handled
11993 : relinking EXEC_BLOCK above. */
11994 7170 : if (code->op == EXEC_DO && outer_loop)
11995 7086 : outer_loop->block->next = code;
11996 :
11997 7170 : return innermost_loop;
11998 : }
11999 :
12000 : /* CODE is an OMP loop construct. Return true if VAR matches an iteration
12001 : variable outer to level DEPTH. */
12002 : static bool
12003 8083 : is_outer_iteration_variable (gfc_code *code, int depth, gfc_symbol *var)
12004 : {
12005 8083 : int i;
12006 8083 : gfc_code *do_code = code;
12007 :
12008 12610 : for (i = 1; i < depth; i++)
12009 : {
12010 5028 : do_code = find_nested_loop_in_chain (do_code->block->next);
12011 5028 : gcc_assert (do_code);
12012 5028 : if (do_code->op == EXEC_OMP_TILE || do_code->op == EXEC_OMP_UNROLL)
12013 : {
12014 51 : --i;
12015 51 : continue;
12016 : }
12017 4977 : gfc_symbol *ivar = do_code->ext.iterator->var->symtree->n.sym;
12018 4977 : if (var == ivar)
12019 : return true;
12020 : }
12021 : return false;
12022 : }
12023 :
12024 : /* Forward declaration for recursive functions. */
12025 : static gfc_code *
12026 : check_nested_loop_in_block (gfc_code *block, gfc_expr *expr, gfc_symbol *sym,
12027 : bool *bad);
12028 :
12029 : /* Like find_nested_loop_in_chain, but additionally check that EXPR
12030 : does not reference any variables bound in intervening EXEC_BLOCKs
12031 : and that SYM is not bound in such intervening blocks. Either EXPR or SYM
12032 : may be null. Sets *BAD to true if either test fails. */
12033 : static gfc_code *
12034 48165 : check_nested_loop_in_chain (gfc_code *chain, gfc_expr *expr, gfc_symbol *sym,
12035 : bool *bad)
12036 : {
12037 51769 : for (gfc_code *code = chain; code; code = code->next)
12038 : {
12039 51481 : if (code->op == EXEC_DO)
12040 : return code;
12041 4123 : else if (code->op == EXEC_OMP_TILE || code->op == EXEC_OMP_UNROLL)
12042 1682 : return check_nested_loop_in_chain (code->block->next, expr, sym, bad);
12043 2441 : else if (code->op == EXEC_BLOCK)
12044 : {
12045 807 : gfc_code *c = check_nested_loop_in_block (code, expr, sym, bad);
12046 807 : if (c)
12047 : return c;
12048 : }
12049 : }
12050 : return NULL;
12051 : }
12052 :
12053 : /* Code walker for block symtrees. It doesn't take any kind of state
12054 : argument, so use a static variable. */
12055 : static struct check_nested_loop_in_block_state_t {
12056 : gfc_expr *expr;
12057 : gfc_symbol *sym;
12058 : bool *bad;
12059 : } check_nested_loop_in_block_state;
12060 :
12061 : static void
12062 766 : check_nested_loop_in_block_symbol (gfc_symbol *sym)
12063 : {
12064 766 : if (sym == check_nested_loop_in_block_state.sym
12065 766 : || (check_nested_loop_in_block_state.expr
12066 567 : && gfc_find_sym_in_expr (sym,
12067 : check_nested_loop_in_block_state.expr)))
12068 5 : *check_nested_loop_in_block_state.bad = true;
12069 766 : }
12070 :
12071 : /* Return the first nested DO loop in BLOCK, or NULL if there
12072 : isn't one. Set *BAD to true if EXPR references any variables in BLOCK, or
12073 : SYM is bound in BLOCK. Either EXPR or SYM may be null. */
12074 : static gfc_code *
12075 807 : check_nested_loop_in_block (gfc_code *block, gfc_expr *expr,
12076 : gfc_symbol *sym, bool *bad)
12077 : {
12078 807 : gfc_namespace *ns;
12079 807 : gcc_assert (block->op == EXEC_BLOCK);
12080 807 : ns = block->ext.block.ns;
12081 807 : gcc_assert (ns);
12082 :
12083 : /* Skip the check if this block doesn't contain the nested loop, or
12084 : if we already know it's bad. */
12085 807 : gfc_code *result = check_nested_loop_in_chain (ns->code, expr, sym, bad);
12086 807 : if (result && !*bad)
12087 : {
12088 519 : check_nested_loop_in_block_state.expr = expr;
12089 519 : check_nested_loop_in_block_state.sym = sym;
12090 519 : check_nested_loop_in_block_state.bad = bad;
12091 519 : gfc_traverse_ns (ns, check_nested_loop_in_block_symbol);
12092 519 : check_nested_loop_in_block_state.expr = NULL;
12093 519 : check_nested_loop_in_block_state.sym = NULL;
12094 519 : check_nested_loop_in_block_state.bad = NULL;
12095 : }
12096 807 : return result;
12097 : }
12098 :
12099 : /* CODE is an OMP loop construct. Return true if EXPR references
12100 : any variables bound in intervening code, to level DEPTH. */
12101 : static bool
12102 22717 : expr_uses_intervening_var (gfc_code *code, int depth, gfc_expr *expr)
12103 : {
12104 22717 : int i;
12105 22717 : gfc_code *do_code = code;
12106 :
12107 58213 : for (i = 0; i < depth; i++)
12108 : {
12109 35499 : bool bad = false;
12110 35499 : do_code = check_nested_loop_in_chain (do_code->block->next,
12111 : expr, NULL, &bad);
12112 35499 : if (bad)
12113 3 : return true;
12114 : }
12115 : return false;
12116 : }
12117 :
12118 : /* CODE is an OMP loop construct. Return true if SYM is bound in
12119 : intervening code, to level DEPTH. */
12120 : static bool
12121 7582 : is_intervening_var (gfc_code *code, int depth, gfc_symbol *sym)
12122 : {
12123 7582 : int i;
12124 7582 : gfc_code *do_code = code;
12125 :
12126 19439 : for (i = 0; i < depth; i++)
12127 : {
12128 11859 : bool bad = false;
12129 11859 : do_code = check_nested_loop_in_chain (do_code->block->next,
12130 : NULL, sym, &bad);
12131 11859 : if (bad)
12132 2 : return true;
12133 : }
12134 : return false;
12135 : }
12136 :
12137 : /* CODE is an OMP loop construct. Return true if EXPR does not reference
12138 : any iteration variables outer to level DEPTH. */
12139 : static bool
12140 23796 : expr_is_invariant (gfc_code *code, int depth, gfc_expr *expr)
12141 : {
12142 23796 : int i;
12143 23796 : gfc_code *do_code = code;
12144 :
12145 37118 : for (i = 1; i < depth; i++)
12146 : {
12147 14388 : do_code = find_nested_loop_in_chain (do_code->block->next);
12148 14388 : gcc_assert (do_code);
12149 14388 : if (do_code->op == EXEC_OMP_TILE || do_code->op == EXEC_OMP_UNROLL)
12150 : {
12151 136 : --i;
12152 136 : continue;
12153 : }
12154 14252 : gfc_symbol *ivar = do_code->ext.iterator->var->symtree->n.sym;
12155 14252 : if (gfc_find_sym_in_expr (ivar, expr))
12156 : return false;
12157 : }
12158 : return true;
12159 : }
12160 :
12161 : /* CODE is an OMP loop construct. Return true if EXPR matches one of the
12162 : canonical forms for a bound expression. It may include references to
12163 : an iteration variable outer to level DEPTH; set OUTER_VARP if so. */
12164 : static bool
12165 15155 : bound_expr_is_canonical (gfc_code *code, int depth, gfc_expr *expr,
12166 : gfc_symbol **outer_varp)
12167 : {
12168 15155 : gfc_expr *expr2 = NULL;
12169 :
12170 : /* Rectangular case. */
12171 15155 : if (depth == 0 || expr_is_invariant (code, depth, expr))
12172 14587 : return true;
12173 :
12174 : /* Any simple variable that didn't pass expr_is_invariant must be
12175 : an outer_var. */
12176 568 : if (expr->expr_type == EXPR_VARIABLE && expr->rank == 0)
12177 : {
12178 63 : *outer_varp = expr->symtree->n.sym;
12179 63 : return true;
12180 : }
12181 :
12182 : /* All other permitted forms are binary operators. */
12183 505 : if (expr->expr_type != EXPR_OP)
12184 : return false;
12185 :
12186 : /* Check for plus/minus a loop invariant expr. */
12187 503 : if (expr->value.op.op == INTRINSIC_PLUS
12188 503 : || expr->value.op.op == INTRINSIC_MINUS)
12189 : {
12190 483 : if (expr_is_invariant (code, depth, expr->value.op.op1))
12191 48 : expr2 = expr->value.op.op2;
12192 435 : else if (expr_is_invariant (code, depth, expr->value.op.op2))
12193 434 : expr2 = expr->value.op.op1;
12194 : else
12195 : return false;
12196 : }
12197 : else
12198 : expr2 = expr;
12199 :
12200 : /* Check for a product with a loop-invariant expr. */
12201 502 : if (expr2->expr_type == EXPR_OP
12202 96 : && expr2->value.op.op == INTRINSIC_TIMES)
12203 : {
12204 96 : if (expr_is_invariant (code, depth, expr2->value.op.op1))
12205 40 : expr2 = expr2->value.op.op2;
12206 56 : else if (expr_is_invariant (code, depth, expr2->value.op.op2))
12207 53 : expr2 = expr2->value.op.op1;
12208 : else
12209 : return false;
12210 : }
12211 :
12212 : /* What's left must be a reference to an outer loop variable. */
12213 499 : if (expr2->expr_type == EXPR_VARIABLE
12214 499 : && expr2->rank == 0
12215 998 : && is_outer_iteration_variable (code, depth, expr2->symtree->n.sym))
12216 : {
12217 499 : *outer_varp = expr2->symtree->n.sym;
12218 499 : return true;
12219 : }
12220 :
12221 : return false;
12222 : }
12223 :
12224 : static void
12225 5420 : resolve_omp_do (gfc_code *code)
12226 : {
12227 5420 : gfc_code *do_code, *next;
12228 5420 : int i, count, non_generated_count;
12229 5420 : gfc_omp_namelist *n;
12230 5420 : gfc_symbol *dovar;
12231 5420 : const char *name;
12232 5420 : bool is_simd = false;
12233 5420 : bool errorp = false;
12234 5420 : bool perfect_nesting_errorp = false;
12235 5420 : bool imperfect = false;
12236 :
12237 5420 : switch (code->op)
12238 : {
12239 : case EXEC_OMP_DISTRIBUTE: name = "!$OMP DISTRIBUTE"; break;
12240 49 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
12241 49 : name = "!$OMP DISTRIBUTE PARALLEL DO";
12242 49 : break;
12243 32 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
12244 32 : name = "!$OMP DISTRIBUTE PARALLEL DO SIMD";
12245 32 : is_simd = true;
12246 32 : break;
12247 50 : case EXEC_OMP_DISTRIBUTE_SIMD:
12248 50 : name = "!$OMP DISTRIBUTE SIMD";
12249 50 : is_simd = true;
12250 50 : break;
12251 1335 : case EXEC_OMP_DO: name = "!$OMP DO"; break;
12252 134 : case EXEC_OMP_DO_SIMD: name = "!$OMP DO SIMD"; is_simd = true; break;
12253 64 : case EXEC_OMP_LOOP: name = "!$OMP LOOP"; break;
12254 1216 : case EXEC_OMP_PARALLEL_DO: name = "!$OMP PARALLEL DO"; break;
12255 304 : case EXEC_OMP_PARALLEL_DO_SIMD:
12256 304 : name = "!$OMP PARALLEL DO SIMD";
12257 304 : is_simd = true;
12258 304 : break;
12259 46 : case EXEC_OMP_PARALLEL_LOOP: name = "!$OMP PARALLEL LOOP"; break;
12260 7 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
12261 7 : name = "!$OMP PARALLEL MASKED TASKLOOP";
12262 7 : break;
12263 10 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
12264 10 : name = "!$OMP PARALLEL MASKED TASKLOOP SIMD";
12265 10 : is_simd = true;
12266 10 : break;
12267 12 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
12268 12 : name = "!$OMP PARALLEL MASTER TASKLOOP";
12269 12 : break;
12270 18 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
12271 18 : name = "!$OMP PARALLEL MASTER TASKLOOP SIMD";
12272 18 : is_simd = true;
12273 18 : break;
12274 8 : case EXEC_OMP_MASKED_TASKLOOP: name = "!$OMP MASKED TASKLOOP"; break;
12275 14 : case EXEC_OMP_MASKED_TASKLOOP_SIMD:
12276 14 : name = "!$OMP MASKED TASKLOOP SIMD";
12277 14 : is_simd = true;
12278 14 : break;
12279 14 : case EXEC_OMP_MASTER_TASKLOOP: name = "!$OMP MASTER TASKLOOP"; break;
12280 19 : case EXEC_OMP_MASTER_TASKLOOP_SIMD:
12281 19 : name = "!$OMP MASTER TASKLOOP SIMD";
12282 19 : is_simd = true;
12283 19 : break;
12284 783 : case EXEC_OMP_SIMD: name = "!$OMP SIMD"; is_simd = true; break;
12285 88 : case EXEC_OMP_TARGET_PARALLEL_DO: name = "!$OMP TARGET PARALLEL DO"; break;
12286 19 : case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
12287 19 : name = "!$OMP TARGET PARALLEL DO SIMD";
12288 19 : is_simd = true;
12289 19 : break;
12290 16 : case EXEC_OMP_TARGET_PARALLEL_LOOP:
12291 16 : name = "!$OMP TARGET PARALLEL LOOP";
12292 16 : break;
12293 33 : case EXEC_OMP_TARGET_SIMD:
12294 33 : name = "!$OMP TARGET SIMD";
12295 33 : is_simd = true;
12296 33 : break;
12297 20 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
12298 20 : name = "!$OMP TARGET TEAMS DISTRIBUTE";
12299 20 : break;
12300 75 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
12301 75 : name = "!$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO";
12302 75 : break;
12303 37 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
12304 37 : name = "!$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD";
12305 37 : is_simd = true;
12306 37 : break;
12307 20 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
12308 20 : name = "!$OMP TARGET TEAMS DISTRIBUTE SIMD";
12309 20 : is_simd = true;
12310 20 : break;
12311 19 : case EXEC_OMP_TARGET_TEAMS_LOOP: name = "!$OMP TARGET TEAMS LOOP"; break;
12312 69 : case EXEC_OMP_TASKLOOP: name = "!$OMP TASKLOOP"; break;
12313 38 : case EXEC_OMP_TASKLOOP_SIMD:
12314 38 : name = "!$OMP TASKLOOP SIMD";
12315 38 : is_simd = true;
12316 38 : break;
12317 20 : case EXEC_OMP_TEAMS_DISTRIBUTE: name = "!$OMP TEAMS DISTRIBUTE"; break;
12318 37 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
12319 37 : name = "!$OMP TEAMS DISTRIBUTE PARALLEL DO";
12320 37 : break;
12321 60 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
12322 60 : name = "!$OMP TEAMS DISTRIBUTE PARALLEL DO SIMD";
12323 60 : is_simd = true;
12324 60 : break;
12325 42 : case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
12326 42 : name = "!$OMP TEAMS DISTRIBUTE SIMD";
12327 42 : is_simd = true;
12328 42 : break;
12329 48 : case EXEC_OMP_TEAMS_LOOP: name = "!$OMP TEAMS LOOP"; break;
12330 195 : case EXEC_OMP_TILE: name = "!$OMP TILE"; break;
12331 415 : case EXEC_OMP_UNROLL: name = "!$OMP UNROLL"; break;
12332 0 : default: gcc_unreachable ();
12333 : }
12334 :
12335 5420 : if (code->ext.omp_clauses)
12336 5420 : resolve_omp_clauses (code, code->ext.omp_clauses, NULL);
12337 :
12338 5420 : if (code->op == EXEC_OMP_TILE && code->ext.omp_clauses->sizes_list == NULL)
12339 0 : gfc_error ("SIZES clause is required on !$OMP TILE construct at %L",
12340 : &code->loc);
12341 :
12342 5420 : do_code = code->block->next;
12343 5420 : if (code->ext.omp_clauses->orderedc)
12344 : count = code->ext.omp_clauses->orderedc;
12345 5276 : else if (code->ext.omp_clauses->sizes_list)
12346 195 : count = gfc_expr_list_len (code->ext.omp_clauses->sizes_list);
12347 : else
12348 : {
12349 5081 : count = code->ext.omp_clauses->collapse;
12350 5081 : if (count <= 0)
12351 : count = 1;
12352 : }
12353 :
12354 5420 : non_generated_count = count;
12355 : /* While the spec defines the loop nest depth independently of the COLLAPSE
12356 : clause, in practice the middle end only pays attention to the COLLAPSE
12357 : depth and treats any further inner loops as the final-loop-body. So
12358 : here we also check canonical loop nest form only for the number of
12359 : outer loops specified by the COLLAPSE clause too. */
12360 8060 : for (i = 1; i <= count; i++)
12361 : {
12362 8060 : gfc_symbol *start_var = NULL, *end_var = NULL;
12363 : /* Parse errors are not recoverable. */
12364 8060 : if (do_code->op == EXEC_DO_WHILE)
12365 : {
12366 6 : gfc_error ("%s cannot be a DO WHILE or DO without loop control "
12367 : "at %L", name, &do_code->loc);
12368 106 : goto fail;
12369 : }
12370 8054 : if (do_code->op == EXEC_DO_CONCURRENT)
12371 : {
12372 4 : gfc_error ("%s cannot be a DO CONCURRENT loop at %L", name,
12373 : &do_code->loc);
12374 4 : goto fail;
12375 : }
12376 8050 : if (do_code->op == EXEC_OMP_TILE || do_code->op == EXEC_OMP_UNROLL)
12377 : {
12378 466 : if (do_code->op == EXEC_OMP_UNROLL)
12379 : {
12380 308 : if (!do_code->ext.omp_clauses->partial)
12381 : {
12382 53 : gfc_error ("Generated loop of UNROLL construct at %L "
12383 : "without PARTIAL clause does not have "
12384 : "canonical form", &do_code->loc);
12385 53 : goto fail;
12386 : }
12387 255 : else if (i != count)
12388 : {
12389 5 : gfc_error ("UNROLL construct at %L with PARTIAL clause "
12390 : "generates just one loop with canonical form "
12391 : "but %d loops are needed",
12392 5 : &do_code->loc, count - i + 1);
12393 5 : goto fail;
12394 : }
12395 : }
12396 158 : else if (do_code->op == EXEC_OMP_TILE)
12397 : {
12398 158 : if (do_code->ext.omp_clauses->sizes_list == NULL)
12399 : /* This should have been diagnosed earlier already. */
12400 0 : return;
12401 158 : int l = gfc_expr_list_len (do_code->ext.omp_clauses->sizes_list);
12402 158 : if (count - i + 1 > l)
12403 : {
12404 14 : gfc_error ("TILE construct at %L generates %d loops "
12405 : "with canonical form but %d loops are needed",
12406 : &do_code->loc, l, count - i + 1);
12407 14 : goto fail;
12408 : }
12409 : }
12410 394 : if (do_code->ext.omp_clauses && do_code->ext.omp_clauses->erroneous)
12411 17 : goto fail;
12412 377 : if (imperfect && !perfect_nesting_errorp)
12413 : {
12414 4 : sorry_at (gfc_get_location (&do_code->loc),
12415 : "Imperfectly nested loop using generated loops");
12416 4 : errorp = true;
12417 : }
12418 377 : if (non_generated_count == count)
12419 329 : non_generated_count = i - 1;
12420 377 : --i;
12421 377 : do_code = do_code->block->next;
12422 377 : continue;
12423 377 : }
12424 7584 : gcc_assert (do_code->op == EXEC_DO);
12425 7584 : if (do_code->ext.iterator->var->ts.type != BT_INTEGER)
12426 : {
12427 3 : gfc_error ("%s iteration variable must be of type integer at %L",
12428 : name, &do_code->loc);
12429 3 : errorp = true;
12430 : }
12431 7584 : dovar = do_code->ext.iterator->var->symtree->n.sym;
12432 7584 : if (dovar->attr.threadprivate)
12433 : {
12434 0 : gfc_error ("%s iteration variable must not be THREADPRIVATE "
12435 : "at %L", name, &do_code->loc);
12436 0 : errorp = true;
12437 : }
12438 7584 : if (code->ext.omp_clauses)
12439 303360 : for (enum gfc_omp_list_type list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
12440 295776 : list = gfc_omp_list_type (list + 1))
12441 97461 : if (!is_simd || code->ext.omp_clauses->collapse > 1
12442 295776 : ? (list != OMP_LIST_PRIVATE && list != OMP_LIST_LASTPRIVATE
12443 254670 : && list != OMP_LIST_ALLOCATE)
12444 41106 : : (list != OMP_LIST_PRIVATE && list != OMP_LIST_LASTPRIVATE
12445 41106 : && list != OMP_LIST_ALLOCATE && list != OMP_LIST_LINEAR))
12446 276351 : for (n = code->ext.omp_clauses->lists[list]; n; n = n->next)
12447 4381 : if (dovar == n->sym)
12448 : {
12449 5 : if (!is_simd || code->ext.omp_clauses->collapse > 1)
12450 4 : gfc_error ("%s iteration variable present on clause "
12451 : "other than PRIVATE, LASTPRIVATE or "
12452 : "ALLOCATE at %L", name, &do_code->loc);
12453 : else
12454 1 : gfc_error ("%s iteration variable present on clause "
12455 : "other than PRIVATE, LASTPRIVATE, ALLOCATE or "
12456 : "LINEAR at %L", name, &do_code->loc);
12457 : errorp = true;
12458 : }
12459 7584 : if (is_outer_iteration_variable (code, i, dovar))
12460 : {
12461 2 : gfc_error ("%s iteration variable used in more than one loop at %L",
12462 : name, &do_code->loc);
12463 2 : errorp = true;
12464 : }
12465 7582 : else if (is_intervening_var (code, i, dovar))
12466 : {
12467 2 : gfc_error ("%s iteration variable at %L is bound in "
12468 : "intervening code",
12469 : name, &do_code->loc);
12470 2 : errorp = true;
12471 : }
12472 7580 : else if (!bound_expr_is_canonical (code, i,
12473 7580 : do_code->ext.iterator->start,
12474 : &start_var))
12475 : {
12476 4 : gfc_error ("%s loop start expression not in canonical form at %L",
12477 : name, &do_code->loc);
12478 4 : errorp = true;
12479 : }
12480 7576 : else if (expr_uses_intervening_var (code, i,
12481 7576 : do_code->ext.iterator->start))
12482 : {
12483 1 : gfc_error ("%s loop start expression at %L uses variable bound in "
12484 : "intervening code",
12485 : name, &do_code->loc);
12486 1 : errorp = true;
12487 : }
12488 7575 : else if (!bound_expr_is_canonical (code, i,
12489 7575 : do_code->ext.iterator->end,
12490 : &end_var))
12491 : {
12492 2 : gfc_error ("%s loop end expression not in canonical form at %L",
12493 : name, &do_code->loc);
12494 2 : errorp = true;
12495 : }
12496 7573 : else if (expr_uses_intervening_var (code, i,
12497 7573 : do_code->ext.iterator->end))
12498 : {
12499 1 : gfc_error ("%s loop end expression at %L uses variable bound in "
12500 : "intervening code",
12501 : name, &do_code->loc);
12502 1 : errorp = true;
12503 : }
12504 7572 : else if (start_var && end_var && start_var != end_var)
12505 : {
12506 1 : gfc_error ("%s loop bounds reference different "
12507 : "iteration variables at %L", name, &do_code->loc);
12508 1 : errorp = true;
12509 : }
12510 7571 : else if (!expr_is_invariant (code, i, do_code->ext.iterator->step))
12511 : {
12512 3 : gfc_error ("%s loop increment not in canonical form at %L",
12513 : name, &do_code->loc);
12514 3 : errorp = true;
12515 : }
12516 7568 : else if (expr_uses_intervening_var (code, i,
12517 7568 : do_code->ext.iterator->step))
12518 : {
12519 1 : gfc_error ("%s loop increment expression at %L uses variable "
12520 : "bound in intervening code",
12521 : name, &do_code->loc);
12522 1 : errorp = true;
12523 : }
12524 7584 : if (start_var || end_var)
12525 : {
12526 528 : code->ext.omp_clauses->non_rectangular = 1;
12527 528 : if (i > non_generated_count)
12528 : {
12529 3 : sorry_at (gfc_get_location (&do_code->loc),
12530 : "Non-rectangular loops from generated loops "
12531 : "unsupported");
12532 3 : errorp = true;
12533 : }
12534 : }
12535 :
12536 : /* Only parse loop body into nested loop and intervening code if
12537 : there are supposed to be more loops in the nest to collapse. */
12538 7584 : if (i == count)
12539 : break;
12540 :
12541 2270 : next = find_nested_loop_in_chain (do_code->block->next);
12542 :
12543 2270 : if (!next)
12544 : {
12545 : /* Parse error, can't recover from this. */
12546 7 : gfc_error ("not enough DO loops for collapsed %s (level %d) at %L",
12547 : name, i, &code->loc);
12548 7 : goto fail;
12549 : }
12550 2263 : else if (next != do_code->block->next
12551 2103 : || (next->next && next->next->op != EXEC_CONTINUE))
12552 : /* Imperfectly nested loop found. */
12553 : {
12554 : /* Only diagnose violation of imperfect nesting constraints once. */
12555 177 : if (!perfect_nesting_errorp)
12556 : {
12557 176 : if (code->ext.omp_clauses->orderedc)
12558 : {
12559 3 : gfc_error ("%s inner loops must be perfectly nested with "
12560 : "ORDERED clause at %L",
12561 : name, &code->loc);
12562 3 : perfect_nesting_errorp = true;
12563 : }
12564 173 : else if (code->ext.omp_clauses->lists[OMP_LIST_REDUCTION_INSCAN])
12565 : {
12566 2 : gfc_error ("%s inner loops must be perfectly nested with "
12567 : "REDUCTION INSCAN clause at %L",
12568 : name, &code->loc);
12569 2 : perfect_nesting_errorp = true;
12570 : }
12571 171 : else if (code->op == EXEC_OMP_TILE)
12572 : {
12573 8 : gfc_error ("%s inner loops must be perfectly nested at %L",
12574 : name, &code->loc);
12575 8 : perfect_nesting_errorp = true;
12576 : }
12577 13 : if (perfect_nesting_errorp)
12578 : errorp = true;
12579 : }
12580 177 : if (diagnose_intervening_code_errors (do_code->block->next,
12581 : name, next))
12582 5 : errorp = true;
12583 : imperfect = true;
12584 : }
12585 2263 : do_code = next;
12586 : }
12587 :
12588 : /* Give up now if we found any constraint violations. */
12589 5314 : if (errorp)
12590 : {
12591 48 : fail:
12592 154 : if (code->ext.omp_clauses)
12593 154 : code->ext.omp_clauses->erroneous = 1;
12594 154 : return;
12595 : }
12596 :
12597 5266 : if (non_generated_count)
12598 4996 : restructure_intervening_code (&code->block->next, code,
12599 : non_generated_count);
12600 : }
12601 :
12602 : /* Resolve the context selector. In particular, SKIP_P is set to true,
12603 : the context can never be matched. */
12604 :
12605 : static void
12606 764 : gfc_resolve_omp_context_selector (gfc_omp_set_selector *oss,
12607 : bool is_metadirective, bool *skip_p)
12608 : {
12609 764 : if (skip_p)
12610 310 : *skip_p = false;
12611 1453 : for (gfc_omp_set_selector *set_selector = oss; set_selector;
12612 689 : set_selector = set_selector->next)
12613 1485 : for (gfc_omp_selector *os = set_selector->trait_selectors; os; os = os->next)
12614 : {
12615 814 : if (os->score)
12616 : {
12617 52 : if (!gfc_resolve_expr (os->score)
12618 52 : || os->score->ts.type != BT_INTEGER
12619 104 : || os->score->rank != 0)
12620 : {
12621 0 : gfc_error ("%<score%> argument must be constant integer "
12622 0 : "expression at %L", &os->score->where);
12623 0 : gfc_free_expr (os->score);
12624 0 : os->score = nullptr;
12625 : }
12626 52 : else if (os->score->expr_type == EXPR_CONSTANT
12627 52 : && mpz_sgn (os->score->value.integer) < 0)
12628 : {
12629 1 : gfc_error ("%<score%> argument must be non-negative at %L",
12630 : &os->score->where);
12631 1 : gfc_free_expr (os->score);
12632 1 : os->score = nullptr;
12633 : }
12634 : }
12635 :
12636 814 : if (os->code == OMP_TRAIT_INVALID)
12637 : break;
12638 796 : enum omp_tp_type property_kind = omp_ts_map[os->code].tp_type;
12639 796 : gfc_omp_trait_property *otp = os->properties;
12640 :
12641 796 : if (!otp)
12642 409 : continue;
12643 387 : switch (property_kind)
12644 : {
12645 139 : case OMP_TRAIT_PROPERTY_DEV_NUM_EXPR:
12646 139 : case OMP_TRAIT_PROPERTY_BOOL_EXPR:
12647 139 : if (!gfc_resolve_expr (otp->expr)
12648 138 : || (property_kind == OMP_TRAIT_PROPERTY_BOOL_EXPR
12649 124 : && otp->expr->ts.type != BT_LOGICAL)
12650 137 : || (property_kind == OMP_TRAIT_PROPERTY_DEV_NUM_EXPR
12651 14 : && otp->expr->ts.type != BT_INTEGER)
12652 137 : || otp->expr->rank != 0
12653 276 : || (!is_metadirective && otp->expr->expr_type != EXPR_CONSTANT))
12654 : {
12655 3 : if (is_metadirective)
12656 : {
12657 0 : if (property_kind == OMP_TRAIT_PROPERTY_BOOL_EXPR)
12658 0 : gfc_error ("property must be a "
12659 : "logical expression at %L",
12660 0 : &otp->expr->where);
12661 : else
12662 0 : gfc_error ("property must be an "
12663 : "integer expression at %L",
12664 0 : &otp->expr->where);
12665 : }
12666 : else
12667 : {
12668 3 : if (property_kind == OMP_TRAIT_PROPERTY_BOOL_EXPR)
12669 2 : gfc_error ("property must be a constant "
12670 : "logical expression at %L",
12671 2 : &otp->expr->where);
12672 : else
12673 1 : gfc_error ("property must be a constant "
12674 : "integer expression at %L",
12675 1 : &otp->expr->where);
12676 : }
12677 : /* Prevent later ICEs. */
12678 3 : gfc_expr *e;
12679 3 : if (property_kind == OMP_TRAIT_PROPERTY_BOOL_EXPR)
12680 2 : e = gfc_get_logical_expr (gfc_default_logical_kind,
12681 2 : &otp->expr->where, true);
12682 : else
12683 1 : e = gfc_get_int_expr (gfc_default_integer_kind,
12684 1 : &otp->expr->where, 0);
12685 3 : gfc_free_expr (otp->expr);
12686 3 : otp->expr = e;
12687 3 : continue;
12688 3 : }
12689 : /* Device number must be conforming, which includes
12690 : omp_initial_device (-1), omp_invalid_device (-4),
12691 : and omp_default_device (-5). */
12692 136 : if (property_kind == OMP_TRAIT_PROPERTY_DEV_NUM_EXPR
12693 14 : && otp->expr->expr_type == EXPR_CONSTANT
12694 5 : && mpz_sgn (otp->expr->value.integer) < 0
12695 3 : && mpz_cmp_si (otp->expr->value.integer, -1) != 0
12696 2 : && mpz_cmp_si (otp->expr->value.integer, -4) != 0
12697 1 : && mpz_cmp_si (otp->expr->value.integer, -5) != 0)
12698 1 : gfc_error ("property must be a conforming device number at %L",
12699 : &otp->expr->where);
12700 : break;
12701 : default:
12702 : break;
12703 : }
12704 : /* This only handles one specific case: User condition.
12705 : FIXME: Handle more cases by calling omp_context_selector_matches;
12706 : unfortunately, we cannot generate the tree here as, e.g., PARM_DECL
12707 : backend decl are not available at this stage - but might be used in,
12708 : e.g. user conditions. See PR122361. */
12709 384 : if (skip_p && otp
12710 138 : && os->code == OMP_TRAIT_USER_CONDITION
12711 81 : && otp->expr->expr_type == EXPR_CONSTANT
12712 14 : && otp->expr->value.logical == false)
12713 12 : *skip_p = true;
12714 : }
12715 764 : }
12716 :
12717 :
12718 : static void
12719 138 : resolve_omp_metadirective (gfc_code *code, gfc_namespace *ns)
12720 : {
12721 138 : gfc_omp_variant *variant = code->ext.omp_variants;
12722 138 : gfc_omp_variant *prev_variant = variant;
12723 :
12724 448 : while (variant)
12725 : {
12726 310 : bool skip;
12727 310 : gfc_resolve_omp_context_selector (variant->selectors, true, &skip);
12728 310 : gfc_code *variant_code = variant->code;
12729 310 : gfc_resolve_code (variant_code, ns);
12730 310 : if (skip)
12731 : {
12732 : /* The following should only be true if an error occurred
12733 : as the 'otherwise' clause should always match. */
12734 12 : if (variant == code->ext.omp_variants && !variant->next)
12735 : break;
12736 12 : gfc_omp_variant *tmp = variant;
12737 12 : if (variant == code->ext.omp_variants)
12738 11 : variant = prev_variant = code->ext.omp_variants = variant->next;
12739 : else
12740 1 : variant = prev_variant->next = variant->next;
12741 12 : gfc_free_omp_set_selector_list (tmp->selectors);
12742 12 : free (tmp);
12743 : }
12744 : else
12745 : {
12746 298 : prev_variant = variant;
12747 298 : variant = variant->next;
12748 : }
12749 : }
12750 : /* Replace metadirective by its body if only 'nothing' remains. */
12751 138 : if (!code->ext.omp_variants->next && code->ext.omp_variants->stmt == ST_NONE)
12752 : {
12753 11 : gfc_code *next = code->next;
12754 11 : gfc_code *inner = code->ext.omp_variants->code;
12755 11 : gfc_free_omp_set_selector_list (code->ext.omp_variants->selectors);
12756 11 : free (code->ext.omp_variants);
12757 11 : *code = *inner;
12758 11 : free (inner);
12759 11 : while (code->next)
12760 : code = code->next;
12761 11 : code->next = next;
12762 : }
12763 138 : }
12764 :
12765 :
12766 : static gfc_statement
12767 63 : omp_code_to_statement (gfc_code *code)
12768 : {
12769 63 : switch (code->op)
12770 : {
12771 : case EXEC_OMP_PARALLEL:
12772 : return ST_OMP_PARALLEL;
12773 0 : case EXEC_OMP_PARALLEL_MASKED:
12774 0 : return ST_OMP_PARALLEL_MASKED;
12775 0 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
12776 0 : return ST_OMP_PARALLEL_MASKED_TASKLOOP;
12777 0 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
12778 0 : return ST_OMP_PARALLEL_MASKED_TASKLOOP_SIMD;
12779 0 : case EXEC_OMP_PARALLEL_MASTER:
12780 0 : return ST_OMP_PARALLEL_MASTER;
12781 0 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
12782 0 : return ST_OMP_PARALLEL_MASTER_TASKLOOP;
12783 0 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
12784 0 : return ST_OMP_PARALLEL_MASTER_TASKLOOP_SIMD;
12785 1 : case EXEC_OMP_PARALLEL_SECTIONS:
12786 1 : return ST_OMP_PARALLEL_SECTIONS;
12787 1 : case EXEC_OMP_SECTIONS:
12788 1 : return ST_OMP_SECTIONS;
12789 1 : case EXEC_OMP_ORDERED:
12790 1 : return ST_OMP_ORDERED;
12791 1 : case EXEC_OMP_CRITICAL:
12792 1 : return ST_OMP_CRITICAL;
12793 0 : case EXEC_OMP_MASKED:
12794 0 : return ST_OMP_MASKED;
12795 0 : case EXEC_OMP_MASKED_TASKLOOP:
12796 0 : return ST_OMP_MASKED_TASKLOOP;
12797 0 : case EXEC_OMP_MASKED_TASKLOOP_SIMD:
12798 0 : return ST_OMP_MASKED_TASKLOOP_SIMD;
12799 1 : case EXEC_OMP_MASTER:
12800 1 : return ST_OMP_MASTER;
12801 0 : case EXEC_OMP_MASTER_TASKLOOP:
12802 0 : return ST_OMP_MASTER_TASKLOOP;
12803 0 : case EXEC_OMP_MASTER_TASKLOOP_SIMD:
12804 0 : return ST_OMP_MASTER_TASKLOOP_SIMD;
12805 1 : case EXEC_OMP_SINGLE:
12806 1 : return ST_OMP_SINGLE;
12807 1 : case EXEC_OMP_TASK:
12808 1 : return ST_OMP_TASK;
12809 1 : case EXEC_OMP_WORKSHARE:
12810 1 : return ST_OMP_WORKSHARE;
12811 1 : case EXEC_OMP_PARALLEL_WORKSHARE:
12812 1 : return ST_OMP_PARALLEL_WORKSHARE;
12813 3 : case EXEC_OMP_DO:
12814 3 : return ST_OMP_DO;
12815 0 : case EXEC_OMP_LOOP:
12816 0 : return ST_OMP_LOOP;
12817 0 : case EXEC_OMP_ALLOCATE:
12818 0 : return ST_OMP_ALLOCATE_EXEC;
12819 0 : case EXEC_OMP_ALLOCATORS:
12820 0 : return ST_OMP_ALLOCATORS;
12821 0 : case EXEC_OMP_ASSUME:
12822 0 : return ST_OMP_ASSUME;
12823 1 : case EXEC_OMP_ATOMIC:
12824 1 : return ST_OMP_ATOMIC;
12825 1 : case EXEC_OMP_BARRIER:
12826 1 : return ST_OMP_BARRIER;
12827 1 : case EXEC_OMP_CANCEL:
12828 1 : return ST_OMP_CANCEL;
12829 1 : case EXEC_OMP_CANCELLATION_POINT:
12830 1 : return ST_OMP_CANCELLATION_POINT;
12831 0 : case EXEC_OMP_ERROR:
12832 0 : return ST_OMP_ERROR;
12833 1 : case EXEC_OMP_FLUSH:
12834 1 : return ST_OMP_FLUSH;
12835 0 : case EXEC_OMP_INTEROP:
12836 0 : return ST_OMP_INTEROP;
12837 1 : case EXEC_OMP_DISTRIBUTE:
12838 1 : return ST_OMP_DISTRIBUTE;
12839 1 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
12840 1 : return ST_OMP_DISTRIBUTE_PARALLEL_DO;
12841 1 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
12842 1 : return ST_OMP_DISTRIBUTE_PARALLEL_DO_SIMD;
12843 1 : case EXEC_OMP_DISTRIBUTE_SIMD:
12844 1 : return ST_OMP_DISTRIBUTE_SIMD;
12845 1 : case EXEC_OMP_DO_SIMD:
12846 1 : return ST_OMP_DO_SIMD;
12847 0 : case EXEC_OMP_SCAN:
12848 0 : return ST_OMP_SCAN;
12849 0 : case EXEC_OMP_SCOPE:
12850 0 : return ST_OMP_SCOPE;
12851 1 : case EXEC_OMP_SIMD:
12852 1 : return ST_OMP_SIMD;
12853 1 : case EXEC_OMP_TARGET:
12854 1 : return ST_OMP_TARGET;
12855 1 : case EXEC_OMP_TARGET_DATA:
12856 1 : return ST_OMP_TARGET_DATA;
12857 1 : case EXEC_OMP_TARGET_ENTER_DATA:
12858 1 : return ST_OMP_TARGET_ENTER_DATA;
12859 1 : case EXEC_OMP_TARGET_EXIT_DATA:
12860 1 : return ST_OMP_TARGET_EXIT_DATA;
12861 1 : case EXEC_OMP_TARGET_PARALLEL:
12862 1 : return ST_OMP_TARGET_PARALLEL;
12863 1 : case EXEC_OMP_TARGET_PARALLEL_DO:
12864 1 : return ST_OMP_TARGET_PARALLEL_DO;
12865 1 : case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
12866 1 : return ST_OMP_TARGET_PARALLEL_DO_SIMD;
12867 0 : case EXEC_OMP_TARGET_PARALLEL_LOOP:
12868 0 : return ST_OMP_TARGET_PARALLEL_LOOP;
12869 1 : case EXEC_OMP_TARGET_SIMD:
12870 1 : return ST_OMP_TARGET_SIMD;
12871 1 : case EXEC_OMP_TARGET_TEAMS:
12872 1 : return ST_OMP_TARGET_TEAMS;
12873 1 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
12874 1 : return ST_OMP_TARGET_TEAMS_DISTRIBUTE;
12875 1 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
12876 1 : return ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO;
12877 1 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
12878 1 : return ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD;
12879 1 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
12880 1 : return ST_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD;
12881 0 : case EXEC_OMP_TARGET_TEAMS_LOOP:
12882 0 : return ST_OMP_TARGET_TEAMS_LOOP;
12883 1 : case EXEC_OMP_TARGET_UPDATE:
12884 1 : return ST_OMP_TARGET_UPDATE;
12885 1 : case EXEC_OMP_TASKGROUP:
12886 1 : return ST_OMP_TASKGROUP;
12887 1 : case EXEC_OMP_TASKLOOP:
12888 1 : return ST_OMP_TASKLOOP;
12889 1 : case EXEC_OMP_TASKLOOP_SIMD:
12890 1 : return ST_OMP_TASKLOOP_SIMD;
12891 1 : case EXEC_OMP_TASKWAIT:
12892 1 : return ST_OMP_TASKWAIT;
12893 1 : case EXEC_OMP_TASKYIELD:
12894 1 : return ST_OMP_TASKYIELD;
12895 1 : case EXEC_OMP_TEAMS:
12896 1 : return ST_OMP_TEAMS;
12897 1 : case EXEC_OMP_TEAMS_DISTRIBUTE:
12898 1 : return ST_OMP_TEAMS_DISTRIBUTE;
12899 1 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
12900 1 : return ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO;
12901 1 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
12902 1 : return ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD;
12903 1 : case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
12904 1 : return ST_OMP_TEAMS_DISTRIBUTE_SIMD;
12905 0 : case EXEC_OMP_TEAMS_LOOP:
12906 0 : return ST_OMP_TEAMS_LOOP;
12907 6 : case EXEC_OMP_PARALLEL_DO:
12908 6 : return ST_OMP_PARALLEL_DO;
12909 1 : case EXEC_OMP_PARALLEL_DO_SIMD:
12910 1 : return ST_OMP_PARALLEL_DO_SIMD;
12911 0 : case EXEC_OMP_PARALLEL_LOOP:
12912 0 : return ST_OMP_PARALLEL_LOOP;
12913 1 : case EXEC_OMP_DEPOBJ:
12914 1 : return ST_OMP_DEPOBJ;
12915 0 : case EXEC_OMP_TILE:
12916 0 : return ST_OMP_TILE;
12917 0 : case EXEC_OMP_UNROLL:
12918 0 : return ST_OMP_UNROLL;
12919 0 : case EXEC_OMP_DISPATCH:
12920 0 : return ST_OMP_DISPATCH;
12921 0 : default:
12922 0 : gcc_unreachable ();
12923 : }
12924 : }
12925 :
12926 : static gfc_statement
12927 63 : oacc_code_to_statement (gfc_code *code)
12928 : {
12929 63 : switch (code->op)
12930 : {
12931 : case EXEC_OACC_PARALLEL:
12932 : return ST_OACC_PARALLEL;
12933 : case EXEC_OACC_KERNELS:
12934 : return ST_OACC_KERNELS;
12935 : case EXEC_OACC_SERIAL:
12936 : return ST_OACC_SERIAL;
12937 : case EXEC_OACC_DATA:
12938 : return ST_OACC_DATA;
12939 : case EXEC_OACC_HOST_DATA:
12940 : return ST_OACC_HOST_DATA;
12941 : case EXEC_OACC_PARALLEL_LOOP:
12942 : return ST_OACC_PARALLEL_LOOP;
12943 : case EXEC_OACC_KERNELS_LOOP:
12944 : return ST_OACC_KERNELS_LOOP;
12945 : case EXEC_OACC_SERIAL_LOOP:
12946 : return ST_OACC_SERIAL_LOOP;
12947 : case EXEC_OACC_LOOP:
12948 : return ST_OACC_LOOP;
12949 : case EXEC_OACC_ATOMIC:
12950 : return ST_OACC_ATOMIC;
12951 : case EXEC_OACC_ROUTINE:
12952 : return ST_OACC_ROUTINE;
12953 : case EXEC_OACC_UPDATE:
12954 : return ST_OACC_UPDATE;
12955 : case EXEC_OACC_WAIT:
12956 : return ST_OACC_WAIT;
12957 : case EXEC_OACC_CACHE:
12958 : return ST_OACC_CACHE;
12959 : case EXEC_OACC_ENTER_DATA:
12960 : return ST_OACC_ENTER_DATA;
12961 : case EXEC_OACC_EXIT_DATA:
12962 : return ST_OACC_EXIT_DATA;
12963 : case EXEC_OACC_DECLARE:
12964 : return ST_OACC_DECLARE;
12965 0 : default:
12966 0 : gcc_unreachable ();
12967 : }
12968 : }
12969 :
12970 : static void
12971 13168 : resolve_oacc_directive_inside_omp_region (gfc_code *code)
12972 : {
12973 13168 : if (omp_current_ctx != NULL && omp_current_ctx->is_openmp)
12974 : {
12975 11 : gfc_statement st = omp_code_to_statement (omp_current_ctx->code);
12976 11 : gfc_statement oacc_st = oacc_code_to_statement (code);
12977 11 : gfc_error ("The %s directive cannot be specified within "
12978 : "a %s region at %L", gfc_ascii_statement (oacc_st),
12979 : gfc_ascii_statement (st), &code->loc);
12980 : }
12981 13168 : }
12982 :
12983 : static void
12984 20795 : resolve_omp_directive_inside_oacc_region (gfc_code *code)
12985 : {
12986 20795 : if (omp_current_ctx != NULL && !omp_current_ctx->is_openmp)
12987 : {
12988 52 : gfc_statement st = oacc_code_to_statement (omp_current_ctx->code);
12989 52 : gfc_statement omp_st = omp_code_to_statement (code);
12990 52 : gfc_error ("The %s directive cannot be specified within "
12991 : "a %s region at %L", gfc_ascii_statement (omp_st),
12992 : gfc_ascii_statement (st), &code->loc);
12993 : }
12994 20795 : }
12995 :
12996 :
12997 : static void
12998 5272 : resolve_oacc_nested_loops (gfc_code *code, gfc_code* do_code, int collapse,
12999 : const char *clause)
13000 : {
13001 5272 : gfc_symbol *dovar;
13002 5272 : gfc_code *c;
13003 5272 : int i;
13004 :
13005 5792 : for (i = 1; i <= collapse; i++)
13006 : {
13007 5792 : if (do_code->op == EXEC_DO_WHILE)
13008 : {
13009 10 : gfc_error ("!$ACC LOOP cannot be a DO WHILE or DO without loop control "
13010 : "at %L", &do_code->loc);
13011 10 : break;
13012 : }
13013 5782 : if (do_code->op == EXEC_DO_CONCURRENT)
13014 : {
13015 3 : gfc_error ("!$ACC LOOP cannot be a DO CONCURRENT loop at %L",
13016 : &do_code->loc);
13017 3 : break;
13018 : }
13019 5779 : gcc_assert (do_code->op == EXEC_DO);
13020 5779 : if (do_code->ext.iterator->var->ts.type != BT_INTEGER)
13021 6 : gfc_error ("!$ACC LOOP iteration variable must be of type integer at %L",
13022 : &do_code->loc);
13023 5779 : dovar = do_code->ext.iterator->var->symtree->n.sym;
13024 5779 : if (i > 1)
13025 : {
13026 518 : gfc_code *do_code2 = code->block->next;
13027 518 : int j;
13028 :
13029 1218 : for (j = 1; j < i; j++)
13030 : {
13031 710 : gfc_symbol *ivar = do_code2->ext.iterator->var->symtree->n.sym;
13032 710 : if (dovar == ivar
13033 710 : || gfc_find_sym_in_expr (ivar, do_code->ext.iterator->start)
13034 701 : || gfc_find_sym_in_expr (ivar, do_code->ext.iterator->end)
13035 1410 : || gfc_find_sym_in_expr (ivar, do_code->ext.iterator->step))
13036 : {
13037 10 : gfc_error ("!$ACC LOOP %s loops don't form rectangular "
13038 : "iteration space at %L", clause, &do_code->loc);
13039 10 : break;
13040 : }
13041 700 : do_code2 = do_code2->block->next;
13042 : }
13043 : }
13044 5779 : if (i == collapse)
13045 : break;
13046 577 : for (c = do_code->next; c; c = c->next)
13047 48 : if (c->op != EXEC_NOP && c->op != EXEC_CONTINUE)
13048 : {
13049 0 : gfc_error ("%s !$ACC LOOP loops not perfectly nested at %L",
13050 : clause, &c->loc);
13051 0 : break;
13052 : }
13053 529 : if (c)
13054 : break;
13055 529 : do_code = do_code->block;
13056 529 : if (do_code->op != EXEC_DO && do_code->op != EXEC_DO_WHILE
13057 0 : && do_code->op != EXEC_DO_CONCURRENT)
13058 : {
13059 0 : gfc_error ("not enough DO loops for %s !$ACC LOOP at %L",
13060 : clause, &code->loc);
13061 0 : break;
13062 : }
13063 529 : do_code = do_code->next;
13064 529 : if (do_code == NULL
13065 522 : || (do_code->op != EXEC_DO && do_code->op != EXEC_DO_WHILE
13066 2 : && do_code->op != EXEC_DO_CONCURRENT))
13067 : {
13068 9 : gfc_error ("not enough DO loops for %s !$ACC LOOP at %L",
13069 : clause, &code->loc);
13070 9 : break;
13071 : }
13072 : }
13073 5272 : }
13074 :
13075 :
13076 : static void
13077 10119 : resolve_oacc_loop_blocks (gfc_code *code)
13078 : {
13079 10119 : if (!oacc_is_loop (code))
13080 : return;
13081 :
13082 5272 : if (code->ext.omp_clauses->tile_list && code->ext.omp_clauses->gang
13083 24 : && code->ext.omp_clauses->worker && code->ext.omp_clauses->vector)
13084 0 : gfc_error ("Tiled loop cannot be parallelized across gangs, workers and "
13085 : "vectors at the same time at %L", &code->loc);
13086 :
13087 5272 : if (code->ext.omp_clauses->tile_list)
13088 : {
13089 : gfc_expr_list *el;
13090 501 : for (el = code->ext.omp_clauses->tile_list; el; el = el->next)
13091 : {
13092 304 : if (el->expr == NULL)
13093 : {
13094 : /* NULL expressions are used to represent '*' arguments.
13095 : Convert those to a 0 expressions. */
13096 113 : el->expr = gfc_get_constant_expr (BT_INTEGER,
13097 : gfc_default_integer_kind,
13098 : &code->loc);
13099 113 : mpz_set_si (el->expr->value.integer, 0);
13100 : }
13101 : else
13102 : {
13103 191 : resolve_positive_int_expr (el->expr, "TILE");
13104 191 : if (el->expr->expr_type != EXPR_CONSTANT)
13105 14 : gfc_error ("TILE requires constant expression at %L",
13106 : &code->loc);
13107 : }
13108 : }
13109 : }
13110 : }
13111 :
13112 :
13113 : void
13114 10119 : gfc_resolve_oacc_blocks (gfc_code *code, gfc_namespace *ns)
13115 : {
13116 10119 : fortran_omp_context ctx;
13117 10119 : gfc_omp_clauses *omp_clauses = code->ext.omp_clauses;
13118 10119 : gfc_omp_namelist *n;
13119 :
13120 10119 : resolve_oacc_loop_blocks (code);
13121 :
13122 10119 : ctx.code = code;
13123 10119 : ctx.sharing_clauses = new hash_set<gfc_symbol *>;
13124 10119 : ctx.private_iterators = new hash_set<gfc_symbol *>;
13125 10119 : ctx.previous = omp_current_ctx;
13126 10119 : ctx.is_openmp = false;
13127 10119 : omp_current_ctx = &ctx;
13128 :
13129 404760 : for (enum gfc_omp_list_type list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
13130 394641 : list = gfc_omp_list_type (list + 1))
13131 394641 : switch (list)
13132 : {
13133 10119 : case OMP_LIST_PRIVATE:
13134 10710 : for (n = omp_clauses->lists[list]; n; n = n->next)
13135 591 : ctx.sharing_clauses->add (n->sym);
13136 : break;
13137 : default:
13138 : break;
13139 : }
13140 :
13141 10119 : gfc_resolve_blocks (code->block, ns);
13142 :
13143 10119 : omp_current_ctx = ctx.previous;
13144 20238 : delete ctx.sharing_clauses;
13145 20238 : delete ctx.private_iterators;
13146 10119 : }
13147 :
13148 :
13149 : static void
13150 5272 : resolve_oacc_loop (gfc_code *code)
13151 : {
13152 5272 : gfc_code *do_code;
13153 5272 : int collapse;
13154 :
13155 5272 : if (code->ext.omp_clauses)
13156 5272 : resolve_omp_clauses (code, code->ext.omp_clauses, NULL, true);
13157 :
13158 5272 : do_code = code->block->next;
13159 5272 : collapse = code->ext.omp_clauses->collapse;
13160 :
13161 : /* Both collapsed and tiled loops are lowered the same way, but are not
13162 : compatible. In gfc_trans_omp_do, the tile is prioritized. */
13163 5272 : if (code->ext.omp_clauses->tile_list)
13164 : {
13165 : int num = 0;
13166 : gfc_expr_list *el;
13167 501 : for (el = code->ext.omp_clauses->tile_list; el; el = el->next)
13168 304 : ++num;
13169 197 : resolve_oacc_nested_loops (code, code->block->next, num, "tiled");
13170 197 : return;
13171 : }
13172 :
13173 5075 : if (collapse <= 0)
13174 : collapse = 1;
13175 5075 : resolve_oacc_nested_loops (code, do_code, collapse, "collapsed");
13176 : }
13177 :
13178 : void
13179 332159 : gfc_resolve_oacc_declare (gfc_namespace *ns)
13180 : {
13181 332159 : enum gfc_omp_list_type list;
13182 332159 : gfc_omp_namelist *n;
13183 332159 : gfc_oacc_declare *oc;
13184 :
13185 332159 : if (ns->oacc_declare == NULL)
13186 : return;
13187 :
13188 290 : for (oc = ns->oacc_declare; oc; oc = oc->next)
13189 : {
13190 6480 : for (list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
13191 6318 : list = gfc_omp_list_type (list + 1))
13192 6574 : for (n = oc->clauses->lists[list]; n; n = n->next)
13193 : {
13194 256 : n->sym->mark = 0;
13195 256 : if (n->sym->attr.flavor != FL_VARIABLE
13196 16 : && (n->sym->attr.flavor != FL_PROCEDURE
13197 8 : || n->sym->result != n->sym))
13198 : {
13199 14 : if (n->sym->attr.flavor != FL_PARAMETER)
13200 : {
13201 8 : gfc_error ("Object %qs is not a variable at %L",
13202 : n->sym->name, &oc->loc);
13203 8 : continue;
13204 : }
13205 : /* Note that OpenACC 3.4 permits name constants, but the
13206 : implementation is permitted to ignore the clause;
13207 : as semantically, device_resident kind of makes sense
13208 : (and the wording with it is a bit odd), the warning
13209 : is suppressed. */
13210 6 : if (list != OMP_LIST_DEVICE_RESIDENT)
13211 5 : gfc_warning (OPT_Wsurprising, "Object %qs at %L is ignored as"
13212 : " parameters need not be copied", n->sym->name,
13213 : &oc->loc);
13214 : }
13215 :
13216 248 : if (n->expr && n->expr->ref->type == REF_ARRAY)
13217 : {
13218 1 : gfc_error ("Array sections: %qs not allowed in"
13219 1 : " !$ACC DECLARE at %L", n->sym->name, &oc->loc);
13220 1 : continue;
13221 : }
13222 : }
13223 :
13224 252 : for (n = oc->clauses->lists[OMP_LIST_DEVICE_RESIDENT]; n; n = n->next)
13225 90 : check_array_not_assumed (n->sym, oc->loc, "DEVICE_RESIDENT");
13226 : }
13227 :
13228 290 : for (oc = ns->oacc_declare; oc; oc = oc->next)
13229 : {
13230 6480 : for (list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
13231 6318 : list = gfc_omp_list_type (list + 1))
13232 6574 : for (n = oc->clauses->lists[list]; n; n = n->next)
13233 : {
13234 256 : if (n->sym->mark)
13235 : {
13236 9 : gfc_error ("Symbol %qs present on multiple clauses at %L",
13237 : n->sym->name, &oc->loc);
13238 9 : continue;
13239 : }
13240 : else
13241 247 : n->sym->mark = 1;
13242 : }
13243 : }
13244 :
13245 290 : for (oc = ns->oacc_declare; oc; oc = oc->next)
13246 : {
13247 6480 : for (list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
13248 6318 : list = gfc_omp_list_type (list + 1))
13249 6574 : for (n = oc->clauses->lists[list]; n; n = n->next)
13250 256 : n->sym->mark = 0;
13251 : }
13252 : }
13253 :
13254 :
13255 : void
13256 332159 : gfc_resolve_oacc_routines (gfc_namespace *ns)
13257 : {
13258 332159 : for (gfc_oacc_routine_name *orn = ns->oacc_routine_names;
13259 332259 : orn;
13260 100 : orn = orn->next)
13261 : {
13262 100 : gfc_symbol *sym = orn->sym;
13263 100 : if (!sym->attr.external
13264 29 : && !sym->attr.function
13265 27 : && !sym->attr.subroutine)
13266 : {
13267 7 : gfc_error ("NAME %qs does not refer to a subroutine or function"
13268 : " in !$ACC ROUTINE ( NAME ) at %L", sym->name, &orn->loc);
13269 7 : continue;
13270 : }
13271 93 : if (!gfc_add_omp_declare_target (&sym->attr, sym->name, &orn->loc))
13272 : {
13273 20 : gfc_error ("NAME %qs invalid"
13274 : " in !$ACC ROUTINE ( NAME ) at %L", sym->name, &orn->loc);
13275 20 : continue;
13276 : }
13277 : }
13278 332159 : }
13279 :
13280 :
13281 : void
13282 13168 : gfc_resolve_oacc_directive (gfc_code *code, gfc_namespace *ns ATTRIBUTE_UNUSED)
13283 : {
13284 13168 : resolve_oacc_directive_inside_omp_region (code);
13285 :
13286 13168 : switch (code->op)
13287 : {
13288 7353 : case EXEC_OACC_PARALLEL:
13289 7353 : case EXEC_OACC_KERNELS:
13290 7353 : case EXEC_OACC_SERIAL:
13291 7353 : case EXEC_OACC_DATA:
13292 7353 : case EXEC_OACC_HOST_DATA:
13293 7353 : case EXEC_OACC_UPDATE:
13294 7353 : case EXEC_OACC_ENTER_DATA:
13295 7353 : case EXEC_OACC_EXIT_DATA:
13296 7353 : case EXEC_OACC_WAIT:
13297 7353 : case EXEC_OACC_CACHE:
13298 7353 : resolve_omp_clauses (code, code->ext.omp_clauses, NULL, true);
13299 7353 : break;
13300 5272 : case EXEC_OACC_PARALLEL_LOOP:
13301 5272 : case EXEC_OACC_KERNELS_LOOP:
13302 5272 : case EXEC_OACC_SERIAL_LOOP:
13303 5272 : case EXEC_OACC_LOOP:
13304 5272 : resolve_oacc_loop (code);
13305 5272 : break;
13306 543 : case EXEC_OACC_ATOMIC:
13307 543 : resolve_omp_atomic (code);
13308 543 : break;
13309 : default:
13310 : break;
13311 : }
13312 13168 : }
13313 :
13314 :
13315 : static void
13316 1928 : resolve_omp_target (gfc_code *code)
13317 : {
13318 : #define GFC_IS_TEAMS_CONSTRUCT(op) \
13319 : (op == EXEC_OMP_TEAMS \
13320 : || op == EXEC_OMP_TEAMS_DISTRIBUTE \
13321 : || op == EXEC_OMP_TEAMS_DISTRIBUTE_SIMD \
13322 : || op == EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO \
13323 : || op == EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD \
13324 : || op == EXEC_OMP_TEAMS_LOOP)
13325 :
13326 1928 : if (!code->ext.omp_clauses->contains_teams_construct)
13327 : return;
13328 203 : gfc_code *c = code->block->next;
13329 203 : if (c->op == EXEC_BLOCK)
13330 30 : c = c->ext.block.ns->code;
13331 203 : if (code->ext.omp_clauses->target_first_st_is_teams_or_meta)
13332 : {
13333 192 : if (c->op == EXEC_OMP_METADIRECTIVE)
13334 : {
13335 15 : struct gfc_omp_variant *mc
13336 : = c->ext.omp_variants;
13337 : /* All mc->(next...->)code should be identical with regards
13338 : to the diagnostic below. */
13339 16 : do
13340 : {
13341 16 : if (mc->stmt != ST_NONE
13342 15 : && GFC_IS_TEAMS_CONSTRUCT (mc->code->op))
13343 : {
13344 14 : if (c->next == NULL && mc->code->next == NULL)
13345 : return;
13346 : c = mc->code;
13347 : break;
13348 : }
13349 2 : mc = mc->next;
13350 : }
13351 2 : while (mc);
13352 : }
13353 177 : else if (GFC_IS_TEAMS_CONSTRUCT (c->op) && c->next == NULL)
13354 : return;
13355 : }
13356 :
13357 31 : while (c && !GFC_IS_TEAMS_CONSTRUCT (c->op))
13358 8 : c = c->next;
13359 23 : if (c)
13360 19 : gfc_error ("!$OMP TARGET region at %L with a nested TEAMS at %L may not "
13361 : "contain any other statement, declaration or directive outside "
13362 : "of the single TEAMS construct", &c->loc, &code->loc);
13363 : else
13364 4 : gfc_error ("!$OMP TARGET region at %L with a nested TEAMS may not "
13365 : "contain any other statement, declaration or directive outside "
13366 : "of the single TEAMS construct", &code->loc);
13367 : #undef GFC_IS_TEAMS_CONSTRUCT
13368 : }
13369 :
13370 : static void
13371 154 : resolve_omp_dispatch (gfc_code *code)
13372 : {
13373 154 : gfc_code *next = code->block->next;
13374 154 : if (next == NULL)
13375 : return;
13376 :
13377 151 : gfc_exec_op op = next->op;
13378 151 : gcc_assert (op == EXEC_CALL || op == EXEC_ASSIGN);
13379 151 : if (op != EXEC_CALL
13380 74 : && (op != EXEC_ASSIGN || next->expr2->expr_type != EXPR_FUNCTION))
13381 3 : gfc_error (
13382 : "%<OMP DISPATCH%> directive at %L must be followed by a procedure "
13383 : "call with optional assignment",
13384 : &code->loc);
13385 :
13386 77 : if ((op == EXEC_CALL && next->resolved_sym != NULL
13387 76 : && next->resolved_sym->attr.proc_pointer)
13388 150 : || (op == EXEC_ASSIGN && gfc_expr_attr (next->expr2).proc_pointer))
13389 1 : gfc_error ("%<OMP DISPATCH%> directive at %L cannot be followed by a "
13390 : "procedure pointer",
13391 : &code->loc);
13392 : }
13393 :
13394 : /* Resolve OpenMP directive clauses and check various requirements
13395 : of each directive. */
13396 :
13397 : void
13398 20795 : gfc_resolve_omp_directive (gfc_code *code, gfc_namespace *ns)
13399 : {
13400 20795 : resolve_omp_directive_inside_oacc_region (code);
13401 :
13402 20795 : if (code->op != EXEC_OMP_ATOMIC)
13403 18641 : gfc_maybe_initialize_eh ();
13404 :
13405 20795 : switch (code->op)
13406 : {
13407 5420 : case EXEC_OMP_DISTRIBUTE:
13408 5420 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
13409 5420 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
13410 5420 : case EXEC_OMP_DISTRIBUTE_SIMD:
13411 5420 : case EXEC_OMP_DO:
13412 5420 : case EXEC_OMP_DO_SIMD:
13413 5420 : case EXEC_OMP_LOOP:
13414 5420 : case EXEC_OMP_PARALLEL_DO:
13415 5420 : case EXEC_OMP_PARALLEL_DO_SIMD:
13416 5420 : case EXEC_OMP_PARALLEL_LOOP:
13417 5420 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
13418 5420 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
13419 5420 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
13420 5420 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
13421 5420 : case EXEC_OMP_MASKED_TASKLOOP:
13422 5420 : case EXEC_OMP_MASKED_TASKLOOP_SIMD:
13423 5420 : case EXEC_OMP_MASTER_TASKLOOP:
13424 5420 : case EXEC_OMP_MASTER_TASKLOOP_SIMD:
13425 5420 : case EXEC_OMP_SIMD:
13426 5420 : case EXEC_OMP_TARGET_PARALLEL_DO:
13427 5420 : case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
13428 5420 : case EXEC_OMP_TARGET_PARALLEL_LOOP:
13429 5420 : case EXEC_OMP_TARGET_SIMD:
13430 5420 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
13431 5420 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
13432 5420 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
13433 5420 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
13434 5420 : case EXEC_OMP_TARGET_TEAMS_LOOP:
13435 5420 : case EXEC_OMP_TASKLOOP:
13436 5420 : case EXEC_OMP_TASKLOOP_SIMD:
13437 5420 : case EXEC_OMP_TEAMS_DISTRIBUTE:
13438 5420 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
13439 5420 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
13440 5420 : case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
13441 5420 : case EXEC_OMP_TEAMS_LOOP:
13442 5420 : case EXEC_OMP_TILE:
13443 5420 : case EXEC_OMP_UNROLL:
13444 5420 : resolve_omp_do (code);
13445 5420 : break;
13446 1928 : case EXEC_OMP_TARGET:
13447 1928 : resolve_omp_target (code);
13448 9848 : gcc_fallthrough ();
13449 9848 : case EXEC_OMP_ALLOCATE:
13450 9848 : case EXEC_OMP_ALLOCATORS:
13451 9848 : case EXEC_OMP_ASSUME:
13452 9848 : case EXEC_OMP_CANCEL:
13453 9848 : case EXEC_OMP_ERROR:
13454 9848 : case EXEC_OMP_INTEROP:
13455 9848 : case EXEC_OMP_MASKED:
13456 9848 : case EXEC_OMP_ORDERED:
13457 9848 : case EXEC_OMP_PARALLEL_WORKSHARE:
13458 9848 : case EXEC_OMP_PARALLEL:
13459 9848 : case EXEC_OMP_PARALLEL_MASKED:
13460 9848 : case EXEC_OMP_PARALLEL_MASTER:
13461 9848 : case EXEC_OMP_PARALLEL_SECTIONS:
13462 9848 : case EXEC_OMP_SCOPE:
13463 9848 : case EXEC_OMP_SECTIONS:
13464 9848 : case EXEC_OMP_SINGLE:
13465 9848 : case EXEC_OMP_TARGET_DATA:
13466 9848 : case EXEC_OMP_TARGET_ENTER_DATA:
13467 9848 : case EXEC_OMP_TARGET_EXIT_DATA:
13468 9848 : case EXEC_OMP_TARGET_PARALLEL:
13469 9848 : case EXEC_OMP_TARGET_TEAMS:
13470 9848 : case EXEC_OMP_TASK:
13471 9848 : case EXEC_OMP_TASKWAIT:
13472 9848 : case EXEC_OMP_TEAMS:
13473 9848 : case EXEC_OMP_WORKSHARE:
13474 9848 : case EXEC_OMP_DEPOBJ:
13475 9848 : if (code->ext.omp_clauses)
13476 9715 : resolve_omp_clauses (code, code->ext.omp_clauses, NULL);
13477 : break;
13478 1704 : case EXEC_OMP_TARGET_UPDATE:
13479 1704 : if (code->ext.omp_clauses)
13480 1704 : resolve_omp_clauses (code, code->ext.omp_clauses, NULL);
13481 1704 : if (code->ext.omp_clauses == NULL
13482 1704 : || (code->ext.omp_clauses->lists[OMP_LIST_TO] == NULL
13483 992 : && code->ext.omp_clauses->lists[OMP_LIST_FROM] == NULL))
13484 0 : gfc_error ("OMP TARGET UPDATE at %L requires at least one TO or "
13485 : "FROM clause", &code->loc);
13486 : break;
13487 2154 : case EXEC_OMP_ATOMIC:
13488 2154 : resolve_omp_clauses (code, code->block->ext.omp_clauses, NULL);
13489 2154 : resolve_omp_atomic (code);
13490 2154 : break;
13491 159 : case EXEC_OMP_CRITICAL:
13492 159 : resolve_omp_clauses (code, code->ext.omp_clauses, NULL);
13493 159 : if (!code->ext.omp_clauses->critical_name
13494 112 : && code->ext.omp_clauses->hint
13495 3 : && code->ext.omp_clauses->hint->ts.type == BT_INTEGER
13496 3 : && code->ext.omp_clauses->hint->expr_type == EXPR_CONSTANT
13497 3 : && mpz_sgn (code->ext.omp_clauses->hint->value.integer) != 0)
13498 1 : gfc_error ("OMP CRITICAL at %L with HINT clause requires a NAME, "
13499 : "except when omp_sync_hint_none is used", &code->loc);
13500 : break;
13501 49 : case EXEC_OMP_SCAN:
13502 : /* Flag is only used to checking, hence, it is unset afterwards. */
13503 49 : if (!code->ext.omp_clauses->if_present)
13504 10 : gfc_error ("Unexpected !$OMP SCAN at %L outside loop construct with "
13505 : "%<inscan%> REDUCTION clause", &code->loc);
13506 49 : code->ext.omp_clauses->if_present = false;
13507 49 : resolve_omp_clauses (code, code->ext.omp_clauses, ns);
13508 49 : break;
13509 154 : case EXEC_OMP_DISPATCH:
13510 154 : if (code->ext.omp_clauses)
13511 154 : resolve_omp_clauses (code, code->ext.omp_clauses, ns);
13512 154 : resolve_omp_dispatch (code);
13513 154 : break;
13514 138 : case EXEC_OMP_METADIRECTIVE:
13515 138 : resolve_omp_metadirective (code, ns);
13516 138 : break;
13517 : default:
13518 : break;
13519 : }
13520 20795 : }
13521 :
13522 : /* Resolve !$omp declare {variant|simd} constructs in NS.
13523 : Note that !$omp declare target is resolved in resolve_symbol. */
13524 :
13525 : void
13526 343587 : gfc_resolve_omp_declare (gfc_namespace *ns)
13527 : {
13528 343587 : gfc_omp_declare_simd *ods;
13529 343823 : for (ods = ns->omp_declare_simd; ods; ods = ods->next)
13530 : {
13531 236 : if (ods->proc_name != NULL
13532 196 : && ods->proc_name != ns->proc_name)
13533 6 : gfc_error ("!$OMP DECLARE SIMD should refer to containing procedure "
13534 : "%qs at %L", ns->proc_name->name, &ods->where);
13535 236 : if (ods->clauses)
13536 218 : resolve_omp_clauses (NULL, ods->clauses, ns);
13537 : }
13538 :
13539 343587 : gfc_omp_declare_variant *odv;
13540 343587 : gfc_omp_namelist *range_begin = NULL;
13541 :
13542 344041 : for (odv = ns->omp_declare_variant; odv; odv = odv->next)
13543 454 : gfc_resolve_omp_context_selector (odv->set_selectors, false, nullptr);
13544 344041 : for (odv = ns->omp_declare_variant; odv; odv = odv->next)
13545 657 : for (gfc_omp_namelist *n = odv->adjust_args_list; n != NULL; n = n->next)
13546 : {
13547 203 : if ((n->expr == NULL
13548 6 : && (range_begin
13549 4 : || n->u.adj_args.range_start
13550 1 : || n->u.adj_args.omp_num_args_plus
13551 1 : || n->u.adj_args.omp_num_args_minus))
13552 198 : || n->u.adj_args.error_p)
13553 : {
13554 : }
13555 197 : else if (range_begin
13556 191 : || n->u.adj_args.range_start
13557 186 : || n->u.adj_args.omp_num_args_plus
13558 186 : || n->u.adj_args.omp_num_args_minus)
13559 : {
13560 11 : if (!n->expr
13561 11 : || !gfc_resolve_expr (n->expr)
13562 11 : || n->expr->expr_type != EXPR_CONSTANT
13563 10 : || n->expr->ts.type != BT_INTEGER
13564 10 : || n->expr->rank != 0
13565 10 : || mpz_sgn (n->expr->value.integer) < 0
13566 20 : || ((n->u.adj_args.omp_num_args_plus
13567 8 : || n->u.adj_args.omp_num_args_minus)
13568 5 : && mpz_sgn (n->expr->value.integer) == 0))
13569 : {
13570 2 : if (n->u.adj_args.omp_num_args_plus
13571 2 : || n->u.adj_args.omp_num_args_minus)
13572 0 : gfc_error ("Expected constant non-negative scalar integer "
13573 : "offset expression at %L", &n->where);
13574 : else
13575 2 : gfc_error ("For range-based %<adjust_args%>, a constant "
13576 : "positive scalar integer expression is required "
13577 : "at %L", &n->where);
13578 : }
13579 : }
13580 186 : else if (n->expr
13581 186 : && n->expr->expr_type == EXPR_CONSTANT
13582 21 : && n->expr->ts.type == BT_INTEGER
13583 20 : && mpz_sgn (n->expr->value.integer) > 0)
13584 : {
13585 : }
13586 166 : else if (!n->expr
13587 166 : || !gfc_resolve_expr (n->expr)
13588 331 : || n->expr->expr_type != EXPR_VARIABLE)
13589 2 : gfc_error ("Expected dummy parameter name or a positive integer "
13590 : "at %L", &n->where);
13591 164 : else if (n->expr->expr_type == EXPR_VARIABLE)
13592 164 : n->sym = n->expr->symtree->n.sym;
13593 :
13594 203 : range_begin = n->u.adj_args.range_start ? n : NULL;
13595 : }
13596 343587 : }
13597 :
13598 : struct omp_udr_callback_data
13599 : {
13600 : gfc_omp_udr *omp_udr;
13601 : bool is_initializer;
13602 : };
13603 :
13604 : static int
13605 3598 : omp_udr_callback (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
13606 : void *data)
13607 : {
13608 3598 : struct omp_udr_callback_data *cd = (struct omp_udr_callback_data *) data;
13609 3598 : if ((*e)->expr_type == EXPR_VARIABLE)
13610 : {
13611 2203 : if (cd->is_initializer)
13612 : {
13613 535 : if ((*e)->symtree->n.sym != cd->omp_udr->omp_priv
13614 140 : && (*e)->symtree->n.sym != cd->omp_udr->omp_orig)
13615 4 : gfc_error ("Variable other than OMP_PRIV or OMP_ORIG used in "
13616 : "INITIALIZER clause of !$OMP DECLARE REDUCTION at %L",
13617 : &(*e)->where);
13618 : }
13619 : else
13620 : {
13621 1668 : if ((*e)->symtree->n.sym != cd->omp_udr->omp_out
13622 597 : && (*e)->symtree->n.sym != cd->omp_udr->omp_in)
13623 6 : gfc_error ("Variable other than OMP_OUT or OMP_IN used in "
13624 : "combiner of !$OMP DECLARE REDUCTION at %L",
13625 : &(*e)->where);
13626 : }
13627 : }
13628 3598 : return 0;
13629 : }
13630 :
13631 : /* Resolve !$omp declare reduction constructs. */
13632 :
13633 : static void
13634 600 : gfc_resolve_omp_udr (gfc_omp_udr *omp_udr)
13635 : {
13636 600 : gfc_actual_arglist *a;
13637 600 : const char *predef_name = NULL;
13638 :
13639 600 : switch (omp_udr->rop)
13640 : {
13641 599 : case OMP_REDUCTION_PLUS:
13642 599 : case OMP_REDUCTION_TIMES:
13643 599 : case OMP_REDUCTION_MINUS:
13644 599 : case OMP_REDUCTION_AND:
13645 599 : case OMP_REDUCTION_OR:
13646 599 : case OMP_REDUCTION_EQV:
13647 599 : case OMP_REDUCTION_NEQV:
13648 599 : case OMP_REDUCTION_MAX:
13649 599 : case OMP_REDUCTION_USER:
13650 599 : break;
13651 1 : default:
13652 1 : gfc_error ("Invalid operator for !$OMP DECLARE REDUCTION %s at %L",
13653 : omp_udr->name, &omp_udr->where);
13654 22 : return;
13655 : }
13656 :
13657 599 : if (gfc_omp_udr_predef (omp_udr->rop, omp_udr->name,
13658 : &omp_udr->ts, &predef_name))
13659 : {
13660 18 : if (predef_name)
13661 18 : gfc_error_now ("Redefinition of predefined %s "
13662 : "!$OMP DECLARE REDUCTION at %L",
13663 : predef_name, &omp_udr->where);
13664 : else
13665 0 : gfc_error_now ("Redefinition of predefined "
13666 : "!$OMP DECLARE REDUCTION at %L", &omp_udr->where);
13667 18 : return;
13668 : }
13669 :
13670 581 : if (omp_udr->ts.type == BT_CHARACTER
13671 62 : && omp_udr->ts.u.cl->length
13672 32 : && omp_udr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
13673 : {
13674 1 : gfc_error ("CHARACTER length in !$OMP DECLARE REDUCTION %s not "
13675 : "constant at %L", omp_udr->name, &omp_udr->where);
13676 1 : return;
13677 : }
13678 :
13679 580 : struct omp_udr_callback_data cd;
13680 580 : cd.omp_udr = omp_udr;
13681 580 : cd.is_initializer = false;
13682 580 : gfc_code_walker (&omp_udr->combiner_ns->code, gfc_dummy_code_callback,
13683 : omp_udr_callback, &cd);
13684 580 : if (omp_udr->combiner_ns->code->op == EXEC_CALL)
13685 : {
13686 346 : for (a = omp_udr->combiner_ns->code->ext.actual; a; a = a->next)
13687 237 : if (a->expr == NULL)
13688 : break;
13689 110 : if (a)
13690 1 : gfc_error ("Subroutine call with alternate returns in combiner "
13691 : "of !$OMP DECLARE REDUCTION at %L",
13692 : &omp_udr->combiner_ns->code->loc);
13693 : }
13694 580 : if (omp_udr->initializer_ns)
13695 : {
13696 373 : cd.is_initializer = true;
13697 373 : gfc_code_walker (&omp_udr->initializer_ns->code, gfc_dummy_code_callback,
13698 : omp_udr_callback, &cd);
13699 373 : if (omp_udr->initializer_ns->code->op == EXEC_CALL)
13700 : {
13701 377 : for (a = omp_udr->initializer_ns->code->ext.actual; a; a = a->next)
13702 243 : if (a->expr == NULL)
13703 : break;
13704 135 : if (a)
13705 1 : gfc_error ("Subroutine call with alternate returns in "
13706 : "INITIALIZER clause of !$OMP DECLARE REDUCTION "
13707 : "at %L", &omp_udr->initializer_ns->code->loc);
13708 136 : for (a = omp_udr->initializer_ns->code->ext.actual; a; a = a->next)
13709 135 : if (a->expr
13710 135 : && a->expr->expr_type == EXPR_VARIABLE
13711 135 : && a->expr->symtree->n.sym == omp_udr->omp_priv
13712 134 : && a->expr->ref == NULL)
13713 : break;
13714 135 : if (a == NULL)
13715 1 : gfc_error ("One of actual subroutine arguments in INITIALIZER "
13716 : "clause of !$OMP DECLARE REDUCTION must be OMP_PRIV "
13717 : "at %L", &omp_udr->initializer_ns->code->loc);
13718 : }
13719 : }
13720 207 : else if (omp_udr->ts.type == BT_DERIVED
13721 207 : && !gfc_has_default_initializer (omp_udr->ts.u.derived))
13722 : {
13723 1 : gfc_error ("Missing INITIALIZER clause for !$OMP DECLARE REDUCTION "
13724 : "of derived type without default initializer at %L",
13725 : &omp_udr->where);
13726 1 : return;
13727 : }
13728 : }
13729 :
13730 : void
13731 344595 : gfc_resolve_omp_udrs (gfc_symtree *st)
13732 : {
13733 344595 : gfc_omp_udr *omp_udr;
13734 :
13735 344595 : if (st == NULL)
13736 : return;
13737 504 : gfc_resolve_omp_udrs (st->left);
13738 504 : gfc_resolve_omp_udrs (st->right);
13739 1104 : for (omp_udr = st->n.omp_udr; omp_udr; omp_udr = omp_udr->next)
13740 600 : gfc_resolve_omp_udr (omp_udr);
13741 : }
|