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 : {"cancellation_point", GFC_OMP_DIR_EXECUTABLE, ST_OMP_CANCELLATION_POINT},
71 : {"cancel", GFC_OMP_DIR_EXECUTABLE, ST_OMP_CANCEL},
72 : {"critical", GFC_OMP_DIR_EXECUTABLE, ST_OMP_CRITICAL},
73 : /* {"declare induction", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_INDUCTION}, */
74 : /* {"declare_induction", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_INDUCTION}, */
75 : {"declare mapper", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_MAPPER},
76 : {"declare_mapper", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_MAPPER},
77 : {"declare reduction", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_REDUCTION},
78 : {"declare_reduction", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_REDUCTION},
79 : {"declare simd", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_SIMD},
80 : {"declare_simd", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_SIMD},
81 : {"declare target", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_TARGET},
82 : {"declare_target", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_TARGET},
83 : {"declare variant", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_VARIANT},
84 : {"declare_variant", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_VARIANT},
85 : {"depobj", GFC_OMP_DIR_EXECUTABLE, ST_OMP_DEPOBJ},
86 : {"dispatch", GFC_OMP_DIR_EXECUTABLE, ST_OMP_DISPATCH},
87 : {"distribute", GFC_OMP_DIR_EXECUTABLE, ST_OMP_DISTRIBUTE},
88 : {"do", GFC_OMP_DIR_EXECUTABLE, ST_OMP_DO},
89 : /* "error" becomes GFC_OMP_DIR_EXECUTABLE with at(execution) */
90 : {"error", GFC_OMP_DIR_UTILITY, ST_OMP_ERROR},
91 : /* {"flatten", GFC_OMP_DIR_EXECUTABLE, ST_OMP_FLATTEN}, */
92 : {"flush", GFC_OMP_DIR_EXECUTABLE, ST_OMP_FLUSH},
93 : /* {"fuse", GFC_OMP_DIR_EXECUTABLE, ST_OMP_FLUSE}, */
94 : {"groupprivate", GFC_OMP_DIR_DECLARATIVE, ST_OMP_GROUPPRIVATE},
95 : /* {"interchange", GFC_OMP_DIR_EXECUTABLE, ST_OMP_INTERCHANGE}, */
96 : {"interop", GFC_OMP_DIR_EXECUTABLE, ST_OMP_INTEROP},
97 : {"loop", GFC_OMP_DIR_EXECUTABLE, ST_OMP_LOOP},
98 : {"masked", GFC_OMP_DIR_EXECUTABLE, ST_OMP_MASKED},
99 : {"metadirective", GFC_OMP_DIR_META, ST_OMP_METADIRECTIVE},
100 : /* Note: gfc_match_omp_nothing returns ST_NONE. */
101 : {"nothing", GFC_OMP_DIR_UTILITY, ST_OMP_NOTHING},
102 : /* Special case; for now map to the first one.
103 : ordered-blockassoc = ST_OMP_ORDERED
104 : ordered-standalone = ST_OMP_ORDERED_DEPEND + depend/doacross. */
105 : {"ordered", GFC_OMP_DIR_EXECUTABLE, ST_OMP_ORDERED},
106 : {"parallel", GFC_OMP_DIR_EXECUTABLE, ST_OMP_PARALLEL},
107 : {"requires", GFC_OMP_DIR_INFORMATIONAL, ST_OMP_REQUIRES},
108 : {"scan", GFC_OMP_DIR_SUBSIDIARY, ST_OMP_SCAN},
109 : {"scope", GFC_OMP_DIR_EXECUTABLE, ST_OMP_SCOPE},
110 : {"sections", GFC_OMP_DIR_EXECUTABLE, ST_OMP_SECTIONS},
111 : {"section", GFC_OMP_DIR_SUBSIDIARY, ST_OMP_SECTION},
112 : {"simd", GFC_OMP_DIR_EXECUTABLE, ST_OMP_SIMD},
113 : {"single", GFC_OMP_DIR_EXECUTABLE, ST_OMP_SINGLE},
114 : /* {"split", GFC_OMP_DIR_EXECUTABLE, ST_OMP_SPLIT}, */
115 : /* {"strip", GFC_OMP_DIR_EXECUTABLE, ST_OMP_STRIP}, */
116 : {"target data", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TARGET_DATA},
117 : {"target_data", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TARGET_DATA},
118 : {"target enter data", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TARGET_ENTER_DATA},
119 : {"target_enter_data", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TARGET_ENTER_DATA},
120 : {"target exit data", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TARGET_EXIT_DATA},
121 : {"target_exit_data", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TARGET_EXIT_DATA},
122 : {"target update", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TARGET_UPDATE},
123 : {"target_update", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TARGET_UPDATE},
124 : {"target", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TARGET},
125 : /* {"taskgraph", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TASKGRAPH}, */
126 : /* {"task iteration", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TASK_ITERATION}, */
127 : {"taskloop", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TASKLOOP},
128 : {"taskwait", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TASKWAIT},
129 : {"taskyield", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TASKYIELD},
130 : {"task", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TASK},
131 : {"teams", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TEAMS},
132 : {"threadprivate", GFC_OMP_DIR_DECLARATIVE, ST_OMP_THREADPRIVATE},
133 : {"tile", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TILE},
134 : {"unroll", GFC_OMP_DIR_EXECUTABLE, ST_OMP_UNROLL},
135 : /* {"workdistribute", GFC_OMP_DIR_EXECUTABLE, ST_OMP_WORKDISTRIBUTE}, */
136 : {"workshare", GFC_OMP_DIR_EXECUTABLE, ST_OMP_WORKSHARE},
137 : };
138 :
139 :
140 : /* Match an end of OpenMP directive. End of OpenMP directive is optional
141 : whitespace, followed by '\n' or comment '!'. In the special case where a
142 : context selector is being matched, match against ')' instead. */
143 :
144 : static match
145 56346 : gfc_match_omp_eos (void)
146 : {
147 56346 : locus old_loc;
148 56346 : char c;
149 :
150 56346 : old_loc = gfc_current_locus;
151 56346 : gfc_gobble_whitespace ();
152 :
153 56346 : if (gfc_matching_omp_context_selector)
154 : {
155 287 : if (gfc_peek_ascii_char () == ')')
156 : return MATCH_YES;
157 : }
158 : else
159 : {
160 56059 : c = gfc_next_ascii_char ();
161 56059 : switch (c)
162 : {
163 0 : case '!':
164 0 : do
165 0 : c = gfc_next_ascii_char ();
166 0 : while (c != '\n');
167 : /* Fall through */
168 :
169 : case '\n':
170 : return MATCH_YES;
171 : }
172 : }
173 :
174 1795 : gfc_current_locus = old_loc;
175 1795 : return MATCH_NO;
176 : }
177 :
178 : match
179 13228 : gfc_match_omp_eos_error (void)
180 : {
181 13228 : if (gfc_match_omp_eos() == MATCH_YES)
182 : return MATCH_YES;
183 :
184 35 : gfc_error ("Unexpected junk at %C");
185 35 : return MATCH_ERROR;
186 : }
187 :
188 :
189 : /* Free an omp_clauses structure. */
190 :
191 : void
192 83867 : gfc_free_omp_clauses (gfc_omp_clauses *c)
193 : {
194 83867 : if (c == NULL)
195 : return;
196 :
197 56828 : gfc_free_expr (c->if_expr);
198 681936 : for (int i = 0; i < OMP_IF_LAST; i++)
199 568280 : gfc_free_expr (c->if_exprs[i]);
200 56828 : gfc_free_expr (c->self_expr);
201 56828 : gfc_free_expr (c->final_expr);
202 56828 : gfc_free_expr (c->chunk_size);
203 56828 : gfc_free_expr (c->safelen_expr);
204 56828 : gfc_free_expr (c->simdlen_expr);
205 56828 : gfc_free_expr (c->simdlen_divisor);
206 56828 : gfc_free_expr (c->device);
207 56828 : gfc_free_expr (c->dyn_groupprivate);
208 56828 : gfc_free_expr (c->dist_chunk_size);
209 56828 : gfc_free_expr (c->grainsize);
210 56828 : gfc_free_expr (c->hint);
211 56828 : gfc_free_expr (c->num_tasks);
212 56828 : gfc_free_expr (c->priority);
213 56828 : gfc_free_expr (c->detach);
214 56828 : gfc_free_expr (c->novariants);
215 56828 : gfc_free_expr (c->nocontext);
216 56828 : gfc_free_expr (c->async_expr);
217 56828 : gfc_free_expr (c->gang_num_expr);
218 56828 : gfc_free_expr (c->gang_static_expr);
219 56828 : gfc_free_expr (c->worker_expr);
220 56828 : gfc_free_expr (c->vector_expr);
221 56828 : gfc_free_expr (c->num_gangs_expr);
222 56828 : gfc_free_expr (c->num_workers_expr);
223 56828 : gfc_free_expr (c->vector_length_expr);
224 56828 : gfc_free_expr (c->device_num_expr);
225 2329948 : for (enum gfc_omp_list_type t = OMP_LIST_FIRST; t < OMP_LIST_NUM;
226 2216292 : t = gfc_omp_list_type (t + 1))
227 2216292 : gfc_free_omp_namelist (c->lists[t], t);
228 56828 : gfc_free_expr_list (c->num_teams_list);
229 56828 : gfc_free_expr_list (c->thread_limit_list);
230 56828 : gfc_free_expr_list (c->num_threads_list);
231 56828 : gfc_free_expr_list (c->wait_list);
232 56828 : gfc_free_expr_list (c->tile_list);
233 56828 : gfc_free_expr_list (c->sizes_list);
234 56828 : free (const_cast<char *> (c->critical_name));
235 56828 : if (c->assume)
236 : {
237 33 : free (c->assume->absent);
238 33 : free (c->assume->contains);
239 33 : gfc_free_expr_list (c->assume->holds);
240 33 : free (c->assume);
241 : }
242 56828 : free (c);
243 : }
244 :
245 : /* Free oacc_declare structures. */
246 :
247 : void
248 76 : gfc_free_oacc_declare_clauses (struct gfc_oacc_declare *oc)
249 : {
250 76 : struct gfc_oacc_declare *decl = oc;
251 :
252 76 : do
253 : {
254 76 : struct gfc_oacc_declare *next;
255 :
256 76 : next = decl->next;
257 76 : gfc_free_omp_clauses (decl->clauses);
258 76 : free (decl);
259 76 : decl = next;
260 : }
261 76 : while (decl);
262 76 : }
263 :
264 : /* Free expression list. */
265 : void
266 342511 : gfc_free_expr_list (gfc_expr_list *list)
267 : {
268 342511 : gfc_expr_list *n;
269 :
270 345453 : for (; list; list = n)
271 : {
272 2942 : n = list->next;
273 2942 : free (list);
274 : }
275 342511 : }
276 :
277 : /* Free an !$omp declare simd construct list. */
278 :
279 : void
280 252 : gfc_free_omp_declare_simd (gfc_omp_declare_simd *ods)
281 : {
282 252 : if (ods)
283 : {
284 252 : gfc_free_omp_clauses (ods->clauses);
285 252 : free (ods);
286 : }
287 252 : }
288 :
289 : void
290 550659 : gfc_free_omp_declare_simd_list (gfc_omp_declare_simd *list)
291 : {
292 550911 : while (list)
293 : {
294 252 : gfc_omp_declare_simd *current = list;
295 252 : list = list->next;
296 252 : gfc_free_omp_declare_simd (current);
297 : }
298 550659 : }
299 :
300 : static void
301 762 : gfc_free_omp_trait_property_list (gfc_omp_trait_property *list)
302 : {
303 1194 : while (list)
304 : {
305 432 : gfc_omp_trait_property *current = list;
306 432 : list = list->next;
307 432 : switch (current->property_kind)
308 : {
309 24 : case OMP_TRAIT_PROPERTY_ID:
310 24 : free (current->name);
311 24 : break;
312 265 : case OMP_TRAIT_PROPERTY_NAME_LIST:
313 265 : if (current->is_name)
314 170 : free (current->name);
315 : break;
316 31 : case OMP_TRAIT_PROPERTY_CLAUSE_LIST:
317 31 : gfc_free_omp_clauses (current->clauses);
318 31 : break;
319 : default:
320 : break;
321 : }
322 432 : free (current);
323 : }
324 762 : }
325 :
326 : static void
327 629 : gfc_free_omp_selector_list (gfc_omp_selector *list)
328 : {
329 1391 : while (list)
330 : {
331 762 : gfc_omp_selector *current = list;
332 762 : list = list->next;
333 762 : gfc_free_omp_trait_property_list (current->properties);
334 762 : free (current);
335 : }
336 629 : }
337 :
338 : static void
339 700 : gfc_free_omp_set_selector_list (gfc_omp_set_selector *list)
340 : {
341 1329 : while (list)
342 : {
343 629 : gfc_omp_set_selector *current = list;
344 629 : list = list->next;
345 629 : gfc_free_omp_selector_list (current->trait_selectors);
346 629 : free (current);
347 : }
348 700 : }
349 :
350 : /* Free an !$omp declare variant construct list. */
351 :
352 : void
353 550659 : gfc_free_omp_declare_variant_list (gfc_omp_declare_variant *list)
354 : {
355 551136 : while (list)
356 : {
357 477 : gfc_omp_declare_variant *current = list;
358 477 : list = list->next;
359 477 : gfc_free_omp_set_selector_list (current->set_selectors);
360 477 : gfc_free_omp_namelist (current->adjust_args_list, OMP_LIST_NONE);
361 477 : free (current);
362 : }
363 550659 : }
364 :
365 : /* Free an !$omp declare reduction. */
366 :
367 : void
368 1285 : gfc_free_omp_udr (gfc_omp_udr *omp_udr)
369 : {
370 1285 : if (omp_udr)
371 : {
372 692 : gfc_free_omp_udr (omp_udr->next);
373 692 : gfc_free_namespace (omp_udr->combiner_ns);
374 692 : if (omp_udr->initializer_ns)
375 392 : gfc_free_namespace (omp_udr->initializer_ns);
376 692 : free (omp_udr);
377 : }
378 1285 : }
379 :
380 : /* Free variants of an !$omp metadirective construct. */
381 :
382 : void
383 97 : gfc_free_omp_variants (gfc_omp_variant *variant)
384 : {
385 297 : while (variant)
386 : {
387 200 : gfc_omp_variant *next_variant = variant->next;
388 200 : gfc_free_omp_set_selector_list (variant->selectors);
389 200 : free (variant);
390 200 : variant = next_variant;
391 : }
392 97 : }
393 :
394 : /* Free an !$omp declare mapper. */
395 :
396 : void
397 60 : gfc_free_omp_udm (gfc_omp_udm *omp_udm)
398 : {
399 60 : if (omp_udm)
400 : {
401 30 : gfc_free_omp_udm (omp_udm->next);
402 30 : gfc_free_namespace (omp_udm->mapper_ns);
403 30 : free (omp_udm);
404 : }
405 60 : }
406 :
407 : static gfc_omp_udr *
408 4719 : gfc_find_omp_udr (gfc_namespace *ns, const char *name, gfc_typespec *ts)
409 : {
410 4719 : gfc_symtree *st;
411 :
412 4719 : if (ns == NULL)
413 471 : ns = gfc_current_ns;
414 5675 : do
415 : {
416 5675 : gfc_omp_udr *omp_udr;
417 :
418 5675 : st = gfc_find_symtree (ns->omp_udr_root, name);
419 5675 : if (st != NULL)
420 : {
421 943 : for (omp_udr = st->n.omp_udr; omp_udr; omp_udr = omp_udr->next)
422 943 : if (ts == NULL)
423 : return omp_udr;
424 572 : else if (gfc_compare_types (&omp_udr->ts, ts))
425 : {
426 483 : if (ts->type == BT_CHARACTER)
427 : {
428 60 : if (omp_udr->ts.u.cl->length == NULL)
429 : return omp_udr;
430 36 : if (ts->u.cl->length == NULL)
431 0 : continue;
432 36 : if (gfc_compare_expr (omp_udr->ts.u.cl->length,
433 : ts->u.cl->length,
434 : INTRINSIC_EQ) != 0)
435 12 : continue;
436 : }
437 : return omp_udr;
438 : }
439 : }
440 :
441 : /* Don't escape an interface block. */
442 4833 : if (ns && !ns->has_import_set
443 4833 : && ns->proc_name && ns->proc_name->attr.if_source == IFSRC_IFBODY)
444 : break;
445 :
446 4833 : ns = ns->parent;
447 : }
448 4833 : while (ns != NULL);
449 :
450 : return NULL;
451 : }
452 :
453 :
454 : /* Match a variable/common block list and construct a namelist from it;
455 : if has_all_memory != NULL, *has_all_memory is set and omp_all_memory
456 : yields a list->sym NULL entry. */
457 :
458 : static match
459 31851 : gfc_match_omp_variable_list (const char *str, gfc_omp_namelist **list,
460 : bool allow_common, bool *end_colon = NULL,
461 : gfc_omp_namelist ***headp = NULL,
462 : bool allow_sections = false,
463 : bool allow_derived = false,
464 : bool *has_all_memory = NULL,
465 : bool reject_common_vars = false,
466 : bool reverse_order = false)
467 : {
468 31851 : gfc_omp_namelist *head, *tail, *p;
469 31851 : locus old_loc, cur_loc;
470 31851 : char n[GFC_MAX_SYMBOL_LEN+1];
471 31851 : gfc_symbol *sym;
472 31851 : match m;
473 31851 : gfc_symtree *st;
474 :
475 31851 : head = tail = NULL;
476 :
477 31851 : old_loc = gfc_current_locus;
478 31851 : if (has_all_memory)
479 709 : *has_all_memory = false;
480 31851 : m = gfc_match (str);
481 31851 : if (m != MATCH_YES)
482 : return m;
483 :
484 38532 : for (;;)
485 : {
486 38532 : gfc_gobble_whitespace ();
487 38532 : cur_loc = gfc_current_locus;
488 :
489 38532 : m = gfc_match_name (n);
490 38532 : if (m == MATCH_YES && strcmp (n, "omp_all_memory") == 0)
491 : {
492 23 : locus loc = gfc_get_location_range (NULL, 0, &cur_loc, 1,
493 : &gfc_current_locus);
494 23 : if (!has_all_memory)
495 : {
496 2 : gfc_error ("%<omp_all_memory%> at %L not permitted in this "
497 : "clause", &loc);
498 2 : goto cleanup;
499 : }
500 21 : *has_all_memory = true;
501 21 : p = gfc_get_omp_namelist ();
502 21 : if (head == NULL)
503 : head = tail = p;
504 : else
505 : {
506 3 : tail->next = p;
507 3 : tail = tail->next;
508 : }
509 21 : tail->where = loc;
510 21 : goto next_item;
511 : }
512 38253 : if (m == MATCH_YES)
513 : {
514 38253 : gfc_symtree *st;
515 38253 : if ((m = gfc_get_ha_sym_tree (n, &st) ? MATCH_ERROR : MATCH_YES)
516 : == MATCH_YES)
517 38253 : sym = st->n.sym;
518 : }
519 38509 : switch (m)
520 : {
521 38253 : case MATCH_YES:
522 38253 : gfc_expr *expr;
523 38253 : expr = NULL;
524 38253 : gfc_gobble_whitespace ();
525 23548 : if ((allow_sections && gfc_peek_ascii_char () == '(')
526 57439 : || (allow_derived && gfc_peek_ascii_char () == '%'))
527 : {
528 6609 : gfc_current_locus = cur_loc;
529 6609 : m = gfc_match_variable (&expr, 0);
530 6609 : switch (m)
531 : {
532 4 : case MATCH_ERROR:
533 12 : goto cleanup;
534 0 : case MATCH_NO:
535 0 : goto syntax;
536 6605 : default:
537 6605 : break;
538 : }
539 6605 : if (gfc_is_coindexed (expr))
540 : {
541 5 : gfc_error ("List item shall not be coindexed at %L",
542 5 : &expr->where);
543 5 : goto cleanup;
544 : }
545 : }
546 38244 : gfc_set_sym_referenced (sym);
547 38244 : p = gfc_get_omp_namelist ();
548 38244 : if (head == NULL)
549 : head = tail = p;
550 10161 : else if (reverse_order)
551 : {
552 57 : p->next = head;
553 57 : head = p;
554 : }
555 : else
556 : {
557 10104 : tail->next = p;
558 10104 : tail = tail->next;
559 : }
560 38244 : p->sym = sym;
561 38244 : p->expr = expr;
562 38244 : p->where = gfc_get_location_range (NULL, 0, &cur_loc, 1,
563 : &gfc_current_locus);
564 38244 : if (reject_common_vars && sym->attr.in_common)
565 : {
566 3 : gcc_assert (allow_common);
567 3 : gfc_error ("%qs at %L is part of the common block %</%s/%> and "
568 : "may only be specified implicitly via the named "
569 : "common block", sym->name, &cur_loc,
570 3 : sym->common_head->name);
571 3 : goto cleanup;
572 : }
573 38241 : goto next_item;
574 256 : case MATCH_NO:
575 256 : break;
576 0 : case MATCH_ERROR:
577 0 : goto cleanup;
578 : }
579 :
580 256 : if (!allow_common)
581 12 : goto syntax;
582 :
583 244 : m = gfc_match ("/ %n /", n);
584 244 : if (m == MATCH_ERROR)
585 0 : goto cleanup;
586 244 : if (m == MATCH_NO)
587 19 : goto syntax;
588 :
589 225 : cur_loc = gfc_get_location_range (NULL, 0, &cur_loc, 1,
590 : &gfc_current_locus);
591 225 : st = gfc_find_symtree (gfc_current_ns->common_root, n);
592 225 : if (st == NULL)
593 : {
594 2 : gfc_error ("COMMON block %</%s/%> not found at %L", n, &cur_loc);
595 2 : goto cleanup;
596 : }
597 724 : for (sym = st->n.common->head; sym; sym = sym->common_next)
598 : {
599 501 : gfc_set_sym_referenced (sym);
600 501 : p = gfc_get_omp_namelist ();
601 501 : if (head == NULL)
602 : head = tail = p;
603 325 : else if (reverse_order)
604 : {
605 0 : p->next = head;
606 0 : head = p;
607 : }
608 : else
609 : {
610 325 : tail->next = p;
611 325 : tail = tail->next;
612 : }
613 501 : p->sym = sym;
614 501 : p->where = cur_loc;
615 : }
616 :
617 223 : next_item:
618 38485 : if (end_colon && gfc_match_char (':') == MATCH_YES)
619 : {
620 806 : *end_colon = true;
621 806 : break;
622 : }
623 37679 : if (gfc_match_char (')') == MATCH_YES)
624 : break;
625 10232 : if (gfc_match_char (',') != MATCH_YES)
626 21 : goto syntax;
627 : }
628 :
629 38297 : while (*list)
630 10044 : list = &(*list)->next;
631 :
632 28253 : *list = head;
633 28253 : if (headp)
634 22352 : *headp = list;
635 : return MATCH_YES;
636 :
637 52 : syntax:
638 52 : gfc_error ("Syntax error in OpenMP variable list at %C");
639 :
640 68 : cleanup:
641 68 : gfc_free_omp_namelist (head, OMP_LIST_NONE);
642 68 : gfc_current_locus = old_loc;
643 68 : return MATCH_ERROR;
644 : }
645 :
646 : /* Match a variable/procedure/common block list and construct a namelist
647 : from it. */
648 :
649 : static match
650 392 : gfc_match_omp_to_link (const char *str, gfc_omp_namelist **list)
651 : {
652 392 : gfc_omp_namelist *head, *tail, *p;
653 392 : locus old_loc, cur_loc;
654 392 : char n[GFC_MAX_SYMBOL_LEN+1];
655 392 : gfc_symbol *sym;
656 392 : match m;
657 392 : gfc_symtree *st;
658 :
659 392 : head = tail = NULL;
660 :
661 392 : old_loc = gfc_current_locus;
662 :
663 392 : m = gfc_match (str);
664 392 : if (m != MATCH_YES)
665 : return m;
666 :
667 569 : for (;;)
668 : {
669 569 : cur_loc = gfc_current_locus;
670 569 : m = gfc_match_symbol (&sym, 1);
671 569 : switch (m)
672 : {
673 527 : case MATCH_YES:
674 527 : p = gfc_get_omp_namelist ();
675 527 : if (head == NULL)
676 : head = tail = p;
677 : else
678 : {
679 194 : tail->next = p;
680 194 : tail = tail->next;
681 : }
682 527 : tail->sym = sym;
683 527 : tail->where = cur_loc;
684 527 : goto next_item;
685 : case MATCH_NO:
686 : break;
687 0 : case MATCH_ERROR:
688 0 : goto cleanup;
689 : }
690 :
691 42 : m = gfc_match (" / %n /", n);
692 42 : if (m == MATCH_ERROR)
693 0 : goto cleanup;
694 42 : if (m == MATCH_NO)
695 0 : goto syntax;
696 :
697 42 : st = gfc_find_symtree (gfc_current_ns->common_root, n);
698 42 : if (st == NULL)
699 : {
700 0 : gfc_error ("COMMON block /%s/ not found at %C", n);
701 0 : goto cleanup;
702 : }
703 42 : p = gfc_get_omp_namelist ();
704 42 : if (head == NULL)
705 : head = tail = p;
706 : else
707 : {
708 4 : tail->next = p;
709 4 : tail = tail->next;
710 : }
711 42 : tail->u.common = st->n.common;
712 42 : tail->where = cur_loc;
713 :
714 569 : next_item:
715 569 : if (gfc_match_char (')') == MATCH_YES)
716 : break;
717 198 : if (gfc_match_char (',') != MATCH_YES)
718 0 : goto syntax;
719 : }
720 :
721 383 : while (*list)
722 12 : list = &(*list)->next;
723 :
724 371 : *list = head;
725 371 : return MATCH_YES;
726 :
727 0 : syntax:
728 0 : gfc_error ("Syntax error in OpenMP variable list at %C");
729 :
730 0 : cleanup:
731 0 : gfc_free_omp_namelist (head, OMP_LIST_NONE);
732 0 : gfc_current_locus = old_loc;
733 0 : return MATCH_ERROR;
734 : }
735 :
736 : /* Match detach(event-handle). */
737 :
738 : static match
739 126 : gfc_match_omp_detach (gfc_expr **expr)
740 : {
741 126 : locus old_loc = gfc_current_locus;
742 :
743 126 : if (gfc_match ("detach ( ") != MATCH_YES)
744 0 : goto syntax_error;
745 :
746 126 : if (gfc_match_variable (expr, 0) != MATCH_YES)
747 0 : goto syntax_error;
748 :
749 126 : if (gfc_match_char (')') != MATCH_YES)
750 0 : goto syntax_error;
751 :
752 : return MATCH_YES;
753 :
754 0 : syntax_error:
755 0 : gfc_error ("Syntax error in OpenMP detach clause at %C");
756 0 : gfc_current_locus = old_loc;
757 0 : return MATCH_ERROR;
758 :
759 : }
760 :
761 : /* Match doacross(sink : ...) construct a namelist from it;
762 : if depend is true, match legacy 'depend(sink : ...)'. */
763 :
764 : static match
765 241 : gfc_match_omp_doacross_sink (gfc_omp_namelist **list, bool depend)
766 : {
767 241 : char n[GFC_MAX_SYMBOL_LEN+1];
768 241 : gfc_omp_namelist *head, *tail, *p;
769 241 : locus old_loc, cur_loc;
770 241 : gfc_symbol *sym;
771 :
772 241 : head = tail = NULL;
773 :
774 241 : old_loc = gfc_current_locus;
775 :
776 2231 : for (;;)
777 : {
778 1236 : gfc_gobble_whitespace ();
779 1236 : cur_loc = gfc_current_locus;
780 :
781 1236 : if (gfc_match_name (n) != MATCH_YES)
782 1 : goto syntax;
783 1235 : locus loc = gfc_get_location_range (NULL, 0, &cur_loc, 1,
784 : &gfc_current_locus);
785 1235 : if (UNLIKELY (strcmp (n, "omp_all_memory") == 0))
786 : {
787 1 : gfc_error ("%<omp_all_memory%> used with dependence-type "
788 : "other than OUT or INOUT at %L", &loc);
789 1 : goto cleanup;
790 : }
791 1234 : sym = NULL;
792 1234 : if (!(strcmp (n, "omp_cur_iteration") == 0))
793 : {
794 1229 : gfc_symtree *st;
795 1229 : if (gfc_get_ha_sym_tree (n, &st))
796 0 : goto syntax;
797 1229 : sym = st->n.sym;
798 1229 : gfc_set_sym_referenced (sym);
799 : }
800 1234 : p = gfc_get_omp_namelist ();
801 1234 : if (head == NULL)
802 : {
803 239 : head = tail = p;
804 253 : head->u.depend_doacross_op = (depend ? OMP_DEPEND_SINK_FIRST
805 : : OMP_DOACROSS_SINK_FIRST);
806 : }
807 : else
808 : {
809 995 : tail->next = p;
810 995 : tail = tail->next;
811 995 : tail->u.depend_doacross_op = OMP_DOACROSS_SINK;
812 : }
813 1234 : tail->sym = sym;
814 1234 : tail->expr = NULL;
815 1234 : tail->where = loc;
816 1234 : if (gfc_match_char ('+') == MATCH_YES)
817 : {
818 154 : if (gfc_match_literal_constant (&tail->expr, 0) != MATCH_YES)
819 0 : goto syntax;
820 : }
821 1080 : else if (gfc_match_char ('-') == MATCH_YES)
822 : {
823 418 : if (gfc_match_literal_constant (&tail->expr, 0) != MATCH_YES)
824 1 : goto syntax;
825 417 : tail->expr = gfc_uminus (tail->expr);
826 : }
827 1233 : if (gfc_match_char (')') == MATCH_YES)
828 : break;
829 995 : if (gfc_match_char (',') != MATCH_YES)
830 0 : goto syntax;
831 995 : }
832 :
833 1030 : while (*list)
834 792 : list = &(*list)->next;
835 :
836 238 : *list = head;
837 238 : return MATCH_YES;
838 :
839 2 : syntax:
840 2 : gfc_error ("Syntax error in OpenMP SINK dependence-type list at %C");
841 :
842 3 : cleanup:
843 3 : gfc_free_omp_namelist (head, OMP_LIST_DEPEND);
844 3 : gfc_current_locus = old_loc;
845 3 : return MATCH_ERROR;
846 : }
847 :
848 : static int
849 332 : match_oacc_device_type_kind (void)
850 : {
851 332 : char name[GFC_MAX_SYMBOL_LEN + 1];
852 :
853 : /* Since device_type arg accept * as all,
854 : we need to check first the case when
855 : the user inputs * as the parameter. */
856 332 : gfc_gobble_whitespace ();
857 332 : name[0] = (char) gfc_next_char ();
858 :
859 332 : if (name[0] == '*')
860 : return GOMP_DEVICE_NONE;
861 :
862 : /* If is not *, we try to match the
863 : pre-defined names. */
864 :
865 332 : match m = gfc_match (" %n ", name + 1);
866 :
867 332 : if (m != MATCH_YES)
868 : return -1;
869 :
870 332 : if (strcmp (name ,"host") == 0)
871 : return GOMP_DEVICE_HOST;
872 144 : if (strcmp (name, "nvidia") == 0)
873 : return GOMP_DEVICE_NVIDIA_PTX;
874 72 : if (strcmp (name, "radeon") == 0)
875 69 : return GOMP_DEVICE_GCN;
876 :
877 : return -1;
878 : }
879 :
880 : static match
881 332 : match_oacc_device_type (gfc_omp_clauses *c)
882 : {
883 332 : locus old_loc = gfc_current_locus;
884 :
885 332 : int result = match_oacc_device_type_kind ();
886 332 : match m;
887 :
888 332 : if (result == -1)
889 3 : goto syntax;
890 :
891 329 : m = gfc_match_char (')', true);
892 :
893 329 : if (m != MATCH_YES)
894 3 : goto single_argument;
895 :
896 326 : c->oacc_device_type = (unsigned) result;
897 326 : c->oacc_device_type_present = 1;
898 :
899 326 : return MATCH_YES;
900 :
901 3 : single_argument:
902 3 : gfc_error ("OpenACC %<DEVICE_TYPE%> clause only accepts one argument, "
903 : "unexpected char at %C");
904 3 : goto cleanup;
905 :
906 3 : syntax:
907 3 : gfc_error ("Syntax error in OpenACC %<DEVICE_TYPE%> argument at %C. Expected "
908 : "host, radeon, nvidia or * as argument.");
909 :
910 6 : cleanup:
911 6 : gfc_current_locus = old_loc;
912 6 : return MATCH_ERROR;
913 : }
914 :
915 : static match
916 1962 : match_omp_oacc_expr_list (const char *str, gfc_expr_list **list,
917 : bool allow_asterisk, bool is_omp)
918 : {
919 1962 : gfc_expr_list *head, *tail, *p;
920 1962 : locus old_loc;
921 1962 : gfc_expr *expr;
922 1962 : match m;
923 :
924 1962 : head = tail = NULL;
925 :
926 1962 : old_loc = gfc_current_locus;
927 :
928 1962 : if (str && (m = gfc_match (str)) != MATCH_YES)
929 : return m;
930 :
931 2239 : for (;;)
932 : {
933 2239 : m = gfc_match_expr (&expr);
934 2239 : if (m == MATCH_YES || allow_asterisk)
935 : {
936 2222 : p = gfc_get_expr_list ();
937 2222 : if (head == NULL)
938 : head = tail = p;
939 : else
940 : {
941 400 : tail->next = p;
942 400 : tail = tail->next;
943 : }
944 2222 : if (m == MATCH_YES)
945 2089 : tail->expr = expr;
946 133 : else if (gfc_match (" *") != MATCH_YES)
947 18 : goto syntax;
948 2204 : goto next_item;
949 : }
950 17 : if (m == MATCH_ERROR)
951 0 : goto cleanup;
952 17 : goto syntax;
953 :
954 2204 : next_item:
955 2204 : if (gfc_match_char (')') == MATCH_YES)
956 : break;
957 422 : if (gfc_match_char (',') != MATCH_YES)
958 17 : goto syntax;
959 : }
960 :
961 1788 : while (*list)
962 6 : list = &(*list)->next;
963 :
964 1782 : *list = head;
965 1782 : return MATCH_YES;
966 :
967 52 : syntax:
968 52 : if (is_omp)
969 23 : gfc_error ("Syntax error in OpenMP expression list at %C");
970 : else
971 29 : gfc_error ("Syntax error in OpenACC expression list at %C");
972 :
973 52 : cleanup:
974 52 : gfc_free_expr_list (head);
975 52 : gfc_current_locus = old_loc;
976 52 : return MATCH_ERROR;
977 : }
978 :
979 : static match
980 3056 : match_oacc_clause_gwv (gfc_omp_clauses *cp, unsigned gwv)
981 : {
982 3056 : match ret = MATCH_YES;
983 :
984 3056 : if (gfc_match (" ( ") != MATCH_YES)
985 : return MATCH_NO;
986 :
987 470 : if (gwv == GOMP_DIM_GANG)
988 : {
989 : /* The gang clause accepts two optional arguments, num and static.
990 : The num argument may either be explicit (num: <val>) or
991 : implicit without (<val> without num:). */
992 :
993 457 : while (ret == MATCH_YES)
994 : {
995 236 : if (gfc_match (" static :") == MATCH_YES)
996 : {
997 114 : if (cp->gang_static)
998 : return MATCH_ERROR;
999 : else
1000 113 : cp->gang_static = true;
1001 113 : if (gfc_match_char ('*') == MATCH_YES)
1002 18 : cp->gang_static_expr = NULL;
1003 95 : else if (gfc_match (" %e ", &cp->gang_static_expr) != MATCH_YES)
1004 : return MATCH_ERROR;
1005 : }
1006 : else
1007 : {
1008 122 : if (cp->gang_num_expr)
1009 : return MATCH_ERROR;
1010 :
1011 : /* The 'num' argument is optional. */
1012 121 : gfc_match (" num :");
1013 :
1014 121 : if (gfc_match (" %e ", &cp->gang_num_expr) != MATCH_YES)
1015 : return MATCH_ERROR;
1016 : }
1017 :
1018 231 : ret = gfc_match (" , ");
1019 : }
1020 : }
1021 244 : else if (gwv == GOMP_DIM_WORKER)
1022 : {
1023 : /* The 'num' argument is optional. */
1024 107 : gfc_match (" num :");
1025 :
1026 107 : if (gfc_match (" %e ", &cp->worker_expr) != MATCH_YES)
1027 : return MATCH_ERROR;
1028 : }
1029 137 : else if (gwv == GOMP_DIM_VECTOR)
1030 : {
1031 : /* The 'length' argument is optional. */
1032 137 : gfc_match (" length :");
1033 :
1034 137 : if (gfc_match (" %e ", &cp->vector_expr) != MATCH_YES)
1035 : return MATCH_ERROR;
1036 : }
1037 : else
1038 0 : gfc_fatal_error ("Unexpected OpenACC parallelism.");
1039 :
1040 459 : return gfc_match (" )");
1041 : }
1042 :
1043 : static match
1044 8 : gfc_match_oacc_clause_link (const char *str, gfc_omp_namelist **list)
1045 : {
1046 8 : gfc_omp_namelist *head = NULL;
1047 8 : gfc_omp_namelist *tail, *p;
1048 8 : locus old_loc;
1049 8 : char n[GFC_MAX_SYMBOL_LEN+1];
1050 8 : gfc_symbol *sym;
1051 8 : match m;
1052 8 : gfc_symtree *st;
1053 :
1054 8 : old_loc = gfc_current_locus;
1055 :
1056 8 : m = gfc_match (str);
1057 8 : if (m != MATCH_YES)
1058 : return m;
1059 :
1060 8 : m = gfc_match (" (");
1061 :
1062 14 : for (;;)
1063 : {
1064 14 : m = gfc_match_symbol (&sym, 0);
1065 14 : switch (m)
1066 : {
1067 8 : case MATCH_YES:
1068 8 : if (sym->attr.in_common)
1069 : {
1070 2 : gfc_error_now ("Variable at %C is an element of a COMMON block");
1071 2 : goto cleanup;
1072 : }
1073 6 : gfc_set_sym_referenced (sym);
1074 6 : p = gfc_get_omp_namelist ();
1075 6 : if (head == NULL)
1076 : head = tail = p;
1077 : else
1078 : {
1079 4 : tail->next = p;
1080 4 : tail = tail->next;
1081 : }
1082 6 : tail->sym = sym;
1083 6 : tail->expr = NULL;
1084 6 : tail->where = gfc_current_locus;
1085 6 : goto next_item;
1086 : case MATCH_NO:
1087 : break;
1088 :
1089 0 : case MATCH_ERROR:
1090 0 : goto cleanup;
1091 : }
1092 :
1093 6 : m = gfc_match (" / %n /", n);
1094 6 : if (m == MATCH_ERROR)
1095 0 : goto cleanup;
1096 6 : if (m == MATCH_NO || n[0] == '\0')
1097 0 : goto syntax;
1098 :
1099 6 : st = gfc_find_symtree (gfc_current_ns->common_root, n);
1100 6 : if (st == NULL)
1101 : {
1102 1 : gfc_error ("COMMON block /%s/ not found at %C", n);
1103 1 : goto cleanup;
1104 : }
1105 :
1106 20 : for (sym = st->n.common->head; sym; sym = sym->common_next)
1107 : {
1108 15 : gfc_set_sym_referenced (sym);
1109 15 : p = gfc_get_omp_namelist ();
1110 15 : if (head == NULL)
1111 : head = tail = p;
1112 : else
1113 : {
1114 12 : tail->next = p;
1115 12 : tail = tail->next;
1116 : }
1117 15 : tail->sym = sym;
1118 15 : tail->where = gfc_current_locus;
1119 : }
1120 :
1121 5 : next_item:
1122 11 : if (gfc_match_char (')') == MATCH_YES)
1123 : break;
1124 6 : if (gfc_match_char (',') != MATCH_YES)
1125 0 : goto syntax;
1126 : }
1127 :
1128 5 : if (gfc_match_omp_eos () != MATCH_YES)
1129 : {
1130 1 : gfc_error ("Unexpected junk after !$ACC DECLARE at %C");
1131 1 : goto cleanup;
1132 : }
1133 :
1134 4 : while (*list)
1135 0 : list = &(*list)->next;
1136 4 : *list = head;
1137 4 : return MATCH_YES;
1138 :
1139 0 : syntax:
1140 0 : gfc_error ("Syntax error in !$ACC DECLARE list at %C");
1141 :
1142 4 : cleanup:
1143 4 : gfc_current_locus = old_loc;
1144 4 : return MATCH_ERROR;
1145 : }
1146 :
1147 : /* OpenMP clauses. */
1148 : enum omp_mask1
1149 : {
1150 : OMP_CLAUSE_PRIVATE,
1151 : OMP_CLAUSE_FIRSTPRIVATE,
1152 : OMP_CLAUSE_LASTPRIVATE,
1153 : OMP_CLAUSE_COPYPRIVATE,
1154 : OMP_CLAUSE_SHARED,
1155 : OMP_CLAUSE_COPYIN,
1156 : OMP_CLAUSE_REDUCTION,
1157 : OMP_CLAUSE_IN_REDUCTION,
1158 : OMP_CLAUSE_TASK_REDUCTION,
1159 : OMP_CLAUSE_IF,
1160 : OMP_CLAUSE_NUM_THREADS,
1161 : OMP_CLAUSE_SCHEDULE,
1162 : OMP_CLAUSE_DEFAULT,
1163 : OMP_CLAUSE_ORDER,
1164 : OMP_CLAUSE_ORDERED,
1165 : OMP_CLAUSE_COLLAPSE,
1166 : OMP_CLAUSE_UNTIED,
1167 : OMP_CLAUSE_FINAL,
1168 : OMP_CLAUSE_MERGEABLE,
1169 : OMP_CLAUSE_ALIGNED,
1170 : OMP_CLAUSE_DEPEND,
1171 : OMP_CLAUSE_INBRANCH,
1172 : OMP_CLAUSE_LINEAR,
1173 : OMP_CLAUSE_NOTINBRANCH,
1174 : OMP_CLAUSE_PROC_BIND,
1175 : OMP_CLAUSE_SAFELEN,
1176 : OMP_CLAUSE_SIMDLEN,
1177 : OMP_CLAUSE_UNIFORM,
1178 : OMP_CLAUSE_DEVICE,
1179 : OMP_CLAUSE_MAP,
1180 : OMP_CLAUSE_TO,
1181 : OMP_CLAUSE_FROM,
1182 : OMP_CLAUSE_NUM_TEAMS,
1183 : OMP_CLAUSE_THREAD_LIMIT,
1184 : OMP_CLAUSE_DIST_SCHEDULE,
1185 : OMP_CLAUSE_DEFAULTMAP,
1186 : OMP_CLAUSE_GRAINSIZE,
1187 : OMP_CLAUSE_HINT,
1188 : OMP_CLAUSE_IS_DEVICE_PTR,
1189 : OMP_CLAUSE_LINK,
1190 : OMP_CLAUSE_NOGROUP,
1191 : OMP_CLAUSE_NOTEMPORAL,
1192 : OMP_CLAUSE_NUM_TASKS,
1193 : OMP_CLAUSE_PRIORITY,
1194 : OMP_CLAUSE_SIMD,
1195 : OMP_CLAUSE_THREADS,
1196 : OMP_CLAUSE_USE_DEVICE_PTR,
1197 : OMP_CLAUSE_USE_DEVICE_ADDR, /* OpenMP 5.0. */
1198 : OMP_CLAUSE_DEVICE_TYPE, /* OpenMP 5.0. */
1199 : OMP_CLAUSE_ATOMIC, /* OpenMP 5.0. */
1200 : OMP_CLAUSE_CAPTURE, /* OpenMP 5.0. */
1201 : OMP_CLAUSE_MEMORDER, /* OpenMP 5.0. */
1202 : OMP_CLAUSE_DETACH, /* OpenMP 5.0. */
1203 : OMP_CLAUSE_AFFINITY, /* OpenMP 5.0. */
1204 : OMP_CLAUSE_ALLOCATE, /* OpenMP 5.0. */
1205 : OMP_CLAUSE_BIND, /* OpenMP 5.0. */
1206 : OMP_CLAUSE_FILTER, /* OpenMP 5.1. */
1207 : OMP_CLAUSE_AT, /* OpenMP 5.1. */
1208 : OMP_CLAUSE_MESSAGE, /* OpenMP 5.1. */
1209 : OMP_CLAUSE_SEVERITY, /* OpenMP 5.1. */
1210 : OMP_CLAUSE_COMPARE, /* OpenMP 5.1. */
1211 : OMP_CLAUSE_FAIL, /* OpenMP 5.1. */
1212 : OMP_CLAUSE_WEAK, /* OpenMP 5.1. */
1213 : OMP_CLAUSE_NOWAIT,
1214 : /* This must come last. */
1215 : OMP_MASK1_LAST
1216 : };
1217 :
1218 : /* More OpenMP clauses and OpenACC 2.0+ specific clauses. */
1219 : enum omp_mask2
1220 : {
1221 : OMP_CLAUSE_ASYNC,
1222 : OMP_CLAUSE_NUM_GANGS,
1223 : OMP_CLAUSE_NUM_WORKERS,
1224 : OMP_CLAUSE_VECTOR_LENGTH,
1225 : OMP_CLAUSE_COPY,
1226 : OMP_CLAUSE_COPYOUT,
1227 : OMP_CLAUSE_CREATE,
1228 : OMP_CLAUSE_NO_CREATE,
1229 : OMP_CLAUSE_PRESENT,
1230 : OMP_CLAUSE_DEVICEPTR,
1231 : OMP_CLAUSE_GANG,
1232 : OMP_CLAUSE_WORKER,
1233 : OMP_CLAUSE_VECTOR,
1234 : OMP_CLAUSE_SEQ,
1235 : OMP_CLAUSE_INDEPENDENT,
1236 : OMP_CLAUSE_USE_DEVICE,
1237 : OMP_CLAUSE_DEVICE_RESIDENT,
1238 : OMP_CLAUSE_SELF,
1239 : OMP_CLAUSE_HOST,
1240 : OMP_CLAUSE_WAIT,
1241 : OMP_CLAUSE_DELETE,
1242 : OMP_CLAUSE_AUTO,
1243 : OMP_CLAUSE_TILE,
1244 : OMP_CLAUSE_IF_PRESENT,
1245 : OMP_CLAUSE_FINALIZE,
1246 : OMP_CLAUSE_ATTACH,
1247 : OMP_CLAUSE_NOHOST,
1248 : OMP_CLAUSE_HAS_DEVICE_ADDR, /* OpenMP 5.1 */
1249 : OMP_CLAUSE_ENTER, /* OpenMP 5.2 */
1250 : OMP_CLAUSE_DOACROSS, /* OpenMP 5.2 */
1251 : OMP_CLAUSE_ASSUMPTIONS, /* OpenMP 5.1. */
1252 : OMP_CLAUSE_USES_ALLOCATORS, /* OpenMP 5.0 */
1253 : OMP_CLAUSE_INDIRECT, /* OpenMP 5.1 */
1254 : OMP_CLAUSE_FULL, /* OpenMP 5.1. */
1255 : OMP_CLAUSE_PARTIAL, /* OpenMP 5.1. */
1256 : OMP_CLAUSE_SIZES, /* OpenMP 5.1. */
1257 : OMP_CLAUSE_INIT, /* OpenMP 5.1. */
1258 : OMP_CLAUSE_DESTROY, /* OpenMP 5.1. */
1259 : OMP_CLAUSE_USE, /* OpenMP 5.1. */
1260 : OMP_CLAUSE_NOVARIANTS, /* OpenMP 5.1 */
1261 : OMP_CLAUSE_NOCONTEXT, /* OpenMP 5.1 */
1262 : OMP_CLAUSE_INTEROP, /* OpenMP 5.1 */
1263 : OMP_CLAUSE_LOCAL, /* OpenMP 6.0 */
1264 : OMP_CLAUSE_DYN_GROUPPRIVATE, /* OpenMP 6.1 */
1265 : OMP_CLAUSE_DEVICE_NUM,
1266 : /* This must come last. */
1267 : OMP_MASK2_LAST
1268 : };
1269 :
1270 : struct omp_inv_mask;
1271 :
1272 : /* Customized bitset for up to 128-bits.
1273 : The two enums above provide bit numbers to use, and which of the
1274 : two enums it is determines which of the two mask fields is used.
1275 : Supported operations are defining a mask, like:
1276 : #define XXX_CLAUSES \
1277 : (omp_mask (OMP_CLAUSE_XXX) | OMP_CLAUSE_YYY | OMP_CLAUSE_ZZZ)
1278 : oring such bitsets together or removing selected bits:
1279 : (XXX_CLAUSES | YYY_CLAUSES) & ~(omp_mask (OMP_CLAUSE_VVV))
1280 : and testing individual bits:
1281 : if (mask & OMP_CLAUSE_UUU) */
1282 :
1283 : struct omp_mask {
1284 : const uint64_t mask1;
1285 : const uint64_t mask2;
1286 : inline omp_mask ();
1287 : inline omp_mask (omp_mask1);
1288 : inline omp_mask (omp_mask2);
1289 : inline omp_mask (uint64_t, uint64_t);
1290 : inline omp_mask operator| (omp_mask1) const;
1291 : inline omp_mask operator| (omp_mask2) const;
1292 : inline omp_mask operator| (omp_mask) const;
1293 : inline omp_mask operator& (const omp_inv_mask &) const;
1294 : inline bool operator& (omp_mask1) const;
1295 : inline bool operator& (omp_mask2) const;
1296 : inline omp_inv_mask operator~ () const;
1297 : };
1298 :
1299 : struct omp_inv_mask : public omp_mask {
1300 : inline omp_inv_mask (const omp_mask &);
1301 : };
1302 :
1303 : omp_mask::omp_mask () : mask1 (0), mask2 (0)
1304 : {
1305 : }
1306 :
1307 33027 : omp_mask::omp_mask (omp_mask1 m) : mask1 (((uint64_t) 1) << m), mask2 (0)
1308 : {
1309 : }
1310 :
1311 2244 : omp_mask::omp_mask (omp_mask2 m) : mask1 (0), mask2 (((uint64_t) 1) << m)
1312 : {
1313 : }
1314 :
1315 33914 : omp_mask::omp_mask (uint64_t m1, uint64_t m2) : mask1 (m1), mask2 (m2)
1316 : {
1317 : }
1318 :
1319 : omp_mask
1320 32954 : omp_mask::operator| (omp_mask1 m) const
1321 : {
1322 32954 : return omp_mask (mask1 | (((uint64_t) 1) << m), mask2);
1323 : }
1324 :
1325 : omp_mask
1326 17307 : omp_mask::operator| (omp_mask2 m) const
1327 : {
1328 17307 : return omp_mask (mask1, mask2 | (((uint64_t) 1) << m));
1329 : }
1330 :
1331 : omp_mask
1332 4383 : omp_mask::operator| (omp_mask m) const
1333 : {
1334 4383 : return omp_mask (mask1 | m.mask1, mask2 | m.mask2);
1335 : }
1336 :
1337 : omp_mask
1338 2037 : omp_mask::operator& (const omp_inv_mask &m) const
1339 : {
1340 2037 : return omp_mask (mask1 & ~m.mask1, mask2 & ~m.mask2);
1341 : }
1342 :
1343 : bool
1344 130385 : omp_mask::operator& (omp_mask1 m) const
1345 : {
1346 130385 : return (mask1 & (((uint64_t) 1) << m)) != 0;
1347 : }
1348 :
1349 : bool
1350 92760 : omp_mask::operator& (omp_mask2 m) const
1351 : {
1352 92760 : return (mask2 & (((uint64_t) 1) << m)) != 0;
1353 : }
1354 :
1355 : omp_inv_mask
1356 2037 : omp_mask::operator~ () const
1357 : {
1358 2037 : return omp_inv_mask (*this);
1359 : }
1360 :
1361 2037 : omp_inv_mask::omp_inv_mask (const omp_mask &m) : omp_mask (m)
1362 : {
1363 : }
1364 :
1365 : /* Helper function for OpenACC and OpenMP clauses involving memory
1366 : mapping. */
1367 :
1368 : static bool
1369 5544 : gfc_match_omp_map_clause (gfc_omp_namelist **list, gfc_omp_map_op map_op,
1370 : bool allow_common, bool allow_derived)
1371 : {
1372 5544 : gfc_omp_namelist **head = NULL;
1373 5544 : if (gfc_match_omp_variable_list ("", list, allow_common, NULL, &head, true,
1374 : allow_derived)
1375 : == MATCH_YES)
1376 : {
1377 5535 : gfc_omp_namelist *n;
1378 13409 : for (n = *head; n; n = n->next)
1379 7874 : n->u.map.op = map_op;
1380 : return true;
1381 : }
1382 :
1383 : return false;
1384 : }
1385 :
1386 : static match
1387 8749 : gfc_match_iterator (gfc_namespace **ns, bool permit_var)
1388 : {
1389 8749 : locus old_loc = gfc_current_locus;
1390 :
1391 8749 : if (gfc_match ("iterator ( ") != MATCH_YES)
1392 : return MATCH_NO;
1393 :
1394 142 : gfc_typespec ts;
1395 142 : gfc_symbol *last = NULL;
1396 142 : gfc_expr *begin, *end, *step;
1397 142 : *ns = gfc_build_block_ns (gfc_current_ns);
1398 161 : char name[GFC_MAX_SYMBOL_LEN + 1];
1399 180 : while (true)
1400 : {
1401 161 : locus prev_loc = gfc_current_locus;
1402 161 : if (gfc_match_type_spec (&ts) == MATCH_YES
1403 161 : && gfc_match (" :: ") == MATCH_YES)
1404 : {
1405 5 : if (ts.type != BT_INTEGER)
1406 : {
1407 2 : gfc_error ("Expected INTEGER type at %L", &prev_loc);
1408 5 : return MATCH_ERROR;
1409 : }
1410 : permit_var = false;
1411 : }
1412 : else
1413 : {
1414 156 : ts.type = BT_INTEGER;
1415 156 : ts.kind = gfc_default_integer_kind;
1416 156 : gfc_current_locus = prev_loc;
1417 : }
1418 159 : prev_loc = gfc_current_locus;
1419 159 : if (gfc_match_name (name) != MATCH_YES)
1420 : {
1421 4 : gfc_error ("Expected identifier at %C");
1422 4 : goto failed;
1423 : }
1424 155 : if (gfc_find_symtree ((*ns)->sym_root, name))
1425 : {
1426 2 : gfc_error ("Same identifier %qs specified again at %C", name);
1427 2 : goto failed;
1428 : }
1429 :
1430 153 : gfc_symbol *sym = gfc_new_symbol (name, *ns);
1431 153 : if (last)
1432 17 : last->tlink = sym;
1433 : else
1434 136 : (*ns)->omp_affinity_iterators = sym;
1435 153 : last = sym;
1436 153 : sym->declared_at = prev_loc;
1437 153 : sym->ts = ts;
1438 153 : sym->attr.flavor = FL_VARIABLE;
1439 153 : sym->attr.artificial = 1;
1440 153 : sym->attr.referenced = 1;
1441 153 : sym->refs++;
1442 153 : gfc_symtree *st = gfc_new_symtree (&(*ns)->sym_root, name);
1443 153 : st->n.sym = sym;
1444 :
1445 153 : prev_loc = gfc_current_locus;
1446 153 : if (gfc_match (" = ") != MATCH_YES)
1447 3 : goto failed;
1448 150 : permit_var = false;
1449 150 : begin = end = step = NULL;
1450 150 : if (gfc_match ("%e : ", &begin) != MATCH_YES
1451 150 : || gfc_match ("%e ", &end) != MATCH_YES)
1452 : {
1453 3 : gfc_error ("Expected range-specification at %C");
1454 3 : gfc_free_expr (begin);
1455 3 : gfc_free_expr (end);
1456 3 : return MATCH_ERROR;
1457 : }
1458 147 : if (':' == gfc_peek_ascii_char ())
1459 : {
1460 23 : if (gfc_match (": %e ", &step) != MATCH_YES)
1461 : {
1462 5 : gfc_free_expr (begin);
1463 5 : gfc_free_expr (end);
1464 5 : gfc_free_expr (step);
1465 5 : goto failed;
1466 : }
1467 : }
1468 :
1469 142 : gfc_expr *e = gfc_get_expr ();
1470 142 : e->where = prev_loc;
1471 142 : e->expr_type = EXPR_ARRAY;
1472 142 : e->ts = ts;
1473 142 : e->rank = 1;
1474 142 : e->shape = gfc_get_shape (1);
1475 266 : mpz_init_set_ui (e->shape[0], step ? 3 : 2);
1476 142 : gfc_constructor_append_expr (&e->value.constructor, begin, &begin->where);
1477 142 : gfc_constructor_append_expr (&e->value.constructor, end, &end->where);
1478 142 : if (step)
1479 18 : gfc_constructor_append_expr (&e->value.constructor, step, &step->where);
1480 142 : sym->value = e;
1481 :
1482 142 : if (gfc_match (") ") == MATCH_YES)
1483 : break;
1484 19 : if (gfc_match (", ") != MATCH_YES)
1485 0 : goto failed;
1486 19 : }
1487 123 : return MATCH_YES;
1488 :
1489 14 : failed:
1490 14 : gfc_namespace *prev_ns = NULL;
1491 14 : for (gfc_namespace *it = gfc_current_ns->contained; it; it = it->sibling)
1492 : {
1493 0 : if (it == *ns)
1494 : {
1495 0 : if (prev_ns)
1496 0 : prev_ns->sibling = it->sibling;
1497 : else
1498 0 : gfc_current_ns->contained = it->sibling;
1499 0 : gfc_free_namespace (it);
1500 0 : break;
1501 : }
1502 0 : prev_ns = it;
1503 : }
1504 14 : *ns = NULL;
1505 14 : if (!permit_var)
1506 : return MATCH_ERROR;
1507 4 : gfc_current_locus = old_loc;
1508 4 : return MATCH_NO;
1509 : }
1510 :
1511 : /* Match target update's to/from( [present:] var-list). */
1512 :
1513 : static match
1514 1738 : gfc_match_motion_var_list (const char *str, gfc_omp_namelist **list,
1515 : gfc_omp_namelist ***headp)
1516 : {
1517 1738 : match m = gfc_match (str);
1518 1738 : if (m != MATCH_YES)
1519 : return m;
1520 :
1521 1738 : gfc_namespace *ns_iter = NULL, *ns_curr = gfc_current_ns;
1522 1738 : locus old_loc = gfc_current_locus;
1523 1738 : int present_modifier = 0;
1524 1738 : int iterator_modifier = 0;
1525 1738 : locus second_present_locus = old_loc;
1526 1738 : locus second_iterator_locus = old_loc;
1527 1738 : bool saw_modifier = false;
1528 :
1529 1750 : for (;;)
1530 : {
1531 1744 : locus current_locus = gfc_current_locus;
1532 1744 : if (gfc_match ("present ") == MATCH_YES)
1533 : {
1534 8 : if (present_modifier++ == 1)
1535 0 : second_present_locus = current_locus;
1536 : }
1537 1736 : else if (gfc_match_iterator (&ns_iter, true) == MATCH_YES)
1538 : {
1539 20 : if (iterator_modifier++ == 1)
1540 1 : second_iterator_locus = current_locus;
1541 : }
1542 1716 : else if (!saw_modifier)
1543 : break;
1544 : else
1545 : {
1546 2 : gfc_error ("Expected clause modifier at %C");
1547 4 : return MATCH_ERROR;
1548 : }
1549 :
1550 : /* OpenMP 5.1 syntax mistakenly allowed commas to be optional
1551 : between and after modifiers in a clause. This was corrected
1552 : in 5.2 and later specifications: they're now required between
1553 : modifiers and a trailing comma is not permitted. We implement
1554 : the 5.2 syntax here. */
1555 28 : saw_modifier = true;
1556 28 : if (gfc_match (" : ") == MATCH_YES)
1557 : break;
1558 8 : else if (gfc_match (", ") == MATCH_YES)
1559 6 : continue;
1560 : else
1561 : {
1562 2 : gfc_error ("Expected %<,%> or %<:%> after clause modifier at %C");
1563 2 : return MATCH_ERROR;
1564 : }
1565 6 : }
1566 :
1567 1734 : if (!saw_modifier)
1568 : {
1569 1714 : gfc_current_locus = old_loc;
1570 1714 : present_modifier = 0;
1571 1714 : iterator_modifier = 0;
1572 : }
1573 :
1574 1734 : if (present_modifier > 1)
1575 : {
1576 0 : gfc_error ("Too many %<present%> modifiers at %L", &second_present_locus);
1577 0 : return MATCH_ERROR;
1578 : }
1579 1734 : if (iterator_modifier > 1)
1580 : {
1581 1 : gfc_error ("Too many %<iterator%> modifiers at %L",
1582 : &second_iterator_locus);
1583 1 : return MATCH_ERROR;
1584 : }
1585 :
1586 1733 : if (ns_iter)
1587 14 : gfc_current_ns = ns_iter;
1588 :
1589 1733 : m = gfc_match_omp_variable_list ("", list, false, NULL, headp, true, true);
1590 1733 : gfc_current_ns = ns_curr;
1591 1733 : if (m != MATCH_YES)
1592 : return m;
1593 1731 : gfc_omp_namelist *n;
1594 3536 : for (n = **headp; n; n = n->next)
1595 : {
1596 1805 : if (present_modifier)
1597 6 : n->u.present_modifier = true;
1598 1805 : if (iterator_modifier)
1599 : {
1600 18 : n->u2.ns = ns_iter;
1601 18 : ns_iter->refs++;
1602 : }
1603 : }
1604 : return MATCH_YES;
1605 : }
1606 :
1607 : /* reduction ( reduction-modifier, reduction-operator : variable-list )
1608 : in_reduction ( reduction-operator : variable-list )
1609 : task_reduction ( reduction-operator : variable-list ) */
1610 :
1611 : static match
1612 4362 : gfc_match_omp_clause_reduction (char pc, gfc_omp_clauses *c, bool openacc,
1613 : bool allow_derived, bool openmp_target = false)
1614 : {
1615 4362 : if (pc == 'r' && gfc_match ("reduction ( ") != MATCH_YES)
1616 : return MATCH_NO;
1617 4362 : else if (pc == 'i' && gfc_match ("in_reduction ( ") != MATCH_YES)
1618 : return MATCH_NO;
1619 4250 : else if (pc == 't' && gfc_match ("task_reduction ( ") != MATCH_YES)
1620 : return MATCH_NO;
1621 :
1622 4250 : locus old_loc = gfc_current_locus;
1623 4250 : enum gfc_omp_list_type list_idx = OMP_LIST_NONE;
1624 :
1625 4250 : if (pc == 'r' && !openacc)
1626 : {
1627 2123 : if (gfc_match ("inscan") == MATCH_YES)
1628 : list_idx = OMP_LIST_REDUCTION_INSCAN;
1629 2053 : else if (gfc_match ("task") == MATCH_YES)
1630 : list_idx = OMP_LIST_REDUCTION_TASK;
1631 1948 : else if (gfc_match ("default") == MATCH_YES)
1632 : list_idx = OMP_LIST_REDUCTION;
1633 231 : if (list_idx != OMP_LIST_NONE && gfc_match (", ") != MATCH_YES)
1634 : {
1635 1 : gfc_error ("Comma expected at %C");
1636 1 : gfc_current_locus = old_loc;
1637 1 : return MATCH_NO;
1638 : }
1639 2122 : if (list_idx == OMP_LIST_NONE)
1640 3836 : list_idx = OMP_LIST_REDUCTION;
1641 : }
1642 2127 : else if (pc == 'i')
1643 : list_idx = OMP_LIST_IN_REDUCTION;
1644 2009 : else if (pc == 't')
1645 : list_idx = OMP_LIST_TASK_REDUCTION;
1646 : else
1647 3836 : list_idx = OMP_LIST_REDUCTION;
1648 :
1649 4249 : gfc_omp_reduction_op rop = OMP_REDUCTION_NONE;
1650 4249 : char buffer[GFC_MAX_SYMBOL_LEN + 3];
1651 4249 : if (gfc_match_char ('+') == MATCH_YES)
1652 : rop = OMP_REDUCTION_PLUS;
1653 2224 : else if (gfc_match_char ('*') == MATCH_YES)
1654 : rop = OMP_REDUCTION_TIMES;
1655 1992 : else if (gfc_match_char ('-') == MATCH_YES)
1656 : {
1657 171 : if (!openacc)
1658 16 : gfc_warning (OPT_Wdeprecated_openmp,
1659 : "%<-%> operator at %C for reductions deprecated in "
1660 : "OpenMP 5.2");
1661 : rop = OMP_REDUCTION_MINUS;
1662 : }
1663 1821 : else if (gfc_match (".and.") == MATCH_YES)
1664 : rop = OMP_REDUCTION_AND;
1665 1715 : else if (gfc_match (".or.") == MATCH_YES)
1666 : rop = OMP_REDUCTION_OR;
1667 930 : else if (gfc_match (".eqv.") == MATCH_YES)
1668 : rop = OMP_REDUCTION_EQV;
1669 832 : else if (gfc_match (".neqv.") == MATCH_YES)
1670 : rop = OMP_REDUCTION_NEQV;
1671 16 : if (rop != OMP_REDUCTION_NONE)
1672 3512 : snprintf (buffer, sizeof buffer, "operator %s",
1673 : gfc_op2string ((gfc_intrinsic_op) rop));
1674 737 : else if (gfc_match_defined_op_name (buffer + 1, 1) == MATCH_YES)
1675 : {
1676 38 : buffer[0] = '.';
1677 38 : strcat (buffer, ".");
1678 : }
1679 699 : else if (gfc_match_name (buffer) == MATCH_YES)
1680 : {
1681 698 : gfc_symbol *sym;
1682 698 : const char *n = buffer;
1683 :
1684 698 : gfc_find_symbol (buffer, NULL, 1, &sym);
1685 698 : if (sym != NULL)
1686 : {
1687 217 : if (sym->attr.intrinsic)
1688 139 : n = sym->name;
1689 78 : else if ((sym->attr.flavor != FL_UNKNOWN
1690 76 : && sym->attr.flavor != FL_PROCEDURE)
1691 76 : || sym->attr.external
1692 65 : || sym->attr.generic
1693 65 : || sym->attr.entry
1694 65 : || sym->attr.result
1695 65 : || sym->attr.dummy
1696 65 : || sym->attr.subroutine
1697 64 : || sym->attr.pointer
1698 64 : || sym->attr.target
1699 64 : || sym->attr.cray_pointer
1700 64 : || sym->attr.cray_pointee
1701 64 : || (sym->attr.proc != PROC_UNKNOWN
1702 2 : && sym->attr.proc != PROC_INTRINSIC)
1703 62 : || sym->attr.if_source != IFSRC_UNKNOWN
1704 62 : || sym == sym->ns->proc_name)
1705 : {
1706 : sym = NULL;
1707 : n = NULL;
1708 : }
1709 : else
1710 62 : n = sym->name;
1711 : }
1712 201 : if (n == NULL)
1713 : rop = OMP_REDUCTION_NONE;
1714 682 : else if (strcmp (n, "max") == 0)
1715 : rop = OMP_REDUCTION_MAX;
1716 517 : else if (strcmp (n, "min") == 0)
1717 : rop = OMP_REDUCTION_MIN;
1718 376 : else if (strcmp (n, "iand") == 0)
1719 : rop = OMP_REDUCTION_IAND;
1720 321 : else if (strcmp (n, "ior") == 0)
1721 : rop = OMP_REDUCTION_IOR;
1722 255 : else if (strcmp (n, "ieor") == 0)
1723 : rop = OMP_REDUCTION_IEOR;
1724 : if (rop != OMP_REDUCTION_NONE
1725 477 : && sym != NULL
1726 200 : && ! sym->attr.intrinsic
1727 61 : && ! sym->attr.use_assoc
1728 61 : && ((sym->attr.flavor == FL_UNKNOWN
1729 2 : && !gfc_add_flavor (&sym->attr, FL_PROCEDURE,
1730 : sym->name, NULL))
1731 61 : || !gfc_add_intrinsic (&sym->attr, NULL)))
1732 : rop = OMP_REDUCTION_NONE;
1733 : }
1734 : else
1735 1 : buffer[0] = '\0';
1736 4249 : gfc_omp_udr *udr = (buffer[0] ? gfc_find_omp_udr (gfc_current_ns, buffer, NULL)
1737 : : NULL);
1738 4249 : gfc_omp_namelist **head = NULL;
1739 4249 : if (rop == OMP_REDUCTION_NONE && udr)
1740 251 : rop = OMP_REDUCTION_USER;
1741 :
1742 4249 : if (gfc_match_omp_variable_list (" :", &c->lists[list_idx], false, NULL,
1743 : &head, openacc, allow_derived) != MATCH_YES)
1744 : {
1745 9 : gfc_current_locus = old_loc;
1746 9 : return MATCH_NO;
1747 : }
1748 4240 : gfc_omp_namelist *n;
1749 4240 : if (rop == OMP_REDUCTION_NONE)
1750 : {
1751 6 : n = *head;
1752 6 : *head = NULL;
1753 6 : gfc_error_now ("!$OMP DECLARE REDUCTION %s not found at %L",
1754 : buffer, &old_loc);
1755 6 : gfc_free_omp_namelist (n, OMP_LIST_NONE);
1756 : }
1757 : else
1758 9120 : for (n = *head; n; n = n->next)
1759 : {
1760 4886 : n->u.reduction_op = rop;
1761 4886 : if (udr)
1762 : {
1763 477 : n->u2.udr = gfc_get_omp_namelist_udr ();
1764 477 : n->u2.udr->udr = udr;
1765 : }
1766 4886 : if (openmp_target && list_idx == OMP_LIST_IN_REDUCTION)
1767 : {
1768 40 : gfc_omp_namelist *p = gfc_get_omp_namelist (), **tl;
1769 40 : p->sym = n->sym;
1770 40 : p->where = n->where;
1771 40 : p->u.map.op = OMP_MAP_ALWAYS_TOFROM;
1772 :
1773 40 : tl = &c->lists[OMP_LIST_MAP];
1774 52 : while (*tl)
1775 12 : tl = &((*tl)->next);
1776 40 : *tl = p;
1777 40 : p->next = NULL;
1778 : }
1779 : }
1780 : return MATCH_YES;
1781 : }
1782 :
1783 : static match
1784 47 : gfc_omp_absent_contains_clause (gfc_omp_assumptions **assume, bool is_absent)
1785 : {
1786 47 : if (*assume == NULL)
1787 22 : *assume = gfc_get_omp_assumptions ();
1788 77 : do
1789 : {
1790 62 : gfc_statement st = ST_NONE;
1791 62 : gfc_gobble_whitespace ();
1792 62 : locus old_loc = gfc_current_locus;
1793 62 : char c = gfc_peek_ascii_char ();
1794 62 : enum gfc_omp_directive_kind kind
1795 : = GFC_OMP_DIR_DECLARATIVE; /* Silence warning. */
1796 2369 : for (size_t i = 0; i < ARRAY_SIZE (gfc_omp_directives); i++)
1797 : {
1798 2307 : if (gfc_omp_directives[i].name[0] > c)
1799 : break;
1800 2245 : if (gfc_omp_directives[i].name[0] != c)
1801 1668 : continue;
1802 577 : if (gfc_match (gfc_omp_directives[i].name) == MATCH_YES)
1803 : {
1804 62 : st = gfc_omp_directives[i].st;
1805 62 : kind = gfc_omp_directives[i].kind;
1806 : }
1807 : }
1808 62 : gfc_gobble_whitespace ();
1809 62 : c = gfc_peek_ascii_char ();
1810 62 : if (st == ST_NONE || (c != ',' && c != ')'))
1811 : {
1812 0 : if (st == ST_NONE)
1813 0 : gfc_error ("Unknown directive at %L", &old_loc);
1814 : else
1815 0 : gfc_error ("Invalid combined or composite directive at %L",
1816 : &old_loc);
1817 9 : return MATCH_ERROR;
1818 : }
1819 62 : if (kind == GFC_OMP_DIR_DECLARATIVE
1820 62 : || kind == GFC_OMP_DIR_INFORMATIONAL
1821 : || kind == GFC_OMP_DIR_META)
1822 : {
1823 15 : gfc_error ("Invalid %qs directive at %L in %s clause: declarative, "
1824 : "informational, and meta directives not permitted",
1825 : gfc_ascii_statement (st, true), &old_loc,
1826 : is_absent ? "ABSENT" : "CONTAINS");
1827 9 : return MATCH_ERROR;
1828 : }
1829 53 : if (is_absent)
1830 : {
1831 : /* Use exponential allocation; equivalent to pow2p(x). */
1832 38 : int i = (*assume)->n_absent;
1833 38 : int size = ((i == 0) ? 4
1834 14 : : pow2p_hwi (i) == 1 ? i*2 : 0);
1835 11 : if (size != 0)
1836 35 : (*assume)->absent = XRESIZEVEC (gfc_statement,
1837 : (*assume)->absent, size);
1838 38 : (*assume)->absent[(*assume)->n_absent++] = st;
1839 : }
1840 : else
1841 : {
1842 15 : int i = (*assume)->n_contains;
1843 15 : int size = ((i == 0) ? 4
1844 4 : : pow2p_hwi (i) == 1 ? i*2 : 0);
1845 4 : if (size != 0)
1846 15 : (*assume)->contains = XRESIZEVEC (gfc_statement,
1847 : (*assume)->contains, size);
1848 15 : (*assume)->contains[(*assume)->n_contains++] = st;
1849 : }
1850 53 : gfc_gobble_whitespace ();
1851 53 : if (gfc_match(",") == MATCH_YES)
1852 15 : continue;
1853 38 : if (gfc_match(")") == MATCH_YES)
1854 : break;
1855 0 : gfc_error ("Expected %<,%> or %<)%> at %C");
1856 0 : return MATCH_ERROR;
1857 15 : }
1858 : while (true);
1859 :
1860 38 : return MATCH_YES;
1861 : }
1862 :
1863 : /* Check 'check' argument for duplicated statements in absent and/or contains
1864 : clauses. If 'merge', merge them from check to 'merge'. */
1865 :
1866 : static match
1867 50 : omp_verify_merge_absent_contains (gfc_statement st, gfc_omp_assumptions *check,
1868 : gfc_omp_assumptions *merge, locus *loc)
1869 : {
1870 50 : if (check == NULL)
1871 : return MATCH_YES;
1872 49 : bitmap_head absent_head, contains_head;
1873 49 : bitmap_obstack_initialize (NULL);
1874 49 : bitmap_initialize (&absent_head, &bitmap_default_obstack);
1875 49 : bitmap_initialize (&contains_head, &bitmap_default_obstack);
1876 :
1877 49 : match m = MATCH_YES;
1878 87 : for (int i = 0; i < check->n_absent; i++)
1879 38 : if (!bitmap_set_bit (&absent_head, check->absent[i]))
1880 : {
1881 2 : gfc_error ("%qs directive mentioned multiple times in %s clause in %s "
1882 : "directive at %L",
1883 2 : gfc_ascii_statement (check->absent[i], true),
1884 : "ABSENT", gfc_ascii_statement (st), loc);
1885 2 : m = MATCH_ERROR;
1886 : }
1887 64 : for (int i = 0; i < check->n_contains; i++)
1888 : {
1889 15 : if (!bitmap_set_bit (&contains_head, check->contains[i]))
1890 : {
1891 2 : gfc_error ("%qs directive mentioned multiple times in %s clause in %s "
1892 : "directive at %L",
1893 2 : gfc_ascii_statement (check->contains[i], true),
1894 : "CONTAINS", gfc_ascii_statement (st), loc);
1895 2 : m = MATCH_ERROR;
1896 : }
1897 15 : if (bitmap_bit_p (&absent_head, check->contains[i]))
1898 : {
1899 2 : gfc_error ("%qs directive mentioned both times in ABSENT and CONTAINS "
1900 : "clauses in %s directive at %L",
1901 2 : gfc_ascii_statement (check->absent[i], true),
1902 : gfc_ascii_statement (st), loc);
1903 2 : m = MATCH_ERROR;
1904 : }
1905 : }
1906 :
1907 49 : if (m == MATCH_ERROR)
1908 : return MATCH_ERROR;
1909 43 : if (merge == NULL)
1910 : return MATCH_YES;
1911 3 : if (merge->absent == NULL && check->absent)
1912 : {
1913 1 : merge->n_absent = check->n_absent;
1914 1 : merge->absent = check->absent;
1915 1 : check->absent = NULL;
1916 : }
1917 2 : else if (merge->absent && check->absent)
1918 : {
1919 0 : check->absent = XRESIZEVEC (gfc_statement, check->absent,
1920 : merge->n_absent + check->n_absent);
1921 0 : for (int i = 0; i < merge->n_absent; i++)
1922 0 : if (!bitmap_bit_p (&absent_head, merge->absent[i]))
1923 0 : check->absent[check->n_absent++] = merge->absent[i];
1924 0 : free (merge->absent);
1925 0 : merge->absent = check->absent;
1926 0 : merge->n_absent = check->n_absent;
1927 0 : check->absent = NULL;
1928 : }
1929 3 : if (merge->contains == NULL && check->contains)
1930 : {
1931 0 : merge->n_contains = check->n_contains;
1932 0 : merge->contains = check->contains;
1933 0 : check->contains = NULL;
1934 : }
1935 3 : else if (merge->contains && check->contains)
1936 : {
1937 0 : check->contains = XRESIZEVEC (gfc_statement, check->contains,
1938 : merge->n_contains + check->n_contains);
1939 0 : for (int i = 0; i < merge->n_contains; i++)
1940 0 : if (!bitmap_bit_p (&contains_head, merge->contains[i]))
1941 0 : check->contains[check->n_contains++] = merge->contains[i];
1942 0 : free (merge->contains);
1943 0 : merge->contains = check->contains;
1944 0 : merge->n_contains = check->n_contains;
1945 0 : check->contains = NULL;
1946 : }
1947 : return MATCH_YES;
1948 : }
1949 :
1950 : /* OpenMP 5.0
1951 : uses_allocators ( allocator-list )
1952 :
1953 : allocator:
1954 : predefined-allocator
1955 : variable ( traits-array )
1956 :
1957 : OpenMP 5.2 deprecated, 6.0 deleted: 'variable ( traits-array )'
1958 :
1959 : OpenMP 5.2:
1960 : uses_allocators ( [modifier-list :] allocator-list )
1961 :
1962 : OpenMP 6.0:
1963 : uses_allocators ( [modifier-list :] allocator-list [; ...])
1964 :
1965 : allocator:
1966 : variable or predefined-allocator
1967 : modifier:
1968 : traits ( traits-array )
1969 : memspace ( mem-space-handle ) */
1970 :
1971 : static match
1972 78 : gfc_match_omp_clause_uses_allocators (gfc_omp_clauses *c)
1973 : {
1974 82 : parse_next:
1975 82 : gfc_symbol *memspace_sym = NULL;
1976 82 : gfc_symbol *traits_sym = NULL;
1977 82 : gfc_omp_namelist *head = NULL;
1978 82 : gfc_omp_namelist *p, *tail, **list;
1979 82 : int ntraits, nmemspace;
1980 82 : bool has_modifiers;
1981 82 : locus old_loc, cur_loc;
1982 :
1983 82 : gfc_gobble_whitespace ();
1984 82 : old_loc = gfc_current_locus;
1985 82 : ntraits = nmemspace = 0;
1986 126 : do
1987 : {
1988 104 : cur_loc = gfc_current_locus;
1989 104 : if (gfc_match ("traits ( %S ) ", &traits_sym) == MATCH_YES)
1990 34 : ntraits++;
1991 70 : else if (gfc_match ("memspace ( %S ) ", &memspace_sym) == MATCH_YES)
1992 33 : nmemspace++;
1993 104 : if (ntraits > 1 || nmemspace > 1)
1994 : {
1995 5 : gfc_error ("Duplicate %s modifier at %L in USES_ALLOCATORS clause",
1996 : ntraits > 1 ? "TRAITS" : "MEMSPACE", &cur_loc);
1997 5 : return MATCH_ERROR;
1998 : }
1999 99 : if (gfc_match (", ") == MATCH_YES)
2000 22 : continue;
2001 77 : if (gfc_match (": ") != MATCH_YES)
2002 : {
2003 : /* Assume no modifier. */
2004 39 : memspace_sym = traits_sym = NULL;
2005 39 : gfc_current_locus = old_loc;
2006 39 : break;
2007 : }
2008 : break;
2009 : } while (true);
2010 :
2011 115 : has_modifiers = traits_sym != NULL || memspace_sym != NULL;
2012 179 : do
2013 : {
2014 128 : p = gfc_get_omp_namelist ();
2015 128 : p->where = gfc_current_locus;
2016 128 : if (head == NULL)
2017 : head = tail = p;
2018 : else
2019 : {
2020 51 : tail->next = p;
2021 51 : tail = tail->next;
2022 : }
2023 128 : if (gfc_match ("%S ", &p->sym) != MATCH_YES)
2024 1 : goto error;
2025 127 : if (!has_modifiers)
2026 : {
2027 83 : if (gfc_match ("( %S ) ", &p->u2.traits_sym) == MATCH_YES)
2028 22 : gfc_warning (OPT_Wdeprecated_openmp,
2029 : "The specification of arguments to "
2030 : "%<uses_allocators%> at %L where each item is of "
2031 : "the form %<allocator(traits)%> is deprecated since "
2032 : "OpenMP 5.2; instead use %<uses_allocators(traits(%s"
2033 22 : "): %s)%>", &p->where, p->u2.traits_sym->name,
2034 22 : p->sym->name);
2035 : }
2036 44 : else if (gfc_peek_ascii_char () == '(')
2037 : {
2038 1 : gfc_error ("Unexpected %<(%> at %C");
2039 1 : goto error;
2040 : }
2041 : else
2042 : {
2043 43 : p->u.memspace_sym = memspace_sym;
2044 43 : p->u2.traits_sym = traits_sym;
2045 : }
2046 126 : gfc_gobble_whitespace ();
2047 126 : const char c = gfc_peek_ascii_char ();
2048 126 : if (c == ';' || c == ')')
2049 : break;
2050 53 : if (c != ',')
2051 : {
2052 2 : gfc_error ("Expected %<,%>, %<)%> or %<;%> at %C");
2053 2 : goto error;
2054 : }
2055 51 : gfc_match_char (',');
2056 51 : gfc_gobble_whitespace ();
2057 51 : } while (true);
2058 :
2059 73 : list = &c->lists[OMP_LIST_USES_ALLOCATORS];
2060 91 : while (*list)
2061 18 : list = &(*list)->next;
2062 73 : *list = head;
2063 :
2064 73 : if (gfc_match_char (';') == MATCH_YES)
2065 4 : goto parse_next;
2066 :
2067 69 : gfc_match_char (')');
2068 69 : return MATCH_YES;
2069 :
2070 4 : error:
2071 4 : gfc_free_omp_namelist (head, OMP_LIST_USES_ALLOCATORS);
2072 4 : return MATCH_ERROR;
2073 : }
2074 :
2075 :
2076 : /* Match the 'prefer_type' modifier of the interop 'init' clause:
2077 : with either OpenMP 5.1's
2078 : prefer_type ( <const-int-expr|string literal> [, ...]
2079 : or
2080 : prefer_type ( '{' <fr(...) | attr (...)>, ...] '}' [, '{' ... '}' ] )
2081 : where 'fr' takes a constant expression or a string literal
2082 : and 'attr takes a list of string literals, starting with 'ompx_')
2083 :
2084 : For the foreign runtime identifiers, string values are converted to
2085 : their integer value; unknown string or integer values are set to
2086 : GOMP_INTEROP_IFR_KNOWN.
2087 :
2088 : Data format:
2089 : For the foreign runtime identifiers, string values are converted to
2090 : their integer value; unknown string or integer values are set to 0.
2091 :
2092 : Each item (a) GOMP_INTEROP_IFR_SEPARATOR
2093 : (b) for any 'fr', its integer value.
2094 : Note: Spec only permits 1 'fr' entry (6.0; changed after TR13)
2095 : (c) GOMP_INTEROP_IFR_SEPARATOR
2096 : (d) list of \0-terminated non-empty strings for 'attr'
2097 : (e) '\0'
2098 : Tailing '\0'. */
2099 :
2100 : static match
2101 82 : gfc_match_omp_prefer_type (char **type_str, int *type_str_len)
2102 : {
2103 82 : gfc_expr *e;
2104 82 : std::string type_string, attr_string;
2105 : /* New syntax. */
2106 82 : if (gfc_peek_ascii_char () == '{')
2107 115 : do
2108 : {
2109 85 : attr_string.clear ();
2110 85 : type_string += (char) GOMP_INTEROP_IFR_SEPARATOR;
2111 85 : if (gfc_match ("{ ") != MATCH_YES)
2112 : {
2113 1 : gfc_error ("Expected %<{%> at %C");
2114 1 : return MATCH_ERROR;
2115 : }
2116 : bool fr_found = false;
2117 148 : do
2118 : {
2119 116 : if (gfc_match ("fr ( ") == MATCH_YES)
2120 : {
2121 62 : if (fr_found)
2122 : {
2123 1 : gfc_error ("Duplicated %<fr%> preference-selector-name "
2124 : "at %C");
2125 1 : return MATCH_ERROR;
2126 : }
2127 61 : fr_found = true;
2128 61 : do
2129 : {
2130 61 : bool found_literal = false;
2131 61 : match m = MATCH_YES;
2132 61 : if (gfc_match_literal_constant (&e, false) == MATCH_YES)
2133 : found_literal = true;
2134 : else
2135 12 : m = gfc_match_expr (&e);
2136 12 : if (m != MATCH_YES
2137 61 : || !gfc_resolve_expr (e)
2138 61 : || e->rank != 0
2139 60 : || e->expr_type != EXPR_CONSTANT
2140 59 : || (e->ts.type != BT_INTEGER
2141 43 : && (!found_literal || e->ts.type != BT_CHARACTER))
2142 58 : || (e->ts.type == BT_INTEGER
2143 16 : && !mpz_fits_sint_p (e->value.integer))
2144 70 : || (e->ts.type == BT_CHARACTER
2145 42 : && (e->ts.kind != gfc_default_character_kind
2146 41 : || e->value.character.length == 0)))
2147 : {
2148 5 : gfc_error ("Expected constant scalar integer expression"
2149 : " or non-empty default-kind character "
2150 5 : "literal at %L", &e->where);
2151 5 : gfc_free_expr (e);
2152 5 : return MATCH_ERROR;
2153 : }
2154 56 : gfc_gobble_whitespace ();
2155 56 : int val;
2156 56 : if (e->ts.type == BT_INTEGER)
2157 : {
2158 16 : val = mpz_get_si (e->value.integer);
2159 16 : if (val < 1 || val > GOMP_INTEROP_IFR_LAST)
2160 : {
2161 0 : gfc_warning_now (OPT_Wopenmp,
2162 : "Unknown foreign runtime "
2163 : "identifier %qd at %L",
2164 : val, &e->where);
2165 0 : val = GOMP_INTEROP_IFR_UNKNOWN;
2166 : }
2167 : }
2168 : else
2169 : {
2170 40 : char *str = XALLOCAVEC (char,
2171 : e->value.character.length+1);
2172 229 : for (int i = 0; i < e->value.character.length + 1; i++)
2173 189 : str[i] = e->value.character.string[i];
2174 40 : if (memchr (str, '\0', e->value.character.length) != 0)
2175 : {
2176 0 : gfc_error ("Unexpected null character in character "
2177 : "literal at %L", &e->where);
2178 0 : return MATCH_ERROR;
2179 : }
2180 40 : val = omp_get_fr_id_from_name (str);
2181 40 : if (val == GOMP_INTEROP_IFR_UNKNOWN)
2182 2 : gfc_warning_now (OPT_Wopenmp,
2183 : "Unknown foreign runtime identifier "
2184 2 : "%qs at %L", str, &e->where);
2185 : }
2186 :
2187 56 : type_string += (char) val;
2188 56 : if (gfc_match (") ") == MATCH_YES)
2189 : break;
2190 4 : gfc_error ("Expected %<)%> at %C");
2191 4 : return MATCH_ERROR;
2192 : }
2193 : while (true);
2194 : }
2195 54 : else if (gfc_match ("attr ( ") == MATCH_YES)
2196 : {
2197 60 : do
2198 : {
2199 57 : if (gfc_match_literal_constant (&e, false) != MATCH_YES
2200 56 : || !gfc_resolve_expr (e)
2201 56 : || e->expr_type != EXPR_CONSTANT
2202 56 : || e->rank != 0
2203 56 : || e->ts.type != BT_CHARACTER
2204 113 : || e->ts.kind != gfc_default_character_kind)
2205 : {
2206 1 : gfc_error ("Expected default-kind character literal "
2207 1 : "at %L", &e->where);
2208 1 : gfc_free_expr (e);
2209 1 : return MATCH_ERROR;
2210 : }
2211 56 : gfc_gobble_whitespace ();
2212 56 : char *str = XALLOCAVEC (char, e->value.character.length+1);
2213 564 : for (int i = 0; i < e->value.character.length + 1; i++)
2214 508 : str[i] = e->value.character.string[i];
2215 56 : if (!startswith (str, "ompx_"))
2216 : {
2217 1 : gfc_error ("Character literal at %L must start with "
2218 : "%<ompx_%>", &e->where);
2219 1 : gfc_free_expr (e);
2220 1 : return MATCH_ERROR;
2221 : }
2222 55 : if (memchr (str, '\0', e->value.character.length) != 0
2223 55 : || memchr (str, ',', e->value.character.length) != 0)
2224 : {
2225 1 : gfc_error ("Unexpected null or %<,%> character in "
2226 : "character literal at %L", &e->where);
2227 1 : return MATCH_ERROR;
2228 : }
2229 54 : attr_string += str;
2230 54 : attr_string += '\0';
2231 54 : if (gfc_match (", ") == MATCH_YES)
2232 3 : continue;
2233 51 : if (gfc_match (") ") == MATCH_YES)
2234 : break;
2235 0 : gfc_error ("Expected %<,%> or %<)%> at %C");
2236 0 : return MATCH_ERROR;
2237 3 : }
2238 : while (true);
2239 : }
2240 : else
2241 : {
2242 0 : gfc_error ("Expected %<fr(%> or %<attr(%> at %C");
2243 0 : return MATCH_ERROR;
2244 : }
2245 103 : if (gfc_match (", ") == MATCH_YES)
2246 32 : continue;
2247 71 : if (gfc_match ("} ") == MATCH_YES)
2248 : break;
2249 2 : gfc_error ("Expected %<,%> or %<}%> at %C");
2250 2 : return MATCH_ERROR;
2251 32 : }
2252 : while (true);
2253 69 : type_string += (char) GOMP_INTEROP_IFR_SEPARATOR;
2254 69 : type_string += attr_string;
2255 69 : type_string += '\0';
2256 69 : if (gfc_match (", ") == MATCH_YES)
2257 30 : continue;
2258 39 : if (gfc_match (") ") == MATCH_YES)
2259 : break;
2260 1 : gfc_error ("Expected %<,%> or %<)%> at %C");
2261 1 : return MATCH_ERROR;
2262 30 : }
2263 : while (true);
2264 : else
2265 75 : do
2266 : {
2267 51 : type_string += (char) GOMP_INTEROP_IFR_SEPARATOR;
2268 51 : bool found_literal = false;
2269 51 : match m = MATCH_YES;
2270 51 : if (gfc_match_literal_constant (&e, false) == MATCH_YES)
2271 : found_literal = true;
2272 : else
2273 19 : m = gfc_match_expr (&e);
2274 19 : if (m != MATCH_YES
2275 51 : || !gfc_resolve_expr (e)
2276 51 : || e->rank != 0
2277 50 : || e->expr_type != EXPR_CONSTANT
2278 49 : || (e->ts.type != BT_INTEGER
2279 28 : && (!found_literal || e->ts.type != BT_CHARACTER))
2280 48 : || (e->ts.type == BT_INTEGER
2281 21 : && !mpz_fits_sint_p (e->value.integer))
2282 67 : || (e->ts.type == BT_CHARACTER
2283 27 : && (e->ts.kind != gfc_default_character_kind
2284 27 : || e->value.character.length == 0)))
2285 : {
2286 3 : gfc_error ("Expected constant scalar integer expression or "
2287 3 : "non-empty default-kind character literal at %L", &e->where);
2288 3 : gfc_free_expr (e);
2289 3 : return MATCH_ERROR;
2290 : }
2291 48 : gfc_gobble_whitespace ();
2292 48 : int val;
2293 48 : if (e->ts.type == BT_INTEGER)
2294 : {
2295 21 : val = mpz_get_si (e->value.integer);
2296 21 : if (val < 1 || val > GOMP_INTEROP_IFR_LAST)
2297 : {
2298 3 : gfc_warning_now (OPT_Wopenmp,
2299 : "Unknown foreign runtime identifier %qd at %L",
2300 : val, &e->where);
2301 3 : val = 0;
2302 : }
2303 : }
2304 : else
2305 : {
2306 27 : char *str = XALLOCAVEC (char, e->value.character.length+1);
2307 169 : for (int i = 0; i < e->value.character.length + 1; i++)
2308 142 : str[i] = e->value.character.string[i];
2309 27 : if (memchr (str, '\0', e->value.character.length) != 0)
2310 : {
2311 0 : gfc_error ("Unexpected null character in character "
2312 : "literal at %L", &e->where);
2313 0 : return MATCH_ERROR;
2314 : }
2315 27 : val = omp_get_fr_id_from_name (str);
2316 27 : if (val == GOMP_INTEROP_IFR_UNKNOWN)
2317 5 : gfc_warning_now (OPT_Wopenmp,
2318 : "Unknown foreign runtime identifier %qs at %L",
2319 5 : str, &e->where);
2320 : }
2321 48 : type_string += (char) val;
2322 48 : type_string += (char) GOMP_INTEROP_IFR_SEPARATOR;
2323 48 : type_string += '\0';
2324 48 : gfc_free_expr (e);
2325 48 : if (gfc_match (", ") == MATCH_YES)
2326 24 : continue;
2327 24 : if (gfc_match (") ") == MATCH_YES)
2328 : break;
2329 2 : gfc_error ("Expected %<,%> or %<)%> at %C");
2330 2 : return MATCH_ERROR;
2331 24 : }
2332 : while (true);
2333 60 : type_string += '\0';
2334 60 : *type_str_len = type_string.length();
2335 60 : *type_str = XNEWVEC (char, type_string.length ());
2336 60 : memcpy (*type_str, type_string.data (), type_string.length ());
2337 60 : return MATCH_YES;
2338 82 : }
2339 :
2340 :
2341 : /* Match OpenMP 5.1's 'init'-clause modifiers, used by the 'init' clause of
2342 : the 'interop' directive and the 'append_args' directive of 'declare variant'.
2343 : [prefer_type(...)][,][<target|targetsync>, ...])
2344 :
2345 : If is_init_clause, the modifier parsing ends with a ':'.
2346 : If not is_init_clause (i.e. append_args), the parsing ends with ')'. */
2347 :
2348 : static match
2349 164 : gfc_parser_omp_clause_init_modifiers (bool &target, bool &targetsync,
2350 : char **type_str, int &type_str_len,
2351 : bool is_init_clause)
2352 : {
2353 164 : target = false;
2354 164 : targetsync = false;
2355 164 : *type_str = NULL;
2356 164 : type_str_len = 0;
2357 286 : match m;
2358 :
2359 286 : do
2360 : {
2361 286 : if (gfc_match ("prefer_type ( ") == MATCH_YES)
2362 : {
2363 83 : if (*type_str)
2364 : {
2365 1 : gfc_error ("Duplicate %<prefer_type%> modifier at %C");
2366 1 : return MATCH_ERROR;
2367 : }
2368 82 : m = gfc_match_omp_prefer_type (type_str, &type_str_len);
2369 82 : if (m != MATCH_YES)
2370 : return m;
2371 60 : if (gfc_match (", ") == MATCH_YES)
2372 14 : continue;
2373 46 : if (is_init_clause)
2374 : {
2375 24 : if (gfc_match (": ") == MATCH_YES)
2376 : break;
2377 0 : gfc_error ("Expected %<,%> or %<:%> at %C");
2378 : }
2379 : else
2380 : {
2381 22 : if (gfc_match (") ") == MATCH_YES)
2382 : break;
2383 0 : gfc_error ("Expected %<,%> or %<)%> at %C");
2384 : }
2385 : return MATCH_ERROR;
2386 : }
2387 :
2388 203 : if (gfc_match ("prefer_type ") == MATCH_YES)
2389 : {
2390 2 : gfc_error ("Expected %<(%> after %<prefer_type%> at %C");
2391 2 : return MATCH_ERROR;
2392 : }
2393 :
2394 201 : if (gfc_match ("targetsync ") == MATCH_YES)
2395 : {
2396 57 : if (targetsync)
2397 : {
2398 3 : gfc_error ("Duplicate %<targetsync%> at %C");
2399 3 : return MATCH_ERROR;
2400 : }
2401 54 : targetsync = true;
2402 54 : if (gfc_match (", ") == MATCH_YES)
2403 13 : continue;
2404 41 : if (!is_init_clause)
2405 : {
2406 23 : if (gfc_match (") ") == MATCH_YES)
2407 : break;
2408 0 : gfc_error ("Expected %<,%> or %<)%> at %C");
2409 0 : return MATCH_ERROR;
2410 : }
2411 18 : if (gfc_match (": ") == MATCH_YES)
2412 : break;
2413 1 : gfc_error ("Expected %<,%> or %<:%> at %C");
2414 1 : return MATCH_ERROR;
2415 : }
2416 144 : if (gfc_match ("target ") == MATCH_YES)
2417 : {
2418 135 : if (target)
2419 : {
2420 3 : gfc_error ("Duplicate %<target%> at %C");
2421 3 : return MATCH_ERROR;
2422 : }
2423 132 : target = true;
2424 132 : if (gfc_match (", ") == MATCH_YES)
2425 95 : continue;
2426 37 : if (!is_init_clause)
2427 : {
2428 11 : if (gfc_match (") ") == MATCH_YES)
2429 : break;
2430 0 : gfc_error ("Expected %<,%> or %<)%> at %C");
2431 0 : return MATCH_ERROR;
2432 : }
2433 26 : if (gfc_match (": ") == MATCH_YES)
2434 : break;
2435 1 : gfc_error ("Expected %<,%> or %<:%> at %C");
2436 1 : return MATCH_ERROR;
2437 : }
2438 9 : gfc_error ("Expected %<prefer_type%>, %<target%>, or %<targetsync%> "
2439 : "at %C");
2440 9 : return MATCH_ERROR;
2441 : }
2442 : while (true);
2443 :
2444 122 : if (!target && !targetsync)
2445 : {
2446 4 : gfc_error ("Missing required %<target%> and/or %<targetsync%> "
2447 : "modifier at %C");
2448 4 : return MATCH_ERROR;
2449 : }
2450 : return MATCH_YES;
2451 : }
2452 :
2453 : /* Match OpenMP 5.1's 'init' clause for 'interop' objects:
2454 : init([prefer_type(...)][,][<target|targetsync>, ...] :] interop-obj-list) */
2455 :
2456 : static match
2457 108 : gfc_match_omp_init (gfc_omp_namelist **list)
2458 : {
2459 108 : bool target, targetsync;
2460 108 : char *type_str = NULL;
2461 108 : int type_str_len;
2462 108 : if (gfc_parser_omp_clause_init_modifiers (target, targetsync, &type_str,
2463 : type_str_len, true) == MATCH_ERROR)
2464 : return MATCH_ERROR;
2465 :
2466 64 : gfc_omp_namelist **head = NULL;
2467 64 : if (gfc_match_omp_variable_list ("", list, false, NULL, &head) != MATCH_YES)
2468 : return MATCH_ERROR;
2469 147 : for (gfc_omp_namelist *n = *head; n; n = n->next)
2470 : {
2471 84 : n->u.init.target = target;
2472 84 : n->u.init.targetsync = targetsync;
2473 84 : n->u.init.len = type_str_len;
2474 84 : n->u2.init_interop = type_str;
2475 : }
2476 : return MATCH_YES;
2477 : }
2478 :
2479 : /* Match boolean-type clause with duplicate check. Matches 'name' then matches
2480 : an optional '(const-logical-expr)'; already_set is used for the duplicate
2481 : check. If the clause is not matched NO is returned, if an error occurs ERROR
2482 : and otherwise YES. In the no-error case RES contains the value of the
2483 : expression or true if no expression exists.
2484 : If FALSE_OK, 'false' implies an absent clause, which can be repeated without
2485 : printing an error; that is the case for clause groups.
2486 : If DUPL_MSG is nonnull, the string is used as error message and must contain
2487 : %qs and %L in that order. */
2488 :
2489 : static match
2490 3748 : gfc_match_boolean_clause (bool *res, const char *name, bool already_set,
2491 : bool false_ok = false, const char *dupl_msg = NULL)
2492 : {
2493 3748 : gfc_expr *expr = NULL;
2494 3748 : match m;
2495 3748 : char c;
2496 3748 : locus old_loc = gfc_current_locus;
2497 3748 : locus old_loc2;
2498 3748 : if ((m = gfc_match (name)) != MATCH_YES)
2499 : return m;
2500 : /* Ensure that no partial string is matched. */
2501 2506 : if (gfc_current_form == FORM_FREE
2502 2506 : && gfc_match_eos () != MATCH_YES
2503 3254 : && ((c = gfc_peek_ascii_char ()) == '_' || ISALNUM (c)))
2504 : {
2505 1 : gfc_current_locus = old_loc;
2506 1 : return MATCH_NO;
2507 : }
2508 2505 : if (already_set && !false_ok)
2509 22 : goto dupl;
2510 2483 : if (gfc_match (" (") == MATCH_NO)
2511 : {
2512 2289 : if (already_set)
2513 3 : goto dupl;
2514 2286 : *res = true; /* Implicit boolean true. */
2515 2286 : return MATCH_YES;
2516 : }
2517 194 : old_loc2 = gfc_current_locus;
2518 194 : m = gfc_match_expr (&expr);
2519 194 : if (m != MATCH_YES
2520 193 : || gfc_match (" )") != MATCH_YES
2521 188 : || !gfc_resolve_expr (expr)
2522 188 : || expr->rank != 0
2523 187 : || expr->expr_type != EXPR_CONSTANT
2524 379 : || expr->ts.type != BT_LOGICAL)
2525 : {
2526 13 : gfc_free_expr (expr);
2527 13 : gfc_error ("Expected %<( const-logical-expr )%> at %L", &old_loc2);
2528 13 : return MATCH_ERROR;
2529 : }
2530 181 : if (already_set && expr->value.logical)
2531 4 : goto dupl;
2532 177 : *res = expr->value.logical;
2533 177 : gfc_free_expr (expr);
2534 177 : return MATCH_YES;
2535 :
2536 29 : dupl:
2537 29 : if (dupl_msg)
2538 12 : gfc_error (dupl_msg, name, &old_loc);
2539 : else
2540 17 : gfc_error ("Duplicated %qs clause at %L", name, &old_loc);
2541 : return MATCH_ERROR;
2542 : }
2543 :
2544 :
2545 : /* Match a clause from the atomic clauses set. */
2546 :
2547 : static match
2548 1231 : gfc_match_dupl_atomic (bool *res, const char *name, bool already_set)
2549 : {
2550 1231 : const char *msg = G_("Duplicated atomic clause: unexpected %qs clause at %L");
2551 0 : return gfc_match_boolean_clause (res, name, already_set, true, msg);
2552 : }
2553 :
2554 :
2555 : /* Match a clause from the memory-order clauses set. */
2556 :
2557 : static match
2558 451 : gfc_match_dupl_memorder (bool *res, const char *name, bool already_set)
2559 : {
2560 451 : const char *msg = G_("Duplicated memory-order clause: unexpected %qs clause "
2561 : "at %L");
2562 0 : return gfc_match_boolean_clause (res, name, already_set, true, msg);
2563 : }
2564 :
2565 :
2566 : /* Match a clause from the branch clauses set; interestingly, here
2567 : inbranch(false) branch(false/true) is not permitted! */
2568 :
2569 : static match
2570 62 : gfc_match_dupl_branch_clause (bool *res, const char *name, bool already_set)
2571 : {
2572 62 : const char *msg = G_("Duplicated branch clause: unexpected %qs clause "
2573 : "at %L");
2574 62 : return gfc_match_boolean_clause (res, name, already_set, false, msg);
2575 : }
2576 :
2577 :
2578 : /* Match with duplicate check. Matches 'name'. If expr != NULL, it
2579 : then matches '(expr)', otherwise, if open_parens is true,
2580 : it matches a ' ( ' after 'name'. */
2581 :
2582 : static match
2583 20454 : gfc_match_dupl_check (bool not_dupl, const char *name, bool open_parens = false,
2584 : gfc_expr **expr = NULL)
2585 : {
2586 20454 : match m;
2587 20454 : char c;
2588 20454 : locus old_loc = gfc_current_locus;
2589 20454 : if ((m = gfc_match (name)) != MATCH_YES)
2590 : return m;
2591 : /* Ensure that no partial string is matched. */
2592 16055 : if (gfc_current_form == FORM_FREE
2593 15557 : && gfc_match_eos () != MATCH_YES
2594 29148 : && ((c = gfc_peek_ascii_char ()) == '_' || ISALNUM (c)))
2595 : {
2596 12 : gfc_current_locus = old_loc;
2597 12 : return MATCH_NO;
2598 : }
2599 16043 : if (!not_dupl)
2600 : {
2601 46 : gfc_error ("Duplicated %qs clause at %L", name, &old_loc);
2602 46 : return MATCH_ERROR;
2603 : }
2604 15997 : if (open_parens || expr)
2605 : {
2606 10201 : if (gfc_match (" ( ") != MATCH_YES)
2607 : {
2608 25 : gfc_error ("Expected %<(%> after %qs at %C", name);
2609 25 : return MATCH_ERROR;
2610 : }
2611 10176 : if (expr)
2612 : {
2613 3289 : if (gfc_match ("%e )", expr) != MATCH_YES)
2614 : {
2615 9 : gfc_error ("Invalid expression after %<%s(%> at %C", name);
2616 9 : return MATCH_ERROR;
2617 : }
2618 : }
2619 : }
2620 : return MATCH_YES;
2621 : }
2622 :
2623 : /* Search upwards though namespace NS and its parents to find an
2624 : !$omp declare mapper named MAPPER_ID, for typespec TS. The default
2625 : mapper has mapper_id == "". */
2626 :
2627 : gfc_omp_udm *
2628 1002 : gfc_find_omp_udm (gfc_namespace *ns, const char *mapper_id, gfc_typespec *ts)
2629 : {
2630 1002 : gfc_symtree *st;
2631 :
2632 1002 : if (ns == NULL)
2633 0 : ns = gfc_current_ns;
2634 :
2635 1181 : do
2636 : {
2637 1181 : gfc_omp_udm *omp_udm;
2638 :
2639 1181 : st = gfc_find_symtree (ns->omp_udm_root, mapper_id);
2640 :
2641 1181 : if (st != NULL)
2642 : {
2643 29 : for (omp_udm = st->n.omp_udm; omp_udm; omp_udm = omp_udm->next)
2644 29 : if (gfc_compare_types (&omp_udm->ts, ts))
2645 : return omp_udm;
2646 : }
2647 :
2648 : /* Don't escape an interface block. */
2649 1154 : if (ns && !ns->has_import_set
2650 1154 : && ns->proc_name && ns->proc_name->attr.if_source == IFSRC_IFBODY)
2651 : break;
2652 :
2653 1154 : ns = ns->parent;
2654 : }
2655 1154 : while (ns != NULL);
2656 :
2657 : return NULL;
2658 : }
2659 :
2660 :
2661 : /* Match OpenMP and OpenACC directive clauses. MASK is a bitmask of
2662 : clauses that are allowed for a particular directive. */
2663 :
2664 : static match
2665 35271 : gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
2666 : bool first_no_comma = true, bool needs_space = true,
2667 : bool openacc = false, bool openmp_target = false,
2668 : gfc_omp_map_op default_map_op = OMP_MAP_TOFROM)
2669 : {
2670 35271 : bool error = false;
2671 35271 : bool bval;
2672 35271 : gfc_omp_clauses *c = gfc_get_omp_clauses ();
2673 35271 : gfc_omp_clauses *cfalse = openacc ? NULL : gfc_get_omp_clauses ();
2674 21403 : locus old_loc;
2675 : /* Determine whether we're dealing with an OpenACC directive that permits
2676 : derived type member accesses. This in particular disallows
2677 : "!$acc declare" from using such accesses, because it's not clear if/how
2678 : that should work. */
2679 21403 : bool allow_derived = (openacc
2680 13868 : && ((mask & OMP_CLAUSE_ATTACH)
2681 6326 : || (mask & OMP_CLAUSE_DETACH)));
2682 :
2683 35271 : gcc_checking_assert (OMP_MASK1_LAST <= 64 && OMP_MASK2_LAST <= 64);
2684 35271 : *cp = NULL;
2685 129551 : while (1)
2686 : {
2687 82411 : match m = MATCH_NO;
2688 82318 : if ((first_no_comma || (m = gfc_match_char (',')) != MATCH_YES)
2689 164284 : && (needs_space && gfc_match_space () != MATCH_YES))
2690 : break;
2691 77872 : needs_space = false;
2692 77872 : first_no_comma = false;
2693 77872 : gfc_gobble_whitespace ();
2694 77872 : bool end_colon;
2695 77872 : gfc_omp_namelist **head;
2696 77872 : old_loc = gfc_current_locus;
2697 77872 : char pc = gfc_peek_ascii_char ();
2698 77872 : if (pc == '\n' && m == MATCH_YES)
2699 : {
2700 1 : gfc_error ("Clause expected at %C after trailing comma");
2701 1 : goto error;
2702 : }
2703 77871 : switch (pc)
2704 : {
2705 1339 : case 'a':
2706 1339 : end_colon = false;
2707 1339 : head = NULL;
2708 1364 : if ((mask & OMP_CLAUSE_ASSUMPTIONS)
2709 1339 : && gfc_match ("absent ( ") == MATCH_YES)
2710 : {
2711 28 : if (gfc_omp_absent_contains_clause (&c->assume, true)
2712 : != MATCH_YES)
2713 3 : goto error;
2714 25 : continue;
2715 : }
2716 1311 : if ((mask & OMP_CLAUSE_ALIGNED)
2717 1311 : && gfc_match_omp_variable_list ("aligned (",
2718 : &c->lists[OMP_LIST_ALIGNED],
2719 : false, &end_colon,
2720 : &head) == MATCH_YES)
2721 : {
2722 112 : gfc_expr *alignment = NULL;
2723 112 : gfc_omp_namelist *n;
2724 :
2725 112 : if (end_colon && gfc_match (" %e )", &alignment) != MATCH_YES)
2726 : {
2727 0 : gfc_free_omp_namelist (*head, OMP_LIST_ALIGNED);
2728 0 : gfc_current_locus = old_loc;
2729 0 : *head = NULL;
2730 0 : break;
2731 : }
2732 268 : for (n = *head; n; n = n->next)
2733 156 : if (n->next && alignment)
2734 42 : n->expr = gfc_copy_expr (alignment);
2735 : else
2736 114 : n->expr = alignment;
2737 112 : continue;
2738 112 : }
2739 1218 : if ((mask & OMP_CLAUSE_MEMORDER)
2740 1234 : && (m = gfc_match_dupl_memorder (&bval, "acq_rel",
2741 35 : c->memorder != OMP_MEMORDER_UNSET)) != MATCH_NO)
2742 : {
2743 19 : if (m == MATCH_ERROR)
2744 0 : goto error;
2745 19 : if (bval)
2746 12 : c->memorder = OMP_MEMORDER_ACQ_REL;
2747 19 : continue;
2748 : }
2749 1196 : if ((mask & OMP_CLAUSE_MEMORDER)
2750 1196 : && (m = gfc_match_dupl_memorder (&bval, "acquire",
2751 16 : c->memorder != OMP_MEMORDER_UNSET)) != MATCH_NO)
2752 : {
2753 16 : if (m == MATCH_ERROR)
2754 0 : goto error;
2755 16 : if (bval)
2756 9 : c->memorder = OMP_MEMORDER_ACQUIRE;
2757 16 : continue;
2758 : }
2759 1164 : if ((mask & OMP_CLAUSE_AFFINITY)
2760 1164 : && gfc_match ("affinity ( ") == MATCH_YES)
2761 : {
2762 41 : gfc_namespace *ns_iter = NULL, *ns_curr = gfc_current_ns;
2763 41 : m = gfc_match_iterator (&ns_iter, true);
2764 41 : if (m == MATCH_ERROR)
2765 : break;
2766 31 : if (m == MATCH_YES && gfc_match (" : ") != MATCH_YES)
2767 : {
2768 1 : gfc_error ("Expected %<:%> at %C");
2769 1 : break;
2770 : }
2771 30 : if (ns_iter)
2772 18 : gfc_current_ns = ns_iter;
2773 30 : head = NULL;
2774 30 : m = gfc_match_omp_variable_list ("", &c->lists[OMP_LIST_AFFINITY],
2775 : false, NULL, &head, true);
2776 30 : gfc_current_ns = ns_curr;
2777 30 : if (m == MATCH_ERROR)
2778 : break;
2779 27 : if (ns_iter)
2780 : {
2781 45 : for (gfc_omp_namelist *n = *head; n; n = n->next)
2782 : {
2783 27 : n->u2.ns = ns_iter;
2784 27 : ns_iter->refs++;
2785 : }
2786 : }
2787 27 : continue;
2788 27 : }
2789 1123 : if ((mask & OMP_CLAUSE_ALLOCATE)
2790 1123 : && gfc_match ("allocate ( ") == MATCH_YES)
2791 : {
2792 281 : gfc_expr *allocator = NULL;
2793 281 : gfc_expr *align = NULL;
2794 281 : old_loc = gfc_current_locus;
2795 281 : if ((m = gfc_match ("allocator ( %e )", &allocator)) == MATCH_YES)
2796 50 : gfc_match (" , align ( %e )", &align);
2797 231 : else if ((m = gfc_match ("align ( %e )", &align)) == MATCH_YES)
2798 29 : gfc_match (" , allocator ( %e )", &allocator);
2799 :
2800 79 : if (m == MATCH_YES)
2801 : {
2802 79 : if (gfc_match (" : ") != MATCH_YES)
2803 : {
2804 5 : gfc_error ("Expected %<:%> at %C");
2805 8 : goto error;
2806 : }
2807 : }
2808 : else
2809 : {
2810 202 : m = gfc_match_expr (&allocator);
2811 202 : if (m == MATCH_YES && gfc_match (" : ") != MATCH_YES)
2812 : {
2813 : /* If no ":" then there is no allocator, we backtrack
2814 : and read the variable list. */
2815 101 : gfc_free_expr (allocator);
2816 101 : allocator = NULL;
2817 101 : gfc_current_locus = old_loc;
2818 : }
2819 : }
2820 276 : gfc_omp_namelist **head = NULL;
2821 276 : m = gfc_match_omp_variable_list ("", &c->lists[OMP_LIST_ALLOCATE],
2822 : true, NULL, &head);
2823 :
2824 276 : if (m != MATCH_YES)
2825 : {
2826 3 : gfc_free_expr (allocator);
2827 3 : gfc_free_expr (align);
2828 3 : gfc_error ("Expected variable list at %C");
2829 3 : goto error;
2830 : }
2831 :
2832 729 : for (gfc_omp_namelist *n = *head; n; n = n->next)
2833 : {
2834 456 : n->u2.allocator = allocator;
2835 456 : n->u.align = (align) ? gfc_copy_expr (align) : NULL;
2836 : }
2837 273 : gfc_free_expr (align);
2838 273 : continue;
2839 273 : }
2840 905 : if ((mask & OMP_CLAUSE_AT)
2841 842 : && (m = gfc_match_dupl_check (c->at == OMP_AT_UNSET, "at", true))
2842 : != MATCH_NO)
2843 : {
2844 69 : if (m == MATCH_ERROR)
2845 2 : goto error;
2846 67 : if (gfc_match ("compilation )") == MATCH_YES)
2847 15 : c->at = OMP_AT_COMPILATION;
2848 52 : else if (gfc_match ("execution )") == MATCH_YES)
2849 48 : c->at = OMP_AT_EXECUTION;
2850 : else
2851 : {
2852 4 : gfc_error ("Expected COMPILATION or EXECUTION in AT clause "
2853 : "at %C");
2854 4 : goto error;
2855 : }
2856 63 : continue;
2857 : }
2858 1416 : if ((mask & OMP_CLAUSE_ASYNC)
2859 773 : && (m = gfc_match_dupl_check (!c->async, "async")) != MATCH_NO)
2860 : {
2861 643 : if (m == MATCH_ERROR)
2862 0 : goto error;
2863 643 : c->async = true;
2864 643 : m = gfc_match (" ( %e )", &c->async_expr);
2865 643 : if (m == MATCH_ERROR)
2866 : {
2867 0 : gfc_current_locus = old_loc;
2868 0 : break;
2869 : }
2870 643 : else if (m == MATCH_NO)
2871 : {
2872 133 : c->async_expr
2873 133 : = gfc_get_constant_expr (BT_INTEGER,
2874 : gfc_default_integer_kind,
2875 : &gfc_current_locus);
2876 133 : mpz_set_si (c->async_expr->value.integer, GOMP_ASYNC_NOVAL);
2877 : }
2878 643 : continue;
2879 : }
2880 193 : if ((mask & OMP_CLAUSE_AUTO)
2881 130 : && (m = gfc_match_dupl_check (!c->par_auto, "auto"))
2882 : != MATCH_NO)
2883 : {
2884 63 : if (m == MATCH_ERROR)
2885 0 : goto error;
2886 63 : c->par_auto = true;
2887 63 : continue;
2888 : }
2889 128 : if ((mask & OMP_CLAUSE_ATTACH)
2890 62 : && gfc_match ("attach ( ") == MATCH_YES
2891 128 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
2892 : OMP_MAP_ATTACH, false,
2893 : allow_derived))
2894 61 : continue;
2895 : break;
2896 36 : case 'b':
2897 70 : if ((mask & OMP_CLAUSE_BIND)
2898 36 : && (m = gfc_match_dupl_check (c->bind == OMP_BIND_UNSET, "bind",
2899 : true)) != MATCH_NO)
2900 : {
2901 36 : if (m == MATCH_ERROR)
2902 1 : goto error;
2903 35 : if (gfc_match ("teams )") == MATCH_YES)
2904 11 : c->bind = OMP_BIND_TEAMS;
2905 24 : else if (gfc_match ("parallel )") == MATCH_YES)
2906 15 : c->bind = OMP_BIND_PARALLEL;
2907 9 : else if (gfc_match ("thread )") == MATCH_YES)
2908 8 : c->bind = OMP_BIND_THREAD;
2909 : else
2910 : {
2911 1 : gfc_error ("Expected TEAMS, PARALLEL or THREAD as binding in "
2912 : "BIND at %C");
2913 1 : break;
2914 : }
2915 34 : continue;
2916 : }
2917 : break;
2918 7123 : case 'c':
2919 7399 : if ((mask & OMP_CLAUSE_CAPTURE)
2920 7571 : && (m = gfc_match_boolean_clause (&bval, "capture",
2921 448 : c->capture || cfalse->capture)) != MATCH_NO)
2922 : {
2923 277 : if (m == MATCH_ERROR)
2924 1 : goto error;
2925 276 : if (bval)
2926 273 : c->capture = true;
2927 : else
2928 3 : cfalse->capture = true;
2929 276 : continue;
2930 : }
2931 6846 : if (mask & OMP_CLAUSE_COLLAPSE)
2932 : {
2933 1996 : gfc_expr *cexpr = NULL;
2934 1996 : if ((m = gfc_match_dupl_check (!c->collapse, "collapse", true,
2935 : &cexpr)) != MATCH_NO)
2936 : {
2937 1506 : int collapse;
2938 1506 : if (m == MATCH_ERROR)
2939 0 : goto error;
2940 1506 : if (gfc_extract_int (cexpr, &collapse, -1))
2941 4 : collapse = 1;
2942 1502 : else if (collapse <= 0)
2943 : {
2944 8 : gfc_error_now ("COLLAPSE clause argument not constant "
2945 : "positive integer at %C");
2946 8 : collapse = 1;
2947 : }
2948 1506 : gfc_free_expr (cexpr);
2949 1506 : c->collapse = collapse;
2950 1506 : continue;
2951 1506 : }
2952 : }
2953 5510 : if ((mask & OMP_CLAUSE_COMPARE)
2954 5511 : && (m = gfc_match_boolean_clause (&bval, "compare",
2955 171 : c->compare || cfalse->compare)) != MATCH_NO)
2956 : {
2957 171 : if (m == MATCH_ERROR)
2958 1 : goto error;
2959 170 : if (bval)
2960 167 : c->compare = true;
2961 : else
2962 3 : cfalse->compare = true;
2963 170 : continue;
2964 : }
2965 5182 : if ((mask & OMP_CLAUSE_ASSUMPTIONS)
2966 5169 : && gfc_match ("contains ( ") == MATCH_YES)
2967 : {
2968 19 : if (gfc_omp_absent_contains_clause (&c->assume, false)
2969 : != MATCH_YES)
2970 6 : goto error;
2971 13 : continue;
2972 : }
2973 7266 : if ((mask & OMP_CLAUSE_COPY)
2974 3723 : && gfc_match ("copy ( ") == MATCH_YES
2975 7267 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
2976 : OMP_MAP_TOFROM, true,
2977 : allow_derived))
2978 2116 : continue;
2979 3034 : if (mask & OMP_CLAUSE_COPYIN)
2980 : {
2981 2628 : if (openacc)
2982 : {
2983 2529 : if (gfc_match ("copyin ( ") == MATCH_YES)
2984 : {
2985 1458 : bool readonly = gfc_match ("readonly : ") == MATCH_YES;
2986 1458 : head = NULL;
2987 1458 : if (gfc_match_omp_variable_list ("",
2988 : &c->lists[OMP_LIST_MAP],
2989 : true, NULL, &head, true,
2990 : allow_derived)
2991 : == MATCH_YES)
2992 : {
2993 1452 : gfc_omp_namelist *n;
2994 3349 : for (n = *head; n; n = n->next)
2995 : {
2996 1897 : n->u.map.op = OMP_MAP_TO;
2997 1897 : n->u.map.readonly = readonly;
2998 : }
2999 1452 : continue;
3000 1452 : }
3001 : }
3002 : }
3003 99 : else if (gfc_match_omp_variable_list ("copyin (",
3004 : &c->lists[OMP_LIST_COPYIN],
3005 : true) == MATCH_YES)
3006 97 : continue;
3007 : }
3008 2556 : if ((mask & OMP_CLAUSE_COPYOUT)
3009 1216 : && gfc_match ("copyout ( ") == MATCH_YES
3010 2556 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
3011 : OMP_MAP_FROM, true, allow_derived))
3012 1071 : continue;
3013 498 : if ((mask & OMP_CLAUSE_COPYPRIVATE)
3014 414 : && gfc_match_omp_variable_list ("copyprivate (",
3015 : &c->lists[OMP_LIST_COPYPRIVATE],
3016 : true) == MATCH_YES)
3017 84 : continue;
3018 651 : if ((mask & OMP_CLAUSE_CREATE)
3019 328 : && gfc_match ("create ( ") == MATCH_YES
3020 651 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
3021 : OMP_MAP_ALLOC, true, allow_derived))
3022 321 : continue;
3023 : break;
3024 4199 : case 'd':
3025 4199 : if ((mask & OMP_CLAUSE_DEFAULTMAP)
3026 4199 : && gfc_match ("defaultmap ( ") == MATCH_YES)
3027 : {
3028 181 : enum gfc_omp_defaultmap behavior;
3029 181 : gfc_omp_defaultmap_category category
3030 : = OMP_DEFAULTMAP_CAT_UNCATEGORIZED;
3031 181 : if (gfc_match ("alloc ") == MATCH_YES)
3032 : behavior = OMP_DEFAULTMAP_ALLOC;
3033 175 : else if (gfc_match ("tofrom ") == MATCH_YES)
3034 : behavior = OMP_DEFAULTMAP_TOFROM;
3035 143 : else if (gfc_match ("to ") == MATCH_YES)
3036 : behavior = OMP_DEFAULTMAP_TO;
3037 133 : else if (gfc_match ("from ") == MATCH_YES)
3038 : behavior = OMP_DEFAULTMAP_FROM;
3039 130 : else if (gfc_match ("firstprivate ") == MATCH_YES)
3040 : behavior = OMP_DEFAULTMAP_FIRSTPRIVATE;
3041 95 : else if (gfc_match ("present ") == MATCH_YES)
3042 : behavior = OMP_DEFAULTMAP_PRESENT;
3043 91 : else if (gfc_match ("none ") == MATCH_YES)
3044 : behavior = OMP_DEFAULTMAP_NONE;
3045 10 : else if (gfc_match ("default ") == MATCH_YES)
3046 : behavior = OMP_DEFAULTMAP_DEFAULT;
3047 : else
3048 : {
3049 1 : gfc_error ("Expected ALLOC, TO, FROM, TOFROM, FIRSTPRIVATE, "
3050 : "PRESENT, NONE or DEFAULT at %C");
3051 1 : break;
3052 : }
3053 180 : if (')' == gfc_peek_ascii_char ())
3054 : ;
3055 102 : else if (gfc_match (": ") != MATCH_YES)
3056 : break;
3057 : else
3058 : {
3059 102 : if (gfc_match ("scalar ") == MATCH_YES)
3060 : category = OMP_DEFAULTMAP_CAT_SCALAR;
3061 67 : else if (gfc_match ("aggregate ") == MATCH_YES)
3062 : category = OMP_DEFAULTMAP_CAT_AGGREGATE;
3063 43 : else if (gfc_match ("allocatable ") == MATCH_YES)
3064 : category = OMP_DEFAULTMAP_CAT_ALLOCATABLE;
3065 31 : else if (gfc_match ("pointer ") == MATCH_YES)
3066 : category = OMP_DEFAULTMAP_CAT_POINTER;
3067 14 : else if (gfc_match ("all ") == MATCH_YES)
3068 : category = OMP_DEFAULTMAP_CAT_ALL;
3069 : else
3070 : {
3071 1 : gfc_error ("Expected SCALAR, AGGREGATE, ALLOCATABLE, "
3072 : "POINTER or ALL at %C");
3073 1 : break;
3074 : }
3075 : }
3076 1200 : for (int i = 0; i < OMP_DEFAULTMAP_CAT_NUM; ++i)
3077 : {
3078 1034 : if (i != category
3079 1034 : && category != OMP_DEFAULTMAP_CAT_UNCATEGORIZED
3080 486 : && category != OMP_DEFAULTMAP_CAT_ALL
3081 486 : && i != OMP_DEFAULTMAP_CAT_UNCATEGORIZED
3082 341 : && i != OMP_DEFAULTMAP_CAT_ALL)
3083 254 : continue;
3084 780 : if (c->defaultmap[i] != OMP_DEFAULTMAP_UNSET)
3085 : {
3086 13 : const char *pcategory = NULL;
3087 13 : switch (i)
3088 : {
3089 : case OMP_DEFAULTMAP_CAT_UNCATEGORIZED: break;
3090 3 : case OMP_DEFAULTMAP_CAT_ALL: pcategory = "ALL"; break;
3091 1 : case OMP_DEFAULTMAP_CAT_SCALAR: pcategory = "SCALAR"; break;
3092 2 : case OMP_DEFAULTMAP_CAT_AGGREGATE:
3093 2 : pcategory = "AGGREGATE";
3094 2 : break;
3095 1 : case OMP_DEFAULTMAP_CAT_ALLOCATABLE:
3096 1 : pcategory = "ALLOCATABLE";
3097 1 : break;
3098 : case OMP_DEFAULTMAP_CAT_POINTER:
3099 : pcategory = "POINTER";
3100 : break;
3101 0 : default: gcc_unreachable ();
3102 : }
3103 7 : if (i == OMP_DEFAULTMAP_CAT_UNCATEGORIZED)
3104 4 : gfc_error ("DEFAULTMAP at %C but prior DEFAULTMAP with "
3105 : "unspecified category");
3106 : else
3107 9 : gfc_error ("DEFAULTMAP at %C but prior DEFAULTMAP for "
3108 : "category %s", pcategory);
3109 13 : goto error;
3110 : }
3111 : }
3112 166 : c->defaultmap[category] = behavior;
3113 166 : if (gfc_match (")") != MATCH_YES)
3114 : break;
3115 166 : continue;
3116 166 : }
3117 4985 : if ((mask & OMP_CLAUSE_DEFAULT)
3118 4018 : && (m = gfc_match_dupl_check (c->default_sharing
3119 : == OMP_DEFAULT_UNKNOWN, "default",
3120 : true)) != MATCH_NO)
3121 : {
3122 1012 : if (m == MATCH_ERROR)
3123 6 : goto error;
3124 1006 : if (gfc_match ("none") == MATCH_YES)
3125 596 : c->default_sharing = OMP_DEFAULT_NONE;
3126 410 : else if (openacc)
3127 : {
3128 225 : if (gfc_match ("present") == MATCH_YES)
3129 195 : c->default_sharing = OMP_DEFAULT_PRESENT;
3130 : }
3131 : else
3132 : {
3133 185 : if (gfc_match ("firstprivate") == MATCH_YES)
3134 8 : c->default_sharing = OMP_DEFAULT_FIRSTPRIVATE;
3135 177 : else if (gfc_match ("private") == MATCH_YES)
3136 24 : c->default_sharing = OMP_DEFAULT_PRIVATE;
3137 153 : else if (gfc_match ("shared") == MATCH_YES)
3138 153 : c->default_sharing = OMP_DEFAULT_SHARED;
3139 : }
3140 1006 : if (c->default_sharing == OMP_DEFAULT_UNKNOWN)
3141 : {
3142 30 : if (openacc)
3143 30 : gfc_error ("Expected NONE or PRESENT in DEFAULT clause "
3144 : "at %C");
3145 : else
3146 0 : gfc_error ("Expected NONE, FIRSTPRIVATE, PRIVATE or SHARED "
3147 : "in DEFAULT clause at %C");
3148 30 : goto error;
3149 : }
3150 976 : if (gfc_match (" )") != MATCH_YES)
3151 9 : goto error;
3152 967 : continue;
3153 : }
3154 3314 : if ((mask & OMP_CLAUSE_DELETE)
3155 345 : && gfc_match ("delete ( ") == MATCH_YES
3156 3314 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
3157 : OMP_MAP_RELEASE, true,
3158 : allow_derived))
3159 308 : continue;
3160 : /* DOACROSS: match 'doacross' and 'depend' with sink/source.
3161 : DEPEND: match 'depend' but not sink/source. */
3162 2698 : m = MATCH_NO;
3163 2698 : if (((mask & OMP_CLAUSE_DOACROSS)
3164 383 : && gfc_match ("doacross ( ") == MATCH_YES)
3165 3054 : || (((mask & OMP_CLAUSE_DEPEND) || (mask & OMP_CLAUSE_DOACROSS))
3166 1610 : && (m = gfc_match ("depend ( ")) == MATCH_YES))
3167 : {
3168 1101 : bool has_omp_all_memory;
3169 1101 : bool is_depend = m == MATCH_YES;
3170 1101 : gfc_namespace *ns_iter = NULL, *ns_curr = gfc_current_ns;
3171 1101 : match m_it = MATCH_NO;
3172 1101 : if (is_depend)
3173 1074 : m_it = gfc_match_iterator (&ns_iter, false);
3174 1074 : if (m_it == MATCH_ERROR)
3175 : break;
3176 1096 : if (m_it == MATCH_YES && gfc_match (" , ") != MATCH_YES)
3177 : break;
3178 1096 : m = MATCH_YES;
3179 1096 : gfc_omp_depend_doacross_op depend_op = OMP_DEPEND_OUT;
3180 1096 : if (gfc_match ("inoutset") == MATCH_YES)
3181 : depend_op = OMP_DEPEND_INOUTSET;
3182 1084 : else if (gfc_match ("inout") == MATCH_YES)
3183 : depend_op = OMP_DEPEND_INOUT;
3184 992 : else if (gfc_match ("in") == MATCH_YES)
3185 : depend_op = OMP_DEPEND_IN;
3186 704 : else if (gfc_match ("out") == MATCH_YES)
3187 : depend_op = OMP_DEPEND_OUT;
3188 442 : else if (gfc_match ("mutexinoutset") == MATCH_YES)
3189 : depend_op = OMP_DEPEND_MUTEXINOUTSET;
3190 424 : else if (gfc_match ("depobj") == MATCH_YES)
3191 : depend_op = OMP_DEPEND_DEPOBJ;
3192 387 : else if (gfc_match ("source") == MATCH_YES)
3193 : {
3194 143 : if (m_it == MATCH_YES)
3195 : {
3196 1 : gfc_error ("ITERATOR may not be combined with SOURCE "
3197 : "at %C");
3198 17 : goto error;
3199 : }
3200 142 : if (!(mask & OMP_CLAUSE_DOACROSS))
3201 : {
3202 1 : gfc_error ("SOURCE at %C not permitted as dependence-type"
3203 : " for this directive");
3204 1 : goto error;
3205 : }
3206 141 : if (c->doacross_source)
3207 : {
3208 0 : gfc_error ("Duplicated clause with SOURCE dependence-type"
3209 : " at %C");
3210 0 : goto error;
3211 : }
3212 141 : gfc_gobble_whitespace ();
3213 141 : m = gfc_match (": ");
3214 141 : if (m != MATCH_YES && !is_depend)
3215 : {
3216 1 : gfc_error ("Expected %<:%> at %C");
3217 1 : goto error;
3218 : }
3219 140 : if (gfc_match (")") != MATCH_YES
3220 146 : && !(m == MATCH_YES
3221 6 : && gfc_match ("omp_cur_iteration )") == MATCH_YES))
3222 : {
3223 2 : gfc_error ("Expected %<)%> or %<omp_cur_iteration)%> "
3224 : "at %C");
3225 2 : goto error;
3226 : }
3227 138 : if (is_depend)
3228 130 : gfc_warning (OPT_Wdeprecated_openmp,
3229 : "%<source%> modifier with %<depend%> clause "
3230 : "at %L deprecated since OpenMP 5.2, use with "
3231 : "%<doacross%>", &old_loc);
3232 138 : c->doacross_source = true;
3233 138 : c->depend_source = is_depend;
3234 1079 : continue;
3235 : }
3236 244 : else if (gfc_match ("sink ") == MATCH_YES)
3237 : {
3238 244 : if (!(mask & OMP_CLAUSE_DOACROSS))
3239 : {
3240 2 : gfc_error ("SINK at %C not permitted as dependence-type "
3241 : "for this directive");
3242 2 : goto error;
3243 : }
3244 242 : if (gfc_match (": ") != MATCH_YES)
3245 : {
3246 1 : gfc_error ("Expected %<:%> at %C");
3247 1 : goto error;
3248 : }
3249 241 : if (m_it == MATCH_YES)
3250 : {
3251 0 : gfc_error ("ITERATOR may not be combined with SINK "
3252 : "at %C");
3253 0 : goto error;
3254 : }
3255 241 : if (is_depend)
3256 226 : gfc_warning (OPT_Wdeprecated_openmp,
3257 : "%<sink%> modifier with %<depend%> clause at "
3258 : "%L deprecated since OpenMP 5.2, use with "
3259 : "%<doacross%>", &old_loc);
3260 241 : m = gfc_match_omp_doacross_sink (&c->lists[OMP_LIST_DEPEND],
3261 : is_depend);
3262 241 : if (m == MATCH_YES)
3263 238 : continue;
3264 3 : goto error;
3265 : }
3266 : else
3267 : m = MATCH_NO;
3268 709 : if (!(mask & OMP_CLAUSE_DEPEND))
3269 : {
3270 0 : gfc_error ("Expected dependence-type SINK or SOURCE at %C");
3271 0 : goto error;
3272 : }
3273 709 : head = NULL;
3274 709 : if (ns_iter)
3275 40 : gfc_current_ns = ns_iter;
3276 709 : if (m == MATCH_YES)
3277 709 : m = gfc_match_omp_variable_list (" : ",
3278 : &c->lists[OMP_LIST_DEPEND],
3279 : false, NULL, &head, true,
3280 : false, &has_omp_all_memory);
3281 709 : if (m != MATCH_YES)
3282 2 : goto error;
3283 707 : gfc_current_ns = ns_curr;
3284 707 : if (has_omp_all_memory && depend_op != OMP_DEPEND_INOUT
3285 21 : && depend_op != OMP_DEPEND_OUT)
3286 : {
3287 4 : gfc_error ("%<omp_all_memory%> used with DEPEND kind "
3288 : "other than OUT or INOUT at %C");
3289 4 : goto error;
3290 : }
3291 703 : gfc_omp_namelist *n;
3292 1437 : for (n = *head; n; n = n->next)
3293 : {
3294 734 : n->u.depend_doacross_op = depend_op;
3295 734 : n->u2.ns = ns_iter;
3296 734 : if (ns_iter)
3297 39 : ns_iter->refs++;
3298 : }
3299 703 : continue;
3300 703 : }
3301 1618 : if ((mask & OMP_CLAUSE_DESTROY)
3302 1597 : && gfc_match_omp_variable_list ("destroy (",
3303 : &c->lists[OMP_LIST_DESTROY],
3304 : true) == MATCH_YES)
3305 21 : continue;
3306 1702 : if ((mask & OMP_CLAUSE_DETACH)
3307 164 : && !openacc
3308 127 : && !c->detach
3309 1702 : && gfc_match_omp_detach (&c->detach) == MATCH_YES)
3310 126 : continue;
3311 1487 : if ((mask & OMP_CLAUSE_DETACH)
3312 38 : && openacc
3313 37 : && gfc_match ("detach ( ") == MATCH_YES
3314 1487 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
3315 : OMP_MAP_DETACH, false,
3316 : allow_derived))
3317 37 : continue;
3318 1449 : if ((mask & OMP_CLAUSE_DEVICEPTR)
3319 87 : && gfc_match ("deviceptr ( ") == MATCH_YES
3320 1451 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
3321 : OMP_MAP_FORCE_DEVICEPTR, false,
3322 : allow_derived))
3323 36 : continue;
3324 832 : if ((mask & OMP_CLAUSE_DEVICE_TYPE) && openacc
3325 444 : && gfc_match_dupl_check (!c->oacc_device_type_present,
3326 : "device_type", true) == MATCH_YES
3327 1709 : && match_oacc_device_type (c) == MATCH_YES)
3328 326 : continue;
3329 506 : if ((mask & OMP_CLAUSE_DEVICE_TYPE) && !openacc
3330 1439 : && gfc_match_dupl_check (c->device_type == OMP_DEVICE_TYPE_UNSET,
3331 : "device_type", true) == MATCH_YES)
3332 : {
3333 95 : if (gfc_match ("host") == MATCH_YES)
3334 32 : c->device_type = OMP_DEVICE_TYPE_HOST;
3335 63 : else if (gfc_match ("nohost") == MATCH_YES)
3336 24 : c->device_type = OMP_DEVICE_TYPE_NOHOST;
3337 39 : else if (gfc_match ("any") == MATCH_YES)
3338 38 : c->device_type = OMP_DEVICE_TYPE_ANY;
3339 : else
3340 : {
3341 1 : gfc_error ("Expected HOST, NOHOST or ANY at %C");
3342 1 : break;
3343 : }
3344 94 : if (gfc_match (" )") != MATCH_YES)
3345 : break;
3346 94 : continue;
3347 : }
3348 1063 : if ((mask & OMP_CLAUSE_DEVICE_NUM)
3349 956 : && (m = gfc_match_dupl_check (!c->device_num_expr,
3350 : "device_num")) != MATCH_NO)
3351 : {
3352 109 : if (m == MATCH_ERROR)
3353 2 : goto error;
3354 107 : if (gfc_match ("( %e )", &c->device_num_expr) != MATCH_YES)
3355 0 : goto error;
3356 107 : continue;
3357 : }
3358 895 : if ((mask & OMP_CLAUSE_DEVICE_RESIDENT)
3359 896 : && gfc_match_omp_variable_list
3360 49 : ("device_resident (",
3361 : &c->lists[OMP_LIST_DEVICE_RESIDENT], true) == MATCH_YES)
3362 48 : continue;
3363 1111 : if ((mask & OMP_CLAUSE_DEVICE)
3364 714 : && openacc
3365 314 : && gfc_match ("device ( ") == MATCH_YES
3366 1112 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
3367 : OMP_MAP_FORCE_TO, true,
3368 : /* allow_derived = */ true))
3369 312 : continue;
3370 487 : if ((mask & OMP_CLAUSE_DEVICE)
3371 402 : && !openacc
3372 887 : && ((m = gfc_match_dupl_check (!c->device, "device", true))
3373 : != MATCH_NO))
3374 : {
3375 352 : if (m == MATCH_ERROR)
3376 0 : goto error;
3377 352 : c->ancestor = false;
3378 352 : if (gfc_match ("device_num : ") == MATCH_YES)
3379 : {
3380 18 : if (gfc_match ("%e )", &c->device) != MATCH_YES)
3381 : {
3382 1 : gfc_error ("Expected integer expression at %C");
3383 1 : break;
3384 : }
3385 : }
3386 334 : else if (gfc_match ("ancestor : ") == MATCH_YES)
3387 : {
3388 45 : bool has_requires = false;
3389 45 : c->ancestor = true;
3390 82 : for (gfc_namespace *ns = gfc_current_ns; ns; ns = ns->parent)
3391 80 : if (ns->omp_requires & OMP_REQ_REVERSE_OFFLOAD)
3392 : {
3393 : has_requires = true;
3394 : break;
3395 : }
3396 45 : if (!has_requires)
3397 : {
3398 2 : gfc_error ("%<ancestor%> device modifier not "
3399 : "preceded by %<requires%> directive "
3400 : "with %<reverse_offload%> clause at %C");
3401 5 : break;
3402 : }
3403 43 : locus old_loc2 = gfc_current_locus;
3404 43 : if (gfc_match ("%e )", &c->device) == MATCH_YES)
3405 : {
3406 43 : int device = 0;
3407 43 : if (!gfc_extract_int (c->device, &device) && device != 1)
3408 : {
3409 1 : gfc_current_locus = old_loc2;
3410 1 : gfc_error ("the %<device%> clause expression must "
3411 : "evaluate to %<1%> at %C");
3412 1 : break;
3413 : }
3414 : }
3415 : else
3416 : {
3417 0 : gfc_error ("Expected integer expression at %C");
3418 0 : break;
3419 : }
3420 : }
3421 289 : else if (gfc_match ("%e )", &c->device) != MATCH_YES)
3422 : {
3423 13 : gfc_error ("Expected integer expression or a single device-"
3424 : "modifier %<device_num%> or %<ancestor%> at %C");
3425 13 : break;
3426 : }
3427 335 : continue;
3428 335 : }
3429 135 : if ((mask & OMP_CLAUSE_DIST_SCHEDULE)
3430 97 : && c->dist_sched_kind == OMP_SCHED_NONE
3431 232 : && gfc_match ("dist_schedule ( static") == MATCH_YES)
3432 : {
3433 97 : m = MATCH_NO;
3434 97 : c->dist_sched_kind = OMP_SCHED_STATIC;
3435 97 : m = gfc_match (" , %e )", &c->dist_chunk_size);
3436 97 : if (m != MATCH_YES)
3437 14 : m = gfc_match_char (')');
3438 14 : if (m != MATCH_YES)
3439 : {
3440 0 : c->dist_sched_kind = OMP_SCHED_NONE;
3441 0 : gfc_current_locus = old_loc;
3442 : }
3443 : else
3444 97 : continue;
3445 : }
3446 38 : if ((mask & OMP_CLAUSE_DYN_GROUPPRIVATE)
3447 38 : && gfc_match_dupl_check (!c->dyn_groupprivate,
3448 : "dyn_groupprivate", true) == MATCH_YES)
3449 : {
3450 : bool cgroup = false;
3451 : bool first = true;
3452 28 : bool error_p = false;
3453 36 : do
3454 : {
3455 28 : old_loc = gfc_current_locus;
3456 28 : if (gfc_match ("cgroup ") == MATCH_YES)
3457 : {
3458 7 : if (cgroup)
3459 : {
3460 1 : gfc_error ("Duplicated %<cgroup%> modifier at %L",
3461 : &old_loc);
3462 1 : goto error;
3463 : }
3464 : cgroup = true;
3465 : }
3466 21 : else if (gfc_match ("fallback ( ") == MATCH_YES)
3467 : {
3468 12 : if (c->fallback != OMP_FALLBACK_NONE)
3469 : {
3470 1 : gfc_error ("Duplicated %<fallback%> modifier at %L",
3471 : &old_loc);
3472 1 : goto error;
3473 : }
3474 11 : old_loc = gfc_current_locus;
3475 11 : if (gfc_match ("abort ) ") == MATCH_YES)
3476 3 : c->fallback = OMP_FALLBACK_ABORT;
3477 8 : else if (gfc_match ("default_mem ) ") == MATCH_YES)
3478 3 : c->fallback = OMP_FALLBACK_DEFAULT_MEM;
3479 5 : else if (gfc_match ("null ) ") == MATCH_YES)
3480 4 : c->fallback = OMP_FALLBACK_NULL;
3481 : else
3482 : {
3483 1 : gfc_error ("Expected %<abort%>, %<default_mem%> or "
3484 : "%<null%> followed by %<)%> at %L",
3485 : &old_loc);
3486 1 : goto error;
3487 : }
3488 : }
3489 9 : else if (!first)
3490 : {
3491 1 : gfc_error ("Expected %<cgroup%> or %<fallback%> clause at %C");
3492 1 : goto error;
3493 : }
3494 24 : if (gfc_match (", ") == MATCH_YES)
3495 : {
3496 8 : first = false;
3497 8 : continue;
3498 : }
3499 16 : if (gfc_match (": ") == MATCH_YES)
3500 : {
3501 7 : old_loc = gfc_current_locus;
3502 7 : break;
3503 : }
3504 9 : if (!first)
3505 : {
3506 0 : gfc_error ("Expected %<:%> at %C");
3507 0 : goto error;
3508 : }
3509 : error_p = true;
3510 : break;
3511 : }
3512 : while (true);
3513 16 : if (gfc_match_expr (&c->dyn_groupprivate) != MATCH_YES)
3514 : {
3515 0 : gfc_error ("Expected numeric expression at %L, optionally preceeded by "
3516 : "the %<cgroup%> and %<fallback%> modifier", &old_loc);
3517 0 : goto error;
3518 : }
3519 16 : if (error_p)
3520 9 : c->fallback = OMP_FALLBACK_NONE;
3521 16 : if (gfc_match (" )") != MATCH_YES)
3522 : {
3523 1 : gfc_error ("Expected %<)%> at %C");
3524 1 : goto error;
3525 : }
3526 15 : continue;
3527 15 : }
3528 : break;
3529 98 : case 'e':
3530 98 : if ((mask & OMP_CLAUSE_ENTER))
3531 : {
3532 98 : m = gfc_match_omp_to_link ("enter (", &c->lists[OMP_LIST_ENTER]);
3533 98 : if (m == MATCH_ERROR)
3534 0 : goto error;
3535 98 : if (m == MATCH_YES)
3536 98 : continue;
3537 : }
3538 : break;
3539 2326 : case 'f':
3540 2375 : if ((mask & OMP_CLAUSE_FAIL)
3541 2326 : && (m = gfc_match_dupl_check (c->fail == OMP_MEMORDER_UNSET,
3542 : "fail", true)) != MATCH_NO)
3543 : {
3544 58 : if (m == MATCH_ERROR)
3545 3 : goto error;
3546 55 : if (gfc_match ("seq_cst") == MATCH_YES)
3547 6 : c->fail = OMP_MEMORDER_SEQ_CST;
3548 49 : else if (gfc_match ("acquire") == MATCH_YES)
3549 14 : c->fail = OMP_MEMORDER_ACQUIRE;
3550 35 : else if (gfc_match ("relaxed") == MATCH_YES)
3551 30 : c->fail = OMP_MEMORDER_RELAXED;
3552 : else
3553 : {
3554 5 : gfc_error ("Expected SEQ_CST, ACQUIRE or RELAXED at %C");
3555 5 : break;
3556 : }
3557 50 : if (gfc_match (" )") != MATCH_YES)
3558 1 : goto error;
3559 49 : continue;
3560 : }
3561 2311 : if ((mask & OMP_CLAUSE_FILTER)
3562 2268 : && (m = gfc_match_dupl_check (!c->filter, "filter", true,
3563 : &c->filter)) != MATCH_NO)
3564 : {
3565 44 : if (m == MATCH_ERROR)
3566 1 : goto error;
3567 43 : continue;
3568 : }
3569 2288 : if ((mask & OMP_CLAUSE_FINAL)
3570 2224 : && (m = gfc_match_dupl_check (!c->final_expr, "final", true,
3571 : &c->final_expr)) != MATCH_NO)
3572 : {
3573 64 : if (m == MATCH_ERROR)
3574 0 : goto error;
3575 64 : continue;
3576 : }
3577 2186 : if ((mask & OMP_CLAUSE_FINALIZE)
3578 2160 : && (m = gfc_match_dupl_check (!c->finalize, "finalize"))
3579 : != MATCH_NO)
3580 : {
3581 26 : if (m == MATCH_ERROR)
3582 0 : goto error;
3583 26 : c->finalize = true;
3584 26 : continue;
3585 : }
3586 3176 : if ((mask & OMP_CLAUSE_FIRSTPRIVATE)
3587 2134 : && gfc_match_omp_variable_list ("firstprivate (",
3588 : &c->lists[OMP_LIST_FIRSTPRIVATE],
3589 : true) == MATCH_YES)
3590 1042 : continue;
3591 2095 : if ((mask & OMP_CLAUSE_FROM)
3592 1092 : && gfc_match_motion_var_list ("from (", &c->lists[OMP_LIST_FROM],
3593 : &head) == MATCH_YES)
3594 1003 : continue;
3595 158 : if ((mask & OMP_CLAUSE_FULL)
3596 165 : && (m = gfc_match_boolean_clause (&bval, "full",
3597 76 : c->full || cfalse->full)) != MATCH_NO)
3598 : {
3599 76 : if (m == MATCH_ERROR)
3600 7 : goto error;
3601 69 : if (bval)
3602 68 : c->full = true;
3603 : else
3604 1 : cfalse->full = true;
3605 69 : continue;
3606 : }
3607 : break;
3608 1231 : case 'g':
3609 2423 : if ((mask & OMP_CLAUSE_GANG)
3610 1231 : && (m = gfc_match_dupl_check (!c->gang, "gang")) != MATCH_NO)
3611 : {
3612 1197 : if (m == MATCH_ERROR)
3613 0 : goto error;
3614 1197 : c->gang = true;
3615 1197 : m = match_oacc_clause_gwv (c, GOMP_DIM_GANG);
3616 1197 : if (m == MATCH_ERROR)
3617 : {
3618 5 : gfc_current_locus = old_loc;
3619 5 : break;
3620 : }
3621 1192 : continue;
3622 : }
3623 68 : if ((mask & OMP_CLAUSE_GRAINSIZE)
3624 34 : && (m = gfc_match_dupl_check (!c->grainsize, "grainsize", true))
3625 : != MATCH_NO)
3626 : {
3627 34 : if (m == MATCH_ERROR)
3628 0 : goto error;
3629 34 : if (gfc_match ("strict : ") == MATCH_YES)
3630 1 : c->grainsize_strict = true;
3631 34 : if (gfc_match (" %e )", &c->grainsize) != MATCH_YES)
3632 0 : goto error;
3633 34 : continue;
3634 : }
3635 : break;
3636 474 : case 'h':
3637 523 : if ((mask & OMP_CLAUSE_HAS_DEVICE_ADDR)
3638 523 : && gfc_match_omp_variable_list
3639 49 : ("has_device_addr (", &c->lists[OMP_LIST_HAS_DEVICE_ADDR],
3640 : false, NULL, NULL, true) == MATCH_YES)
3641 49 : continue;
3642 473 : if ((mask & OMP_CLAUSE_HINT)
3643 425 : && (m = gfc_match_dupl_check (!c->hint, "hint", true, &c->hint))
3644 : != MATCH_NO)
3645 : {
3646 48 : if (m == MATCH_ERROR)
3647 0 : goto error;
3648 48 : continue;
3649 : }
3650 377 : if ((mask & OMP_CLAUSE_ASSUMPTIONS)
3651 377 : && gfc_match ("holds ( ") == MATCH_YES)
3652 : {
3653 22 : gfc_expr *e;
3654 22 : if (gfc_match ("%e )", &e) != MATCH_YES)
3655 0 : goto error;
3656 22 : if (c->assume == NULL)
3657 15 : c->assume = gfc_get_omp_assumptions ();
3658 22 : gfc_expr_list *el = XCNEW (gfc_expr_list);
3659 22 : el->expr = e;
3660 22 : el->next = c->assume->holds;
3661 22 : c->assume->holds = el;
3662 22 : continue;
3663 22 : }
3664 709 : if ((mask & OMP_CLAUSE_HOST)
3665 355 : && gfc_match ("host ( ") == MATCH_YES
3666 710 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
3667 : OMP_MAP_FORCE_FROM, true,
3668 : /* allow_derived = */ true))
3669 354 : continue;
3670 : break;
3671 2251 : case 'i':
3672 2274 : if ((mask & OMP_CLAUSE_IF_PRESENT)
3673 2251 : && (m = gfc_match_dupl_check (!c->if_present, "if_present"))
3674 : != MATCH_NO)
3675 : {
3676 23 : if (m == MATCH_ERROR)
3677 0 : goto error;
3678 23 : c->if_present = true;
3679 23 : continue;
3680 : }
3681 2228 : if ((mask & OMP_CLAUSE_IF)
3682 2228 : && (m = gfc_match_dupl_check (!c->if_expr, "if", true))
3683 : != MATCH_NO)
3684 : {
3685 1470 : if (m == MATCH_ERROR)
3686 14 : goto error;
3687 1456 : if (!openacc)
3688 : {
3689 : /* This should match the enum gfc_omp_if_kind order. */
3690 : static const char *ifs[OMP_IF_LAST] = {
3691 : "cancel : %e )",
3692 : "parallel : %e )",
3693 : "simd : %e )",
3694 : "task : %e )",
3695 : "taskloop : %e )",
3696 : "target : %e )",
3697 : "target data : %e )",
3698 : "target update : %e )",
3699 : "target enter data : %e )",
3700 : "target exit data : %e )" };
3701 : static const char *ifs2[] = {
3702 : "target_data : %e )",
3703 : "target_update : %e )",
3704 : "target_enter_data : %e )",
3705 : "target_exit_data : %e )" };
3706 : int i;
3707 4951 : for (i = 0; i < OMP_IF_LAST; i++)
3708 4543 : if (c->if_exprs[i] == NULL
3709 4543 : && gfc_match (ifs[i], &c->if_exprs[i]) == MATCH_YES)
3710 : break;
3711 546 : if (i < OMP_IF_LAST)
3712 138 : continue;
3713 2030 : for (i = 0; i < (int) ARRAY_SIZE (ifs2); i++)
3714 1626 : if (c->if_exprs[OMP_IF_TARGET_DATA + i] == NULL
3715 1626 : && (gfc_match (ifs2[i],
3716 : &c->if_exprs[OMP_IF_TARGET_DATA + i])
3717 : == MATCH_YES))
3718 : break;
3719 408 : if (i < (int) ARRAY_SIZE (ifs2))
3720 4 : continue;
3721 : }
3722 1314 : if (gfc_match (" %e )", &c->if_expr) == MATCH_YES)
3723 1309 : continue;
3724 5 : goto error;
3725 : }
3726 875 : if ((mask & OMP_CLAUSE_IN_REDUCTION)
3727 758 : && gfc_match_omp_clause_reduction (pc, c, openacc, allow_derived,
3728 : openmp_target) == MATCH_YES)
3729 117 : continue;
3730 668 : if ((mask & OMP_CLAUSE_INBRANCH)
3731 670 : && (m = gfc_match_dupl_branch_clause (&bval, "inbranch",
3732 29 : c->notinbranch || cfalse->notinbranch
3733 27 : || c->inbranch || cfalse->inbranch)) != MATCH_NO)
3734 : {
3735 29 : if (m == MATCH_ERROR)
3736 2 : goto error;
3737 27 : if (bval)
3738 25 : c->inbranch = true;
3739 : else
3740 2 : cfalse->inbranch = true;
3741 27 : continue;
3742 : }
3743 854 : if ((mask & OMP_CLAUSE_INDEPENDENT)
3744 612 : && (m = gfc_match_dupl_check (!c->independent, "independent"))
3745 : != MATCH_NO)
3746 : {
3747 242 : if (m == MATCH_ERROR)
3748 0 : goto error;
3749 242 : c->independent = true;
3750 242 : continue;
3751 : }
3752 426 : if ((mask & OMP_CLAUSE_INDIRECT)
3753 431 : && (m = gfc_match_boolean_clause (&bval, "indirect",
3754 61 : c->indirect || cfalse->indirect)) != MATCH_NO)
3755 : {
3756 61 : if (m == MATCH_ERROR)
3757 5 : goto error;
3758 56 : if (bval)
3759 51 : c->indirect = true;
3760 : else
3761 5 : cfalse->indirect = true;
3762 56 : continue;
3763 : }
3764 309 : if ((mask & OMP_CLAUSE_INIT)
3765 309 : && gfc_match ("init ( ") == MATCH_YES)
3766 : {
3767 108 : m = gfc_match_omp_init (&c->lists[OMP_LIST_INIT]);
3768 108 : if (m == MATCH_YES)
3769 63 : continue;
3770 45 : goto error;
3771 : }
3772 201 : if ((mask & OMP_CLAUSE_INTEROP)
3773 201 : && (m = gfc_match_dupl_check (!c->lists[OMP_LIST_INTEROP],
3774 : "interop", true)) != MATCH_NO)
3775 : {
3776 : /* Note: the interop objects are saved in reverse order to match
3777 : the order in C/C++. */
3778 125 : if (m == MATCH_YES
3779 63 : && (gfc_match_omp_variable_list ("",
3780 : &c->lists[OMP_LIST_INTEROP],
3781 : false, NULL, NULL, false,
3782 : false, NULL, false, true)
3783 : == MATCH_YES))
3784 62 : continue;
3785 1 : goto error;
3786 : }
3787 258 : if ((mask & OMP_CLAUSE_IS_DEVICE_PTR)
3788 258 : && gfc_match_omp_variable_list
3789 120 : ("is_device_ptr (",
3790 : &c->lists[OMP_LIST_IS_DEVICE_PTR], false) == MATCH_YES)
3791 120 : continue;
3792 : break;
3793 2360 : case 'l':
3794 2360 : if ((mask & OMP_CLAUSE_LASTPRIVATE)
3795 2360 : && gfc_match ("lastprivate ( ") == MATCH_YES)
3796 : {
3797 1433 : bool conditional = gfc_match ("conditional : ") == MATCH_YES;
3798 1433 : head = NULL;
3799 1433 : if (gfc_match_omp_variable_list ("",
3800 : &c->lists[OMP_LIST_LASTPRIVATE],
3801 : false, NULL, &head) == MATCH_YES)
3802 : {
3803 1433 : gfc_omp_namelist *n;
3804 3741 : for (n = *head; n; n = n->next)
3805 2308 : n->u.lastprivate_conditional = conditional;
3806 1433 : continue;
3807 1433 : }
3808 0 : gfc_current_locus = old_loc;
3809 0 : break;
3810 : }
3811 927 : end_colon = false;
3812 927 : head = NULL;
3813 927 : if ((mask & OMP_CLAUSE_LINEAR)
3814 927 : && gfc_match ("linear (") == MATCH_YES)
3815 : {
3816 849 : bool old_linear_modifier = false;
3817 849 : gfc_omp_linear_op linear_op = OMP_LINEAR_DEFAULT;
3818 849 : gfc_expr *step = NULL;
3819 849 : locus saved_loc = gfc_current_locus;
3820 :
3821 849 : if (gfc_match_omp_variable_list (" ref (",
3822 : &c->lists[OMP_LIST_LINEAR],
3823 : false, NULL, &head)
3824 : == MATCH_YES)
3825 : {
3826 : linear_op = OMP_LINEAR_REF;
3827 : old_linear_modifier = true;
3828 : }
3829 821 : else if (gfc_match_omp_variable_list (" val (",
3830 : &c->lists[OMP_LIST_LINEAR],
3831 : false, NULL, &head)
3832 : == MATCH_YES)
3833 : {
3834 : linear_op = OMP_LINEAR_VAL;
3835 : old_linear_modifier = true;
3836 : }
3837 810 : else if (gfc_match_omp_variable_list (" uval (",
3838 : &c->lists[OMP_LIST_LINEAR],
3839 : false, NULL, &head)
3840 : == MATCH_YES)
3841 : {
3842 : linear_op = OMP_LINEAR_UVAL;
3843 : old_linear_modifier = true;
3844 : }
3845 801 : else if (gfc_match_omp_variable_list ("",
3846 : &c->lists[OMP_LIST_LINEAR],
3847 : false, &end_colon, &head)
3848 : == MATCH_YES)
3849 : linear_op = OMP_LINEAR_DEFAULT;
3850 : else
3851 : {
3852 2 : gfc_current_locus = old_loc;
3853 2 : break;
3854 : }
3855 : if (linear_op != OMP_LINEAR_DEFAULT)
3856 : {
3857 48 : if (gfc_match (" :") == MATCH_YES)
3858 31 : end_colon = true;
3859 17 : else if (gfc_match (" )") != MATCH_YES)
3860 : {
3861 0 : gfc_free_omp_namelist (*head, OMP_LIST_LINEAR);
3862 0 : gfc_current_locus = old_loc;
3863 0 : *head = NULL;
3864 0 : break;
3865 : }
3866 : }
3867 847 : gfc_gobble_whitespace ();
3868 847 : if (old_linear_modifier && end_colon)
3869 : {
3870 31 : if (gfc_match (" %e )", &step) != MATCH_YES)
3871 : {
3872 1 : gfc_free_omp_namelist (*head, OMP_LIST_LINEAR);
3873 1 : gfc_current_locus = old_loc;
3874 1 : *head = NULL;
3875 5 : goto error;
3876 : }
3877 : }
3878 47 : if (old_linear_modifier)
3879 : {
3880 47 : char var_names[512]{};
3881 47 : int count, offset = 0;
3882 106 : for (gfc_omp_namelist *n = *head; n; n = n->next)
3883 : {
3884 59 : if (!n->next)
3885 47 : count = snprintf (var_names + offset,
3886 47 : sizeof (var_names) - offset,
3887 47 : "%s", n->sym->name);
3888 : else
3889 12 : count = snprintf (var_names + offset,
3890 12 : sizeof (var_names) - offset,
3891 12 : "%s, ", n->sym->name);
3892 59 : if (count < 0 || count >= ((int)sizeof (var_names))
3893 59 : - offset)
3894 : {
3895 0 : snprintf (var_names, 512, "%s, ..., ",
3896 0 : (*head)->sym->name);
3897 0 : while (n->next)
3898 : n = n->next;
3899 0 : offset = strlen (var_names);
3900 0 : snprintf (var_names + offset,
3901 0 : sizeof (var_names) - offset,
3902 0 : "%s", n->sym->name);
3903 0 : break;
3904 : }
3905 59 : offset += count;
3906 : }
3907 47 : char *var_names_for_warn = var_names;
3908 47 : const char *op_name;
3909 47 : switch (linear_op)
3910 : {
3911 : case OMP_LINEAR_REF: op_name = "ref"; break;
3912 10 : case OMP_LINEAR_VAL: op_name = "val"; break;
3913 9 : case OMP_LINEAR_UVAL: op_name = "uval"; break;
3914 0 : default: gcc_unreachable ();
3915 : }
3916 47 : gfc_warning (OPT_Wdeprecated_openmp,
3917 : "Specification of the list items as "
3918 : "arguments to the modifiers at %L is "
3919 : "deprecated; since OpenMP 5.2, use "
3920 : "%<linear(%s : %s%s)%>", &saved_loc,
3921 : var_names_for_warn, op_name,
3922 47 : step == nullptr ? "" : ", step(...)");
3923 : }
3924 799 : else if (end_colon)
3925 : {
3926 732 : bool has_error = false;
3927 : bool has_modifiers = false;
3928 : bool has_step = false;
3929 732 : bool duplicate_step = false;
3930 732 : bool duplicate_mod = false;
3931 732 : while (true)
3932 : {
3933 732 : old_loc = gfc_current_locus;
3934 732 : bool close_paren = gfc_match ("val )") == MATCH_YES;
3935 732 : if (close_paren || gfc_match ("val , ") == MATCH_YES)
3936 : {
3937 23 : if (linear_op != OMP_LINEAR_DEFAULT)
3938 : {
3939 : duplicate_mod = true;
3940 : break;
3941 : }
3942 22 : linear_op = OMP_LINEAR_VAL;
3943 22 : has_modifiers = true;
3944 22 : if (close_paren)
3945 : break;
3946 16 : continue;
3947 : }
3948 709 : close_paren = gfc_match ("uval )") == MATCH_YES;
3949 709 : if (close_paren || gfc_match ("uval , ") == MATCH_YES)
3950 : {
3951 7 : if (linear_op != OMP_LINEAR_DEFAULT)
3952 : {
3953 : duplicate_mod = true;
3954 : break;
3955 : }
3956 7 : linear_op = OMP_LINEAR_UVAL;
3957 7 : has_modifiers = true;
3958 7 : if (close_paren)
3959 : break;
3960 2 : continue;
3961 : }
3962 702 : close_paren = gfc_match ("ref )") == MATCH_YES;
3963 702 : if (close_paren || gfc_match ("ref , ") == MATCH_YES)
3964 : {
3965 16 : if (linear_op != OMP_LINEAR_DEFAULT)
3966 : {
3967 : duplicate_mod = true;
3968 : break;
3969 : }
3970 15 : linear_op = OMP_LINEAR_REF;
3971 15 : has_modifiers = true;
3972 15 : if (close_paren)
3973 : break;
3974 7 : continue;
3975 : }
3976 686 : close_paren = (gfc_match ("step ( %e ) )", &step)
3977 : == MATCH_YES);
3978 697 : if (close_paren
3979 686 : || gfc_match ("step ( %e ) , ", &step) == MATCH_YES)
3980 : {
3981 50 : if (has_step)
3982 : {
3983 : duplicate_step = true;
3984 : break;
3985 : }
3986 49 : has_modifiers = has_step = true;
3987 49 : if (close_paren)
3988 : break;
3989 11 : continue;
3990 : }
3991 636 : if (!has_modifiers
3992 636 : && gfc_match ("%e )", &step) == MATCH_YES)
3993 : {
3994 636 : if ((step->expr_type == EXPR_FUNCTION
3995 635 : || step->expr_type == EXPR_VARIABLE)
3996 31 : && strcmp (step->symtree->name, "step") == 0)
3997 : {
3998 1 : gfc_current_locus = old_loc;
3999 1 : gfc_match ("step (");
4000 1 : has_error = true;
4001 : }
4002 : break;
4003 : }
4004 : has_error = true;
4005 : break;
4006 : }
4007 61 : if (duplicate_mod || duplicate_step)
4008 : {
4009 3 : gfc_error ("Multiple %qs modifiers specified at %C",
4010 : duplicate_mod ? "linear" : "step");
4011 3 : has_error = true;
4012 : }
4013 696 : if (has_error)
4014 : {
4015 4 : gfc_free_omp_namelist (*head, OMP_LIST_LINEAR);
4016 4 : *head = NULL;
4017 4 : goto error;
4018 : }
4019 : }
4020 842 : if (step == NULL)
4021 : {
4022 130 : step = gfc_get_constant_expr (BT_INTEGER,
4023 : gfc_default_integer_kind,
4024 : &old_loc);
4025 130 : mpz_set_si (step->value.integer, 1);
4026 : }
4027 842 : (*head)->expr = step;
4028 842 : if (linear_op != OMP_LINEAR_DEFAULT || old_linear_modifier)
4029 188 : for (gfc_omp_namelist *n = *head; n; n = n->next)
4030 : {
4031 100 : n->u.linear.op = linear_op;
4032 100 : n->u.linear.old_modifier = old_linear_modifier;
4033 : }
4034 842 : continue;
4035 842 : }
4036 82 : if ((mask & OMP_CLAUSE_LINK)
4037 78 : && openacc
4038 86 : && (gfc_match_oacc_clause_link ("link (",
4039 : &c->lists[OMP_LIST_LINK])
4040 : == MATCH_YES))
4041 4 : continue;
4042 123 : else if ((mask & OMP_CLAUSE_LINK)
4043 74 : && !openacc
4044 144 : && (gfc_match_omp_to_link ("link (",
4045 : &c->lists[OMP_LIST_LINK])
4046 : == MATCH_YES))
4047 49 : continue;
4048 46 : if ((mask & OMP_CLAUSE_LOCAL)
4049 25 : && (gfc_match_omp_to_link ("local (", &c->lists[OMP_LIST_LOCAL])
4050 : == MATCH_YES))
4051 21 : continue;
4052 : break;
4053 5964 : case 'm':
4054 5964 : if ((mask & OMP_CLAUSE_MAP)
4055 5964 : && gfc_match ("map ( ") == MATCH_YES)
4056 : {
4057 5856 : locus old_loc2 = gfc_current_locus;
4058 5856 : int always_modifier = 0;
4059 5856 : int close_modifier = 0;
4060 5856 : int present_modifier = 0;
4061 5856 : int mapper_modifier = 0;
4062 5856 : int iterator_modifier = 0;
4063 5856 : gfc_namespace *ns_iter = NULL, *ns_curr = gfc_current_ns;
4064 5856 : locus second_always_locus = old_loc2;
4065 5856 : locus second_close_locus = old_loc2;
4066 5856 : locus second_mapper_locus = old_loc2;
4067 5856 : locus second_present_locus = old_loc2;
4068 5856 : char mapper_id[GFC_MAX_SYMBOL_LEN + 1] = { '\0' };
4069 5856 : locus second_iterator_locus = old_loc2;
4070 :
4071 6524 : for (;;)
4072 : {
4073 6190 : locus current_locus = gfc_current_locus;
4074 6190 : if (gfc_match ("always ") == MATCH_YES)
4075 : {
4076 148 : if (always_modifier++ == 1)
4077 5 : second_always_locus = current_locus;
4078 : }
4079 6042 : else if (gfc_match ("close ") == MATCH_YES)
4080 : {
4081 69 : if (close_modifier++ == 1)
4082 5 : second_close_locus = current_locus;
4083 : }
4084 5973 : else if (gfc_match ("present ") == MATCH_YES)
4085 : {
4086 67 : if (present_modifier++ == 1)
4087 4 : second_present_locus = current_locus;
4088 : }
4089 5906 : else if (gfc_match ("mapper ( ") == MATCH_YES)
4090 : {
4091 8 : if (mapper_modifier++ == 1)
4092 0 : second_mapper_locus = current_locus;
4093 8 : m = gfc_match (" %n ) ", mapper_id);
4094 8 : if (m != MATCH_YES)
4095 0 : goto error;
4096 8 : if (strcmp (mapper_id, "default") == 0)
4097 3 : mapper_id[0] = '\0';
4098 : }
4099 5898 : else if (gfc_match_iterator (&ns_iter, true) == MATCH_YES)
4100 : {
4101 42 : if (iterator_modifier++ == 1)
4102 1 : second_iterator_locus = current_locus;
4103 : }
4104 : else
4105 : break;
4106 334 : if (gfc_match (", ") != MATCH_YES)
4107 62 : gfc_warning (OPT_Wdeprecated_openmp,
4108 : "The specification of modifiers without "
4109 : "comma separators for the %<map%> clause "
4110 : "at %C has been deprecated since "
4111 : "OpenMP 5.2");
4112 334 : }
4113 :
4114 5856 : gfc_omp_map_op map_op = default_map_op;
4115 5856 : int always_present_modifier
4116 5856 : = always_modifier && present_modifier;
4117 :
4118 5856 : if (gfc_match ("alloc : ") == MATCH_YES)
4119 799 : map_op = (present_modifier ? OMP_MAP_PRESENT_ALLOC
4120 : : OMP_MAP_ALLOC);
4121 5057 : else if (gfc_match ("tofrom : ") == MATCH_YES)
4122 954 : map_op = (always_present_modifier ? OMP_MAP_ALWAYS_PRESENT_TOFROM
4123 950 : : present_modifier ? OMP_MAP_PRESENT_TOFROM
4124 945 : : always_modifier ? OMP_MAP_ALWAYS_TOFROM
4125 : : OMP_MAP_TOFROM);
4126 4103 : else if (gfc_match ("to : ") == MATCH_YES)
4127 1815 : map_op = (always_present_modifier ? OMP_MAP_ALWAYS_PRESENT_TO
4128 1809 : : present_modifier ? OMP_MAP_PRESENT_TO
4129 1797 : : always_modifier ? OMP_MAP_ALWAYS_TO
4130 : : OMP_MAP_TO);
4131 2288 : else if (gfc_match ("from : ") == MATCH_YES)
4132 1656 : map_op = (always_present_modifier ? OMP_MAP_ALWAYS_PRESENT_FROM
4133 1652 : : present_modifier ? OMP_MAP_PRESENT_FROM
4134 1647 : : always_modifier ? OMP_MAP_ALWAYS_FROM
4135 : : OMP_MAP_FROM);
4136 632 : else if (gfc_match ("release : ") == MATCH_YES)
4137 : map_op = OMP_MAP_RELEASE;
4138 578 : else if (gfc_match ("delete : ") == MATCH_YES)
4139 : map_op = OMP_MAP_DELETE;
4140 : else
4141 : {
4142 501 : gfc_current_locus = old_loc2;
4143 501 : always_modifier = 0;
4144 501 : close_modifier = 0;
4145 501 : mapper_modifier = 0;
4146 : }
4147 :
4148 1579 : if (always_modifier > 1)
4149 : {
4150 5 : gfc_error ("too many %<always%> modifiers at %L",
4151 : &second_always_locus);
4152 24 : break;
4153 : }
4154 5851 : if (close_modifier > 1)
4155 : {
4156 4 : gfc_error ("too many %<close%> modifiers at %L",
4157 : &second_close_locus);
4158 4 : break;
4159 : }
4160 5847 : if (present_modifier > 1)
4161 : {
4162 4 : gfc_error ("too many %<present%> modifiers at %L",
4163 : &second_present_locus);
4164 4 : break;
4165 : }
4166 5843 : if (mapper_modifier > 1)
4167 : {
4168 0 : gfc_error ("too many %<mapper%> modifiers at %L",
4169 : &second_mapper_locus);
4170 0 : break;
4171 : }
4172 5843 : if (iterator_modifier > 1)
4173 : {
4174 1 : gfc_error ("too many %<iterator%> modifiers at %L",
4175 : &second_iterator_locus);
4176 1 : break;
4177 : }
4178 :
4179 5842 : head = NULL;
4180 5842 : if (ns_iter)
4181 40 : gfc_current_ns = ns_iter;
4182 5842 : m = gfc_match_omp_variable_list ("", &c->lists[OMP_LIST_MAP],
4183 : false, NULL, &head, true, true);
4184 5842 : gfc_current_ns = ns_curr;
4185 5842 : if (m == MATCH_YES)
4186 : {
4187 5837 : gfc_omp_namelist *n;
4188 13257 : for (n = *head; n; n = n->next)
4189 : {
4190 7420 : n->u.map.op = map_op;
4191 7420 : if (mapper_id[0] != '\0')
4192 : {
4193 5 : n->u3.udm = gfc_get_omp_namelist_udm ();
4194 5 : n->u3.udm->requested_mapper_id
4195 5 : = gfc_get_string ("%s", mapper_id);
4196 : }
4197 7420 : n->u2.ns = ns_iter;
4198 7420 : if (ns_iter)
4199 42 : ns_iter->refs++;
4200 : }
4201 5837 : continue;
4202 5837 : }
4203 5 : gfc_current_locus = old_loc;
4204 5 : break;
4205 : }
4206 142 : if ((mask & OMP_CLAUSE_MERGEABLE)
4207 142 : && (m = gfc_match_boolean_clause (&bval, "mergeable",
4208 34 : c->mergeable || cfalse->mergeable)) != MATCH_NO)
4209 : {
4210 34 : if (m == MATCH_ERROR)
4211 0 : goto error;
4212 34 : if (bval)
4213 34 : c->mergeable = true;
4214 : else
4215 0 : cfalse->mergeable = true;
4216 34 : continue;
4217 : }
4218 143 : if ((mask & OMP_CLAUSE_MESSAGE)
4219 74 : && (m = gfc_match_dupl_check (!c->message, "message", true,
4220 : &c->message)) != MATCH_NO)
4221 : {
4222 74 : if (m == MATCH_ERROR)
4223 5 : goto error;
4224 69 : continue;
4225 : }
4226 : break;
4227 3037 : case 'n':
4228 3089 : if ((mask & OMP_CLAUSE_NO_CREATE)
4229 1343 : && gfc_match ("no_create ( ") == MATCH_YES
4230 3089 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4231 : OMP_MAP_IF_PRESENT, true,
4232 : allow_derived))
4233 52 : continue;
4234 2988 : if ((mask & OMP_CLAUSE_ASSUMPTIONS)
4235 3019 : && ((m = gfc_match_boolean_clause (&bval, "no_openmp_constructs",
4236 34 : (c->assume && c->assume->no_openmp_constructs)
4237 31 : || (cfalse->assume && cfalse->assume->no_openmp_constructs)))
4238 : != MATCH_NO))
4239 : {
4240 4 : if (m == MATCH_ERROR)
4241 1 : goto error;
4242 3 : if (bval)
4243 : {
4244 2 : if (c->assume == NULL)
4245 0 : c->assume = gfc_get_omp_assumptions ();
4246 2 : c->assume->no_openmp_constructs = true;
4247 : }
4248 : else
4249 : {
4250 1 : if (cfalse->assume == NULL)
4251 0 : cfalse->assume = gfc_get_omp_assumptions ();
4252 1 : cfalse->assume->no_openmp_constructs = true;
4253 : }
4254 3 : continue;
4255 : }
4256 2996 : if ((mask & OMP_CLAUSE_ASSUMPTIONS)
4257 3011 : && ((m = gfc_match_boolean_clause (&bval, "no_openmp_routines",
4258 30 : (c->assume && c->assume->no_openmp_routines)
4259 29 : || (cfalse->assume && cfalse->assume->no_openmp_routines)))
4260 : != MATCH_NO))
4261 : {
4262 15 : if (m == MATCH_ERROR)
4263 0 : goto error;
4264 15 : if (bval)
4265 : {
4266 14 : if (c->assume == NULL)
4267 12 : c->assume = gfc_get_omp_assumptions ();
4268 14 : c->assume->no_openmp_routines = true;
4269 : }
4270 : else
4271 : {
4272 1 : if (cfalse->assume == NULL)
4273 0 : cfalse->assume = gfc_get_omp_assumptions ();
4274 1 : cfalse->assume->no_openmp_routines = true;
4275 : }
4276 15 : continue;
4277 : }
4278 2972 : if ((mask & OMP_CLAUSE_ASSUMPTIONS)
4279 2981 : && ((m = gfc_match_boolean_clause (&bval, "no_openmp",
4280 15 : (c->assume && c->assume->no_openmp)
4281 13 : || (cfalse->assume && cfalse->assume->no_openmp)))
4282 : != MATCH_NO))
4283 : {
4284 6 : if (m == MATCH_ERROR)
4285 0 : goto error;
4286 6 : if (bval)
4287 : {
4288 5 : if (c->assume == NULL)
4289 5 : c->assume = gfc_get_omp_assumptions ();
4290 5 : c->assume->no_openmp = true;
4291 : }
4292 : else
4293 : {
4294 1 : if (cfalse->assume == NULL)
4295 1 : cfalse->assume = gfc_get_omp_assumptions ();
4296 1 : cfalse->assume->no_openmp = true;
4297 : }
4298 6 : continue;
4299 : }
4300 2968 : if ((mask & OMP_CLAUSE_ASSUMPTIONS)
4301 2969 : && ((m = gfc_match_boolean_clause (&bval, "no_parallelism",
4302 9 : (c->assume && c->assume->no_parallelism)
4303 9 : || (cfalse->assume && cfalse->assume->no_parallelism)))
4304 : != MATCH_NO))
4305 : {
4306 8 : if (m == MATCH_ERROR)
4307 0 : goto error;
4308 8 : if (bval)
4309 : {
4310 7 : if (c->assume == NULL)
4311 6 : c->assume = gfc_get_omp_assumptions ();
4312 7 : c->assume->no_parallelism = true;
4313 : }
4314 : else
4315 : {
4316 1 : if (cfalse->assume == NULL)
4317 0 : cfalse->assume = gfc_get_omp_assumptions ();
4318 1 : cfalse->assume->no_parallelism = true;
4319 : }
4320 8 : continue;
4321 : }
4322 :
4323 2962 : if ((mask & OMP_CLAUSE_NOVARIANTS)
4324 2952 : && (m = gfc_match_dupl_check (!c->novariants, "novariants", true,
4325 : &c->novariants))
4326 : != MATCH_NO)
4327 : {
4328 12 : if (m == MATCH_ERROR)
4329 2 : goto error;
4330 10 : continue;
4331 : }
4332 2953 : if ((mask & OMP_CLAUSE_NOCONTEXT)
4333 2940 : && (m = gfc_match_dupl_check (!c->nocontext, "nocontext", true,
4334 : &c->nocontext))
4335 : != MATCH_NO)
4336 : {
4337 15 : if (m == MATCH_ERROR)
4338 2 : goto error;
4339 13 : continue;
4340 : }
4341 2939 : if ((mask & OMP_CLAUSE_NOGROUP)
4342 3009 : && ((m = gfc_match_boolean_clause (&bval, "nogroup",
4343 84 : c->nogroup || cfalse->nogroup))
4344 : != MATCH_NO))
4345 : {
4346 14 : if (m == MATCH_ERROR)
4347 0 : goto error;
4348 14 : if (bval)
4349 14 : c->nogroup = true;
4350 : else
4351 0 : cfalse->nogroup = true;
4352 14 : continue;
4353 : }
4354 3061 : if ((mask & OMP_CLAUSE_NOHOST)
4355 2911 : && (m = gfc_match_dupl_check (!c->nohost, "nohost")) != MATCH_NO)
4356 : {
4357 151 : if (m == MATCH_ERROR)
4358 1 : goto error;
4359 150 : c->nohost = true;
4360 150 : continue;
4361 : }
4362 2802 : if ((mask & OMP_CLAUSE_NOTEMPORAL)
4363 2760 : && gfc_match_omp_variable_list ("nontemporal (",
4364 : &c->lists[OMP_LIST_NONTEMPORAL],
4365 : true) == MATCH_YES)
4366 42 : continue;
4367 2748 : if ((mask & OMP_CLAUSE_NOTINBRANCH)
4368 2751 : && (m = gfc_match_dupl_branch_clause (&bval, "notinbranch",
4369 33 : c->notinbranch || cfalse->notinbranch
4370 33 : || c->inbranch || cfalse->inbranch)) != MATCH_NO)
4371 : {
4372 33 : if (m == MATCH_ERROR)
4373 3 : goto error;
4374 30 : if (bval)
4375 27 : c->notinbranch = true;
4376 : else
4377 3 : cfalse->notinbranch = true;
4378 30 : continue;
4379 : }
4380 2818 : if ((mask & OMP_CLAUSE_NOWAIT)
4381 2685 : && (m = gfc_match_dupl_check (!c->nowait, "nowait")) != MATCH_NO)
4382 : {
4383 136 : if (m == MATCH_ERROR)
4384 3 : goto error;
4385 133 : c->nowait = true;
4386 133 : continue;
4387 : }
4388 3231 : if ((mask & OMP_CLAUSE_NUM_GANGS)
4389 2549 : && (m = gfc_match_dupl_check (!c->num_gangs_expr, "num_gangs",
4390 : true)) != MATCH_NO)
4391 : {
4392 686 : if (m == MATCH_ERROR)
4393 2 : goto error;
4394 684 : if (gfc_match (" %e )", &c->num_gangs_expr) != MATCH_YES)
4395 2 : goto error;
4396 682 : continue;
4397 : }
4398 1889 : if ((mask & OMP_CLAUSE_NUM_TASKS)
4399 1863 : && (m = gfc_match_dupl_check (!c->num_tasks, "num_tasks", true))
4400 : != MATCH_NO)
4401 : {
4402 26 : if (m == MATCH_ERROR)
4403 0 : goto error;
4404 26 : if (gfc_match ("strict : ") == MATCH_YES)
4405 1 : c->num_tasks_strict = true;
4406 26 : if (gfc_match (" %e )", &c->num_tasks) != MATCH_YES)
4407 0 : goto error;
4408 26 : continue;
4409 : }
4410 1837 : if ((mask & OMP_CLAUSE_NUM_TEAMS)
4411 1837 : && (m = gfc_match_dupl_check (!c->num_teams_list,
4412 : "num_teams", true)) != MATCH_NO)
4413 : {
4414 178 : if (m == MATCH_ERROR)
4415 20 : goto error;
4416 176 : gfc_expr *expr;
4417 176 : if (gfc_match ("dims ( %e ) : ", &expr) == MATCH_YES
4418 176 : && match_omp_oacc_expr_list (NULL, &c->num_teams_list,
4419 : false, true) == MATCH_YES)
4420 : {
4421 19 : int num = 0;
4422 19 : gfc_expr_list *el;
4423 55 : for (el = c->num_teams_list; el; el = el->next)
4424 36 : ++num;
4425 19 : if (!gfc_resolve_expr (expr)
4426 19 : || expr->ts.type != BT_INTEGER
4427 18 : || expr->rank != 0
4428 17 : || expr->expr_type != EXPR_CONSTANT
4429 34 : || mpz_sgn (expr->value.integer) <= 0)
4430 : {
4431 5 : gfc_error ("DIMS must be a constant positive integer "
4432 5 : "at %L", &expr->where);
4433 5 : goto error;
4434 : }
4435 14 : if (mpz_cmp_si (expr->value.integer, num) != 0)
4436 : {
4437 1 : gfc_error ("The number of arguments (%d) must be the same"
4438 : " as specified for DIMS at %L", num,
4439 : &expr->where);
4440 1 : goto error;
4441 : }
4442 13 : c->num_teams_dims = true;
4443 158 : continue;
4444 13 : }
4445 157 : else if (gfc_match ("%e ", &expr) == MATCH_YES)
4446 : {
4447 154 : c->num_teams_list = gfc_get_expr_list();
4448 154 : c->num_teams_list->expr = expr;
4449 154 : if (gfc_peek_ascii_char () == ':')
4450 : {
4451 31 : expr = NULL;
4452 31 : if (gfc_match (": %e ", &expr) == MATCH_YES)
4453 : {
4454 30 : c->num_teams_list->next = gfc_get_expr_list();
4455 30 : c->num_teams_list->next->expr = expr;
4456 30 : if (gfc_match (") ") == MATCH_YES)
4457 28 : continue;
4458 : }
4459 : }
4460 123 : else if (gfc_match (") ") == MATCH_YES)
4461 117 : continue;
4462 : }
4463 12 : gfc_error ("Expected either %<[lower-expr : ] upper-expr%> or "
4464 : "%<dims(N): expr-list%> at %C");
4465 12 : goto error;
4466 : }
4467 1659 : if ((mask & OMP_CLAUSE_NUM_THREADS)
4468 1659 : && (m = gfc_match_dupl_check (!c->num_threads_list,
4469 : "num_threads", true, NULL))
4470 : != MATCH_NO)
4471 : {
4472 1018 : int nstrict = 0, nrelaxed = 0, ndims = 0;
4473 1018 : bool fail = false;
4474 1018 : gfc_expr *dims = NULL;
4475 1018 : locus old_loc = gfc_current_locus;
4476 :
4477 1018 : if (m == MATCH_ERROR)
4478 27 : goto error;
4479 1068 : while (true)
4480 : {
4481 1042 : if (gfc_match ("strict ") == MATCH_YES)
4482 16 : nstrict++;
4483 1026 : else if (gfc_match ("relaxed ") == MATCH_YES)
4484 21 : nrelaxed++;
4485 1005 : else if (gfc_match ("dims ") == MATCH_YES)
4486 : {
4487 32 : ndims++;
4488 32 : if (dims)
4489 3 : gfc_free_expr (dims);
4490 32 : if (gfc_match ("( %e ) ", &dims) != MATCH_YES)
4491 : break;
4492 : }
4493 : else
4494 : {
4495 : fail = true;
4496 : break;
4497 : }
4498 68 : if (gfc_match (", ") == MATCH_YES)
4499 26 : continue;
4500 : break;
4501 : }
4502 1016 : if (gfc_match (" : ") == MATCH_YES)
4503 : {
4504 40 : if (nstrict + nrelaxed + ndims == 0 || fail)
4505 : {
4506 1 : gfc_error ("Expected STRICT, RELAXED or DIMS modifier at "
4507 : "%C");
4508 1 : goto error;
4509 : }
4510 39 : else if (nstrict + nrelaxed > 1)
4511 : {
4512 8 : gfc_error ("Only one STRICT or RELAXED modifier permitted"
4513 : " at %L", &old_loc);
4514 8 : goto error;
4515 : }
4516 31 : if (ndims > 1)
4517 : {
4518 3 : gfc_error ("Duplicated DIMS expression at %L",
4519 3 : &dims->where);
4520 3 : goto error;
4521 : }
4522 28 : if (nstrict || (dims && !nrelaxed))
4523 17 : c->num_threads_strict = true;
4524 : }
4525 : else
4526 : {
4527 976 : gfc_free_expr (dims);
4528 976 : dims = NULL;
4529 976 : gfc_current_locus = old_loc;
4530 : }
4531 :
4532 1004 : m = match_omp_oacc_expr_list (NULL, &c->num_threads_list, false,
4533 : true);
4534 1004 : if (m != MATCH_YES)
4535 : {
4536 7 : gfc_error ("Expected a list of integer expressions followed "
4537 : "by a %<)%> and optionally preceded by the STRICT,"
4538 : " RELAXED, or DIMS as modifiers and a colon at %C");
4539 7 : goto error;
4540 : }
4541 997 : if (dims)
4542 : {
4543 17 : int num = 0;
4544 17 : gfc_expr_list *el;
4545 46 : for (el = c->num_threads_list; el; el = el->next)
4546 29 : ++num;
4547 17 : if (!gfc_resolve_expr (dims)
4548 17 : || dims->ts.type != BT_INTEGER
4549 16 : || dims->rank != 0
4550 15 : || dims->expr_type != EXPR_CONSTANT
4551 30 : || mpz_sgn (dims->value.integer) <= 0)
4552 : {
4553 5 : gfc_error ("DIMS must be a constant positive integer "
4554 5 : "at %L", &dims->where);
4555 5 : goto error;
4556 : }
4557 12 : if (mpz_cmp_si (dims->value.integer, num) != 0)
4558 : {
4559 1 : gfc_error ("The number of arguments (%d) must be the same"
4560 : " as specified for DIMS at %L", num,
4561 : &dims->where);
4562 1 : goto error;
4563 : }
4564 11 : c->num_threads_dims = true;
4565 : }
4566 991 : continue;
4567 991 : }
4568 1240 : if ((mask & OMP_CLAUSE_NUM_WORKERS)
4569 641 : && (m = gfc_match_dupl_check (!c->num_workers_expr, "num_workers",
4570 : true, &c->num_workers_expr))
4571 : != MATCH_NO)
4572 : {
4573 603 : if (m == MATCH_ERROR)
4574 4 : goto error;
4575 599 : continue;
4576 : }
4577 : break;
4578 591 : case 'o':
4579 591 : if ((mask & OMP_CLAUSE_ORDERED)
4580 591 : && (m = gfc_match_dupl_check (!c->ordered, "ordered"))
4581 : != MATCH_NO)
4582 : {
4583 343 : if (m == MATCH_ERROR)
4584 0 : goto error;
4585 343 : gfc_expr *cexpr = NULL;
4586 343 : m = gfc_match (" ( %e )", &cexpr);
4587 :
4588 343 : c->ordered = true;
4589 343 : if (m == MATCH_YES)
4590 : {
4591 144 : int ordered = 0;
4592 144 : if (gfc_extract_int (cexpr, &ordered, -1))
4593 0 : ordered = 0;
4594 144 : else if (ordered <= 0)
4595 : {
4596 0 : gfc_error_now ("ORDERED clause argument not"
4597 : " constant positive integer at %C");
4598 0 : ordered = 0;
4599 : }
4600 144 : c->orderedc = ordered;
4601 144 : gfc_free_expr (cexpr);
4602 144 : continue;
4603 144 : }
4604 :
4605 199 : continue;
4606 199 : }
4607 482 : if ((mask & OMP_CLAUSE_ORDER)
4608 248 : && (m = gfc_match_dupl_check (!c->order_concurrent, "order", true))
4609 : != MATCH_NO)
4610 : {
4611 247 : if (m == MATCH_ERROR)
4612 10 : goto error;
4613 237 : if (gfc_match (" reproducible : concurrent )") == MATCH_YES)
4614 55 : c->order_reproducible = true;
4615 182 : else if (gfc_match (" concurrent )") == MATCH_YES)
4616 : ;
4617 50 : else if (gfc_match (" unconstrained : concurrent )") == MATCH_YES)
4618 47 : c->order_unconstrained = true;
4619 : else
4620 : {
4621 3 : gfc_error ("Expected ORDER(CONCURRENT) at %C "
4622 : "with optional %<reproducible%> or "
4623 : "%<unconstrained%> modifier");
4624 3 : goto error;
4625 : }
4626 234 : c->order_concurrent = true;
4627 234 : continue;
4628 : }
4629 : break;
4630 3108 : case 'p':
4631 3108 : if (mask & OMP_CLAUSE_PARTIAL)
4632 : {
4633 276 : if ((m = gfc_match_dupl_check (!c->partial, "partial"))
4634 : != MATCH_NO)
4635 : {
4636 276 : int expr;
4637 276 : if (m == MATCH_ERROR)
4638 0 : goto error;
4639 :
4640 276 : c->partial = -1;
4641 :
4642 276 : gfc_expr *cexpr = NULL;
4643 276 : m = gfc_match (" ( %e )", &cexpr);
4644 276 : if (m == MATCH_NO)
4645 : ;
4646 251 : else if (m == MATCH_YES
4647 251 : && !gfc_extract_int (cexpr, &expr, -1)
4648 502 : && expr > 0)
4649 247 : c->partial = expr;
4650 : else
4651 4 : gfc_error_now ("PARTIAL clause argument not constant "
4652 : "positive integer at %C");
4653 276 : gfc_free_expr (cexpr);
4654 276 : continue;
4655 276 : }
4656 : }
4657 2901 : if ((mask & OMP_CLAUSE_COPY)
4658 877 : && gfc_match ("pcopy ( ") == MATCH_YES
4659 2902 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4660 : OMP_MAP_TOFROM, true, allow_derived))
4661 69 : continue;
4662 2837 : if ((mask & OMP_CLAUSE_COPYIN)
4663 1911 : && gfc_match ("pcopyin ( ") == MATCH_YES
4664 2837 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4665 : OMP_MAP_TO, true, allow_derived))
4666 74 : continue;
4667 2762 : if ((mask & OMP_CLAUSE_COPYOUT)
4668 735 : && gfc_match ("pcopyout ( ") == MATCH_YES
4669 2762 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4670 : OMP_MAP_FROM, true, allow_derived))
4671 73 : continue;
4672 2631 : if ((mask & OMP_CLAUSE_CREATE)
4673 672 : && gfc_match ("pcreate ( ") == MATCH_YES
4674 2631 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4675 : OMP_MAP_ALLOC, true, allow_derived))
4676 15 : continue;
4677 3017 : if ((mask & OMP_CLAUSE_PRESENT)
4678 647 : && gfc_match ("present ( ") == MATCH_YES
4679 3019 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4680 : OMP_MAP_FORCE_PRESENT, false,
4681 : allow_derived))
4682 416 : continue;
4683 2208 : if ((mask & OMP_CLAUSE_COPY)
4684 231 : && gfc_match ("present_or_copy ( ") == MATCH_YES
4685 2208 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4686 : OMP_MAP_TOFROM, true,
4687 : allow_derived))
4688 23 : continue;
4689 2202 : if ((mask & OMP_CLAUSE_COPYIN)
4690 1310 : && gfc_match ("present_or_copyin ( ") == MATCH_YES
4691 2202 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4692 : OMP_MAP_TO, true, allow_derived))
4693 40 : continue;
4694 2157 : if ((mask & OMP_CLAUSE_COPYOUT)
4695 173 : && gfc_match ("present_or_copyout ( ") == MATCH_YES
4696 2157 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4697 : OMP_MAP_FROM, true, allow_derived))
4698 35 : continue;
4699 2115 : if ((mask & OMP_CLAUSE_CREATE)
4700 143 : && gfc_match ("present_or_create ( ") == MATCH_YES
4701 2115 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4702 : OMP_MAP_ALLOC, true, allow_derived))
4703 28 : continue;
4704 2094 : if ((mask & OMP_CLAUSE_PRIORITY)
4705 2059 : && (m = gfc_match_dupl_check (!c->priority, "priority", true,
4706 : &c->priority)) != MATCH_NO)
4707 : {
4708 35 : if (m == MATCH_ERROR)
4709 0 : goto error;
4710 35 : continue;
4711 : }
4712 3971 : if ((mask & OMP_CLAUSE_PRIVATE)
4713 2024 : && gfc_match_omp_variable_list ("private (",
4714 : &c->lists[OMP_LIST_PRIVATE],
4715 : true) == MATCH_YES)
4716 1947 : continue;
4717 141 : if ((mask & OMP_CLAUSE_PROC_BIND)
4718 141 : && (m = gfc_match_dupl_check ((c->proc_bind
4719 64 : == OMP_PROC_BIND_UNKNOWN),
4720 : "proc_bind", true)) != MATCH_NO)
4721 : {
4722 64 : if (m == MATCH_ERROR)
4723 0 : goto error;
4724 64 : if (gfc_match ("primary )") == MATCH_YES)
4725 1 : c->proc_bind = OMP_PROC_BIND_PRIMARY;
4726 63 : else if (gfc_match ("master )") == MATCH_YES)
4727 : {
4728 9 : gfc_warning (OPT_Wdeprecated_openmp,
4729 : "%<master%> affinity policy at %C deprecated "
4730 : "since OpenMP 5.1, use %<primary%>");
4731 9 : c->proc_bind = OMP_PROC_BIND_MASTER;
4732 : }
4733 54 : else if (gfc_match ("spread )") == MATCH_YES)
4734 53 : c->proc_bind = OMP_PROC_BIND_SPREAD;
4735 1 : else if (gfc_match ("close )") == MATCH_YES)
4736 1 : c->proc_bind = OMP_PROC_BIND_CLOSE;
4737 : else
4738 0 : goto error;
4739 64 : continue;
4740 : }
4741 : break;
4742 4614 : case 'r':
4743 5115 : if ((mask & OMP_CLAUSE_ATOMIC)
4744 5161 : && (m = gfc_match_dupl_atomic (&bval, "read",
4745 547 : c->atomic_op != GFC_OMP_ATOMIC_UNSET)) != MATCH_NO)
4746 : {
4747 501 : if (m == MATCH_ERROR)
4748 0 : goto error;
4749 501 : if (bval)
4750 493 : c->atomic_op = GFC_OMP_ATOMIC_READ;
4751 501 : continue;
4752 : }
4753 8171 : if ((mask & OMP_CLAUSE_REDUCTION)
4754 4113 : && gfc_match_omp_clause_reduction (pc, c, openacc,
4755 : allow_derived) == MATCH_YES)
4756 4058 : continue;
4757 74 : if ((mask & OMP_CLAUSE_MEMORDER)
4758 101 : && (m = gfc_match_dupl_memorder (&bval, "relaxed",
4759 46 : c->memorder != OMP_MEMORDER_UNSET)) != MATCH_NO)
4760 : {
4761 19 : if (m == MATCH_ERROR)
4762 0 : goto error;
4763 19 : if (bval)
4764 12 : c->memorder = OMP_MEMORDER_RELAXED;
4765 19 : continue;
4766 : }
4767 61 : if ((mask & OMP_CLAUSE_MEMORDER)
4768 63 : && (m = gfc_match_dupl_memorder (&bval, "release",
4769 27 : c->memorder != OMP_MEMORDER_UNSET)) != MATCH_NO)
4770 : {
4771 27 : if (m == MATCH_ERROR)
4772 2 : goto error;
4773 25 : if (bval)
4774 17 : c->memorder = OMP_MEMORDER_RELEASE;
4775 25 : continue;
4776 : }
4777 : break;
4778 3091 : case 's':
4779 3184 : if ((mask & OMP_CLAUSE_SAFELEN)
4780 3091 : && (m = gfc_match_dupl_check (!c->safelen_expr, "safelen",
4781 : true, &c->safelen_expr))
4782 : != MATCH_NO)
4783 : {
4784 93 : if (m == MATCH_ERROR)
4785 0 : goto error;
4786 93 : continue;
4787 : }
4788 2998 : if ((mask & OMP_CLAUSE_SCHEDULE)
4789 2998 : && (m = gfc_match_dupl_check (c->sched_kind == OMP_SCHED_NONE,
4790 : "schedule", true)) != MATCH_NO)
4791 : {
4792 809 : if (m == MATCH_ERROR)
4793 0 : goto error;
4794 809 : int nmodifiers = 0;
4795 809 : locus old_loc2 = gfc_current_locus;
4796 827 : do
4797 : {
4798 818 : if (gfc_match ("simd") == MATCH_YES)
4799 : {
4800 18 : c->sched_simd = true;
4801 18 : nmodifiers++;
4802 : }
4803 800 : else if (gfc_match ("monotonic") == MATCH_YES)
4804 : {
4805 30 : c->sched_monotonic = true;
4806 30 : nmodifiers++;
4807 : }
4808 770 : else if (gfc_match ("nonmonotonic") == MATCH_YES)
4809 : {
4810 35 : c->sched_nonmonotonic = true;
4811 35 : nmodifiers++;
4812 : }
4813 : else
4814 : {
4815 735 : if (nmodifiers)
4816 0 : gfc_current_locus = old_loc2;
4817 : break;
4818 : }
4819 92 : if (nmodifiers == 1
4820 83 : && gfc_match (" , ") == MATCH_YES)
4821 9 : continue;
4822 74 : else if (gfc_match (" : ") == MATCH_YES)
4823 : break;
4824 0 : gfc_current_locus = old_loc2;
4825 0 : break;
4826 : }
4827 : while (1);
4828 809 : if (gfc_match ("static") == MATCH_YES)
4829 425 : c->sched_kind = OMP_SCHED_STATIC;
4830 384 : else if (gfc_match ("dynamic") == MATCH_YES)
4831 164 : c->sched_kind = OMP_SCHED_DYNAMIC;
4832 220 : else if (gfc_match ("guided") == MATCH_YES)
4833 127 : c->sched_kind = OMP_SCHED_GUIDED;
4834 93 : else if (gfc_match ("runtime") == MATCH_YES)
4835 85 : c->sched_kind = OMP_SCHED_RUNTIME;
4836 8 : else if (gfc_match ("auto") == MATCH_YES)
4837 8 : c->sched_kind = OMP_SCHED_AUTO;
4838 809 : if (c->sched_kind != OMP_SCHED_NONE)
4839 : {
4840 809 : m = MATCH_NO;
4841 809 : if (c->sched_kind != OMP_SCHED_RUNTIME
4842 724 : && c->sched_kind != OMP_SCHED_AUTO)
4843 716 : m = gfc_match (" , %e )", &c->chunk_size);
4844 716 : if (m != MATCH_YES)
4845 299 : m = gfc_match_char (')');
4846 299 : if (m != MATCH_YES)
4847 0 : c->sched_kind = OMP_SCHED_NONE;
4848 : }
4849 809 : if (c->sched_kind != OMP_SCHED_NONE)
4850 809 : continue;
4851 : else
4852 0 : gfc_current_locus = old_loc;
4853 : }
4854 2372 : if ((mask & OMP_CLAUSE_SELF)
4855 335 : && !(mask & OMP_CLAUSE_HOST) /* OpenACC compute construct */
4856 2429 : && (m = gfc_match_dupl_check (!c->self_expr, "self"))
4857 : != MATCH_NO)
4858 : {
4859 186 : if (m == MATCH_ERROR)
4860 3 : goto error;
4861 183 : m = gfc_match (" ( %e )", &c->self_expr);
4862 183 : if (m == MATCH_ERROR)
4863 : {
4864 0 : gfc_current_locus = old_loc;
4865 0 : break;
4866 : }
4867 183 : else if (m == MATCH_NO)
4868 9 : c->self_expr = gfc_get_logical_expr (gfc_default_logical_kind,
4869 : NULL, true);
4870 183 : continue;
4871 : }
4872 2097 : if ((mask & OMP_CLAUSE_SELF)
4873 149 : && (mask & OMP_CLAUSE_HOST) /* OpenACC 'update' directive */
4874 95 : && gfc_match ("self ( ") == MATCH_YES
4875 2098 : && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
4876 : OMP_MAP_FORCE_FROM, true,
4877 : /* allow_derived = */ true))
4878 94 : continue;
4879 2257 : if ((mask & OMP_CLAUSE_SEQ)
4880 1909 : && (m = gfc_match_dupl_check (!c->seq, "seq")) != MATCH_NO)
4881 : {
4882 348 : if (m == MATCH_ERROR)
4883 0 : goto error;
4884 348 : c->seq = true;
4885 348 : continue;
4886 : }
4887 1710 : if ((mask & OMP_CLAUSE_MEMORDER)
4888 1710 : && (m = gfc_match_dupl_memorder (&bval, "seq_cst",
4889 149 : c->memorder != OMP_MEMORDER_UNSET)) != MATCH_NO)
4890 : {
4891 149 : if (m == MATCH_ERROR)
4892 0 : goto error;
4893 149 : if (bval)
4894 143 : c->memorder = OMP_MEMORDER_SEQ_CST;
4895 149 : continue;
4896 : }
4897 2387 : if ((mask & OMP_CLAUSE_SHARED)
4898 1412 : && gfc_match_omp_variable_list ("shared (",
4899 : &c->lists[OMP_LIST_SHARED],
4900 : true) == MATCH_YES)
4901 975 : continue;
4902 437 : if ((mask & OMP_CLAUSE_SIMDLEN)
4903 437 : && (m = gfc_match_dupl_check (!c->simdlen_expr, "simdlen",
4904 : true)) != MATCH_NO)
4905 : {
4906 151 : if (m == MATCH_ERROR)
4907 0 : goto error;
4908 151 : if (gfc_match ("scaled ( ") == MATCH_YES)
4909 : {
4910 27 : old_loc = gfc_current_locus;
4911 27 : gfc_typespec ts;
4912 : /* This does not match 'type(integer)'; should it? */
4913 27 : if (gfc_match_type_spec (&ts) != MATCH_YES
4914 27 : || (ts.type != BT_INTEGER && ts.type != BT_UNSIGNED
4915 : && ts.type != BT_REAL && ts.type != BT_COMPLEX))
4916 : {
4917 2 : gfc_error ("Expected numerical type name at %L",
4918 : &old_loc);
4919 5 : goto error;
4920 : }
4921 25 : c->simdlen_type.type = ts.type;
4922 25 : c->simdlen_type.kind = ts.kind;
4923 25 : if (gfc_match (" , ") == MATCH_YES)
4924 : {
4925 17 : if (gfc_match_expr (&c->simdlen_divisor) != MATCH_YES)
4926 : {
4927 0 : gfc_error ("Expected divisor expression at %C");
4928 0 : goto error;
4929 : }
4930 : }
4931 25 : if (gfc_match (" ) ") != MATCH_YES)
4932 : {
4933 2 : gfc_error ("Expected %<)%> at %C");
4934 2 : goto error;
4935 : }
4936 23 : if (gfc_match (" : ") != MATCH_YES)
4937 : {
4938 1 : gfc_error ("Expected %<:%> at %C");
4939 1 : goto error;
4940 : }
4941 : }
4942 146 : if (gfc_match_expr (&c->simdlen_expr) != MATCH_YES)
4943 : {
4944 0 : gfc_error ("Expected length expression at %C");
4945 0 : goto error;
4946 : }
4947 146 : if (gfc_match (" ) ") != MATCH_YES)
4948 : {
4949 0 : gfc_error ("Expected %<)%> at %C");
4950 0 : goto error;
4951 : }
4952 146 : continue;
4953 146 : }
4954 312 : if ((mask & OMP_CLAUSE_SIMD)
4955 312 : && ((m = gfc_match_boolean_clause (&bval, "simd",
4956 26 : c->simd || cfalse->simd))
4957 : != MATCH_NO))
4958 : {
4959 26 : if (m == MATCH_ERROR)
4960 0 : goto error;
4961 26 : if (bval)
4962 24 : c->simd = true;
4963 : else
4964 2 : cfalse->simd = false;
4965 26 : continue;
4966 : }
4967 305 : if ((mask & OMP_CLAUSE_SEVERITY)
4968 260 : && (m = gfc_match_dupl_check (!c->severity, "severity", true))
4969 : != MATCH_NO)
4970 : {
4971 51 : if (m == MATCH_ERROR)
4972 2 : goto error;
4973 49 : if (gfc_match ("fatal )") == MATCH_YES)
4974 12 : c->severity = OMP_SEVERITY_FATAL;
4975 37 : else if (gfc_match ("warning )") == MATCH_YES)
4976 33 : c->severity = OMP_SEVERITY_WARNING;
4977 : else
4978 : {
4979 4 : gfc_error ("Expected FATAL or WARNING in SEVERITY clause "
4980 : "at %C");
4981 4 : goto error;
4982 : }
4983 45 : continue;
4984 : }
4985 209 : if ((mask & OMP_CLAUSE_SIZES)
4986 209 : && ((m = gfc_match_dupl_check (!c->sizes_list, "sizes"))
4987 : != MATCH_NO))
4988 : {
4989 203 : if (m == MATCH_ERROR)
4990 0 : goto error;
4991 203 : m = match_omp_oacc_expr_list (" (", &c->sizes_list, false, true);
4992 203 : if (m == MATCH_ERROR)
4993 7 : goto error;
4994 196 : if (m == MATCH_YES)
4995 195 : continue;
4996 1 : gfc_error ("Expected %<(%> after %qs at %C", "sizes");
4997 1 : goto error;
4998 : }
4999 : break;
5000 1288 : case 't':
5001 1353 : if ((mask & OMP_CLAUSE_TASK_REDUCTION)
5002 1288 : && gfc_match_omp_clause_reduction (pc, c, openacc,
5003 : allow_derived) == MATCH_YES)
5004 65 : continue;
5005 1223 : if ((mask & OMP_CLAUSE_THREAD_LIMIT)
5006 1223 : && (m = gfc_match_dupl_check (!c->thread_limit_list, "thread_limit",
5007 : true, NULL)) != MATCH_NO)
5008 : {
5009 133 : int nstrict = 0, nrelaxed = 0, ndims = 0;
5010 133 : bool fail = false;
5011 133 : gfc_expr *dims = NULL;
5012 133 : locus old_loc = gfc_current_locus;
5013 :
5014 133 : if (m == MATCH_ERROR)
5015 28 : goto error;
5016 179 : while (true)
5017 : {
5018 155 : if (gfc_match ("strict ") == MATCH_YES)
5019 15 : nstrict++;
5020 140 : else if (gfc_match ("relaxed ") == MATCH_YES)
5021 25 : nrelaxed++;
5022 115 : else if (gfc_match ("dims ") == MATCH_YES)
5023 : {
5024 31 : ndims++;
5025 31 : if (dims)
5026 3 : gfc_free_expr (dims);
5027 31 : if (gfc_match ("( %e ) ", &dims) != MATCH_YES)
5028 : break;
5029 : }
5030 : else
5031 : {
5032 : fail = true;
5033 : break;
5034 : }
5035 70 : if (gfc_match (", ") == MATCH_YES)
5036 24 : continue;
5037 : break;
5038 : }
5039 131 : if (gfc_match (" : ") == MATCH_YES)
5040 : {
5041 44 : if (nstrict + nrelaxed + ndims == 0 || fail)
5042 : {
5043 1 : gfc_error ("Expected STRICT, RELAXED or DIMS modifier at "
5044 : "%C");
5045 1 : goto error;
5046 : }
5047 43 : else if (nstrict + nrelaxed > 1)
5048 : {
5049 8 : gfc_error ("Only one STRICT or RELAXED modifier permitted"
5050 : " at %L", &old_loc);
5051 8 : goto error;
5052 : }
5053 35 : if (ndims > 1)
5054 : {
5055 3 : gfc_error ("Duplicated DIMS expression at %L",
5056 3 : &dims->where);
5057 3 : goto error;
5058 : }
5059 : }
5060 : else
5061 : {
5062 87 : gfc_free_expr (dims);
5063 87 : dims = NULL;
5064 87 : gfc_current_locus = old_loc;
5065 : }
5066 :
5067 119 : m = match_omp_oacc_expr_list (NULL, &c->thread_limit_list,
5068 : false, true);
5069 119 : if (m != MATCH_YES)
5070 : {
5071 7 : gfc_error ("Expected a list of integer expressions followed "
5072 : "by a %<)%> and optionally preceded by the STRICT,"
5073 : " RELAXED, or DIMS as modifiers and a colon at %C");
5074 7 : goto error;
5075 : }
5076 112 : c->thread_limit_strict = (nstrict != 0) || (dims && !nrelaxed);
5077 :
5078 112 : if (!dims && c->thread_limit_list->next)
5079 : {
5080 1 : gfc_error ("Without the DIM modifier, only a single integer "
5081 : "expression may be specified at %L",
5082 1 : &c->thread_limit_list->next->expr->where);
5083 1 : goto error;
5084 : }
5085 111 : else if (dims)
5086 : {
5087 16 : int num = 0;
5088 16 : gfc_expr_list *el;
5089 53 : for (el = c->thread_limit_list; el; el = el->next)
5090 37 : ++num;
5091 16 : if (!gfc_resolve_expr (dims)
5092 16 : || dims->ts.type != BT_INTEGER
5093 15 : || dims->rank != 0
5094 14 : || dims->expr_type != EXPR_CONSTANT
5095 28 : || mpz_sgn (dims->value.integer) <= 0)
5096 : {
5097 5 : gfc_error ("DIMS must be a constant positive integer "
5098 5 : "at %L", &dims->where);
5099 5 : goto error;
5100 : }
5101 11 : if (mpz_cmp_si (dims->value.integer, num) != 0)
5102 : {
5103 1 : gfc_error ("The number of arguments (%d) must be the same"
5104 : " as specified for DIMS at %L", num,
5105 : &dims->where);
5106 1 : goto error;
5107 : }
5108 10 : c->thread_limit_dims = true;
5109 : }
5110 105 : continue;
5111 105 : }
5112 1107 : if ((mask & OMP_CLAUSE_THREADS)
5113 1107 : && ((m = gfc_match_boolean_clause (&bval, "threads",
5114 17 : c->threads || cfalse->threads))
5115 : != MATCH_NO))
5116 : {
5117 17 : if (m == MATCH_ERROR)
5118 0 : goto error;
5119 17 : if (bval)
5120 15 : c->threads = true;
5121 : else
5122 2 : cfalse->threads = false;
5123 17 : continue;
5124 : }
5125 1270 : if ((mask & OMP_CLAUSE_TILE)
5126 221 : && !c->tile_list
5127 1294 : && match_omp_oacc_expr_list ("tile (", &c->tile_list,
5128 : true, false) == MATCH_YES)
5129 197 : continue;
5130 876 : if ((mask & OMP_CLAUSE_TO) && (mask & OMP_CLAUSE_LINK))
5131 : {
5132 : /* Declare target: 'to' is an alias for 'enter';
5133 : 'to' is deprecated since 5.2. */
5134 117 : m = gfc_match_omp_to_link ("to (", &c->lists[OMP_LIST_TO]);
5135 117 : if (m == MATCH_ERROR)
5136 0 : goto error;
5137 117 : if (m == MATCH_YES)
5138 : {
5139 117 : gfc_warning (OPT_Wdeprecated_openmp,
5140 : "%<to%> clause with %<declare target%> at %L "
5141 : "deprecated since OpenMP 5.2, use %<enter%>",
5142 : &old_loc);
5143 117 : continue;
5144 : }
5145 : }
5146 1487 : else if ((mask & OMP_CLAUSE_TO)
5147 759 : && gfc_match_motion_var_list ("to (", &c->lists[OMP_LIST_TO],
5148 : &head) == MATCH_YES)
5149 728 : continue;
5150 : break;
5151 1551 : case 'u':
5152 1609 : if ((mask & OMP_CLAUSE_UNIFORM)
5153 1551 : && gfc_match_omp_variable_list ("uniform (",
5154 : &c->lists[OMP_LIST_UNIFORM],
5155 : false) == MATCH_YES)
5156 58 : continue;
5157 1636 : if ((mask & OMP_CLAUSE_UNTIED)
5158 1636 : && ((m = gfc_match_boolean_clause (&bval, "untied",
5159 143 : c->untied || cfalse->untied))
5160 : != MATCH_NO))
5161 : {
5162 143 : if (m == MATCH_ERROR)
5163 0 : goto error;
5164 143 : if (bval)
5165 142 : c->untied = true;
5166 : else
5167 1 : cfalse->untied = true;
5168 143 : continue;
5169 : }
5170 1605 : if ((mask & OMP_CLAUSE_ATOMIC)
5171 1606 : && (m = gfc_match_dupl_atomic (&bval, "update",
5172 256 : c->atomic_op != GFC_OMP_ATOMIC_UNSET)) != MATCH_NO)
5173 : {
5174 256 : if (m == MATCH_ERROR)
5175 1 : goto error;
5176 255 : if (bval)
5177 249 : c->atomic_op = GFC_OMP_ATOMIC_UPDATE;
5178 255 : continue;
5179 : }
5180 1116 : if ((mask & OMP_CLAUSE_USE)
5181 1094 : && gfc_match_omp_variable_list ("use (",
5182 : &c->lists[OMP_LIST_USE],
5183 : true) == MATCH_YES)
5184 22 : continue;
5185 1132 : if ((mask & OMP_CLAUSE_USE_DEVICE)
5186 1072 : && gfc_match_omp_variable_list ("use_device (",
5187 : &c->lists[OMP_LIST_USE_DEVICE],
5188 : true) == MATCH_YES)
5189 60 : continue;
5190 1175 : if ((mask & OMP_CLAUSE_USE_DEVICE_PTR)
5191 1940 : && gfc_match_omp_variable_list
5192 928 : ("use_device_ptr (",
5193 : &c->lists[OMP_LIST_USE_DEVICE_PTR], false) == MATCH_YES)
5194 163 : continue;
5195 1614 : if ((mask & OMP_CLAUSE_USE_DEVICE_ADDR)
5196 1614 : && gfc_match_omp_variable_list
5197 765 : ("use_device_addr (", &c->lists[OMP_LIST_USE_DEVICE_ADDR],
5198 : false, NULL, NULL, true) == MATCH_YES)
5199 765 : continue;
5200 153 : if ((mask & OMP_CLAUSE_USES_ALLOCATORS)
5201 84 : && (gfc_match ("uses_allocators ( ") == MATCH_YES))
5202 : {
5203 78 : if (gfc_match_omp_clause_uses_allocators (c) != MATCH_YES)
5204 9 : goto error;
5205 69 : continue;
5206 : }
5207 : break;
5208 1570 : case 'v':
5209 : /* VECTOR_LENGTH must be matched before VECTOR, because the latter
5210 : doesn't unconditionally match '('. */
5211 2139 : if ((mask & OMP_CLAUSE_VECTOR_LENGTH)
5212 1570 : && (m = gfc_match_dupl_check (!c->vector_length_expr,
5213 : "vector_length", true,
5214 : &c->vector_length_expr))
5215 : != MATCH_NO)
5216 : {
5217 573 : if (m == MATCH_ERROR)
5218 4 : goto error;
5219 569 : continue;
5220 : }
5221 1989 : if ((mask & OMP_CLAUSE_VECTOR)
5222 997 : && (m = gfc_match_dupl_check (!c->vector, "vector")) != MATCH_NO)
5223 : {
5224 995 : if (m == MATCH_ERROR)
5225 0 : goto error;
5226 995 : c->vector = true;
5227 995 : m = match_oacc_clause_gwv (c, GOMP_DIM_VECTOR);
5228 995 : if (m == MATCH_ERROR)
5229 3 : goto error;
5230 992 : continue;
5231 : }
5232 : break;
5233 1505 : case 'w':
5234 1505 : if ((mask & OMP_CLAUSE_WAIT)
5235 1505 : && gfc_match ("wait") == MATCH_YES)
5236 : {
5237 192 : m = match_omp_oacc_expr_list (" (", &c->wait_list, false, false);
5238 192 : if (m == MATCH_ERROR)
5239 9 : goto error;
5240 183 : else if (m == MATCH_NO)
5241 : {
5242 47 : gfc_expr *expr
5243 47 : = gfc_get_constant_expr (BT_INTEGER,
5244 : gfc_default_integer_kind,
5245 : &gfc_current_locus);
5246 47 : mpz_set_si (expr->value.integer, GOMP_ASYNC_NOVAL);
5247 47 : gfc_expr_list **expr_list = &c->wait_list;
5248 56 : while (*expr_list)
5249 9 : expr_list = &(*expr_list)->next;
5250 47 : *expr_list = gfc_get_expr_list ();
5251 47 : (*expr_list)->expr = expr;
5252 47 : needs_space = true;
5253 : }
5254 183 : continue;
5255 183 : }
5256 1330 : if ((mask & OMP_CLAUSE_WEAK)
5257 1759 : && ((m = gfc_match_boolean_clause (&bval, "weak",
5258 446 : c->weak || cfalse->weak))
5259 : != MATCH_NO))
5260 : {
5261 18 : if (m == MATCH_ERROR)
5262 1 : goto error;
5263 17 : if (bval)
5264 14 : c->weak = true;
5265 : else
5266 3 : cfalse->weak = true;
5267 17 : continue;
5268 : }
5269 2156 : if ((mask & OMP_CLAUSE_WORKER)
5270 1295 : && (m = gfc_match_dupl_check (!c->worker, "worker")) != MATCH_NO)
5271 : {
5272 864 : if (m == MATCH_ERROR)
5273 0 : goto error;
5274 864 : c->worker = true;
5275 864 : m = match_oacc_clause_gwv (c, GOMP_DIM_WORKER);
5276 864 : if (m == MATCH_ERROR)
5277 3 : goto error;
5278 861 : continue;
5279 : }
5280 856 : if ((mask & OMP_CLAUSE_ATOMIC)
5281 859 : && (m = gfc_match_dupl_atomic (&bval, "write",
5282 428 : c->atomic_op != GFC_OMP_ATOMIC_UNSET)) != MATCH_NO)
5283 : {
5284 428 : if (m == MATCH_ERROR)
5285 3 : goto error;
5286 425 : if (bval)
5287 418 : c->atomic_op = GFC_OMP_ATOMIC_WRITE;
5288 425 : continue;
5289 : }
5290 : break;
5291 : }
5292 : break;
5293 47140 : }
5294 :
5295 35271 : end:
5296 35271 : if (cfalse)
5297 21403 : gfc_free_omp_clauses (cfalse);
5298 35271 : if (error || gfc_match_omp_eos () != MATCH_YES)
5299 : {
5300 669 : if (!gfc_error_flag_test ())
5301 152 : gfc_error ("Failed to match clause at %C");
5302 669 : gfc_free_omp_clauses (c);
5303 669 : return MATCH_ERROR;
5304 : }
5305 :
5306 34602 : *cp = c;
5307 34602 : return MATCH_YES;
5308 :
5309 368 : error:
5310 368 : error = true;
5311 368 : goto end;
5312 : }
5313 :
5314 :
5315 : #define OACC_PARALLEL_CLAUSES \
5316 : (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_NUM_GANGS \
5317 : | OMP_CLAUSE_NUM_WORKERS | OMP_CLAUSE_VECTOR_LENGTH | OMP_CLAUSE_REDUCTION \
5318 : | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT \
5319 : | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT \
5320 : | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE \
5321 : | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH \
5322 : | OMP_CLAUSE_SELF)
5323 : #define OACC_KERNELS_CLAUSES \
5324 : (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_NUM_GANGS \
5325 : | OMP_CLAUSE_NUM_WORKERS | OMP_CLAUSE_VECTOR_LENGTH | OMP_CLAUSE_DEVICEPTR \
5326 : | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT \
5327 : | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT \
5328 : | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH \
5329 : | OMP_CLAUSE_SELF)
5330 : #define OACC_SERIAL_CLAUSES \
5331 : (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_REDUCTION \
5332 : | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT \
5333 : | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT \
5334 : | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE \
5335 : | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH \
5336 : | OMP_CLAUSE_SELF)
5337 : #define OACC_DATA_CLAUSES \
5338 : (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_COPY \
5339 : | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_CREATE \
5340 : | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT | OMP_CLAUSE_ATTACH \
5341 : | OMP_CLAUSE_DEFAULT)
5342 : #define OACC_LOOP_CLAUSES \
5343 : (omp_mask (OMP_CLAUSE_COLLAPSE) | OMP_CLAUSE_GANG | OMP_CLAUSE_WORKER \
5344 : | OMP_CLAUSE_VECTOR | OMP_CLAUSE_SEQ | OMP_CLAUSE_INDEPENDENT \
5345 : | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_AUTO \
5346 : | OMP_CLAUSE_TILE)
5347 : #define OACC_PARALLEL_LOOP_CLAUSES \
5348 : (OACC_LOOP_CLAUSES | OACC_PARALLEL_CLAUSES)
5349 : #define OACC_KERNELS_LOOP_CLAUSES \
5350 : (OACC_LOOP_CLAUSES | OACC_KERNELS_CLAUSES)
5351 : #define OACC_SERIAL_LOOP_CLAUSES \
5352 : (OACC_LOOP_CLAUSES | OACC_SERIAL_CLAUSES)
5353 : #define OACC_HOST_DATA_CLAUSES \
5354 : (omp_mask (OMP_CLAUSE_USE_DEVICE) \
5355 : | OMP_CLAUSE_IF \
5356 : | OMP_CLAUSE_IF_PRESENT)
5357 : #define OACC_DECLARE_CLAUSES \
5358 : (omp_mask (OMP_CLAUSE_COPY) | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT \
5359 : | OMP_CLAUSE_CREATE | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_DEVICE_RESIDENT \
5360 : | OMP_CLAUSE_PRESENT \
5361 : | OMP_CLAUSE_LINK)
5362 : #define OACC_UPDATE_CLAUSES \
5363 : (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_HOST \
5364 : | OMP_CLAUSE_DEVICE | OMP_CLAUSE_WAIT | OMP_CLAUSE_IF_PRESENT \
5365 : | OMP_CLAUSE_SELF)
5366 : #define OACC_ENTER_DATA_CLAUSES \
5367 : (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_WAIT \
5368 : | OMP_CLAUSE_COPYIN | OMP_CLAUSE_CREATE | OMP_CLAUSE_ATTACH)
5369 : #define OACC_EXIT_DATA_CLAUSES \
5370 : (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_WAIT \
5371 : | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_DELETE | OMP_CLAUSE_FINALIZE \
5372 : | OMP_CLAUSE_DETACH)
5373 : #define OACC_WAIT_CLAUSES \
5374 : omp_mask (OMP_CLAUSE_ASYNC) | OMP_CLAUSE_IF
5375 : #define OACC_ROUTINE_CLAUSES \
5376 : (omp_mask (OMP_CLAUSE_GANG) | OMP_CLAUSE_WORKER | OMP_CLAUSE_VECTOR \
5377 : | OMP_CLAUSE_SEQ \
5378 : | OMP_CLAUSE_NOHOST)
5379 : #define OACC_INIT_CLAUSES \
5380 : (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_DEVICE_NUM | OMP_CLAUSE_DEVICE_TYPE)
5381 : #define OACC_SHUTDOWN_CLAUSES \
5382 : (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_DEVICE_NUM | OMP_CLAUSE_DEVICE_TYPE)
5383 : #define OACC_SET_CLAUSES \
5384 : (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_DEVICE_NUM | OMP_CLAUSE_DEVICE_TYPE)
5385 :
5386 :
5387 : static match
5388 12198 : match_acc (gfc_exec_op op, const omp_mask mask)
5389 : {
5390 12198 : gfc_omp_clauses *c;
5391 12198 : if (gfc_match_omp_clauses (&c, mask, false, false, true) != MATCH_YES)
5392 : return MATCH_ERROR;
5393 11969 : new_st.op = op;
5394 11969 : new_st.ext.omp_clauses = c;
5395 11969 : return MATCH_YES;
5396 : }
5397 :
5398 : match
5399 1378 : gfc_match_oacc_parallel_loop (void)
5400 : {
5401 1378 : return match_acc (EXEC_OACC_PARALLEL_LOOP, OACC_PARALLEL_LOOP_CLAUSES);
5402 : }
5403 :
5404 :
5405 : match
5406 2974 : gfc_match_oacc_parallel (void)
5407 : {
5408 2974 : return match_acc (EXEC_OACC_PARALLEL, OACC_PARALLEL_CLAUSES);
5409 : }
5410 :
5411 :
5412 : match
5413 129 : gfc_match_oacc_kernels_loop (void)
5414 : {
5415 129 : return match_acc (EXEC_OACC_KERNELS_LOOP, OACC_KERNELS_LOOP_CLAUSES);
5416 : }
5417 :
5418 :
5419 : match
5420 906 : gfc_match_oacc_kernels (void)
5421 : {
5422 906 : return match_acc (EXEC_OACC_KERNELS, OACC_KERNELS_CLAUSES);
5423 : }
5424 :
5425 :
5426 : match
5427 230 : gfc_match_oacc_serial_loop (void)
5428 : {
5429 230 : return match_acc (EXEC_OACC_SERIAL_LOOP, OACC_SERIAL_LOOP_CLAUSES);
5430 : }
5431 :
5432 :
5433 : match
5434 359 : gfc_match_oacc_serial (void)
5435 : {
5436 359 : return match_acc (EXEC_OACC_SERIAL, OACC_SERIAL_CLAUSES);
5437 : }
5438 :
5439 :
5440 : match
5441 689 : gfc_match_oacc_data (void)
5442 : {
5443 689 : return match_acc (EXEC_OACC_DATA, OACC_DATA_CLAUSES);
5444 : }
5445 :
5446 :
5447 : match
5448 65 : gfc_match_oacc_host_data (void)
5449 : {
5450 65 : return match_acc (EXEC_OACC_HOST_DATA, OACC_HOST_DATA_CLAUSES);
5451 : }
5452 :
5453 :
5454 : match
5455 3585 : gfc_match_oacc_loop (void)
5456 : {
5457 3585 : return match_acc (EXEC_OACC_LOOP, OACC_LOOP_CLAUSES);
5458 : }
5459 :
5460 :
5461 : match
5462 178 : gfc_match_oacc_declare (void)
5463 : {
5464 178 : gfc_omp_clauses *c;
5465 178 : gfc_omp_namelist *n;
5466 178 : gfc_namespace *ns = gfc_current_ns;
5467 178 : gfc_oacc_declare *new_oc;
5468 178 : bool module_var = false;
5469 178 : locus where = gfc_current_locus;
5470 :
5471 178 : if (gfc_match_omp_clauses (&c, OACC_DECLARE_CLAUSES, false, false, true)
5472 : != MATCH_YES)
5473 : return MATCH_ERROR;
5474 :
5475 262 : for (n = c->lists[OMP_LIST_DEVICE_RESIDENT]; n != NULL; n = n->next)
5476 90 : n->sym->attr.oacc_declare_device_resident = 1;
5477 :
5478 192 : for (n = c->lists[OMP_LIST_LINK]; n != NULL; n = n->next)
5479 20 : n->sym->attr.oacc_declare_link = 1;
5480 :
5481 318 : for (n = c->lists[OMP_LIST_MAP]; n != NULL; n = n->next)
5482 : {
5483 156 : gfc_symbol *s = n->sym;
5484 :
5485 156 : if (gfc_current_ns->proc_name
5486 156 : && gfc_current_ns->proc_name->attr.flavor == FL_MODULE)
5487 : {
5488 52 : if (n->u.map.op != OMP_MAP_ALLOC && n->u.map.op != OMP_MAP_TO)
5489 : {
5490 6 : gfc_error ("Invalid clause in module with !$ACC DECLARE at %L",
5491 : &where);
5492 6 : return MATCH_ERROR;
5493 : }
5494 :
5495 : module_var = true;
5496 : }
5497 :
5498 150 : if (s->attr.use_assoc)
5499 : {
5500 0 : gfc_error ("Variable is USE-associated with !$ACC DECLARE at %L",
5501 : &where);
5502 0 : return MATCH_ERROR;
5503 : }
5504 :
5505 150 : if ((s->result == s && s->ns->contained != gfc_current_ns)
5506 150 : || ((s->attr.flavor == FL_UNKNOWN || s->attr.flavor == FL_VARIABLE)
5507 135 : && s->ns != gfc_current_ns))
5508 : {
5509 2 : gfc_error ("Variable %qs shall be declared in the same scoping unit "
5510 : "as !$ACC DECLARE at %L", s->name, &where);
5511 2 : return MATCH_ERROR;
5512 : }
5513 :
5514 148 : if ((s->attr.dimension || s->attr.codimension)
5515 76 : && s->attr.dummy && s->as->type != AS_EXPLICIT)
5516 : {
5517 2 : gfc_error ("Assumed-size dummy array with !$ACC DECLARE at %L",
5518 : &where);
5519 2 : return MATCH_ERROR;
5520 : }
5521 :
5522 146 : switch (n->u.map.op)
5523 : {
5524 49 : case OMP_MAP_FORCE_ALLOC:
5525 49 : case OMP_MAP_ALLOC:
5526 49 : s->attr.oacc_declare_create = 1;
5527 49 : break;
5528 :
5529 63 : case OMP_MAP_FORCE_TO:
5530 63 : case OMP_MAP_TO:
5531 63 : s->attr.oacc_declare_copyin = 1;
5532 63 : break;
5533 :
5534 1 : case OMP_MAP_FORCE_DEVICEPTR:
5535 1 : s->attr.oacc_declare_deviceptr = 1;
5536 1 : break;
5537 :
5538 : default:
5539 : break;
5540 : }
5541 : }
5542 :
5543 162 : new_oc = gfc_get_oacc_declare ();
5544 162 : new_oc->next = ns->oacc_declare;
5545 162 : new_oc->module_var = module_var;
5546 162 : new_oc->clauses = c;
5547 162 : new_oc->loc = gfc_current_locus;
5548 162 : ns->oacc_declare = new_oc;
5549 :
5550 162 : return MATCH_YES;
5551 : }
5552 :
5553 :
5554 : match
5555 760 : gfc_match_oacc_update (void)
5556 : {
5557 760 : gfc_omp_clauses *c;
5558 760 : locus here = gfc_current_locus;
5559 :
5560 760 : if (gfc_match_omp_clauses (&c, OACC_UPDATE_CLAUSES, false, false, true)
5561 : != MATCH_YES)
5562 : return MATCH_ERROR;
5563 :
5564 756 : if (!c->lists[OMP_LIST_MAP])
5565 : {
5566 1 : gfc_error ("%<acc update%> must contain at least one "
5567 : "%<device%> or %<host%> or %<self%> clause at %L", &here);
5568 1 : return MATCH_ERROR;
5569 : }
5570 :
5571 755 : new_st.op = EXEC_OACC_UPDATE;
5572 755 : new_st.ext.omp_clauses = c;
5573 755 : return MATCH_YES;
5574 : }
5575 :
5576 :
5577 : match
5578 877 : gfc_match_oacc_enter_data (void)
5579 : {
5580 877 : return match_acc (EXEC_OACC_ENTER_DATA, OACC_ENTER_DATA_CLAUSES);
5581 : }
5582 :
5583 :
5584 : match
5585 612 : gfc_match_oacc_exit_data (void)
5586 : {
5587 612 : return match_acc (EXEC_OACC_EXIT_DATA, OACC_EXIT_DATA_CLAUSES);
5588 : }
5589 :
5590 :
5591 : match
5592 202 : gfc_match_oacc_wait (void)
5593 : {
5594 202 : gfc_omp_clauses *c = gfc_get_omp_clauses ();
5595 202 : gfc_expr_list *wait_list = NULL, *el;
5596 202 : bool space = true;
5597 202 : match m;
5598 :
5599 202 : m = match_omp_oacc_expr_list (" (", &wait_list, true, false);
5600 202 : if (m == MATCH_ERROR)
5601 : return m;
5602 196 : else if (m == MATCH_YES)
5603 126 : space = false;
5604 :
5605 196 : if (gfc_match_omp_clauses (&c, OACC_WAIT_CLAUSES, space, space, true)
5606 : == MATCH_ERROR)
5607 : return MATCH_ERROR;
5608 :
5609 184 : if (wait_list)
5610 261 : for (el = wait_list; el; el = el->next)
5611 : {
5612 140 : if (el->expr == NULL)
5613 : {
5614 2 : gfc_error ("Invalid argument to !$ACC WAIT at %C");
5615 2 : return MATCH_ERROR;
5616 : }
5617 :
5618 138 : if (!gfc_resolve_expr (el->expr)
5619 138 : || el->expr->ts.type != BT_INTEGER || el->expr->rank != 0)
5620 : {
5621 3 : gfc_error ("WAIT clause at %L requires a scalar INTEGER expression",
5622 3 : &el->expr->where);
5623 :
5624 3 : return MATCH_ERROR;
5625 : }
5626 : }
5627 179 : c->wait_list = wait_list;
5628 179 : new_st.op = EXEC_OACC_WAIT;
5629 179 : new_st.ext.omp_clauses = c;
5630 179 : return MATCH_YES;
5631 : }
5632 :
5633 :
5634 : match
5635 97 : gfc_match_oacc_cache (void)
5636 : {
5637 97 : bool readonly = false;
5638 97 : gfc_omp_clauses *c = gfc_get_omp_clauses ();
5639 : /* The OpenACC cache directive explicitly only allows "array elements or
5640 : subarrays", which we're currently not checking here. Either check this
5641 : after the call of gfc_match_omp_variable_list, or add something like a
5642 : only_sections variant next to its allow_sections parameter. */
5643 97 : match m = gfc_match (" ( ");
5644 97 : if (m != MATCH_YES)
5645 : {
5646 0 : gfc_free_omp_clauses(c);
5647 0 : return m;
5648 : }
5649 :
5650 97 : if (gfc_match ("readonly : ") == MATCH_YES)
5651 8 : readonly = true;
5652 :
5653 97 : gfc_omp_namelist **head = NULL;
5654 97 : m = gfc_match_omp_variable_list ("", &c->lists[OMP_LIST_CACHE], true,
5655 : NULL, &head, true);
5656 97 : if (m != MATCH_YES)
5657 : {
5658 2 : gfc_free_omp_clauses(c);
5659 2 : return m;
5660 : }
5661 :
5662 95 : if (readonly)
5663 24 : for (gfc_omp_namelist *n = *head; n; n = n->next)
5664 16 : n->u.map.readonly = true;
5665 :
5666 95 : if (gfc_current_state() != COMP_DO
5667 56 : && gfc_current_state() != COMP_DO_CONCURRENT)
5668 : {
5669 2 : gfc_error ("ACC CACHE directive must be inside of loop %C");
5670 2 : gfc_free_omp_clauses(c);
5671 2 : return MATCH_ERROR;
5672 : }
5673 :
5674 93 : new_st.op = EXEC_OACC_CACHE;
5675 93 : new_st.ext.omp_clauses = c;
5676 93 : return MATCH_YES;
5677 : }
5678 :
5679 : match
5680 134 : gfc_match_oacc_init (void)
5681 : {
5682 134 : return match_acc (EXEC_OACC_INIT, OACC_INIT_CLAUSES);
5683 : }
5684 :
5685 : match
5686 130 : gfc_match_oacc_shutdown (void)
5687 : {
5688 130 : return match_acc (EXEC_OACC_SHUTDOWN, OACC_SHUTDOWN_CLAUSES);
5689 : }
5690 :
5691 : match
5692 130 : gfc_match_oacc_set (void)
5693 : {
5694 130 : return match_acc (EXEC_OACC_SET, OACC_SET_CLAUSES);
5695 : }
5696 :
5697 : /* Determine the OpenACC 'routine' directive's level of parallelism. */
5698 :
5699 : static oacc_routine_lop
5700 734 : gfc_oacc_routine_lop (gfc_omp_clauses *clauses)
5701 : {
5702 734 : oacc_routine_lop ret = OACC_ROUTINE_LOP_SEQ;
5703 :
5704 734 : if (clauses)
5705 : {
5706 584 : unsigned n_lop_clauses = 0;
5707 :
5708 584 : if (clauses->gang)
5709 : {
5710 164 : ++n_lop_clauses;
5711 164 : ret = OACC_ROUTINE_LOP_GANG;
5712 : }
5713 584 : if (clauses->worker)
5714 : {
5715 114 : ++n_lop_clauses;
5716 114 : ret = OACC_ROUTINE_LOP_WORKER;
5717 : }
5718 584 : if (clauses->vector)
5719 : {
5720 116 : ++n_lop_clauses;
5721 116 : ret = OACC_ROUTINE_LOP_VECTOR;
5722 : }
5723 584 : if (clauses->seq)
5724 : {
5725 206 : ++n_lop_clauses;
5726 206 : ret = OACC_ROUTINE_LOP_SEQ;
5727 : }
5728 :
5729 584 : if (n_lop_clauses > 1)
5730 47 : ret = OACC_ROUTINE_LOP_ERROR;
5731 : }
5732 :
5733 734 : return ret;
5734 : }
5735 :
5736 : match
5737 698 : gfc_match_oacc_routine (void)
5738 : {
5739 698 : locus old_loc;
5740 698 : match m;
5741 698 : gfc_intrinsic_sym *isym = NULL;
5742 698 : gfc_symbol *sym = NULL;
5743 698 : gfc_omp_clauses *c = NULL;
5744 698 : gfc_oacc_routine_name *n = NULL;
5745 698 : oacc_routine_lop lop = OACC_ROUTINE_LOP_NONE;
5746 698 : bool nohost;
5747 :
5748 698 : old_loc = gfc_current_locus;
5749 :
5750 698 : m = gfc_match (" (");
5751 :
5752 698 : if (gfc_current_ns->proc_name
5753 696 : && gfc_current_ns->proc_name->attr.if_source == IFSRC_IFBODY
5754 90 : && m == MATCH_YES)
5755 : {
5756 3 : gfc_error ("Only the !$ACC ROUTINE form without "
5757 : "list is allowed in interface block at %C");
5758 3 : goto cleanup;
5759 : }
5760 :
5761 608 : if (m == MATCH_YES)
5762 : {
5763 295 : char buffer[GFC_MAX_SYMBOL_LEN + 1];
5764 :
5765 295 : m = gfc_match_name (buffer);
5766 295 : if (m == MATCH_YES)
5767 : {
5768 294 : gfc_symtree *st = NULL;
5769 :
5770 : /* First look for an intrinsic symbol. */
5771 294 : isym = gfc_find_function (buffer);
5772 294 : if (!isym)
5773 294 : isym = gfc_find_subroutine (buffer);
5774 : /* If no intrinsic symbol found, search the current namespace. */
5775 294 : if (!isym)
5776 276 : st = gfc_find_symtree (gfc_current_ns->sym_root, buffer);
5777 276 : if (st)
5778 : {
5779 270 : sym = st->n.sym;
5780 : /* If the name in a 'routine' directive refers to the containing
5781 : subroutine or function, then make sure that we'll later handle
5782 : this accordingly. */
5783 270 : if (gfc_current_ns->proc_name != NULL
5784 270 : && strcmp (sym->name, gfc_current_ns->proc_name->name) == 0)
5785 294 : sym = NULL;
5786 : }
5787 :
5788 294 : if (isym == NULL && st == NULL)
5789 : {
5790 6 : gfc_error ("Invalid NAME %qs in !$ACC ROUTINE ( NAME ) at %C",
5791 : buffer);
5792 6 : gfc_current_locus = old_loc;
5793 9 : return MATCH_ERROR;
5794 : }
5795 : }
5796 : else
5797 : {
5798 1 : gfc_error ("Syntax error in !$ACC ROUTINE ( NAME ) at %C");
5799 1 : gfc_current_locus = old_loc;
5800 1 : return MATCH_ERROR;
5801 : }
5802 :
5803 288 : if (gfc_match_char (')') != MATCH_YES)
5804 : {
5805 2 : gfc_error ("Syntax error in !$ACC ROUTINE ( NAME ) at %C, expecting"
5806 : " %<)%> after NAME");
5807 2 : gfc_current_locus = old_loc;
5808 2 : return MATCH_ERROR;
5809 : }
5810 : }
5811 :
5812 686 : if (gfc_match_omp_eos () != MATCH_YES
5813 686 : && (gfc_match_omp_clauses (&c, OACC_ROUTINE_CLAUSES, false, false, true)
5814 : != MATCH_YES))
5815 : return MATCH_ERROR;
5816 :
5817 683 : lop = gfc_oacc_routine_lop (c);
5818 683 : if (lop == OACC_ROUTINE_LOP_ERROR)
5819 : {
5820 47 : gfc_error ("Multiple loop axes specified for routine at %C");
5821 47 : goto cleanup;
5822 : }
5823 636 : nohost = c ? c->nohost : false;
5824 :
5825 636 : if (isym != NULL)
5826 : {
5827 : /* Diagnose any OpenACC 'routine' directive that doesn't match the
5828 : (implicit) one with a 'seq' clause. */
5829 16 : if (c && (c->gang || c->worker || c->vector))
5830 : {
5831 10 : gfc_error ("Intrinsic symbol specified in !$ACC ROUTINE ( NAME )"
5832 : " at %C marked with incompatible GANG, WORKER, or VECTOR"
5833 : " clause");
5834 10 : goto cleanup;
5835 : }
5836 : /* ..., and no 'nohost' clause. */
5837 6 : if (nohost)
5838 : {
5839 2 : gfc_error ("Intrinsic symbol specified in !$ACC ROUTINE ( NAME )"
5840 : " at %C marked with incompatible NOHOST clause");
5841 2 : goto cleanup;
5842 : }
5843 : }
5844 620 : else if (sym != NULL)
5845 : {
5846 151 : bool add = true;
5847 :
5848 : /* For a repeated OpenACC 'routine' directive, diagnose if it doesn't
5849 : match the first one. */
5850 151 : for (gfc_oacc_routine_name *n_p = gfc_current_ns->oacc_routine_names;
5851 346 : n_p;
5852 195 : n_p = n_p->next)
5853 235 : if (n_p->sym == sym)
5854 : {
5855 51 : add = false;
5856 51 : bool nohost_p = n_p->clauses ? n_p->clauses->nohost : false;
5857 51 : if (lop != gfc_oacc_routine_lop (n_p->clauses)
5858 51 : || nohost != nohost_p)
5859 : {
5860 40 : gfc_error ("!$ACC ROUTINE already applied at %C");
5861 40 : goto cleanup;
5862 : }
5863 : }
5864 :
5865 111 : if (add)
5866 : {
5867 100 : sym->attr.oacc_routine_lop = lop;
5868 100 : sym->attr.oacc_routine_nohost = nohost;
5869 :
5870 100 : n = gfc_get_oacc_routine_name ();
5871 100 : n->sym = sym;
5872 100 : n->clauses = c;
5873 100 : n->next = gfc_current_ns->oacc_routine_names;
5874 100 : n->loc = old_loc;
5875 100 : gfc_current_ns->oacc_routine_names = n;
5876 : }
5877 : }
5878 469 : else if (gfc_current_ns->proc_name)
5879 : {
5880 : /* For a repeated OpenACC 'routine' directive, diagnose if it doesn't
5881 : match the first one. */
5882 468 : oacc_routine_lop lop_p = gfc_current_ns->proc_name->attr.oacc_routine_lop;
5883 468 : bool nohost_p = gfc_current_ns->proc_name->attr.oacc_routine_nohost;
5884 468 : if (lop_p != OACC_ROUTINE_LOP_NONE
5885 86 : && (lop != lop_p
5886 86 : || nohost != nohost_p))
5887 : {
5888 56 : gfc_error ("!$ACC ROUTINE already applied at %C");
5889 56 : goto cleanup;
5890 : }
5891 :
5892 412 : if (!gfc_add_omp_declare_target (&gfc_current_ns->proc_name->attr,
5893 : gfc_current_ns->proc_name->name,
5894 : &old_loc))
5895 1 : goto cleanup;
5896 411 : gfc_current_ns->proc_name->attr.oacc_routine_lop = lop;
5897 411 : gfc_current_ns->proc_name->attr.oacc_routine_nohost = nohost;
5898 : }
5899 : else
5900 : /* Something has gone wrong, possibly a syntax error. */
5901 1 : goto cleanup;
5902 :
5903 526 : if (gfc_pure (NULL) && c && (c->gang || c->worker || c->vector))
5904 : {
5905 6 : gfc_error ("!$ACC ROUTINE with GANG, WORKER, or VECTOR clause is not "
5906 : "permitted in PURE procedure at %C");
5907 6 : goto cleanup;
5908 : }
5909 :
5910 :
5911 520 : if (n)
5912 100 : n->clauses = c;
5913 420 : else if (gfc_current_ns->oacc_routine)
5914 0 : gfc_current_ns->oacc_routine_clauses = c;
5915 :
5916 520 : new_st.op = EXEC_OACC_ROUTINE;
5917 520 : new_st.ext.omp_clauses = c;
5918 520 : return MATCH_YES;
5919 :
5920 166 : cleanup:
5921 166 : gfc_current_locus = old_loc;
5922 166 : return MATCH_ERROR;
5923 : }
5924 :
5925 :
5926 : #define OMP_PARALLEL_CLAUSES \
5927 : (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
5928 : | OMP_CLAUSE_SHARED | OMP_CLAUSE_COPYIN | OMP_CLAUSE_REDUCTION \
5929 : | OMP_CLAUSE_IF | OMP_CLAUSE_NUM_THREADS | OMP_CLAUSE_DEFAULT \
5930 : | OMP_CLAUSE_PROC_BIND | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_MESSAGE \
5931 : | OMP_CLAUSE_SEVERITY)
5932 : #define OMP_DECLARE_SIMD_CLAUSES \
5933 : (omp_mask (OMP_CLAUSE_SIMDLEN) | OMP_CLAUSE_LINEAR \
5934 : | OMP_CLAUSE_UNIFORM | OMP_CLAUSE_ALIGNED | OMP_CLAUSE_INBRANCH \
5935 : | OMP_CLAUSE_NOTINBRANCH)
5936 : #define OMP_DO_CLAUSES \
5937 : (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
5938 : | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION \
5939 : | OMP_CLAUSE_SCHEDULE | OMP_CLAUSE_ORDERED | OMP_CLAUSE_COLLAPSE \
5940 : | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ORDER | OMP_CLAUSE_ALLOCATE \
5941 : | OMP_CLAUSE_NOWAIT)
5942 : #define OMP_LOOP_CLAUSES \
5943 : (omp_mask (OMP_CLAUSE_BIND) | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_ORDER \
5944 : | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION)
5945 :
5946 : #define OMP_SCOPE_CLAUSES \
5947 : (omp_mask (OMP_CLAUSE_PRIVATE) |OMP_CLAUSE_FIRSTPRIVATE \
5948 : | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT)
5949 : #define OMP_SECTIONS_CLAUSES \
5950 : (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
5951 : | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION \
5952 : | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT)
5953 : #define OMP_SIMD_CLAUSES \
5954 : (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_LASTPRIVATE \
5955 : | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_SAFELEN \
5956 : | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ALIGNED | OMP_CLAUSE_SIMDLEN \
5957 : | OMP_CLAUSE_IF | OMP_CLAUSE_ORDER | OMP_CLAUSE_NOTEMPORAL)
5958 : #define OMP_TASK_CLAUSES \
5959 : (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
5960 : | OMP_CLAUSE_SHARED | OMP_CLAUSE_IF | OMP_CLAUSE_DEFAULT \
5961 : | OMP_CLAUSE_UNTIED | OMP_CLAUSE_FINAL | OMP_CLAUSE_MERGEABLE \
5962 : | OMP_CLAUSE_DEPEND | OMP_CLAUSE_PRIORITY | OMP_CLAUSE_IN_REDUCTION \
5963 : | OMP_CLAUSE_DETACH | OMP_CLAUSE_AFFINITY | OMP_CLAUSE_ALLOCATE)
5964 : #define OMP_TASKLOOP_CLAUSES \
5965 : (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
5966 : | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_IF \
5967 : | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_UNTIED | OMP_CLAUSE_FINAL \
5968 : | OMP_CLAUSE_MERGEABLE | OMP_CLAUSE_PRIORITY | OMP_CLAUSE_GRAINSIZE \
5969 : | OMP_CLAUSE_NUM_TASKS | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_NOGROUP \
5970 : | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_IN_REDUCTION | OMP_CLAUSE_ALLOCATE)
5971 : #define OMP_TASKGROUP_CLAUSES \
5972 : (omp_mask (OMP_CLAUSE_TASK_REDUCTION) | OMP_CLAUSE_ALLOCATE)
5973 : #define OMP_TARGET_CLAUSES \
5974 : (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF \
5975 : | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_PRIVATE \
5976 : | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_DEFAULTMAP \
5977 : | OMP_CLAUSE_IS_DEVICE_PTR | OMP_CLAUSE_IN_REDUCTION \
5978 : | OMP_CLAUSE_THREAD_LIMIT | OMP_CLAUSE_ALLOCATE \
5979 : | OMP_CLAUSE_HAS_DEVICE_ADDR | OMP_CLAUSE_USES_ALLOCATORS \
5980 : | OMP_CLAUSE_DYN_GROUPPRIVATE | OMP_CLAUSE_DEVICE_TYPE \
5981 : | OMP_CLAUSE_MESSAGE)
5982 : #define OMP_TARGET_DATA_CLAUSES \
5983 : (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF \
5984 : | OMP_CLAUSE_USE_DEVICE_PTR | OMP_CLAUSE_USE_DEVICE_ADDR)
5985 : #define OMP_TARGET_ENTER_DATA_CLAUSES \
5986 : (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF \
5987 : | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT)
5988 : #define OMP_TARGET_EXIT_DATA_CLAUSES \
5989 : (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF \
5990 : | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT)
5991 : #define OMP_TARGET_UPDATE_CLAUSES \
5992 : (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_IF | OMP_CLAUSE_TO \
5993 : | OMP_CLAUSE_FROM | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT)
5994 : #define OMP_TEAMS_CLAUSES \
5995 : (omp_mask (OMP_CLAUSE_NUM_TEAMS) | OMP_CLAUSE_THREAD_LIMIT \
5996 : | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE \
5997 : | OMP_CLAUSE_SHARED | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_ALLOCATE \
5998 : | OMP_CLAUSE_MESSAGE)
5999 : #define OMP_DISTRIBUTE_CLAUSES \
6000 : (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
6001 : | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_DIST_SCHEDULE \
6002 : | OMP_CLAUSE_ORDER | OMP_CLAUSE_ALLOCATE)
6003 : #define OMP_SINGLE_CLAUSES \
6004 : (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
6005 : | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_COPYPRIVATE)
6006 : #define OMP_ORDERED_CLAUSES \
6007 : (omp_mask (OMP_CLAUSE_THREADS) | OMP_CLAUSE_SIMD)
6008 : #define OMP_DECLARE_TARGET_CLAUSES \
6009 : (omp_mask (OMP_CLAUSE_ENTER) | OMP_CLAUSE_LINK | OMP_CLAUSE_DEVICE_TYPE \
6010 : | OMP_CLAUSE_TO | OMP_CLAUSE_INDIRECT | OMP_CLAUSE_LOCAL)
6011 : #define OMP_ATOMIC_CLAUSES \
6012 : (omp_mask (OMP_CLAUSE_ATOMIC) | OMP_CLAUSE_CAPTURE | OMP_CLAUSE_HINT \
6013 : | OMP_CLAUSE_MEMORDER | OMP_CLAUSE_COMPARE | OMP_CLAUSE_FAIL \
6014 : | OMP_CLAUSE_WEAK)
6015 : #define OMP_MASKED_CLAUSES \
6016 : (omp_mask (OMP_CLAUSE_FILTER))
6017 : #define OMP_ERROR_CLAUSES \
6018 : (omp_mask (OMP_CLAUSE_AT) | OMP_CLAUSE_MESSAGE | OMP_CLAUSE_SEVERITY)
6019 : #define OMP_WORKSHARE_CLAUSES \
6020 : omp_mask (OMP_CLAUSE_NOWAIT)
6021 : #define OMP_UNROLL_CLAUSES \
6022 : (omp_mask (OMP_CLAUSE_FULL) | OMP_CLAUSE_PARTIAL)
6023 : #define OMP_TILE_CLAUSES \
6024 : (omp_mask (OMP_CLAUSE_SIZES))
6025 : #define OMP_ALLOCATORS_CLAUSES \
6026 : omp_mask (OMP_CLAUSE_ALLOCATE)
6027 : #define OMP_INTEROP_CLAUSES \
6028 : (omp_mask (OMP_CLAUSE_DEPEND) | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_DEVICE \
6029 : | OMP_CLAUSE_INIT | OMP_CLAUSE_DESTROY | OMP_CLAUSE_USE)
6030 : #define OMP_DISPATCH_CLAUSES \
6031 : (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOVARIANTS \
6032 : | OMP_CLAUSE_NOCONTEXT | OMP_CLAUSE_IS_DEVICE_PTR | OMP_CLAUSE_NOWAIT \
6033 : | OMP_CLAUSE_HAS_DEVICE_ADDR | OMP_CLAUSE_INTEROP)
6034 :
6035 :
6036 : static match
6037 17433 : match_omp (gfc_exec_op op, const omp_mask mask)
6038 : {
6039 17433 : gfc_omp_clauses *c;
6040 17433 : if (gfc_match_omp_clauses (&c, mask, false, true, false,
6041 : op == EXEC_OMP_TARGET) != MATCH_YES)
6042 : return MATCH_ERROR;
6043 17075 : new_st.op = op;
6044 17075 : new_st.ext.omp_clauses = c;
6045 17075 : return MATCH_YES;
6046 : }
6047 :
6048 : /* Handles both declarative and (deprecated) executable ALLOCATE directive;
6049 : accepts optional list (for executable) and common blocks.
6050 : If no variables have been provided, the single omp namelist has sym == NULL.
6051 :
6052 : Note that the executable ALLOCATE directive permits structure elements only
6053 : in OpenMP 5.0 and 5.1 but not longer in 5.2. See also the comment on the
6054 : 'omp allocators' directive below. The accidental change was reverted for
6055 : OpenMP TR12, permitting them again. See also gfc_match_omp_allocators.
6056 :
6057 : Hence, structure elements are rejected for now, also to make resolving
6058 : OMP_LIST_ALLOCATE simpler (check for duplicates, same symbol in
6059 : Fortran allocate stmt). TODO: Permit structure elements. */
6060 :
6061 : match
6062 274 : gfc_match_omp_allocate (void)
6063 : {
6064 274 : match m;
6065 274 : gfc_omp_namelist *vars = NULL;
6066 274 : gfc_expr *align = NULL;
6067 274 : gfc_expr *allocator = NULL;
6068 274 : locus loc = gfc_current_locus;
6069 :
6070 274 : m = gfc_match_omp_variable_list (" (", &vars, true, NULL, NULL, true, true,
6071 : NULL, true);
6072 :
6073 274 : if (m == MATCH_ERROR)
6074 : return m;
6075 :
6076 502 : while (true)
6077 : {
6078 502 : gfc_gobble_whitespace ();
6079 502 : if (gfc_match_omp_eos () == MATCH_YES)
6080 : break;
6081 234 : gfc_match (", "); /* optionally */
6082 234 : if ((m = gfc_match_dupl_check (!align, "align", true, &align))
6083 : != MATCH_NO)
6084 : {
6085 62 : if (m == MATCH_ERROR)
6086 1 : goto error;
6087 61 : continue;
6088 : }
6089 172 : if ((m = gfc_match_dupl_check (!allocator, "allocator",
6090 : true, &allocator)) != MATCH_NO)
6091 : {
6092 171 : if (m == MATCH_ERROR)
6093 1 : goto error;
6094 170 : continue;
6095 : }
6096 1 : gfc_error ("Expected ALIGN or ALLOCATOR clause at %C");
6097 1 : return MATCH_ERROR;
6098 : }
6099 541 : for (gfc_omp_namelist *n = vars; n; n = n->next)
6100 276 : if (n->expr)
6101 : {
6102 3 : if ((n->expr->ref && n->expr->ref->type == REF_COMPONENT)
6103 3 : || (n->expr->ref->next && n->expr->ref->type == REF_COMPONENT))
6104 1 : gfc_error ("Sorry, structure-element list item at %L in ALLOCATE "
6105 : "directive is not yet supported", &n->expr->where);
6106 : else
6107 2 : gfc_error ("Unexpected expression as list item at %L in ALLOCATE "
6108 : "directive", &n->expr->where);
6109 :
6110 3 : gfc_free_omp_namelist (vars, OMP_LIST_ALLOCATE);
6111 3 : goto error;
6112 : }
6113 :
6114 265 : new_st.op = EXEC_OMP_ALLOCATE;
6115 265 : new_st.ext.omp_clauses = gfc_get_omp_clauses ();
6116 265 : if (vars == NULL)
6117 : {
6118 27 : vars = gfc_get_omp_namelist ();
6119 27 : vars->where = loc;
6120 27 : vars->u.align = align;
6121 27 : vars->u2.allocator = allocator;
6122 27 : new_st.ext.omp_clauses->lists[OMP_LIST_ALLOCATE] = vars;
6123 : }
6124 : else
6125 : {
6126 238 : new_st.ext.omp_clauses->lists[OMP_LIST_ALLOCATE] = vars;
6127 511 : for (; vars; vars = vars->next)
6128 : {
6129 273 : vars->u.align = (align) ? gfc_copy_expr (align) : NULL;
6130 273 : vars->u2.allocator = allocator;
6131 : }
6132 238 : gfc_free_expr (align);
6133 : }
6134 : return MATCH_YES;
6135 :
6136 5 : error:
6137 5 : gfc_free_expr (align);
6138 5 : gfc_free_expr (allocator);
6139 5 : return MATCH_ERROR;
6140 : }
6141 :
6142 : /* In line with OpenMP 5.2 derived-type components are rejected.
6143 : See also comment before gfc_match_omp_allocate. */
6144 :
6145 : match
6146 26 : gfc_match_omp_allocators (void)
6147 : {
6148 26 : return match_omp (EXEC_OMP_ALLOCATORS, OMP_ALLOCATORS_CLAUSES);
6149 : }
6150 :
6151 :
6152 : match
6153 25 : gfc_match_omp_assume (void)
6154 : {
6155 25 : gfc_omp_clauses *c;
6156 25 : locus loc = gfc_current_locus;
6157 32 : if ((gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_ASSUMPTIONS), false)
6158 : != MATCH_YES)
6159 25 : || (omp_verify_merge_absent_contains (ST_OMP_ASSUME, c->assume, NULL,
6160 : &loc) != MATCH_YES))
6161 : return MATCH_ERROR;
6162 18 : new_st.op = EXEC_OMP_ASSUME;
6163 18 : new_st.ext.omp_clauses = c;
6164 18 : return MATCH_YES;
6165 : }
6166 :
6167 :
6168 : match
6169 38 : gfc_match_omp_assumes (void)
6170 : {
6171 38 : gfc_omp_clauses *c;
6172 38 : locus loc = gfc_current_locus;
6173 38 : if (!gfc_current_ns->proc_name
6174 37 : || (gfc_current_ns->proc_name->attr.flavor != FL_MODULE
6175 23 : && !gfc_current_ns->proc_name->attr.subroutine
6176 10 : && !gfc_current_ns->proc_name->attr.function))
6177 : {
6178 2 : gfc_error ("!$OMP ASSUMES at %C must be in the specification part of a "
6179 : "subprogram or module");
6180 2 : return MATCH_ERROR;
6181 : }
6182 46 : if ((gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_ASSUMPTIONS), false)
6183 : != MATCH_YES)
6184 65 : || (omp_verify_merge_absent_contains (ST_OMP_ASSUMES, c->assume,
6185 29 : gfc_current_ns->omp_assumes, &loc)
6186 : != MATCH_YES))
6187 : return MATCH_ERROR;
6188 26 : if (gfc_current_ns->omp_assumes == NULL)
6189 : {
6190 23 : gfc_current_ns->omp_assumes = c->assume;
6191 23 : c->assume = NULL;
6192 : }
6193 3 : else if (gfc_current_ns->omp_assumes && c->assume)
6194 : {
6195 3 : gfc_current_ns->omp_assumes->no_openmp |= c->assume->no_openmp;
6196 3 : gfc_current_ns->omp_assumes->no_openmp_routines
6197 3 : |= c->assume->no_openmp_routines;
6198 3 : gfc_current_ns->omp_assumes->no_openmp_constructs
6199 3 : |= c->assume->no_openmp_constructs;
6200 3 : gfc_current_ns->omp_assumes->no_parallelism |= c->assume->no_parallelism;
6201 3 : if (gfc_current_ns->omp_assumes->holds && c->assume->holds)
6202 : {
6203 : gfc_expr_list *el = gfc_current_ns->omp_assumes->holds;
6204 1 : for ( ; el->next ; el = el->next)
6205 : ;
6206 1 : el->next = c->assume->holds;
6207 1 : }
6208 2 : else if (c->assume->holds)
6209 1 : gfc_current_ns->omp_assumes->holds = c->assume->holds;
6210 3 : c->assume->holds = NULL;
6211 : }
6212 26 : gfc_free_omp_clauses (c);
6213 26 : return MATCH_YES;
6214 : }
6215 :
6216 :
6217 : match
6218 168 : gfc_match_omp_critical (void)
6219 : {
6220 168 : char n[GFC_MAX_SYMBOL_LEN+1];
6221 168 : gfc_omp_clauses *c = NULL;
6222 :
6223 168 : if (gfc_match (" ( %n )", n) != MATCH_YES)
6224 117 : n[0] = '\0';
6225 :
6226 168 : if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_HINT), false,
6227 168 : /* needs_space = */ n[0] == '\0') != MATCH_YES)
6228 : return MATCH_ERROR;
6229 :
6230 166 : new_st.op = EXEC_OMP_CRITICAL;
6231 166 : new_st.ext.omp_clauses = c;
6232 166 : if (n[0])
6233 51 : c->critical_name = xstrdup (n);
6234 : return MATCH_YES;
6235 : }
6236 :
6237 :
6238 : match
6239 166 : gfc_match_omp_end_critical (void)
6240 : {
6241 166 : char n[GFC_MAX_SYMBOL_LEN+1];
6242 :
6243 166 : if (gfc_match (" ( %n )", n) != MATCH_YES)
6244 115 : n[0] = '\0';
6245 166 : if (gfc_match_omp_eos () != MATCH_YES)
6246 : {
6247 1 : gfc_error ("Unexpected junk after $OMP CRITICAL statement at %C");
6248 1 : return MATCH_ERROR;
6249 : }
6250 :
6251 165 : new_st.op = EXEC_OMP_END_CRITICAL;
6252 165 : new_st.ext.omp_name = n[0] ? xstrdup (n) : NULL;
6253 165 : return MATCH_YES;
6254 : }
6255 :
6256 : /* depobj(depobj) depend(dep-type:loc)|destroy|update(dep-type)
6257 : dep-type = in/out/inout/mutexinoutset/depobj/source/sink
6258 : depend: !source, !sink
6259 : update: !source, !sink, !depobj
6260 : locator = exactly one list item .*/
6261 : match
6262 128 : gfc_match_omp_depobj (void)
6263 : {
6264 128 : gfc_omp_clauses *c = NULL;
6265 128 : gfc_expr *depobj;
6266 :
6267 128 : if (gfc_match (" ( %v ) ", &depobj) != MATCH_YES)
6268 : {
6269 2 : gfc_error ("Expected %<( depobj )%> at %C");
6270 2 : return MATCH_ERROR;
6271 : }
6272 126 : gfc_match (", "); /* optionally */
6273 126 : if (gfc_match ("update ( ") == MATCH_YES)
6274 : {
6275 12 : c = gfc_get_omp_clauses ();
6276 12 : if (gfc_match ("inoutset )") == MATCH_YES)
6277 2 : c->depobj_update = OMP_DEPEND_INOUTSET;
6278 10 : else if (gfc_match ("inout )") == MATCH_YES)
6279 1 : c->depobj_update = OMP_DEPEND_INOUT;
6280 9 : else if (gfc_match ("in )") == MATCH_YES)
6281 2 : c->depobj_update = OMP_DEPEND_IN;
6282 7 : else if (gfc_match ("out )") == MATCH_YES)
6283 2 : c->depobj_update = OMP_DEPEND_OUT;
6284 5 : else if (gfc_match ("mutexinoutset )") == MATCH_YES)
6285 2 : c->depobj_update = OMP_DEPEND_MUTEXINOUTSET;
6286 : else
6287 : {
6288 3 : gfc_error ("Expected IN, OUT, INOUT, INOUTSET or MUTEXINOUTSET "
6289 : "followed by %<)%> at %C");
6290 3 : goto error;
6291 : }
6292 : }
6293 114 : else if (gfc_match ("destroy ") == MATCH_YES)
6294 : {
6295 18 : gfc_expr *destroyobj = NULL;
6296 18 : c = gfc_get_omp_clauses ();
6297 18 : c->destroy = true;
6298 :
6299 18 : if (gfc_match (" ( %v ) ", &destroyobj) == MATCH_YES)
6300 : {
6301 3 : if (destroyobj->symtree != depobj->symtree)
6302 2 : gfc_warning (OPT_Wopenmp, "The same depend object should be used as"
6303 : " DEPOBJ argument at %L and as DESTROY argument at %L",
6304 : &depobj->where, &destroyobj->where);
6305 3 : gfc_free_expr (destroyobj);
6306 : }
6307 : }
6308 96 : else if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_DEPEND), false, false)
6309 : != MATCH_YES)
6310 2 : goto error;
6311 :
6312 121 : if (c->depobj_update == OMP_DEPEND_UNSET && !c->destroy)
6313 : {
6314 94 : if (!c->doacross_source && !c->lists[OMP_LIST_DEPEND])
6315 : {
6316 1 : gfc_error ("Expected DEPEND, UPDATE, or DESTROY clause at %C");
6317 1 : goto error;
6318 : }
6319 93 : if (c->lists[OMP_LIST_DEPEND]->u.depend_doacross_op == OMP_DEPEND_DEPOBJ)
6320 : {
6321 1 : gfc_error ("DEPEND clause at %L of OMP DEPOBJ construct shall not "
6322 : "have dependence-type DEPOBJ",
6323 : c->lists[OMP_LIST_DEPEND]
6324 : ? &c->lists[OMP_LIST_DEPEND]->where : &gfc_current_locus);
6325 1 : goto error;
6326 : }
6327 92 : if (c->lists[OMP_LIST_DEPEND]->next)
6328 : {
6329 1 : gfc_error ("DEPEND clause at %L of OMP DEPOBJ construct shall have "
6330 : "only a single locator",
6331 : &c->lists[OMP_LIST_DEPEND]->next->where);
6332 1 : goto error;
6333 : }
6334 : }
6335 :
6336 118 : c->depobj = depobj;
6337 118 : new_st.op = EXEC_OMP_DEPOBJ;
6338 118 : new_st.ext.omp_clauses = c;
6339 118 : return MATCH_YES;
6340 :
6341 8 : error:
6342 8 : gfc_free_expr (depobj);
6343 8 : gfc_free_omp_clauses (c);
6344 8 : return MATCH_ERROR;
6345 : }
6346 :
6347 : match
6348 160 : gfc_match_omp_dispatch (void)
6349 : {
6350 160 : return match_omp (EXEC_OMP_DISPATCH, OMP_DISPATCH_CLAUSES);
6351 : }
6352 :
6353 : match
6354 57 : gfc_match_omp_distribute (void)
6355 : {
6356 57 : return match_omp (EXEC_OMP_DISTRIBUTE, OMP_DISTRIBUTE_CLAUSES);
6357 : }
6358 :
6359 :
6360 : match
6361 47 : gfc_match_omp_distribute_parallel_do (void)
6362 : {
6363 47 : return match_omp (EXEC_OMP_DISTRIBUTE_PARALLEL_DO,
6364 47 : (OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
6365 47 : | OMP_DO_CLAUSES)
6366 47 : & ~(omp_mask (OMP_CLAUSE_ORDERED)
6367 47 : | OMP_CLAUSE_LINEAR | OMP_CLAUSE_NOWAIT));
6368 : }
6369 :
6370 :
6371 : match
6372 34 : gfc_match_omp_distribute_parallel_do_simd (void)
6373 : {
6374 34 : return match_omp (EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD,
6375 34 : (OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
6376 34 : | OMP_DO_CLAUSES | OMP_SIMD_CLAUSES)
6377 34 : & ~(omp_mask (OMP_CLAUSE_ORDERED) | OMP_CLAUSE_NOWAIT));
6378 : }
6379 :
6380 :
6381 : match
6382 52 : gfc_match_omp_distribute_simd (void)
6383 : {
6384 52 : return match_omp (EXEC_OMP_DISTRIBUTE_SIMD,
6385 52 : OMP_DISTRIBUTE_CLAUSES | OMP_SIMD_CLAUSES);
6386 : }
6387 :
6388 :
6389 : match
6390 1255 : gfc_match_omp_do (void)
6391 : {
6392 1255 : return match_omp (EXEC_OMP_DO, OMP_DO_CLAUSES);
6393 : }
6394 :
6395 :
6396 : match
6397 139 : gfc_match_omp_do_simd (void)
6398 : {
6399 139 : return match_omp (EXEC_OMP_DO_SIMD, OMP_DO_CLAUSES | OMP_SIMD_CLAUSES);
6400 : }
6401 :
6402 :
6403 : match
6404 70 : gfc_match_omp_loop (void)
6405 : {
6406 70 : return match_omp (EXEC_OMP_LOOP, OMP_LOOP_CLAUSES);
6407 : }
6408 :
6409 :
6410 : match
6411 35 : gfc_match_omp_teams_loop (void)
6412 : {
6413 35 : return match_omp (EXEC_OMP_TEAMS_LOOP, OMP_TEAMS_CLAUSES | OMP_LOOP_CLAUSES);
6414 : }
6415 :
6416 :
6417 : match
6418 18 : gfc_match_omp_target_teams_loop (void)
6419 : {
6420 18 : return match_omp (EXEC_OMP_TARGET_TEAMS_LOOP,
6421 18 : OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES | OMP_LOOP_CLAUSES);
6422 : }
6423 :
6424 :
6425 : match
6426 31 : gfc_match_omp_parallel_loop (void)
6427 : {
6428 31 : return match_omp (EXEC_OMP_PARALLEL_LOOP,
6429 31 : OMP_PARALLEL_CLAUSES | OMP_LOOP_CLAUSES);
6430 : }
6431 :
6432 :
6433 : match
6434 16 : gfc_match_omp_target_parallel_loop (void)
6435 : {
6436 16 : return match_omp (EXEC_OMP_TARGET_PARALLEL_LOOP,
6437 16 : (OMP_TARGET_CLAUSES | OMP_PARALLEL_CLAUSES
6438 16 : | OMP_LOOP_CLAUSES));
6439 : }
6440 :
6441 :
6442 : match
6443 104 : gfc_match_omp_error (void)
6444 : {
6445 104 : locus loc = gfc_current_locus;
6446 104 : match m = match_omp (EXEC_OMP_ERROR, OMP_ERROR_CLAUSES);
6447 104 : if (m != MATCH_YES)
6448 : return m;
6449 :
6450 85 : gfc_omp_clauses *c = new_st.ext.omp_clauses;
6451 85 : if (c->severity == OMP_SEVERITY_UNSET)
6452 48 : c->severity = OMP_SEVERITY_FATAL;
6453 85 : if (new_st.ext.omp_clauses->at == OMP_AT_EXECUTION)
6454 : return MATCH_YES;
6455 37 : if (c->message
6456 37 : && (!gfc_resolve_expr (c->message)
6457 16 : || c->message->ts.type != BT_CHARACTER
6458 14 : || c->message->ts.kind != gfc_default_character_kind
6459 13 : || c->message->rank != 0))
6460 : {
6461 4 : gfc_error ("MESSAGE clause at %L requires a scalar default-kind "
6462 : "CHARACTER expression",
6463 4 : &new_st.ext.omp_clauses->message->where);
6464 4 : return MATCH_ERROR;
6465 : }
6466 33 : if (c->message && !gfc_is_constant_expr (c->message))
6467 : {
6468 2 : gfc_error ("Constant character expression required in MESSAGE clause "
6469 2 : "at %L", &new_st.ext.omp_clauses->message->where);
6470 2 : return MATCH_ERROR;
6471 : }
6472 31 : if (c->message)
6473 : {
6474 10 : const char *msg = G_("$OMP ERROR encountered at %L: %s");
6475 10 : gcc_assert (c->message->expr_type == EXPR_CONSTANT);
6476 10 : gfc_charlen_t slen = c->message->value.character.length;
6477 10 : int i = gfc_validate_kind (BT_CHARACTER, gfc_default_character_kind,
6478 : false);
6479 10 : size_t size = slen * gfc_character_kinds[i].bit_size / 8;
6480 10 : unsigned char *s = XCNEWVAR (unsigned char, size + 1);
6481 10 : gfc_encode_character (gfc_default_character_kind, slen,
6482 10 : c->message->value.character.string,
6483 : (unsigned char *) s, size);
6484 10 : s[size] = '\0';
6485 10 : if (c->severity == OMP_SEVERITY_WARNING)
6486 6 : gfc_warning_now (0, msg, &loc, s);
6487 : else
6488 4 : gfc_error_now (msg, &loc, s);
6489 10 : free (s);
6490 : }
6491 : else
6492 : {
6493 21 : const char *msg = G_("$OMP ERROR encountered at %L");
6494 21 : if (c->severity == OMP_SEVERITY_WARNING)
6495 7 : gfc_warning_now (0, msg, &loc);
6496 : else
6497 14 : gfc_error_now (msg, &loc);
6498 : }
6499 : return MATCH_YES;
6500 : }
6501 :
6502 : match
6503 100 : gfc_match_omp_flush (void)
6504 : {
6505 100 : gfc_omp_namelist *list = NULL;
6506 100 : gfc_omp_clauses *c = NULL;
6507 100 : gfc_gobble_whitespace ();
6508 100 : enum gfc_omp_memorder mo = OMP_MEMORDER_UNSET;
6509 100 : if (gfc_match_omp_variable_list (" (", &list, true) == MATCH_ERROR)
6510 : return MATCH_ERROR;
6511 : match m = MATCH_YES;
6512 150 : while (gfc_match_omp_eos () != MATCH_YES)
6513 : {
6514 59 : gfc_gobble_whitespace ();
6515 59 : gfc_match (", "); /* optionally */
6516 59 : enum gfc_omp_memorder mo2 = OMP_MEMORDER_UNSET;
6517 59 : bool bval = false;
6518 59 : locus loc = gfc_current_locus;
6519 59 : if ((m = gfc_match_dupl_memorder (&bval, "seq_cst",
6520 : mo != OMP_MEMORDER_UNSET)) != MATCH_NO)
6521 : mo2 = OMP_MEMORDER_SEQ_CST;
6522 48 : else if ((m = gfc_match_dupl_memorder (&bval, "acq_rel",
6523 : mo != OMP_MEMORDER_UNSET))
6524 : != MATCH_NO)
6525 : mo2 = OMP_MEMORDER_ACQ_REL;
6526 35 : else if ((m = gfc_match_dupl_memorder (&bval, "release",
6527 : mo != OMP_MEMORDER_UNSET))
6528 : != MATCH_NO)
6529 : mo2 = OMP_MEMORDER_RELEASE;
6530 24 : else if ((m = gfc_match_dupl_memorder (&bval, "acquire",
6531 : mo != OMP_MEMORDER_UNSET))
6532 : != MATCH_NO)
6533 : mo2 = OMP_MEMORDER_ACQUIRE;
6534 12 : else if ((m = gfc_match_dupl_memorder (&bval, "relaxed",
6535 : mo != OMP_MEMORDER_UNSET))
6536 : != MATCH_NO)
6537 : {
6538 10 : if (m == MATCH_YES && bval)
6539 : {
6540 : /* relaxed only permitted with 'false'. */
6541 2 : gfc_current_locus = loc;
6542 2 : m = MATCH_NO;
6543 2 : break;
6544 : }
6545 : }
6546 : else
6547 : break;
6548 55 : if (m == MATCH_ERROR)
6549 5 : return MATCH_ERROR;
6550 50 : if (bval)
6551 18 : mo = mo2;
6552 : }
6553 95 : if (m == MATCH_NO)
6554 : {
6555 4 : gfc_error ("Expected SEQ_CST, AQC_REL, RELEASE, or ACQUIRE at %C");
6556 4 : gfc_free_omp_namelist (list, OMP_LIST_NONE);
6557 4 : return MATCH_ERROR;
6558 : }
6559 91 : if (list && mo != OMP_MEMORDER_UNSET)
6560 : {
6561 1 : gfc_error ("List specified together with memory order clause in FLUSH "
6562 : "directive at %C");
6563 1 : gfc_free_omp_namelist (list, OMP_LIST_NONE);
6564 1 : return MATCH_ERROR;
6565 : }
6566 90 : if (gfc_match_omp_eos () != MATCH_YES)
6567 : {
6568 0 : gfc_error ("Unexpected junk after $OMP FLUSH statement at %C");
6569 0 : gfc_free_omp_namelist (list, OMP_LIST_NONE);
6570 0 : return MATCH_ERROR;
6571 : }
6572 90 : if (mo != OMP_MEMORDER_UNSET)
6573 : {
6574 16 : c = gfc_get_omp_clauses ();
6575 16 : c->memorder = mo;
6576 : }
6577 90 : new_st.op = EXEC_OMP_FLUSH;
6578 90 : new_st.ext.omp_namelist = list;
6579 90 : new_st.ext.omp_clauses = c;
6580 90 : return MATCH_YES;
6581 : }
6582 :
6583 :
6584 : match
6585 208 : gfc_match_omp_declare_simd (void)
6586 : {
6587 208 : locus where = gfc_current_locus;
6588 208 : gfc_symbol *proc_name;
6589 208 : gfc_omp_clauses *c;
6590 208 : gfc_omp_declare_simd *ods;
6591 208 : bool needs_space = false;
6592 :
6593 208 : switch (gfc_match (" ( "))
6594 : {
6595 145 : case MATCH_YES:
6596 145 : if (gfc_match_symbol (&proc_name, /* host assoc = */ true) != MATCH_YES
6597 145 : || gfc_match (" ) ") != MATCH_YES)
6598 : return MATCH_ERROR;
6599 : break;
6600 63 : case MATCH_NO: proc_name = NULL; needs_space = true; break;
6601 : case MATCH_ERROR: return MATCH_ERROR;
6602 : }
6603 :
6604 208 : if (gfc_match_omp_clauses (&c, OMP_DECLARE_SIMD_CLAUSES, false,
6605 : needs_space) != MATCH_YES)
6606 : return MATCH_ERROR;
6607 :
6608 199 : if (gfc_current_ns->is_block_data)
6609 : {
6610 1 : gfc_free_omp_clauses (c);
6611 1 : return MATCH_YES;
6612 : }
6613 :
6614 198 : ods = gfc_get_omp_declare_simd ();
6615 198 : ods->where = where;
6616 198 : ods->proc_name = proc_name;
6617 198 : ods->clauses = c;
6618 198 : ods->next = gfc_current_ns->omp_declare_simd;
6619 198 : gfc_current_ns->omp_declare_simd = ods;
6620 198 : return MATCH_YES;
6621 : }
6622 :
6623 :
6624 : /* Find a matching "!$omp declare mapper" for typespec TS in symtree ST. */
6625 :
6626 : gfc_omp_udm *
6627 37 : gfc_omp_udm_find (gfc_symtree *st, gfc_typespec *ts)
6628 : {
6629 37 : gfc_omp_udm *omp_udm;
6630 :
6631 37 : if (st == NULL)
6632 : return NULL;
6633 :
6634 14 : gfc_symbol *dt = (ts->type == BT_CLASS
6635 0 : ? CLASS_DATA (ts->u.derived)->ts.u.derived
6636 : : ts->u.derived);
6637 15 : for (omp_udm = st->n.omp_udm; omp_udm; omp_udm = omp_udm->next)
6638 : {
6639 5 : if (dt == omp_udm->ts.u.derived)
6640 : return omp_udm;
6641 : /* Special case for comparing derived types across namespaces. If the
6642 : true names and module names are the same and the module name is
6643 : nonnull, then they are equal. */
6644 1 : if (dt->module && omp_udm->ts.u.derived->module
6645 1 : && strcmp (dt->name, omp_udm->ts.u.derived->name) == 0
6646 1 : && strcmp (dt->module, omp_udm->ts.u.derived->module) == 0)
6647 : return omp_udm;
6648 : }
6649 :
6650 : return NULL;
6651 : }
6652 :
6653 :
6654 : /* Match !$omp declare mapper([ mapper-identifier : ] type :: var) clauses-list */
6655 :
6656 : match
6657 35 : gfc_match_omp_declare_mapper (void)
6658 : {
6659 35 : match m;
6660 35 : gfc_typespec ts;
6661 35 : char mapper_id[GFC_MAX_SYMBOL_LEN + 1];
6662 35 : char var[GFC_MAX_SYMBOL_LEN + 1];
6663 35 : gfc_namespace *mapper_ns = NULL;
6664 35 : gfc_symtree *var_st;
6665 35 : gfc_symtree *st;
6666 35 : gfc_omp_udm *omp_udm = NULL, *prev_udm = NULL;
6667 35 : locus where = gfc_current_locus;
6668 :
6669 35 : if (gfc_match_char ('(') != MATCH_YES)
6670 : {
6671 1 : gfc_error ("Expected %<(%> at %C");
6672 1 : return MATCH_ERROR;
6673 : }
6674 :
6675 34 : locus old_locus = gfc_current_locus;
6676 :
6677 34 : m = gfc_match (" %n : ", mapper_id);
6678 :
6679 34 : if (m == MATCH_ERROR)
6680 : return MATCH_ERROR;
6681 :
6682 : /* As a special case, a mapper named "default" and an unnamed mapper are
6683 : both the default mapper for a given type. */
6684 34 : if (strcmp (mapper_id, "default") == 0)
6685 0 : mapper_id[0] = '\0';
6686 :
6687 34 : if (gfc_peek_ascii_char () == ':')
6688 : {
6689 : /* If we see '::', the user did not name the mapper, and instead we just
6690 : saw the type. So backtrack and try parsing as a type instead. */
6691 15 : mapper_id[0] = '\0';
6692 15 : gfc_current_locus = old_locus;
6693 : }
6694 34 : old_locus = gfc_current_locus;
6695 :
6696 34 : m = gfc_match_type_spec (&ts);
6697 34 : if (m != MATCH_YES)
6698 : {
6699 4 : gfc_error ("Expected either a type name at %L or a map-type "
6700 : "identifier, a colon, or a type name", &old_locus);
6701 4 : return MATCH_ERROR;
6702 : }
6703 :
6704 30 : if (ts.type != BT_DERIVED)
6705 : {
6706 1 : gfc_error ("!$OMP DECLARE MAPPER with non-derived type at %L", &old_locus);
6707 1 : return MATCH_ERROR;
6708 : }
6709 :
6710 29 : if (gfc_match (" :: ") != MATCH_YES)
6711 : {
6712 0 : gfc_error ("Expected %<::%> at %C");
6713 0 : return MATCH_ERROR;
6714 : }
6715 :
6716 29 : if (gfc_match_name (var) != MATCH_YES)
6717 : {
6718 1 : gfc_error ("Expected variable name at %C");
6719 1 : return MATCH_ERROR;
6720 : }
6721 :
6722 28 : if (gfc_match_char (')') != MATCH_YES)
6723 : {
6724 2 : gfc_error ("Expected %<)%> at %C");
6725 2 : return MATCH_ERROR;
6726 : }
6727 :
6728 26 : st = gfc_find_symtree (gfc_current_ns->omp_udm_root, mapper_id);
6729 :
6730 : /* Now we need to set up a new namespace, and create a new sym_tree for our
6731 : dummy variable so we can use it in the following list of mapping
6732 : clauses. */
6733 :
6734 26 : gfc_current_ns = mapper_ns = gfc_get_namespace (gfc_current_ns, 1);
6735 26 : mapper_ns->proc_name = mapper_ns->parent->proc_name;
6736 26 : mapper_ns->omp_udm_ns = 1;
6737 :
6738 26 : gfc_get_sym_tree (var, mapper_ns, &var_st, false);
6739 26 : var_st->n.sym->ts = ts;
6740 26 : var_st->n.sym->attr.omp_udm_artificial_var = 1;
6741 26 : var_st->n.sym->attr.flavor = FL_VARIABLE;
6742 26 : gfc_commit_symbols ();
6743 :
6744 26 : gfc_omp_clauses *clauses = NULL;
6745 :
6746 26 : m = gfc_match_omp_clauses (&clauses, omp_mask (OMP_CLAUSE_MAP), false, false,
6747 : false, false, OMP_MAP_UNSET);
6748 26 : if (m != MATCH_YES)
6749 1 : goto failure;
6750 :
6751 25 : omp_udm = gfc_get_omp_udm ();
6752 25 : omp_udm->next = NULL;
6753 25 : omp_udm->where = where;
6754 25 : omp_udm->mapper_id = gfc_get_string ("%s", mapper_id);
6755 25 : omp_udm->ts = ts;
6756 25 : omp_udm->var_sym = var_st->n.sym;
6757 25 : omp_udm->mapper_ns = mapper_ns;
6758 25 : omp_udm->clauses = clauses;
6759 :
6760 25 : gfc_current_ns = mapper_ns->parent;
6761 :
6762 25 : prev_udm = gfc_omp_udm_find (st, &ts);
6763 25 : if (prev_udm)
6764 : {
6765 2 : if (mapper_id[0])
6766 1 : gfc_error ("Redefinition of !$OMP DECLARE MAPPER at %L for type %qs with id %qs",
6767 : &where, gfc_typename (&ts), mapper_id);
6768 : else
6769 1 : gfc_error ("Redefinition of !$OMP DECLARE MAPPER at %L for type %qs",
6770 : &where, gfc_typename (&ts));
6771 2 : inform (gfc_get_location (&prev_udm->where),
6772 : "Previous !$OMP DECLARE MAPPER here");
6773 2 : return MATCH_ERROR;
6774 : }
6775 23 : else if (st)
6776 : {
6777 0 : omp_udm->next = st->n.omp_udm;
6778 0 : st->n.omp_udm = omp_udm;
6779 : }
6780 : else
6781 : {
6782 23 : st = gfc_new_symtree (&gfc_current_ns->omp_udm_root, mapper_id);
6783 23 : st->n.omp_udm = omp_udm;
6784 : }
6785 :
6786 : return MATCH_YES;
6787 :
6788 1 : failure:
6789 1 : if (mapper_ns)
6790 1 : gfc_current_ns = mapper_ns->parent;
6791 1 : gfc_free_omp_udm (omp_udm);
6792 :
6793 1 : return MATCH_ERROR;
6794 : }
6795 :
6796 : /* For 'declare reduction', matches either the combiner or initializer
6797 : expression, either can be an assignment of 'omp_sym1 = ...'
6798 : or a subroutine call, i.e. 'subroutine-name(argument-list)'. */
6799 :
6800 : static bool
6801 935 : match_udr_expr (gfc_symtree *omp_sym1, gfc_symtree *omp_sym2)
6802 : {
6803 935 : match m;
6804 935 : locus old_loc = gfc_current_locus;
6805 935 : char sname[GFC_MAX_SYMBOL_LEN + 1];
6806 935 : gfc_symbol *sym;
6807 935 : gfc_namespace *ns = gfc_current_ns;
6808 935 : gfc_expr *lvalue = NULL, *rvalue = NULL;
6809 935 : gfc_symtree *st;
6810 935 : gfc_actual_arglist *arglist;
6811 :
6812 935 : m = gfc_match (" %v =", &lvalue);
6813 935 : if (m != MATCH_YES)
6814 210 : gfc_current_locus = old_loc;
6815 : else
6816 : {
6817 725 : m = gfc_match (" %e )", &rvalue);
6818 725 : if (m == MATCH_YES)
6819 : {
6820 715 : ns->code = gfc_get_code (EXEC_ASSIGN);
6821 715 : ns->code->expr1 = lvalue;
6822 715 : ns->code->expr2 = rvalue;
6823 715 : ns->code->loc = old_loc;
6824 715 : return true;
6825 : }
6826 :
6827 10 : gfc_current_locus = old_loc;
6828 10 : gfc_free_expr (lvalue);
6829 : }
6830 :
6831 220 : m = gfc_match (" %n", sname);
6832 220 : if (m != MATCH_YES)
6833 4 : goto syntax;
6834 :
6835 216 : if (strcmp (sname, omp_sym1->name) == 0
6836 203 : || strcmp (sname, omp_sym2->name) == 0)
6837 14 : goto syntax;
6838 :
6839 202 : gfc_current_ns = ns->parent;
6840 202 : if (gfc_get_ha_sym_tree (sname, &st))
6841 0 : goto syntax;
6842 :
6843 202 : sym = st->n.sym;
6844 202 : if (sym->attr.flavor != FL_PROCEDURE
6845 74 : && sym->attr.flavor != FL_UNKNOWN)
6846 1 : goto syntax;
6847 :
6848 201 : if (!sym->attr.generic
6849 191 : && !sym->attr.subroutine
6850 73 : && !sym->attr.function)
6851 : {
6852 73 : if (!(sym->attr.external && !sym->attr.referenced))
6853 : {
6854 : /* ...create a symbol in this scope... */
6855 73 : if (sym->ns != gfc_current_ns
6856 73 : && gfc_get_sym_tree (sname, NULL, &st, false) == 1)
6857 0 : goto syntax;
6858 :
6859 73 : if (sym != st->n.sym)
6860 73 : sym = st->n.sym;
6861 : }
6862 :
6863 : /* ...and then to try to make the symbol into a subroutine. */
6864 73 : if (!gfc_add_subroutine (&sym->attr, sym->name, NULL))
6865 0 : goto syntax;
6866 : }
6867 :
6868 201 : gfc_set_sym_referenced (sym);
6869 201 : gfc_gobble_whitespace ();
6870 201 : if (gfc_peek_ascii_char () != '(')
6871 6 : goto syntax;
6872 :
6873 195 : gfc_current_ns = ns;
6874 195 : m = gfc_match_actual_arglist (1, &arglist);
6875 195 : if (m != MATCH_YES)
6876 0 : goto syntax;
6877 :
6878 195 : if (gfc_match_char (')') != MATCH_YES)
6879 0 : goto syntax;
6880 :
6881 195 : gfc_clear_error ();
6882 195 : ns->code = gfc_get_code (EXEC_CALL);
6883 195 : ns->code->symtree = st;
6884 195 : ns->code->ext.actual = arglist;
6885 195 : ns->code->loc = old_loc;
6886 195 : return true;
6887 25 : syntax:
6888 25 : gfc_clear_error ();
6889 25 : gfc_error ("Expected either %<%s = expr%> or %<subroutine-name(argument-list)"
6890 : "%> followed by %<)%> at %L", omp_sym1->name, &old_loc);
6891 25 : return false;
6892 : }
6893 :
6894 : static bool
6895 1217 : gfc_omp_udr_predef (gfc_omp_reduction_op rop, const char *name,
6896 : gfc_typespec *ts, const char **n)
6897 : {
6898 1217 : if (!gfc_numeric_ts (ts) && ts->type != BT_LOGICAL)
6899 : return false;
6900 :
6901 675 : switch (rop)
6902 : {
6903 19 : case OMP_REDUCTION_PLUS:
6904 19 : case OMP_REDUCTION_MINUS:
6905 19 : case OMP_REDUCTION_TIMES:
6906 19 : return ts->type != BT_LOGICAL;
6907 12 : case OMP_REDUCTION_AND:
6908 12 : case OMP_REDUCTION_OR:
6909 12 : case OMP_REDUCTION_EQV:
6910 12 : case OMP_REDUCTION_NEQV:
6911 12 : return ts->type == BT_LOGICAL;
6912 643 : case OMP_REDUCTION_USER:
6913 643 : if (name[0] != '.' && (ts->type == BT_INTEGER || ts->type == BT_REAL))
6914 : {
6915 571 : gfc_symbol *sym;
6916 :
6917 571 : gfc_find_symbol (name, NULL, 1, &sym);
6918 571 : if (sym != NULL)
6919 : {
6920 94 : if (sym->attr.intrinsic)
6921 0 : *n = sym->name;
6922 94 : else if ((sym->attr.flavor != FL_UNKNOWN
6923 82 : && sym->attr.flavor != FL_PROCEDURE)
6924 70 : || sym->attr.external
6925 55 : || sym->attr.generic
6926 55 : || sym->attr.entry
6927 55 : || sym->attr.result
6928 55 : || sym->attr.dummy
6929 55 : || sym->attr.subroutine
6930 51 : || sym->attr.pointer
6931 51 : || sym->attr.target
6932 51 : || sym->attr.cray_pointer
6933 51 : || sym->attr.cray_pointee
6934 51 : || (sym->attr.proc != PROC_UNKNOWN
6935 1 : && sym->attr.proc != PROC_INTRINSIC)
6936 50 : || sym->attr.if_source != IFSRC_UNKNOWN
6937 50 : || sym == sym->ns->proc_name)
6938 44 : *n = NULL;
6939 : else
6940 50 : *n = sym->name;
6941 : }
6942 : else
6943 477 : *n = name;
6944 571 : if (*n
6945 527 : && (strcmp (*n, "max") == 0 || strcmp (*n, "min") == 0))
6946 56 : return true;
6947 533 : else if (*n
6948 489 : && ts->type == BT_INTEGER
6949 403 : && (strcmp (*n, "iand") == 0
6950 397 : || strcmp (*n, "ior") == 0
6951 391 : || strcmp (*n, "ieor") == 0))
6952 : return true;
6953 : }
6954 : break;
6955 : default:
6956 : break;
6957 : }
6958 : return false;
6959 : }
6960 :
6961 : gfc_omp_udr *
6962 673 : gfc_omp_udr_find (gfc_symtree *st, gfc_typespec *ts)
6963 : {
6964 673 : gfc_omp_udr *omp_udr;
6965 :
6966 673 : if (st == NULL)
6967 : return NULL;
6968 :
6969 112 : gfc_symbol *dt = NULL;
6970 112 : if (ts->type == BT_DERIVED || ts->type == BT_CLASS)
6971 25 : dt = (ts->type == BT_CLASS
6972 0 : ? CLASS_DATA (ts->u.derived)->ts.u.derived : ts->u.derived);
6973 260 : for (omp_udr = st->n.omp_udr; omp_udr; omp_udr = omp_udr->next)
6974 161 : if (omp_udr->ts.type == ts->type
6975 91 : || (dt && omp_udr->ts.type == BT_DERIVED))
6976 : {
6977 70 : if (dt && omp_udr->ts.type == BT_DERIVED)
6978 : {
6979 15 : gfc_symbol *dtu = omp_udr->ts.u.derived;
6980 15 : if (dt == dtu)
6981 : return omp_udr;
6982 : /* Special case for comparing derived types across namespaces. If
6983 : the true names and module names are the same and the module name
6984 : is nonnull, then they are equal. */
6985 7 : if (dt->module && dtu->module
6986 1 : && strcmp (dt->name, dtu->name) == 0
6987 1 : && strcmp (dt->module, dtu->module) == 0)
6988 : return omp_udr;
6989 : }
6990 55 : else if (omp_udr->ts.kind == ts->kind)
6991 : {
6992 20 : if (omp_udr->ts.type == BT_CHARACTER)
6993 : {
6994 17 : if (omp_udr->ts.u.cl->length == NULL
6995 15 : || ts->u.cl->length == NULL)
6996 : return omp_udr;
6997 15 : if (omp_udr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
6998 : return omp_udr;
6999 15 : if (ts->u.cl->length->expr_type != EXPR_CONSTANT)
7000 : return omp_udr;
7001 15 : if (omp_udr->ts.u.cl->length->ts.type != BT_INTEGER)
7002 : return omp_udr;
7003 15 : if (ts->u.cl->length->ts.type != BT_INTEGER)
7004 : return omp_udr;
7005 15 : if (gfc_compare_expr (omp_udr->ts.u.cl->length,
7006 : ts->u.cl->length, INTRINSIC_EQ) != 0)
7007 15 : continue;
7008 : }
7009 : return omp_udr;
7010 : }
7011 : }
7012 : return NULL;
7013 : }
7014 :
7015 : match
7016 594 : gfc_match_omp_declare_reduction (void)
7017 : {
7018 594 : match m;
7019 594 : gfc_intrinsic_op op;
7020 594 : char name[GFC_MAX_SYMBOL_LEN + 3];
7021 594 : auto_vec<gfc_typespec, 5> tss;
7022 594 : gfc_typespec ts;
7023 594 : unsigned int i;
7024 594 : gfc_symtree *st;
7025 594 : locus where = gfc_current_locus;
7026 594 : locus end_loc = gfc_current_locus;
7027 594 : bool end_loc_set = false;
7028 594 : gfc_omp_reduction_op rop = OMP_REDUCTION_NONE;
7029 :
7030 594 : if (gfc_match_char ('(') != MATCH_YES)
7031 : {
7032 4 : gfc_error ("Expected %<(%> at %C");
7033 4 : return MATCH_ERROR;
7034 : }
7035 :
7036 590 : m = gfc_match (" %o : ", &op);
7037 590 : if (m == MATCH_ERROR)
7038 : return MATCH_ERROR;
7039 590 : if (m == MATCH_YES)
7040 : {
7041 142 : snprintf (name, sizeof name, "operator %s", gfc_op2string (op));
7042 142 : rop = (gfc_omp_reduction_op) op;
7043 : }
7044 : else
7045 : {
7046 448 : m = gfc_match_defined_op_name (name + 1, 1);
7047 448 : if (m == MATCH_ERROR)
7048 : return MATCH_ERROR;
7049 447 : if (m == MATCH_YES)
7050 : {
7051 41 : name[0] = '.';
7052 41 : strcat (name, ".");
7053 41 : if (gfc_match (" : ") != MATCH_YES)
7054 : {
7055 0 : gfc_error ("Expected %<:%> at %C");
7056 0 : return MATCH_ERROR;
7057 : }
7058 : }
7059 : else
7060 : {
7061 406 : if (gfc_match (" %n : ", name) != MATCH_YES)
7062 : {
7063 4 : gfc_error ("Expected an identfifier or operator as reduction "
7064 : "identifier followed by a colon at %C");
7065 4 : return MATCH_ERROR;
7066 : }
7067 : }
7068 : rop = OMP_REDUCTION_USER;
7069 : }
7070 :
7071 585 : m = gfc_match_type_spec (&ts);
7072 585 : if (m != MATCH_YES)
7073 : {
7074 4 : gfc_error ("Expected type spec at %C");
7075 4 : return MATCH_ERROR;
7076 : }
7077 : /* Treat len=: the same as len=*. */
7078 581 : if (ts.type == BT_CHARACTER)
7079 61 : ts.deferred = false;
7080 581 : tss.safe_push (ts);
7081 :
7082 1203 : while (gfc_match_char (',') == MATCH_YES)
7083 : {
7084 42 : m = gfc_match_type_spec (&ts);
7085 42 : if (m != MATCH_YES)
7086 : {
7087 1 : gfc_error ("Expected type spec at %C");
7088 1 : return MATCH_ERROR;
7089 : }
7090 41 : tss.safe_push (ts);
7091 : }
7092 580 : if (gfc_match_char (':') != MATCH_YES)
7093 : {
7094 6 : gfc_error ("Expected %<:%> or %<,%> at %C");
7095 6 : return MATCH_ERROR;
7096 : }
7097 :
7098 574 : st = gfc_find_symtree (gfc_current_ns->omp_udr_root, name);
7099 1699 : for (i = 0; i < tss.length (); i++)
7100 : {
7101 610 : gfc_symtree *omp_out, *omp_in;
7102 610 : gfc_symtree *omp_priv = NULL, *omp_orig = NULL;
7103 610 : gfc_namespace *combiner_ns, *initializer_ns = NULL;
7104 610 : gfc_omp_udr *prev_udr, *omp_udr;
7105 610 : const char *predef_name = NULL;
7106 :
7107 610 : omp_udr = gfc_get_omp_udr ();
7108 610 : omp_udr->name = gfc_get_string ("%s", name);
7109 610 : omp_udr->rop = rop;
7110 610 : omp_udr->ts = tss[i];
7111 610 : omp_udr->where = where;
7112 :
7113 610 : gfc_current_ns = combiner_ns = gfc_get_namespace (gfc_current_ns, 1);
7114 610 : combiner_ns->proc_name = combiner_ns->parent->proc_name;
7115 :
7116 610 : gfc_get_sym_tree ("omp_out", combiner_ns, &omp_out, false);
7117 610 : gfc_get_sym_tree ("omp_in", combiner_ns, &omp_in, false);
7118 610 : combiner_ns->omp_udr_ns = 1;
7119 610 : omp_out->n.sym->ts = tss[i];
7120 610 : omp_in->n.sym->ts = tss[i];
7121 610 : omp_out->n.sym->attr.omp_udr_artificial_var = 1;
7122 610 : omp_in->n.sym->attr.omp_udr_artificial_var = 1;
7123 610 : omp_out->n.sym->attr.flavor = FL_VARIABLE;
7124 610 : omp_in->n.sym->attr.flavor = FL_VARIABLE;
7125 610 : gfc_commit_symbols ();
7126 610 : omp_udr->combiner_ns = combiner_ns;
7127 610 : omp_udr->omp_out = omp_out->n.sym;
7128 610 : omp_udr->omp_in = omp_in->n.sym;
7129 :
7130 610 : locus old_loc = gfc_current_locus;
7131 :
7132 610 : if (!match_udr_expr (omp_out, omp_in))
7133 : {
7134 19 : syntax:
7135 59 : gfc_current_ns = combiner_ns->parent;
7136 59 : gfc_undo_symbols ();
7137 59 : gfc_free_omp_udr (omp_udr);
7138 59 : return MATCH_ERROR;
7139 : }
7140 591 : gfc_match_char (','); /* optionally */
7141 591 : if (gfc_match (" initializer ( ") == MATCH_YES)
7142 : {
7143 325 : gfc_current_ns = combiner_ns->parent;
7144 325 : initializer_ns = gfc_get_namespace (gfc_current_ns, 1);
7145 325 : gfc_current_ns = initializer_ns;
7146 325 : initializer_ns->proc_name = initializer_ns->parent->proc_name;
7147 :
7148 325 : gfc_get_sym_tree ("omp_priv", initializer_ns, &omp_priv, false);
7149 325 : gfc_get_sym_tree ("omp_orig", initializer_ns, &omp_orig, false);
7150 325 : initializer_ns->omp_udr_ns = 1;
7151 325 : omp_priv->n.sym->ts = tss[i];
7152 325 : omp_orig->n.sym->ts = tss[i];
7153 325 : omp_priv->n.sym->attr.omp_udr_artificial_var = 1;
7154 325 : omp_orig->n.sym->attr.omp_udr_artificial_var = 1;
7155 325 : omp_priv->n.sym->attr.flavor = FL_VARIABLE;
7156 325 : omp_orig->n.sym->attr.flavor = FL_VARIABLE;
7157 325 : gfc_commit_symbols ();
7158 325 : omp_udr->initializer_ns = initializer_ns;
7159 325 : omp_udr->omp_priv = omp_priv->n.sym;
7160 325 : omp_udr->omp_orig = omp_orig->n.sym;
7161 :
7162 325 : if (!match_udr_expr (omp_priv, omp_orig))
7163 6 : goto syntax;
7164 : }
7165 :
7166 585 : gfc_current_ns = combiner_ns->parent;
7167 585 : if (!end_loc_set)
7168 : {
7169 549 : end_loc_set = true;
7170 549 : end_loc = gfc_current_locus;
7171 : }
7172 585 : gfc_current_locus = old_loc;
7173 :
7174 585 : prev_udr = gfc_omp_udr_find (st, &tss[i]);
7175 585 : if (gfc_omp_udr_predef (rop, name, &tss[i], &predef_name)
7176 : /* Don't error on !$omp declare reduction (min : integer : ...)
7177 : just yet, there could be integer :: min afterwards,
7178 : making it valid. When the UDR is resolved, we'll get
7179 : to it again. */
7180 585 : && (rop != OMP_REDUCTION_USER || name[0] == '.'))
7181 : {
7182 27 : if (predef_name)
7183 0 : gfc_error_now ("Redefinition of predefined %qs in "
7184 : "!$OMP DECLARE REDUCTION at %L",
7185 : predef_name, &where);
7186 : else
7187 27 : gfc_error_now ("Redefinition of predefined %qs in "
7188 : "!$OMP DECLARE REDUCTION at %L", name, &where);
7189 27 : goto syntax;
7190 : }
7191 558 : else if (prev_udr)
7192 : {
7193 7 : gfc_error_now ("Redefinition of %qs in !$OMP DECLARE REDUCTION at %L",
7194 : name, &where);
7195 7 : inform (gfc_get_location (&prev_udr->where),
7196 : "Previous !$OMP DECLARE REDUCTION");
7197 7 : goto syntax;
7198 : }
7199 551 : else if (st)
7200 : {
7201 98 : omp_udr->next = st->n.omp_udr;
7202 98 : st->n.omp_udr = omp_udr;
7203 : }
7204 : else
7205 : {
7206 453 : st = gfc_new_symtree (&gfc_current_ns->omp_udr_root, name);
7207 453 : st->n.omp_udr = omp_udr;
7208 : }
7209 : }
7210 :
7211 515 : if (end_loc_set)
7212 : {
7213 515 : gfc_current_locus = end_loc;
7214 515 : if (gfc_match_omp_eos () != MATCH_YES)
7215 : {
7216 4 : gfc_error ("Unexpected junk at %C");
7217 4 : return MATCH_ERROR;
7218 : }
7219 : return MATCH_YES;
7220 : }
7221 : return MATCH_ERROR;
7222 594 : }
7223 :
7224 :
7225 : match
7226 490 : gfc_match_omp_declare_target (void)
7227 : {
7228 490 : locus old_loc;
7229 490 : match m;
7230 490 : gfc_omp_clauses *c = NULL;
7231 490 : enum gfc_omp_list_type list;
7232 490 : gfc_omp_namelist *n;
7233 490 : gfc_symbol *s;
7234 :
7235 490 : old_loc = gfc_current_locus;
7236 :
7237 490 : if (gfc_current_ns->proc_name
7238 490 : && gfc_match_omp_eos () == MATCH_YES)
7239 : {
7240 138 : if (!gfc_add_omp_declare_target (&gfc_current_ns->proc_name->attr,
7241 138 : gfc_current_ns->proc_name->name,
7242 : &old_loc))
7243 0 : goto cleanup;
7244 : return MATCH_YES;
7245 : }
7246 :
7247 352 : if (gfc_current_ns->proc_name
7248 352 : && gfc_current_ns->proc_name->attr.if_source == IFSRC_IFBODY)
7249 : {
7250 2 : gfc_error ("Only the !$OMP DECLARE TARGET form without "
7251 : "clauses is allowed in interface block at %C");
7252 2 : goto cleanup;
7253 : }
7254 :
7255 350 : m = gfc_match (" (");
7256 350 : if (m == MATCH_YES)
7257 : {
7258 86 : c = gfc_get_omp_clauses ();
7259 86 : gfc_current_locus = old_loc;
7260 86 : m = gfc_match_omp_to_link (" (", &c->lists[OMP_LIST_ENTER]);
7261 86 : if (m != MATCH_YES)
7262 0 : goto syntax;
7263 86 : if (gfc_match_omp_eos () != MATCH_YES)
7264 : {
7265 0 : gfc_error ("Unexpected junk after !$OMP DECLARE TARGET at %C");
7266 0 : goto cleanup;
7267 : }
7268 : }
7269 264 : else if (gfc_match_omp_clauses (&c, OMP_DECLARE_TARGET_CLAUSES, false)
7270 : != MATCH_YES)
7271 : return MATCH_ERROR;
7272 :
7273 344 : gfc_buffer_error (false);
7274 :
7275 344 : static const enum gfc_omp_list_type to_enter_link_lists[]
7276 : = { OMP_LIST_TO, OMP_LIST_ENTER, OMP_LIST_LINK, OMP_LIST_LOCAL };
7277 1720 : for (size_t listn = 0; listn < ARRAY_SIZE (to_enter_link_lists)
7278 1720 : && (list = to_enter_link_lists[listn], true); ++listn)
7279 1941 : for (n = c->lists[list]; n; n = n->next)
7280 565 : if (n->sym)
7281 523 : n->sym->mark = 0;
7282 42 : else if (n->u.common->head)
7283 42 : n->u.common->head->mark = 0;
7284 :
7285 344 : if (c->device_type == OMP_DEVICE_TYPE_UNSET)
7286 276 : c->device_type = OMP_DEVICE_TYPE_ANY;
7287 1720 : for (size_t listn = 0; listn < ARRAY_SIZE (to_enter_link_lists)
7288 1720 : && (list = to_enter_link_lists[listn], true); ++listn)
7289 1941 : for (n = c->lists[list]; n; n = n->next)
7290 565 : if (n->sym)
7291 : {
7292 523 : if (n->sym->attr.in_common)
7293 1 : gfc_error_now ("OMP DECLARE TARGET variable at %L is an "
7294 : "element of a COMMON block", &n->where);
7295 522 : else if (n->sym->attr.omp_groupprivate && list != OMP_LIST_LOCAL)
7296 12 : gfc_error_now ("List item %qs at %L should not appear in the %qs "
7297 : "clause, as it was previously specified in a "
7298 : "GROUPPRIVATE directive", n->sym->name, &n->where,
7299 : list == OMP_LIST_LINK
7300 5 : ? "link" : list == OMP_LIST_TO ? "to" : "enter");
7301 515 : else if (n->sym->mark)
7302 11 : gfc_error_now ("Variable at %L mentioned multiple times in "
7303 : "clauses of the same OMP DECLARE TARGET directive",
7304 : &n->where);
7305 504 : else if ((list != OMP_LIST_LINK
7306 471 : && n->sym->attr.omp_declare_target_link)
7307 469 : || (list != OMP_LIST_LOCAL
7308 488 : && n->sym->attr.omp_declare_target_local))
7309 10 : gfc_error_now ("OMP DECLARE TARGET variable at %L previously "
7310 : "mentioned in %s clause and later in %s clause",
7311 : &n->where,
7312 5 : n->sym->attr.omp_declare_target_link ? "LINK"
7313 : : "LOCAL",
7314 : (list == OMP_LIST_LOCAL ? "LOCAL"
7315 : : list == OMP_LIST_LINK ? "LINK"
7316 : : list == OMP_LIST_TO ? "TO" : "ENTER"));
7317 499 : else if (n->sym->attr.omp_declare_target
7318 15 : && (list == OMP_LIST_LINK || list == OMP_LIST_LOCAL))
7319 3 : gfc_error_now ("OMP DECLARE TARGET variable at %L previously "
7320 : "mentioned in TO or ENTER clause and later in "
7321 : "%s clause", &n->where,
7322 : list == OMP_LIST_LINK ? "LINK" : "LOCAL");
7323 : else
7324 : {
7325 497 : if (list == OMP_LIST_TO || list == OMP_LIST_ENTER)
7326 453 : gfc_add_omp_declare_target (&n->sym->attr, n->sym->name,
7327 : &n->sym->declared_at);
7328 497 : if (list == OMP_LIST_LINK)
7329 31 : gfc_add_omp_declare_target_link (&n->sym->attr, n->sym->name,
7330 31 : &n->sym->declared_at);
7331 497 : if (list == OMP_LIST_LOCAL)
7332 13 : gfc_add_omp_declare_target_local (&n->sym->attr, n->sym->name,
7333 13 : &n->sym->declared_at);
7334 : }
7335 523 : if (n->sym->attr.omp_device_type != OMP_DEVICE_TYPE_UNSET
7336 43 : && n->sym->attr.omp_device_type != c->device_type)
7337 : {
7338 12 : const char *dt = "any";
7339 12 : if (n->sym->attr.omp_device_type == OMP_DEVICE_TYPE_NOHOST)
7340 : dt = "nohost";
7341 8 : else if (n->sym->attr.omp_device_type == OMP_DEVICE_TYPE_HOST)
7342 4 : dt = "host";
7343 12 : if (n->sym->attr.omp_groupprivate)
7344 1 : gfc_error_now ("List item %qs at %L set in previous OMP "
7345 : "GROUPPRIVATE directive to the different "
7346 : "DEVICE_TYPE %qs", n->sym->name, &n->where, dt);
7347 : else
7348 11 : gfc_error_now ("List item %qs at %L set in previous OMP "
7349 : "DECLARE TARGET directive to the different "
7350 : "DEVICE_TYPE %qs", n->sym->name, &n->where, dt);
7351 : }
7352 523 : n->sym->attr.omp_device_type = c->device_type;
7353 523 : if (c->indirect && c->device_type != OMP_DEVICE_TYPE_ANY)
7354 : {
7355 1 : gfc_error_now ("DEVICE_TYPE must be ANY when used with INDIRECT "
7356 : "at %L", &n->where);
7357 1 : c->indirect = 0;
7358 : }
7359 523 : n->sym->attr.omp_declare_target_indirect = c->indirect;
7360 523 : if (list == OMP_LIST_LINK && c->device_type == OMP_DEVICE_TYPE_NOHOST)
7361 3 : gfc_error_now ("List item %qs at %L set with NOHOST specified may "
7362 : "not appear in a LINK clause", n->sym->name,
7363 : &n->where);
7364 523 : n->sym->mark = 1;
7365 : }
7366 : else /* common block */
7367 : {
7368 42 : if (n->u.common->omp_groupprivate && list != OMP_LIST_LOCAL)
7369 7 : gfc_error_now ("Common block %</%s/%> at %L not appear in the %qs "
7370 : "clause as it was previously specified in a "
7371 : "GROUPPRIVATE directive",
7372 7 : n->u.common->name, &n->where,
7373 : list == OMP_LIST_LINK
7374 5 : ? "link" : list == OMP_LIST_TO ? "to" : "enter");
7375 35 : else if (n->u.common->head && n->u.common->head->mark)
7376 4 : gfc_error_now ("Common block %</%s/%> at %L mentioned multiple "
7377 : "times in clauses of the same OMP DECLARE TARGET "
7378 4 : "directive", n->u.common->name, &n->where);
7379 31 : else if ((n->u.common->omp_declare_target_link
7380 27 : || n->u.common->omp_declare_target_local)
7381 : && list != OMP_LIST_LINK
7382 6 : && list != OMP_LIST_LOCAL)
7383 2 : gfc_error_now ("Common block %</%s/%> at %L previously mentioned "
7384 : "in %s clause and later in %s clause",
7385 1 : n->u.common->name, &n->where,
7386 : n->u.common->omp_declare_target_link ? "LINK"
7387 : : "LOCAL",
7388 : list == OMP_LIST_TO ? "TO" : "ENTER");
7389 30 : else if (n->u.common->omp_declare_target
7390 4 : && (list == OMP_LIST_LINK || list == OMP_LIST_LOCAL))
7391 1 : gfc_error_now ("Common block %</%s/%> at %L previously mentioned "
7392 : "in TO or ENTER clause and later in %s clause",
7393 1 : n->u.common->name, &n->where,
7394 : list == OMP_LIST_LINK ? "LINK" : "LOCAL");
7395 42 : if (n->u.common->omp_device_type != OMP_DEVICE_TYPE_UNSET
7396 21 : && n->u.common->omp_device_type != c->device_type)
7397 : {
7398 1 : const char *dt = "any";
7399 1 : if (n->u.common->omp_device_type == OMP_DEVICE_TYPE_NOHOST)
7400 : dt = "nohost";
7401 0 : else if (n->u.common->omp_device_type == OMP_DEVICE_TYPE_HOST)
7402 0 : dt = "host";
7403 1 : if (n->u.common->omp_groupprivate)
7404 1 : gfc_error_now ("Common block %</%s/%> at %L set in previous OMP "
7405 : "GROUPPRIVATE directive to the different "
7406 1 : "DEVICE_TYPE %qs", n->u.common->name, &n->where,
7407 : dt);
7408 : else
7409 0 : gfc_error_now ("Common block %</%s/%> at %L set in previous OMP "
7410 : "DECLARE TARGET directive to the different "
7411 0 : "DEVICE_TYPE %qs", n->u.common->name, &n->where,
7412 : dt);
7413 : }
7414 42 : n->u.common->omp_device_type = c->device_type;
7415 :
7416 42 : if (c->indirect && c->device_type != OMP_DEVICE_TYPE_ANY)
7417 : {
7418 0 : gfc_error_now ("DEVICE_TYPE must be ANY when used with INDIRECT "
7419 : "at %L", &n->where);
7420 0 : c->indirect = 0;
7421 : }
7422 42 : if (list == OMP_LIST_LINK && c->device_type == OMP_DEVICE_TYPE_NOHOST)
7423 1 : gfc_error_now ("Common block %</%s/%> at %L set with NOHOST "
7424 : "specified may not appear in a LINK clause",
7425 1 : n->u.common->name, &n->where);
7426 :
7427 42 : if (list == OMP_LIST_TO || list == OMP_LIST_ENTER)
7428 21 : n->u.common->omp_declare_target = 1;
7429 42 : if (list == OMP_LIST_LINK)
7430 15 : n->u.common->omp_declare_target_link = 1;
7431 42 : if (list == OMP_LIST_LOCAL)
7432 6 : n->u.common->omp_declare_target_local = 1;
7433 :
7434 112 : for (s = n->u.common->head; s; s = s->common_next)
7435 : {
7436 70 : s->mark = 1;
7437 70 : if (list == OMP_LIST_TO || list == OMP_LIST_ENTER)
7438 33 : gfc_add_omp_declare_target (&s->attr, s->name, &n->where);
7439 70 : if (list == OMP_LIST_LINK)
7440 31 : gfc_add_omp_declare_target_link (&s->attr, s->name, &n->where);
7441 70 : if (list == OMP_LIST_LOCAL)
7442 6 : gfc_add_omp_declare_target_local (&s->attr, s->name, &n->where);
7443 70 : s->attr.omp_device_type = c->device_type;
7444 70 : s->attr.omp_declare_target_indirect = c->indirect;
7445 : }
7446 : }
7447 344 : if ((c->device_type || c->indirect)
7448 344 : && !c->lists[OMP_LIST_ENTER]
7449 161 : && !c->lists[OMP_LIST_TO]
7450 56 : && !c->lists[OMP_LIST_LINK]
7451 17 : && !c->lists[OMP_LIST_LOCAL])
7452 2 : gfc_warning_now (OPT_Wopenmp,
7453 : "OMP DECLARE TARGET directive at %L with only "
7454 : "DEVICE_TYPE or INDIRECT clauses is ignored",
7455 : &old_loc);
7456 :
7457 344 : gfc_buffer_error (true);
7458 :
7459 344 : if (c)
7460 344 : gfc_free_omp_clauses (c);
7461 : return MATCH_YES;
7462 :
7463 0 : syntax:
7464 0 : gfc_error ("Syntax error in !$OMP DECLARE TARGET list at %C");
7465 :
7466 2 : cleanup:
7467 2 : gfc_current_locus = old_loc;
7468 2 : if (c)
7469 0 : gfc_free_omp_clauses (c);
7470 : return MATCH_ERROR;
7471 : }
7472 :
7473 : /* Skip over and ignore trait-property-extensions.
7474 :
7475 : trait-property-extension :
7476 : trait-property-name
7477 : identifier (trait-property-extension[, trait-property-extension[, ...]])
7478 : constant integer expression
7479 : */
7480 :
7481 : static match gfc_ignore_trait_property_extension_list (void);
7482 :
7483 : static match
7484 7 : gfc_ignore_trait_property_extension (void)
7485 : {
7486 7 : char buf[GFC_MAX_SYMBOL_LEN + 1];
7487 7 : gfc_expr *expr;
7488 :
7489 : /* Identifier form of trait-property name, possibly followed by
7490 : a list of (recursive) trait-property-extensions. */
7491 7 : if (gfc_match_name (buf) == MATCH_YES)
7492 : {
7493 0 : if (gfc_match (" (") == MATCH_YES)
7494 0 : return gfc_ignore_trait_property_extension_list ();
7495 : return MATCH_YES;
7496 : }
7497 :
7498 : /* Literal constant. */
7499 7 : if (gfc_match_literal_constant (&expr, 0) == MATCH_YES)
7500 : return MATCH_YES;
7501 :
7502 : /* FIXME: constant integer expressions. */
7503 0 : gfc_error ("Expected trait-property-extension at %C");
7504 0 : return MATCH_ERROR;
7505 : }
7506 :
7507 : static match
7508 5 : gfc_ignore_trait_property_extension_list (void)
7509 : {
7510 9 : while (1)
7511 : {
7512 7 : if (gfc_ignore_trait_property_extension () != MATCH_YES)
7513 : return MATCH_ERROR;
7514 7 : if (gfc_match (" ,") == MATCH_YES)
7515 2 : continue;
7516 5 : if (gfc_match (" )") == MATCH_YES)
7517 : return MATCH_YES;
7518 0 : gfc_error ("expected %<)%> at %C");
7519 0 : return MATCH_ERROR;
7520 : }
7521 : }
7522 :
7523 :
7524 : match
7525 110 : gfc_match_omp_interop (void)
7526 : {
7527 110 : return match_omp (EXEC_OMP_INTEROP, OMP_INTEROP_CLAUSES);
7528 : }
7529 :
7530 :
7531 : /* OpenMP 5.0:
7532 :
7533 : trait-selector:
7534 : trait-selector-name[([trait-score:]trait-property[,trait-property[,...]])]
7535 :
7536 : trait-score:
7537 : score(score-expression) */
7538 :
7539 : static match
7540 662 : gfc_match_omp_context_selector (gfc_omp_set_selector *oss)
7541 : {
7542 803 : do
7543 : {
7544 803 : char selector[GFC_MAX_SYMBOL_LEN + 1];
7545 :
7546 803 : if (gfc_match_name (selector) != MATCH_YES)
7547 : {
7548 2 : gfc_error ("expected trait selector name at %C");
7549 39 : return MATCH_ERROR;
7550 : }
7551 :
7552 801 : gfc_omp_selector *os = gfc_get_omp_selector ();
7553 801 : if (oss->code == OMP_TRAIT_SET_CONSTRUCT
7554 351 : && !strcmp (selector, "do"))
7555 48 : os->code = OMP_TRAIT_CONSTRUCT_FOR;
7556 753 : else if (oss->code == OMP_TRAIT_SET_CONSTRUCT
7557 303 : && !strcmp (selector, "for"))
7558 1 : os->code = OMP_TRAIT_INVALID;
7559 : else
7560 752 : os->code = omp_lookup_ts_code (oss->code, selector);
7561 801 : os->next = oss->trait_selectors;
7562 801 : oss->trait_selectors = os;
7563 :
7564 801 : if (os->code == OMP_TRAIT_INVALID)
7565 : {
7566 18 : gfc_warning (OPT_Wopenmp,
7567 : "unknown selector %qs for context selector set %qs "
7568 : "at %C",
7569 18 : selector, omp_tss_map[oss->code]);
7570 18 : if (gfc_match (" (") == MATCH_YES
7571 18 : && gfc_ignore_trait_property_extension_list () != MATCH_YES)
7572 : return MATCH_ERROR;
7573 18 : if (gfc_match (" ,") == MATCH_YES)
7574 1 : continue;
7575 623 : break;
7576 : }
7577 :
7578 783 : enum omp_tp_type property_kind = omp_ts_map[os->code].tp_type;
7579 783 : bool allow_score = omp_ts_map[os->code].allow_score;
7580 :
7581 783 : if (gfc_match (" (") == MATCH_YES)
7582 : {
7583 451 : if (property_kind == OMP_TRAIT_PROPERTY_NONE)
7584 : {
7585 6 : gfc_error ("selector %qs does not accept any properties at %C",
7586 : selector);
7587 6 : return MATCH_ERROR;
7588 : }
7589 :
7590 445 : if (gfc_match (" score") == MATCH_YES)
7591 : {
7592 63 : if (!allow_score)
7593 : {
7594 10 : gfc_error ("%<score%> cannot be specified in traits "
7595 : "in the %qs trait-selector-set at %C",
7596 10 : omp_tss_map[oss->code]);
7597 10 : return MATCH_ERROR;
7598 : }
7599 53 : if (gfc_match (" (") != MATCH_YES)
7600 : {
7601 0 : gfc_error ("expected %<(%> at %C");
7602 0 : return MATCH_ERROR;
7603 : }
7604 53 : if (gfc_match_expr (&os->score) != MATCH_YES)
7605 : return MATCH_ERROR;
7606 :
7607 52 : if (gfc_match (" )") != MATCH_YES)
7608 : {
7609 0 : gfc_error ("expected %<)%> at %C");
7610 0 : return MATCH_ERROR;
7611 : }
7612 :
7613 52 : if (gfc_match (" :") != MATCH_YES)
7614 : {
7615 0 : gfc_error ("expected : at %C");
7616 0 : return MATCH_ERROR;
7617 : }
7618 : }
7619 :
7620 434 : gfc_omp_trait_property *otp = gfc_get_omp_trait_property ();
7621 434 : otp->property_kind = property_kind;
7622 434 : otp->next = os->properties;
7623 434 : os->properties = otp;
7624 :
7625 434 : switch (property_kind)
7626 : {
7627 25 : case OMP_TRAIT_PROPERTY_ID:
7628 25 : {
7629 25 : char buf[GFC_MAX_SYMBOL_LEN + 1];
7630 25 : if (gfc_match_name (buf) == MATCH_YES)
7631 : {
7632 24 : otp->name = XNEWVEC (char, strlen (buf) + 1);
7633 24 : strcpy (otp->name, buf);
7634 : }
7635 : else
7636 : {
7637 1 : gfc_error ("expected identifier at %C");
7638 1 : free (otp);
7639 1 : os->properties = nullptr;
7640 1 : return MATCH_ERROR;
7641 : }
7642 : }
7643 24 : break;
7644 294 : case OMP_TRAIT_PROPERTY_NAME_LIST:
7645 347 : do
7646 : {
7647 294 : char buf[GFC_MAX_SYMBOL_LEN + 1];
7648 294 : if (gfc_match_name (buf) == MATCH_YES)
7649 : {
7650 172 : otp->name = XNEWVEC (char, strlen (buf) + 1);
7651 172 : strcpy (otp->name, buf);
7652 172 : otp->is_name = true;
7653 : }
7654 122 : else if (gfc_match_literal_constant (&otp->expr, 0)
7655 : != MATCH_YES
7656 122 : || otp->expr->ts.type != BT_CHARACTER)
7657 : {
7658 5 : gfc_error ("expected identifier or string literal "
7659 : "at %C");
7660 5 : free (otp);
7661 5 : os->properties = nullptr;
7662 5 : return MATCH_ERROR;
7663 : }
7664 :
7665 289 : if (gfc_match (" ,") == MATCH_YES)
7666 : {
7667 53 : otp = gfc_get_omp_trait_property ();
7668 53 : otp->property_kind = property_kind;
7669 53 : otp->next = os->properties;
7670 53 : os->properties = otp;
7671 : }
7672 : else
7673 : break;
7674 53 : }
7675 : while (1);
7676 236 : break;
7677 145 : case OMP_TRAIT_PROPERTY_DEV_NUM_EXPR:
7678 145 : case OMP_TRAIT_PROPERTY_BOOL_EXPR:
7679 145 : if (gfc_match_expr (&otp->expr) != MATCH_YES)
7680 : {
7681 3 : gfc_error ("expected expression at %C");
7682 3 : free (otp);
7683 3 : os->properties = nullptr;
7684 3 : return MATCH_ERROR;
7685 : }
7686 : break;
7687 23 : case OMP_TRAIT_PROPERTY_CLAUSE_LIST:
7688 23 : {
7689 23 : if (os->code == OMP_TRAIT_CONSTRUCT_SIMD)
7690 : {
7691 23 : gfc_matching_omp_context_selector = true;
7692 23 : if (gfc_match_omp_clauses (&otp->clauses,
7693 23 : OMP_DECLARE_SIMD_CLAUSES,
7694 : true, false, false)
7695 : != MATCH_YES)
7696 : {
7697 1 : gfc_matching_omp_context_selector = false;
7698 1 : gfc_error ("expected simd clause at %C");
7699 1 : return MATCH_ERROR;
7700 : }
7701 22 : gfc_matching_omp_context_selector = false;
7702 : }
7703 0 : else if (os->code == OMP_TRAIT_IMPLEMENTATION_REQUIRES)
7704 : {
7705 : /* FIXME: The "requires" selector was added in OpenMP 5.1.
7706 : Currently only the now-deprecated syntax
7707 : from OpenMP 5.0 is supported.
7708 : TODO: When implementing, update modules.cc as well. */
7709 0 : sorry_at (gfc_get_location (&gfc_current_locus),
7710 : "%<requires%> selector is not supported yet");
7711 0 : return MATCH_ERROR;
7712 : }
7713 : else
7714 0 : gcc_unreachable ();
7715 22 : break;
7716 : }
7717 0 : default:
7718 0 : gcc_unreachable ();
7719 : }
7720 :
7721 424 : if (gfc_match (" )") != MATCH_YES)
7722 : {
7723 2 : gfc_error ("expected %<)%> at %C");
7724 2 : return MATCH_ERROR;
7725 : }
7726 : }
7727 332 : else if (property_kind != OMP_TRAIT_PROPERTY_NONE
7728 332 : && property_kind != OMP_TRAIT_PROPERTY_CLAUSE_LIST
7729 8 : && property_kind != OMP_TRAIT_PROPERTY_EXTENSION)
7730 : {
7731 8 : if (gfc_match (" (") != MATCH_YES)
7732 : {
7733 8 : gfc_error ("expected %<(%> at %C");
7734 8 : return MATCH_ERROR;
7735 : }
7736 : }
7737 :
7738 746 : if (gfc_match (" ,") != MATCH_YES)
7739 : break;
7740 : }
7741 : while (1);
7742 :
7743 623 : return MATCH_YES;
7744 : }
7745 :
7746 : /* OpenMP 5.0:
7747 :
7748 : trait-set-selector[,trait-set-selector[,...]]
7749 :
7750 : trait-set-selector:
7751 : trait-set-selector-name = { trait-selector[, trait-selector[, ...]] }
7752 :
7753 : trait-set-selector-name:
7754 : constructor
7755 : device
7756 : implementation
7757 : user */
7758 :
7759 : static match
7760 600 : gfc_match_omp_context_selector_specification (gfc_omp_set_selector **oss_head)
7761 : {
7762 740 : do
7763 : {
7764 670 : match m;
7765 670 : char buf[GFC_MAX_SYMBOL_LEN + 1];
7766 670 : enum omp_tss_code set = OMP_TRAIT_SET_INVALID;
7767 :
7768 670 : m = gfc_match_name (buf);
7769 670 : if (m == MATCH_YES)
7770 668 : set = omp_lookup_tss_code (buf);
7771 :
7772 668 : if (set == OMP_TRAIT_SET_INVALID)
7773 : {
7774 5 : gfc_error ("expected context selector set name at %C");
7775 47 : return MATCH_ERROR;
7776 : }
7777 :
7778 665 : m = gfc_match (" =");
7779 665 : if (m != MATCH_YES)
7780 : {
7781 1 : gfc_error ("expected %<=%> at %C");
7782 1 : return MATCH_ERROR;
7783 : }
7784 :
7785 664 : m = gfc_match (" {");
7786 664 : if (m != MATCH_YES)
7787 : {
7788 2 : gfc_error ("expected %<{%> at %C");
7789 2 : return MATCH_ERROR;
7790 : }
7791 :
7792 662 : gfc_omp_set_selector *oss = gfc_get_omp_set_selector ();
7793 662 : oss->next = *oss_head;
7794 662 : oss->code = set;
7795 662 : *oss_head = oss;
7796 :
7797 662 : if (gfc_match_omp_context_selector (oss) != MATCH_YES)
7798 : return MATCH_ERROR;
7799 :
7800 623 : m = gfc_match (" }");
7801 623 : if (m != MATCH_YES)
7802 : {
7803 0 : gfc_error ("expected %<}%> at %C");
7804 0 : return MATCH_ERROR;
7805 : }
7806 :
7807 623 : m = gfc_match (" ,");
7808 623 : if (m != MATCH_YES)
7809 : break;
7810 70 : }
7811 : while (1);
7812 :
7813 553 : return MATCH_YES;
7814 : }
7815 :
7816 :
7817 : match
7818 434 : gfc_match_omp_declare_variant (void)
7819 : {
7820 434 : char buf[GFC_MAX_SYMBOL_LEN + 1];
7821 :
7822 434 : if (gfc_match (" (") != MATCH_YES)
7823 : {
7824 2 : gfc_error ("expected %<(%> at %C");
7825 2 : return MATCH_ERROR;
7826 : }
7827 :
7828 432 : gfc_symtree *base_proc_st, *variant_proc_st;
7829 432 : if (gfc_match_name (buf) != MATCH_YES)
7830 : {
7831 2 : gfc_error ("expected name at %C");
7832 2 : return MATCH_ERROR;
7833 : }
7834 :
7835 430 : if (gfc_get_ha_sym_tree (buf, &base_proc_st))
7836 : return MATCH_ERROR;
7837 :
7838 430 : if (gfc_match (" :") == MATCH_YES)
7839 : {
7840 16 : if (gfc_match_name (buf) != MATCH_YES)
7841 : {
7842 0 : gfc_error ("expected variant name at %C");
7843 0 : return MATCH_ERROR;
7844 : }
7845 :
7846 16 : if (gfc_get_ha_sym_tree (buf, &variant_proc_st))
7847 : return MATCH_ERROR;
7848 : }
7849 : else
7850 : {
7851 : /* Base procedure not specified. */
7852 414 : variant_proc_st = base_proc_st;
7853 414 : base_proc_st = NULL;
7854 : }
7855 :
7856 430 : gfc_omp_declare_variant *odv;
7857 430 : odv = gfc_get_omp_declare_variant ();
7858 430 : odv->where = gfc_current_locus;
7859 430 : odv->variant_proc_symtree = variant_proc_st;
7860 430 : odv->adjust_args_list = NULL;
7861 430 : odv->base_proc_symtree = base_proc_st;
7862 430 : odv->next = NULL;
7863 430 : odv->error_p = false;
7864 :
7865 : /* Add the new declare variant to the end of the list. */
7866 430 : gfc_omp_declare_variant **prev_next = &gfc_current_ns->omp_declare_variant;
7867 597 : while (*prev_next)
7868 167 : prev_next = &((*prev_next)->next);
7869 430 : *prev_next = odv;
7870 :
7871 430 : if (gfc_match (" )") != MATCH_YES)
7872 : {
7873 1 : gfc_error ("expected %<)%> at %C");
7874 1 : return MATCH_ERROR;
7875 : }
7876 :
7877 429 : bool has_match = false, has_adjust_args = false, has_append_args = false;
7878 429 : bool error_p = false;
7879 429 : locus adjust_args_loc;
7880 429 : locus append_args_loc;
7881 :
7882 429 : gfc_gobble_whitespace ();
7883 429 : gfc_match_char (',');
7884 647 : for (;;)
7885 : {
7886 538 : gfc_gobble_whitespace ();
7887 :
7888 538 : enum clause
7889 : {
7890 : clause_match,
7891 : clause_adjust_args,
7892 : clause_append_args
7893 : } ccode;
7894 :
7895 538 : if (gfc_match ("match") == MATCH_YES)
7896 : ccode = clause_match;
7897 119 : else if (gfc_match ("adjust_args") == MATCH_YES)
7898 : {
7899 532 : ccode = clause_adjust_args;
7900 : adjust_args_loc = gfc_current_locus;
7901 : }
7902 38 : else if (gfc_match ("append_args") == MATCH_YES)
7903 : {
7904 532 : ccode = clause_append_args;
7905 : append_args_loc = gfc_current_locus;
7906 : }
7907 : else
7908 : {
7909 : error_p = true;
7910 : break;
7911 : }
7912 :
7913 532 : if (gfc_match (" ( ") != MATCH_YES)
7914 : {
7915 1 : gfc_error ("expected %<(%> at %C");
7916 1 : return MATCH_ERROR;
7917 : }
7918 :
7919 531 : if (ccode == clause_match)
7920 : {
7921 418 : if (has_match)
7922 : {
7923 1 : gfc_error ("%qs clause at %L specified more than once",
7924 : "match", &gfc_current_locus);
7925 1 : return MATCH_ERROR;
7926 : }
7927 417 : has_match = true;
7928 417 : if (gfc_match_omp_context_selector_specification (&odv->set_selectors)
7929 : != MATCH_YES)
7930 : return MATCH_ERROR;
7931 377 : if (gfc_match (" )") != MATCH_YES)
7932 : {
7933 0 : gfc_error ("expected %<)%> at %C");
7934 0 : return MATCH_ERROR;
7935 : }
7936 : }
7937 113 : else if (ccode == clause_adjust_args)
7938 : {
7939 81 : has_adjust_args = true;
7940 81 : bool need_device_ptr_p = false;
7941 81 : bool need_device_addr_p = false;
7942 81 : if (gfc_match ("nothing ") == MATCH_YES)
7943 : ;
7944 58 : else if (gfc_match ("need_device_ptr ") == MATCH_YES)
7945 : need_device_ptr_p = true;
7946 9 : else if (gfc_match ("need_device_addr ") == MATCH_YES)
7947 : need_device_addr_p = true;
7948 : else
7949 : {
7950 2 : gfc_error ("expected %<nothing%>, %<need_device_ptr%> or "
7951 : "%<need_device_addr%> at %C");
7952 2 : return MATCH_ERROR;
7953 : }
7954 79 : if (gfc_match (": ") != MATCH_YES)
7955 : {
7956 1 : gfc_error ("expected %<:%> at %C");
7957 1 : return MATCH_ERROR;
7958 : }
7959 : gfc_omp_namelist *tail = NULL;
7960 : bool need_range = false, have_range = false;
7961 125 : while (true)
7962 : {
7963 125 : gfc_omp_namelist *p = gfc_get_omp_namelist ();
7964 125 : p->where = gfc_current_locus;
7965 125 : p->u.adj_args.need_ptr = need_device_ptr_p;
7966 125 : p->u.adj_args.need_addr = need_device_addr_p;
7967 125 : if (tail)
7968 : {
7969 47 : tail->next = p;
7970 47 : tail = tail->next;
7971 : }
7972 : else
7973 : {
7974 78 : gfc_omp_namelist **q = &odv->adjust_args_list;
7975 78 : if (*q)
7976 : {
7977 50 : for (; (*q)->next; q = &(*q)->next)
7978 : ;
7979 28 : (*q)->next = p;
7980 : }
7981 : else
7982 50 : *q = p;
7983 : tail = p;
7984 : }
7985 125 : if (gfc_match (": ") == MATCH_YES)
7986 : {
7987 2 : if (have_range)
7988 : {
7989 0 : gfc_error ("unexpected %<:%> at %C");
7990 2 : return MATCH_ERROR;
7991 : }
7992 2 : p->u.adj_args.range_start = have_range = true;
7993 2 : need_range = false;
7994 47 : continue;
7995 : }
7996 123 : if (have_range && gfc_match (", ") == MATCH_YES)
7997 : {
7998 1 : have_range = false;
7999 1 : continue;
8000 : }
8001 122 : if (have_range && gfc_match (") ") == MATCH_YES)
8002 : break;
8003 121 : locus saved_loc = gfc_current_locus;
8004 :
8005 : /* Without ranges, only arg names or integer literals permitted;
8006 : handle literals here as gfc_match_expr simplifies the expr. */
8007 121 : if (gfc_match_literal_constant (&p->expr, true) == MATCH_YES)
8008 : {
8009 17 : gfc_gobble_whitespace ();
8010 17 : char c = gfc_peek_ascii_char ();
8011 17 : if (c != ')' && c != ',' && c != ':')
8012 : {
8013 1 : gfc_free_expr (p->expr);
8014 1 : p->expr = NULL;
8015 1 : gfc_current_locus = saved_loc;
8016 : }
8017 : }
8018 121 : if (!p->expr && gfc_match ("omp_num_args") == MATCH_YES)
8019 : {
8020 6 : if (!have_range)
8021 3 : p->u.adj_args.range_start = need_range = true;
8022 : else
8023 : need_range = false;
8024 :
8025 6 : locus saved_loc2 = gfc_current_locus;
8026 6 : gfc_gobble_whitespace ();
8027 6 : char c = gfc_peek_ascii_char ();
8028 6 : if (c == '+' || c == '-')
8029 : {
8030 5 : if (gfc_match ("+ %e", &p->expr) == MATCH_YES)
8031 1 : p->u.adj_args.omp_num_args_plus = true;
8032 4 : else if (gfc_match ("- %e", &p->expr) == MATCH_YES)
8033 4 : p->u.adj_args.omp_num_args_minus = true;
8034 0 : else if (!gfc_error_check ())
8035 : {
8036 0 : gfc_error ("expected constant integer expression "
8037 : "at %C");
8038 0 : p->u.adj_args.error_p = true;
8039 0 : return MATCH_ERROR;
8040 : }
8041 5 : p->where = gfc_get_location_range (&saved_loc, 1,
8042 : &saved_loc, 1,
8043 : &gfc_current_locus);
8044 : }
8045 : else
8046 : {
8047 1 : p->where = gfc_get_location_range (&saved_loc, 1,
8048 : &saved_loc, 1,
8049 : &saved_loc2);
8050 1 : p->u.adj_args.omp_num_args_plus = true;
8051 : }
8052 : }
8053 115 : else if (!p->expr)
8054 : {
8055 99 : match m = gfc_match_expr (&p->expr);
8056 99 : if (m != MATCH_YES)
8057 : {
8058 1 : gfc_error ("expected dummy parameter name, "
8059 : "%<omp_num_args%> or constant positive integer"
8060 : " at %C");
8061 1 : p->u.adj_args.error_p = true;
8062 1 : return MATCH_ERROR;
8063 : }
8064 98 : if (p->expr->expr_type == EXPR_CONSTANT && !have_range)
8065 98 : need_range = true; /* Constant expr but not literal. */
8066 98 : p->where = p->expr->where;
8067 : }
8068 : else
8069 16 : p->where = p->expr->where;
8070 120 : gfc_gobble_whitespace ();
8071 120 : match m = gfc_match (": ");
8072 120 : if (need_range && m != MATCH_YES)
8073 : {
8074 1 : gfc_error ("expected %<:%> at %C");
8075 1 : return MATCH_ERROR;
8076 : }
8077 119 : if (m == MATCH_YES)
8078 : {
8079 6 : p->u.adj_args.range_start = have_range = true;
8080 6 : need_range = false;
8081 6 : continue;
8082 : }
8083 113 : need_range = have_range = false;
8084 113 : if (gfc_match (", ") == MATCH_YES)
8085 38 : continue;
8086 75 : if (gfc_match (") ") == MATCH_YES)
8087 : break;
8088 : }
8089 : }
8090 32 : else if (ccode == clause_append_args)
8091 : {
8092 32 : if (has_append_args)
8093 : {
8094 1 : gfc_error ("%qs clause at %L specified more than once",
8095 : "append_args", &gfc_current_locus);
8096 1 : return MATCH_ERROR;
8097 : }
8098 56 : has_append_args = true;
8099 : gfc_omp_namelist *append_args_last = NULL;
8100 81 : do
8101 : {
8102 56 : gfc_gobble_whitespace ();
8103 56 : if (gfc_match ("interop ") != MATCH_YES)
8104 : {
8105 0 : gfc_error ("expected %<interop%> at %C");
8106 3 : return MATCH_ERROR;
8107 : }
8108 56 : if (gfc_match ("( ") != MATCH_YES)
8109 : {
8110 0 : gfc_error ("expected %<(%> at %C");
8111 0 : return MATCH_ERROR;
8112 : }
8113 :
8114 56 : bool target, targetsync;
8115 56 : char *type_str = NULL;
8116 56 : int type_str_len;
8117 56 : locus loc = gfc_current_locus;
8118 56 : if (gfc_parser_omp_clause_init_modifiers (target, targetsync,
8119 : &type_str, type_str_len,
8120 : false) == MATCH_ERROR)
8121 : return MATCH_ERROR;
8122 :
8123 54 : gfc_omp_namelist *n = gfc_get_omp_namelist();
8124 54 : n->where = loc;
8125 54 : n->u.init.target = target;
8126 54 : n->u.init.targetsync = targetsync;
8127 54 : n->u.init.len = type_str_len;
8128 54 : n->u2.init_interop = type_str;
8129 54 : if (odv->append_args_list)
8130 : {
8131 25 : append_args_last->next = n;
8132 25 : append_args_last = n;
8133 : }
8134 : else
8135 29 : append_args_last = odv->append_args_list = n;
8136 :
8137 54 : gfc_gobble_whitespace ();
8138 54 : if (gfc_match_char (',') == MATCH_YES)
8139 25 : continue;
8140 29 : if (gfc_match_char (')') == MATCH_YES)
8141 : break;
8142 1 : gfc_error ("Expected %<,%> or %<)%> at %C");
8143 1 : return MATCH_ERROR;
8144 25 : }
8145 : while (true);
8146 : }
8147 481 : gfc_gobble_whitespace ();
8148 481 : if (gfc_match_omp_eos () == MATCH_YES)
8149 : break;
8150 109 : gfc_match_char (',');
8151 109 : }
8152 :
8153 378 : if (error_p || (!has_match && !has_adjust_args && !has_append_args))
8154 : {
8155 6 : gfc_error ("expected %<match%>, %<adjust_args%> or %<append_args%> at %C");
8156 6 : return MATCH_ERROR;
8157 : }
8158 :
8159 372 : if (!has_match)
8160 : {
8161 3 : gfc_error ("expected %<match%> clause at %C");
8162 3 : return MATCH_ERROR;
8163 : }
8164 :
8165 : return MATCH_YES;
8166 : }
8167 :
8168 :
8169 : static match
8170 167 : match_omp_metadirective (bool begin_p)
8171 : {
8172 167 : locus old_loc = gfc_current_locus;
8173 167 : gfc_omp_variant *variants_head;
8174 167 : gfc_omp_variant **next_variant = &variants_head;
8175 167 : bool default_seen = false;
8176 :
8177 : /* Parse the context selectors. */
8178 681 : for (;;)
8179 : {
8180 424 : bool default_p = false;
8181 424 : gfc_omp_set_selector *selectors = NULL;
8182 :
8183 424 : gfc_gobble_whitespace ();
8184 424 : if (gfc_match_eos () == MATCH_YES)
8185 : break;
8186 275 : gfc_match_char (',');
8187 275 : gfc_gobble_whitespace ();
8188 :
8189 275 : locus variant_locus = gfc_current_locus;
8190 :
8191 275 : if (gfc_match ("default ( ") == MATCH_YES)
8192 : {
8193 82 : default_p = true;
8194 82 : gfc_warning (OPT_Wdeprecated_openmp,
8195 : "%<default%> clause with metadirective at %L "
8196 : "deprecated since OpenMP 5.2", &variant_locus);
8197 : }
8198 193 : else if (gfc_match ("otherwise ( ") == MATCH_YES)
8199 : default_p = true;
8200 185 : else if (gfc_match ("when ( ") != MATCH_YES)
8201 : {
8202 1 : gfc_error ("expected %<when%>, %<otherwise%>, or %<default%> at %C");
8203 1 : gfc_current_locus = old_loc;
8204 18 : return MATCH_ERROR;
8205 : }
8206 90 : if (default_p && default_seen)
8207 : {
8208 3 : gfc_error ("too many %<otherwise%> or %<default%> clauses "
8209 : "in %<metadirective%> at %C");
8210 3 : gfc_current_locus = old_loc;
8211 3 : return MATCH_ERROR;
8212 : }
8213 271 : else if (default_seen)
8214 : {
8215 1 : gfc_error ("%<otherwise%> or %<default%> clause "
8216 : "must appear last in %<metadirective%> at %C");
8217 1 : gfc_current_locus = old_loc;
8218 1 : return MATCH_ERROR;
8219 : }
8220 :
8221 270 : if (!default_p)
8222 : {
8223 183 : if (gfc_match_omp_context_selector_specification (&selectors)
8224 : != MATCH_YES)
8225 : return MATCH_ERROR;
8226 :
8227 176 : if (gfc_match (" : ") != MATCH_YES)
8228 : {
8229 1 : gfc_error ("expected %<:%> at %C");
8230 1 : gfc_current_locus = old_loc;
8231 1 : return MATCH_ERROR;
8232 : }
8233 :
8234 175 : gfc_commit_symbols ();
8235 : }
8236 :
8237 262 : gfc_matching_omp_context_selector = true;
8238 262 : gfc_statement directive = match_omp_directive ();
8239 262 : gfc_matching_omp_context_selector = false;
8240 :
8241 262 : if (is_omp_declarative_stmt (directive))
8242 0 : sorry_at (gfc_get_location (&gfc_current_locus),
8243 : "declarative directive variants are not supported");
8244 :
8245 262 : if (gfc_error_flag_test ())
8246 : {
8247 2 : gfc_current_locus = old_loc;
8248 2 : return MATCH_ERROR;
8249 : }
8250 :
8251 260 : if (gfc_match (" )") != MATCH_YES)
8252 : {
8253 0 : gfc_error ("Expected %<)%> at %C");
8254 0 : gfc_current_locus = old_loc;
8255 0 : return MATCH_ERROR;
8256 : }
8257 :
8258 260 : gfc_commit_symbols ();
8259 :
8260 260 : if (begin_p
8261 260 : && directive != ST_NONE
8262 260 : && gfc_omp_end_stmt (directive) == ST_NONE)
8263 : {
8264 3 : gfc_error ("variant directive used in OMP BEGIN METADIRECTIVE "
8265 : "at %C must have a corresponding end directive");
8266 3 : gfc_current_locus = old_loc;
8267 3 : return MATCH_ERROR;
8268 : }
8269 :
8270 257 : if (default_p)
8271 : default_seen = true;
8272 :
8273 257 : gfc_omp_variant *omv = gfc_get_omp_variant ();
8274 257 : omv->selectors = selectors;
8275 257 : omv->stmt = directive;
8276 257 : omv->where = variant_locus;
8277 :
8278 257 : if (directive == ST_NONE)
8279 : {
8280 : /* The directive was a 'nothing' directive. */
8281 15 : omv->code = gfc_get_code (EXEC_CONTINUE);
8282 15 : omv->code->ext.omp_clauses = NULL;
8283 : }
8284 : else
8285 : {
8286 242 : omv->code = gfc_get_code (new_st.op);
8287 242 : omv->code->ext.omp_clauses = new_st.ext.omp_clauses;
8288 : /* Prevent the OpenMP clauses from being freed via NEW_ST. */
8289 242 : new_st.ext.omp_clauses = NULL;
8290 : }
8291 :
8292 257 : *next_variant = omv;
8293 257 : next_variant = &omv->next;
8294 257 : }
8295 :
8296 149 : if (gfc_match_omp_eos () != MATCH_YES)
8297 : {
8298 0 : gfc_error ("Unexpected junk after OMP METADIRECTIVE at %C");
8299 0 : gfc_current_locus = old_loc;
8300 0 : return MATCH_ERROR;
8301 : }
8302 :
8303 : /* Add a 'default (nothing)' clause if no default is explicitly given. */
8304 149 : if (!default_seen)
8305 : {
8306 71 : gfc_omp_variant *omv = gfc_get_omp_variant ();
8307 71 : omv->stmt = ST_NONE;
8308 71 : omv->code = gfc_get_code (EXEC_CONTINUE);
8309 71 : omv->code->ext.omp_clauses = NULL;
8310 71 : omv->where = old_loc;
8311 71 : omv->selectors = NULL;
8312 :
8313 71 : *next_variant = omv;
8314 71 : next_variant = &omv->next;
8315 : }
8316 :
8317 149 : new_st.op = EXEC_OMP_METADIRECTIVE;
8318 149 : new_st.ext.omp_variants = variants_head;
8319 :
8320 149 : return MATCH_YES;
8321 : }
8322 :
8323 : match
8324 47 : gfc_match_omp_begin_metadirective (void)
8325 : {
8326 47 : return match_omp_metadirective (true);
8327 : }
8328 :
8329 : match
8330 120 : gfc_match_omp_metadirective (void)
8331 : {
8332 120 : return match_omp_metadirective (false);
8333 : }
8334 :
8335 : /* Match 'omp threadprivate' or 'omp groupprivate'. */
8336 : static match
8337 262 : gfc_match_omp_thread_group_private (bool is_groupprivate)
8338 : {
8339 262 : locus old_loc;
8340 262 : char n[GFC_MAX_SYMBOL_LEN+1];
8341 262 : gfc_symbol *sym;
8342 262 : match m;
8343 262 : gfc_symtree *st;
8344 262 : struct sym_loc_t { gfc_symbol *sym; gfc_common_head *com; locus loc; };
8345 262 : auto_vec<sym_loc_t> syms;
8346 :
8347 262 : old_loc = gfc_current_locus;
8348 :
8349 262 : m = gfc_match (" ( ");
8350 262 : if (m != MATCH_YES)
8351 : return m;
8352 :
8353 372 : for (;;)
8354 : {
8355 317 : locus sym_loc = gfc_current_locus;
8356 317 : m = gfc_match_symbol (&sym, 0);
8357 317 : switch (m)
8358 : {
8359 212 : case MATCH_YES:
8360 212 : if (sym->attr.in_common)
8361 0 : gfc_error_now ("%qs variable at %L is an element of a COMMON block",
8362 : is_groupprivate ? "groupprivate" : "threadprivate",
8363 : &sym_loc);
8364 212 : else if (!is_groupprivate
8365 212 : && !gfc_add_threadprivate (&sym->attr, sym->name, &sym_loc))
8366 16 : goto cleanup;
8367 210 : else if (is_groupprivate)
8368 : {
8369 33 : if (!gfc_add_omp_groupprivate (&sym->attr, sym->name, &sym_loc))
8370 4 : goto cleanup;
8371 29 : syms.safe_push ({sym, nullptr, sym_loc});
8372 : }
8373 206 : goto next_item;
8374 : case MATCH_NO:
8375 : break;
8376 0 : case MATCH_ERROR:
8377 0 : goto cleanup;
8378 : }
8379 :
8380 105 : m = gfc_match (" / %n /", n);
8381 105 : if (m == MATCH_ERROR)
8382 0 : goto cleanup;
8383 105 : if (m == MATCH_NO || n[0] == '\0')
8384 0 : goto syntax;
8385 :
8386 105 : st = gfc_find_symtree (gfc_current_ns->common_root, n);
8387 105 : if (st == NULL)
8388 : {
8389 2 : gfc_error ("COMMON block /%s/ not found at %L", n, &sym_loc);
8390 2 : goto cleanup;
8391 : }
8392 103 : syms.safe_push ({nullptr, st->n.common, sym_loc});
8393 103 : if (is_groupprivate)
8394 30 : st->n.common->omp_groupprivate = 1;
8395 : else
8396 73 : st->n.common->threadprivate = 1;
8397 236 : for (sym = st->n.common->head; sym; sym = sym->common_next)
8398 141 : if (!is_groupprivate
8399 141 : && !gfc_add_threadprivate (&sym->attr, sym->name, &sym_loc))
8400 3 : goto cleanup;
8401 138 : else if (is_groupprivate
8402 138 : && !gfc_add_omp_groupprivate (&sym->attr, sym->name, &sym_loc))
8403 5 : goto cleanup;
8404 :
8405 95 : next_item:
8406 301 : if (gfc_match_char (')') == MATCH_YES)
8407 : break;
8408 55 : if (gfc_match_char (',') != MATCH_YES)
8409 0 : goto syntax;
8410 55 : }
8411 :
8412 246 : if (is_groupprivate)
8413 : {
8414 42 : gfc_omp_clauses *c;
8415 42 : m = gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_DEVICE_TYPE), false, false);
8416 42 : if (m == MATCH_ERROR)
8417 0 : return MATCH_ERROR;
8418 :
8419 42 : if (c->device_type == OMP_DEVICE_TYPE_UNSET)
8420 19 : c->device_type = OMP_DEVICE_TYPE_ANY;
8421 :
8422 92 : for (size_t i = 0; i < syms.length (); i++)
8423 50 : if (syms[i].sym)
8424 : {
8425 27 : sym_loc_t &n = syms[i];
8426 27 : if (n.sym->attr.in_common)
8427 0 : gfc_error_now ("Variable %qs at %L is an element of a COMMON "
8428 : "block", n.sym->name, &n.loc);
8429 27 : else if (n.sym->attr.omp_declare_target
8430 26 : || n.sym->attr.omp_declare_target_link)
8431 2 : gfc_error_now ("List item %qs at %L implies OMP DECLARE TARGET "
8432 : "with the LOCAL clause, but it has been specified"
8433 : " with a different clause before",
8434 : n.sym->name, &n.loc);
8435 27 : if (n.sym->attr.omp_device_type != OMP_DEVICE_TYPE_UNSET
8436 5 : && n.sym->attr.omp_device_type != c->device_type)
8437 : {
8438 2 : const char *dt = "any";
8439 2 : if (n.sym->attr.omp_device_type == OMP_DEVICE_TYPE_HOST)
8440 : dt = "host";
8441 0 : else if (n.sym->attr.omp_device_type == OMP_DEVICE_TYPE_NOHOST)
8442 0 : dt = "nohost";
8443 2 : gfc_error_now ("List item %qs at %L set in previous OMP DECLARE "
8444 : "TARGET directive to the different DEVICE_TYPE %qs",
8445 : n.sym->name, &n.loc, dt);
8446 : }
8447 27 : gfc_add_omp_declare_target_local (&n.sym->attr, n.sym->name,
8448 : &n.loc);
8449 27 : n.sym->attr.omp_device_type = c->device_type;
8450 : }
8451 : else /* Common block. */
8452 : {
8453 23 : sym_loc_t &n = syms[i];
8454 23 : if (n.com->omp_declare_target
8455 22 : || n.com->omp_declare_target_link)
8456 2 : gfc_error_now ("List item %</%s/%> at %L implies OMP DECLARE "
8457 : "TARGET with the LOCAL clause, but it has been "
8458 : "specified with a different clause before",
8459 2 : n.com->name, &n.loc);
8460 23 : if (n.com->omp_device_type != OMP_DEVICE_TYPE_UNSET
8461 5 : && n.com->omp_device_type != c->device_type)
8462 : {
8463 2 : const char *dt = "any";
8464 2 : if (n.com->omp_device_type == OMP_DEVICE_TYPE_HOST)
8465 : dt = "host";
8466 0 : else if (n.com->omp_device_type == OMP_DEVICE_TYPE_NOHOST)
8467 0 : dt = "nohost";
8468 2 : gfc_error_now ("List item %qs at %L set in previous OMP DECLARE"
8469 : " TARGET directive to the different DEVICE_TYPE "
8470 2 : "%qs", n.com->name, &n.loc, dt);
8471 : }
8472 23 : n.com->omp_declare_target_local = 1;
8473 23 : n.com->omp_device_type = c->device_type;
8474 46 : for (gfc_symbol *s = n.com->head; s; s = s->common_next)
8475 : {
8476 23 : gfc_add_omp_declare_target_local (&s->attr, s->name, &n.loc);
8477 23 : s->attr.omp_device_type = c->device_type;
8478 : }
8479 : }
8480 42 : free (c);
8481 : }
8482 :
8483 246 : if (gfc_match_omp_eos () != MATCH_YES)
8484 : {
8485 0 : gfc_error ("Unexpected junk after OMP %s at %C",
8486 : is_groupprivate ? "GROUPPRIVATE" : "THREADPRIVATE");
8487 0 : goto cleanup;
8488 : }
8489 :
8490 : return MATCH_YES;
8491 :
8492 0 : syntax:
8493 0 : gfc_error ("Syntax error in !$OMP %s list at %C",
8494 : is_groupprivate ? "GROUPPRIVATE" : "THREADPRIVATE");
8495 :
8496 16 : cleanup:
8497 16 : gfc_current_locus = old_loc;
8498 16 : return MATCH_ERROR;
8499 262 : }
8500 :
8501 :
8502 : match
8503 51 : gfc_match_omp_groupprivate (void)
8504 : {
8505 51 : return gfc_match_omp_thread_group_private (true);
8506 : }
8507 :
8508 :
8509 : match
8510 211 : gfc_match_omp_threadprivate (void)
8511 : {
8512 211 : return gfc_match_omp_thread_group_private (false);
8513 : }
8514 :
8515 :
8516 : match
8517 2215 : gfc_match_omp_parallel (void)
8518 : {
8519 2215 : return match_omp (EXEC_OMP_PARALLEL, OMP_PARALLEL_CLAUSES);
8520 : }
8521 :
8522 :
8523 : match
8524 1203 : gfc_match_omp_parallel_do (void)
8525 : {
8526 1203 : return match_omp (EXEC_OMP_PARALLEL_DO,
8527 1203 : (OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES)
8528 1203 : & ~(omp_mask (OMP_CLAUSE_NOWAIT)));
8529 : }
8530 :
8531 :
8532 : match
8533 298 : gfc_match_omp_parallel_do_simd (void)
8534 : {
8535 298 : return match_omp (EXEC_OMP_PARALLEL_DO_SIMD,
8536 298 : (OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES | OMP_SIMD_CLAUSES)
8537 298 : & ~(omp_mask (OMP_CLAUSE_NOWAIT)));
8538 : }
8539 :
8540 :
8541 : match
8542 14 : gfc_match_omp_parallel_masked (void)
8543 : {
8544 14 : return match_omp (EXEC_OMP_PARALLEL_MASKED,
8545 14 : OMP_PARALLEL_CLAUSES | OMP_MASKED_CLAUSES);
8546 : }
8547 :
8548 : match
8549 10 : gfc_match_omp_parallel_masked_taskloop (void)
8550 : {
8551 10 : return match_omp (EXEC_OMP_PARALLEL_MASKED_TASKLOOP,
8552 10 : (OMP_PARALLEL_CLAUSES | OMP_MASKED_CLAUSES
8553 10 : | OMP_TASKLOOP_CLAUSES)
8554 10 : & ~(omp_mask (OMP_CLAUSE_IN_REDUCTION)));
8555 : }
8556 :
8557 : match
8558 13 : gfc_match_omp_parallel_masked_taskloop_simd (void)
8559 : {
8560 13 : return match_omp (EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD,
8561 13 : (OMP_PARALLEL_CLAUSES | OMP_MASKED_CLAUSES
8562 13 : | OMP_TASKLOOP_CLAUSES | OMP_SIMD_CLAUSES)
8563 13 : & ~(omp_mask (OMP_CLAUSE_IN_REDUCTION)));
8564 : }
8565 :
8566 : match
8567 14 : gfc_match_omp_parallel_master (void)
8568 : {
8569 14 : gfc_warning (OPT_Wdeprecated_openmp,
8570 : "%<master%> construct at %C deprecated since OpenMP 5.1, use "
8571 : "%<masked%>");
8572 14 : return match_omp (EXEC_OMP_PARALLEL_MASTER, OMP_PARALLEL_CLAUSES);
8573 : }
8574 :
8575 : match
8576 16 : gfc_match_omp_parallel_master_taskloop (void)
8577 : {
8578 16 : gfc_warning (OPT_Wdeprecated_openmp,
8579 : "%<master%> construct at %C deprecated since OpenMP 5.1, "
8580 : "use %<masked%>");
8581 16 : return match_omp (EXEC_OMP_PARALLEL_MASTER_TASKLOOP,
8582 16 : (OMP_PARALLEL_CLAUSES | OMP_TASKLOOP_CLAUSES)
8583 16 : & ~(omp_mask (OMP_CLAUSE_IN_REDUCTION)));
8584 : }
8585 :
8586 : match
8587 21 : gfc_match_omp_parallel_master_taskloop_simd (void)
8588 : {
8589 21 : gfc_warning (OPT_Wdeprecated_openmp,
8590 : "%<master%> construct at %C deprecated since OpenMP 5.1, "
8591 : "use %<masked%>");
8592 21 : return match_omp (EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD,
8593 21 : (OMP_PARALLEL_CLAUSES | OMP_TASKLOOP_CLAUSES
8594 21 : | OMP_SIMD_CLAUSES)
8595 21 : & ~(omp_mask (OMP_CLAUSE_IN_REDUCTION)));
8596 : }
8597 :
8598 : match
8599 59 : gfc_match_omp_parallel_sections (void)
8600 : {
8601 59 : return match_omp (EXEC_OMP_PARALLEL_SECTIONS,
8602 59 : (OMP_PARALLEL_CLAUSES | OMP_SECTIONS_CLAUSES)
8603 59 : & ~(omp_mask (OMP_CLAUSE_NOWAIT)));
8604 : }
8605 :
8606 :
8607 : match
8608 56 : gfc_match_omp_parallel_workshare (void)
8609 : {
8610 56 : return match_omp (EXEC_OMP_PARALLEL_WORKSHARE, OMP_PARALLEL_CLAUSES);
8611 : }
8612 :
8613 : void
8614 50799 : gfc_check_omp_requires (gfc_namespace *ns, int ref_omp_requires)
8615 : {
8616 50799 : const char *msg = G_("Program unit at %L has OpenMP device "
8617 : "constructs/routines but does not set !$OMP REQUIRES %s "
8618 : "but other program units do");
8619 50799 : if (ns->omp_target_seen
8620 1304 : && (ns->omp_requires & OMP_REQ_TARGET_MASK)
8621 1304 : != (ref_omp_requires & OMP_REQ_TARGET_MASK))
8622 : {
8623 6 : gcc_assert (ns->proc_name);
8624 6 : if ((ref_omp_requires & OMP_REQ_REVERSE_OFFLOAD)
8625 5 : && !(ns->omp_requires & OMP_REQ_REVERSE_OFFLOAD))
8626 4 : gfc_error (msg, &ns->proc_name->declared_at, "REVERSE_OFFLOAD");
8627 6 : if ((ref_omp_requires & OMP_REQ_UNIFIED_ADDRESS)
8628 1 : && !(ns->omp_requires & OMP_REQ_UNIFIED_ADDRESS))
8629 1 : gfc_error (msg, &ns->proc_name->declared_at, "UNIFIED_ADDRESS");
8630 6 : if ((ref_omp_requires & OMP_REQ_UNIFIED_SHARED_MEMORY)
8631 4 : && !(ns->omp_requires & OMP_REQ_UNIFIED_SHARED_MEMORY))
8632 2 : gfc_error (msg, &ns->proc_name->declared_at, "UNIFIED_SHARED_MEMORY");
8633 6 : if ((ref_omp_requires & OMP_REQ_SELF_MAPS)
8634 1 : && !(ns->omp_requires & OMP_REQ_UNIFIED_SHARED_MEMORY))
8635 1 : gfc_error (msg, &ns->proc_name->declared_at, "SELF_MAPS");
8636 : }
8637 50799 : }
8638 :
8639 : bool
8640 138 : gfc_omp_requires_add_clause (gfc_omp_requires_kind clause,
8641 : const char *clause_name, locus *loc,
8642 : const char *module_name)
8643 : {
8644 138 : gfc_namespace *prog_unit = gfc_current_ns;
8645 162 : while (prog_unit->parent)
8646 : {
8647 26 : if (gfc_state_stack->previous
8648 26 : && gfc_state_stack->previous->state == COMP_INTERFACE)
8649 : break;
8650 : /* A submodule namespace may have its parent set to the ancestor module
8651 : for host-association purposes. Do not escape the submodule boundary:
8652 : the submodule itself is the program unit for OMP REQUIRES purposes. */
8653 25 : if (prog_unit->proc_name
8654 25 : && prog_unit->proc_name->attr.flavor == FL_MODULE)
8655 : break;
8656 24 : prog_unit = prog_unit->parent;
8657 : }
8658 :
8659 : /* Requires added after use. */
8660 138 : if (prog_unit->omp_target_seen
8661 24 : && (clause & OMP_REQ_TARGET_MASK)
8662 24 : && !(prog_unit->omp_requires & clause))
8663 : {
8664 0 : if (module_name)
8665 0 : gfc_error ("!$OMP REQUIRES clause %qs specified via module %qs use "
8666 : "at %L comes after using a device construct/routine",
8667 : clause_name, module_name, loc);
8668 : else
8669 0 : gfc_error ("!$OMP REQUIRES clause %qs specified at %L comes after "
8670 : "using a device construct/routine", clause_name, loc);
8671 : return false;
8672 : }
8673 :
8674 : /* Overriding atomic_default_mem_order clause value. */
8675 138 : if ((clause & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
8676 34 : && (prog_unit->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
8677 6 : && (prog_unit->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
8678 6 : != (int) clause)
8679 : {
8680 3 : const char *other;
8681 3 : switch (prog_unit->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
8682 : {
8683 : case OMP_REQ_ATOMIC_MEM_ORDER_SEQ_CST: other = "seq_cst"; break;
8684 0 : case OMP_REQ_ATOMIC_MEM_ORDER_ACQ_REL: other = "acq_rel"; break;
8685 1 : case OMP_REQ_ATOMIC_MEM_ORDER_ACQUIRE: other = "acquire"; break;
8686 1 : case OMP_REQ_ATOMIC_MEM_ORDER_RELAXED: other = "relaxed"; break;
8687 0 : case OMP_REQ_ATOMIC_MEM_ORDER_RELEASE: other = "release"; break;
8688 0 : default: gcc_unreachable ();
8689 : }
8690 :
8691 3 : if (module_name)
8692 0 : gfc_error ("!$OMP REQUIRES clause %<atomic_default_mem_order(%s)%> "
8693 : "specified via module %qs use at %L overrides a previous "
8694 : "%<atomic_default_mem_order(%s)%> (which might be through "
8695 : "using a module)", clause_name, module_name, loc, other);
8696 : else
8697 3 : gfc_error ("!$OMP REQUIRES clause %<atomic_default_mem_order(%s)%> "
8698 : "specified at %L overrides a previous "
8699 : "%<atomic_default_mem_order(%s)%> (which might be through "
8700 : "using a module)", clause_name, loc, other);
8701 : return false;
8702 : }
8703 :
8704 : /* Requires via module not at program-unit level and not repeating clause. */
8705 135 : if (prog_unit != gfc_current_ns && !(prog_unit->omp_requires & clause))
8706 : {
8707 0 : if (clause & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
8708 0 : gfc_error ("!$OMP REQUIRES clause %<atomic_default_mem_order(%s)%> "
8709 : "specified via module %qs use at %L but same clause is "
8710 : "not specified for the program unit", clause_name,
8711 : module_name, loc);
8712 : else
8713 0 : gfc_error ("!$OMP REQUIRES clause %qs specified via module %qs use at "
8714 : "%L but same clause is not specified for the program unit",
8715 : clause_name, module_name, loc);
8716 : return false;
8717 : }
8718 :
8719 135 : if (!gfc_state_stack->previous
8720 127 : || gfc_state_stack->previous->state != COMP_INTERFACE)
8721 134 : prog_unit->omp_requires |= clause;
8722 : return true;
8723 : }
8724 :
8725 : match
8726 110 : gfc_match_omp_requires (void)
8727 : {
8728 110 : static const char *clauses[] = {"reverse_offload",
8729 : "unified_address",
8730 : "unified_shared_memory",
8731 : "self_maps",
8732 : "dynamic_allocators",
8733 : "atomic_default_mem_order"};
8734 110 : const char *clause = NULL;
8735 110 : int requires_clauses = 0;
8736 110 : int seen_clauses = 0;
8737 110 : bool first = true;
8738 110 : locus old_loc;
8739 :
8740 : /* A submodule's namespace may have its parent pointer set to the ancestor
8741 : module namespace for host-association purposes. The submodule spec part
8742 : is still a valid program-unit spec part for OMP REQUIRES. Only reject
8743 : the directive when we are genuinely nested inside a procedure. */
8744 110 : if (gfc_current_ns->parent
8745 8 : && !(gfc_current_ns->proc_name
8746 8 : && gfc_current_ns->proc_name->attr.flavor == FL_MODULE)
8747 7 : && (!gfc_state_stack->previous
8748 7 : || gfc_state_stack->previous->state != COMP_INTERFACE))
8749 : {
8750 6 : gfc_error ("!$OMP REQUIRES at %C must appear in the specification part "
8751 : "of a program unit");
8752 6 : return MATCH_ERROR;
8753 : }
8754 :
8755 : /* Specifying '<clause>(.false.)' in this directive does not affect requirements
8756 : set in another 'requires' directive in the same compilation unit; however,
8757 : specifying it multiple times in the same directive is disallowed. */
8758 336 : while (true)
8759 : {
8760 220 : bool bval;
8761 220 : match m;
8762 220 : old_loc = gfc_current_locus;
8763 220 : gfc_omp_requires_kind requires_clause = OMP_REQ_NONE;
8764 220 : if (gfc_match_char (',') != MATCH_YES
8765 220 : && (first && gfc_match_space () != MATCH_YES))
8766 17 : goto error;
8767 220 : first = false;
8768 220 : gfc_gobble_whitespace ();
8769 220 : old_loc = gfc_current_locus;
8770 :
8771 220 : if (gfc_match_omp_eos () != MATCH_NO)
8772 : break;
8773 133 : if ((m = gfc_match_boolean_clause (&bval, clauses[0],
8774 133 : seen_clauses & OMP_REQ_REVERSE_OFFLOAD)) != MATCH_NO)
8775 : {
8776 40 : if (m == MATCH_ERROR)
8777 2 : goto error;
8778 38 : clause = clauses[0];
8779 38 : seen_clauses |= OMP_REQ_REVERSE_OFFLOAD;
8780 38 : if (bval)
8781 : requires_clause = OMP_REQ_REVERSE_OFFLOAD;
8782 : }
8783 93 : else if ((m = gfc_match_boolean_clause (&bval, clauses[1],
8784 93 : seen_clauses & OMP_REQ_UNIFIED_ADDRESS)) != MATCH_NO)
8785 : {
8786 14 : if (m == MATCH_ERROR)
8787 2 : goto error;
8788 12 : clause = clauses[1];
8789 12 : seen_clauses |= OMP_REQ_UNIFIED_ADDRESS;
8790 12 : if (bval)
8791 : requires_clause = OMP_REQ_UNIFIED_ADDRESS;
8792 : }
8793 79 : else if ((m = gfc_match_boolean_clause (&bval, clauses[2],
8794 79 : seen_clauses & OMP_REQ_UNIFIED_SHARED_MEMORY))
8795 : != MATCH_NO)
8796 : {
8797 17 : if (m == MATCH_ERROR)
8798 1 : goto error;
8799 16 : clause = clauses[2];
8800 16 : seen_clauses |= OMP_REQ_UNIFIED_SHARED_MEMORY;
8801 16 : if (bval)
8802 : requires_clause = OMP_REQ_UNIFIED_SHARED_MEMORY;
8803 : }
8804 62 : else if ((m = gfc_match_boolean_clause (&bval, clauses[3],
8805 62 : seen_clauses & OMP_REQ_SELF_MAPS)) != MATCH_NO)
8806 : {
8807 19 : if (m == MATCH_ERROR)
8808 4 : goto error;
8809 15 : clause = clauses[3];
8810 15 : seen_clauses |= OMP_REQ_SELF_MAPS;
8811 15 : if (bval)
8812 : requires_clause = OMP_REQ_SELF_MAPS;
8813 : }
8814 43 : else if ((m = gfc_match_boolean_clause (&bval, clauses[4],
8815 43 : seen_clauses & OMP_REQ_DYNAMIC_ALLOCATORS)) != MATCH_NO)
8816 : {
8817 11 : if (m == MATCH_ERROR)
8818 1 : goto error;
8819 10 : clause = clauses[4];
8820 10 : seen_clauses |= OMP_REQ_DYNAMIC_ALLOCATORS;
8821 10 : if (bval)
8822 : requires_clause = OMP_REQ_DYNAMIC_ALLOCATORS;
8823 : }
8824 32 : else if ((m = gfc_match_dupl_check (
8825 32 : !(seen_clauses & OMP_REQ_ATOMIC_MEM_ORDER_MASK),
8826 : clauses[5], true)) != MATCH_NO)
8827 : {
8828 31 : if (m == MATCH_ERROR)
8829 1 : goto error;
8830 30 : seen_clauses |= OMP_REQ_ATOMIC_MEM_ORDER_MASK;
8831 30 : if (gfc_match (" seq_cst )") == MATCH_YES)
8832 : {
8833 : clause = "seq_cst";
8834 : requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_SEQ_CST;
8835 : }
8836 18 : else if (gfc_match (" acq_rel )") == MATCH_YES)
8837 : {
8838 : clause = "acq_rel";
8839 : requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_ACQ_REL;
8840 : }
8841 12 : else if (gfc_match (" acquire )") == MATCH_YES)
8842 : {
8843 : clause = "acquire";
8844 : requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_ACQUIRE;
8845 : }
8846 9 : else if (gfc_match (" relaxed )") == MATCH_YES)
8847 : {
8848 : clause = "relaxed";
8849 : requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_RELAXED;
8850 : }
8851 5 : else if (gfc_match (" release )") == MATCH_YES)
8852 : {
8853 : clause = "release";
8854 : requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_RELEASE;
8855 : }
8856 : else
8857 : {
8858 2 : gfc_error ("Expected ACQ_REL, ACQUIRE, RELAXED, RELEASE or "
8859 : "SEQ_CST for ATOMIC_DEFAULT_MEM_ORDER clause at %C");
8860 2 : goto error;
8861 : }
8862 : }
8863 : else
8864 1 : goto error;
8865 :
8866 : if (requires_clause != OMP_REQ_NONE
8867 107 : && !gfc_omp_requires_add_clause (requires_clause, clause, &old_loc, NULL))
8868 3 : goto error;
8869 116 : requires_clauses |= requires_clause;
8870 116 : }
8871 :
8872 87 : if (requires_clauses == 0)
8873 2 : goto error;
8874 : return MATCH_YES;
8875 :
8876 19 : error:
8877 19 : if (!gfc_error_flag_test ())
8878 3 : gfc_error ("Expected UNIFIED_ADDRESS, UNIFIED_SHARED_MEMORY, SELF_MAPS, "
8879 : "DYNAMIC_ALLOCATORS, REVERSE_OFFLOAD, or "
8880 : "ATOMIC_DEFAULT_MEM_ORDER clause at %L", &old_loc);
8881 : return MATCH_ERROR;
8882 : }
8883 :
8884 :
8885 : match
8886 51 : gfc_match_omp_scan (void)
8887 : {
8888 51 : bool incl;
8889 51 : gfc_omp_clauses *c = gfc_get_omp_clauses ();
8890 51 : gfc_gobble_whitespace ();
8891 51 : gfc_match (", "); /* optionally */
8892 51 : if ((incl = (gfc_match ("inclusive") == MATCH_YES))
8893 51 : || gfc_match ("exclusive") == MATCH_YES)
8894 : {
8895 70 : if (gfc_match_omp_variable_list (" (", &c->lists[incl ? OMP_LIST_SCAN_IN
8896 : : OMP_LIST_SCAN_EX],
8897 : false) != MATCH_YES)
8898 : {
8899 0 : gfc_free_omp_clauses (c);
8900 0 : return MATCH_ERROR;
8901 : }
8902 : }
8903 : else
8904 : {
8905 1 : gfc_error ("Expected INCLUSIVE or EXCLUSIVE clause at %C");
8906 1 : gfc_free_omp_clauses (c);
8907 1 : return MATCH_ERROR;
8908 : }
8909 50 : if (gfc_match_omp_eos () != MATCH_YES)
8910 : {
8911 1 : gfc_error ("Unexpected junk after !$OMP SCAN at %C");
8912 1 : gfc_free_omp_clauses (c);
8913 1 : return MATCH_ERROR;
8914 : }
8915 :
8916 49 : new_st.op = EXEC_OMP_SCAN;
8917 49 : new_st.ext.omp_clauses = c;
8918 49 : return MATCH_YES;
8919 : }
8920 :
8921 :
8922 : match
8923 58 : gfc_match_omp_scope (void)
8924 : {
8925 58 : return match_omp (EXEC_OMP_SCOPE, OMP_SCOPE_CLAUSES);
8926 : }
8927 :
8928 :
8929 : match
8930 82 : gfc_match_omp_sections (void)
8931 : {
8932 82 : return match_omp (EXEC_OMP_SECTIONS, OMP_SECTIONS_CLAUSES);
8933 : }
8934 :
8935 :
8936 : match
8937 805 : gfc_match_omp_simd (void)
8938 : {
8939 805 : return match_omp (EXEC_OMP_SIMD, OMP_SIMD_CLAUSES);
8940 : }
8941 :
8942 :
8943 : match
8944 574 : gfc_match_omp_single (void)
8945 : {
8946 574 : return match_omp (EXEC_OMP_SINGLE, OMP_SINGLE_CLAUSES);
8947 : }
8948 :
8949 :
8950 : match
8951 2260 : gfc_match_omp_target (void)
8952 : {
8953 2260 : return match_omp (EXEC_OMP_TARGET, OMP_TARGET_CLAUSES);
8954 : }
8955 :
8956 :
8957 : match
8958 1401 : gfc_match_omp_target_data (void)
8959 : {
8960 1401 : return match_omp (EXEC_OMP_TARGET_DATA, OMP_TARGET_DATA_CLAUSES);
8961 : }
8962 :
8963 :
8964 : match
8965 472 : gfc_match_omp_target_enter_data (void)
8966 : {
8967 472 : return match_omp (EXEC_OMP_TARGET_ENTER_DATA, OMP_TARGET_ENTER_DATA_CLAUSES);
8968 : }
8969 :
8970 :
8971 : match
8972 367 : gfc_match_omp_target_exit_data (void)
8973 : {
8974 367 : return match_omp (EXEC_OMP_TARGET_EXIT_DATA, OMP_TARGET_EXIT_DATA_CLAUSES);
8975 : }
8976 :
8977 :
8978 : match
8979 29 : gfc_match_omp_target_parallel (void)
8980 : {
8981 29 : return match_omp (EXEC_OMP_TARGET_PARALLEL,
8982 29 : (OMP_TARGET_CLAUSES | OMP_PARALLEL_CLAUSES)
8983 29 : & ~(omp_mask (OMP_CLAUSE_COPYIN)));
8984 : }
8985 :
8986 :
8987 : match
8988 81 : gfc_match_omp_target_parallel_do (void)
8989 : {
8990 81 : return match_omp (EXEC_OMP_TARGET_PARALLEL_DO,
8991 81 : (OMP_TARGET_CLAUSES | OMP_PARALLEL_CLAUSES
8992 81 : | OMP_DO_CLAUSES) & ~(omp_mask (OMP_CLAUSE_COPYIN)));
8993 : }
8994 :
8995 :
8996 : match
8997 20 : gfc_match_omp_target_parallel_do_simd (void)
8998 : {
8999 20 : return match_omp (EXEC_OMP_TARGET_PARALLEL_DO_SIMD,
9000 20 : (OMP_TARGET_CLAUSES | OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES
9001 20 : | OMP_SIMD_CLAUSES) & ~(omp_mask (OMP_CLAUSE_COPYIN)));
9002 : }
9003 :
9004 :
9005 : match
9006 34 : gfc_match_omp_target_simd (void)
9007 : {
9008 34 : return match_omp (EXEC_OMP_TARGET_SIMD,
9009 34 : OMP_TARGET_CLAUSES | OMP_SIMD_CLAUSES);
9010 : }
9011 :
9012 :
9013 : match
9014 77 : gfc_match_omp_target_teams (void)
9015 : {
9016 77 : return match_omp (EXEC_OMP_TARGET_TEAMS,
9017 77 : OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES);
9018 : }
9019 :
9020 :
9021 : match
9022 19 : gfc_match_omp_target_teams_distribute (void)
9023 : {
9024 19 : return match_omp (EXEC_OMP_TARGET_TEAMS_DISTRIBUTE,
9025 19 : OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES
9026 19 : | OMP_DISTRIBUTE_CLAUSES);
9027 : }
9028 :
9029 :
9030 : match
9031 66 : gfc_match_omp_target_teams_distribute_parallel_do (void)
9032 : {
9033 66 : return match_omp (EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO,
9034 66 : (OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES
9035 66 : | OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
9036 66 : | OMP_DO_CLAUSES)
9037 66 : & ~(omp_mask (OMP_CLAUSE_ORDERED))
9038 66 : & ~(omp_mask (OMP_CLAUSE_LINEAR)));
9039 : }
9040 :
9041 :
9042 : match
9043 36 : gfc_match_omp_target_teams_distribute_parallel_do_simd (void)
9044 : {
9045 36 : return match_omp (EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD,
9046 36 : (OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES
9047 36 : | OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
9048 36 : | OMP_DO_CLAUSES | OMP_SIMD_CLAUSES)
9049 36 : & ~(omp_mask (OMP_CLAUSE_ORDERED)));
9050 : }
9051 :
9052 :
9053 : match
9054 21 : gfc_match_omp_target_teams_distribute_simd (void)
9055 : {
9056 21 : return match_omp (EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD,
9057 21 : OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES
9058 21 : | OMP_DISTRIBUTE_CLAUSES | OMP_SIMD_CLAUSES);
9059 : }
9060 :
9061 :
9062 : match
9063 1727 : gfc_match_omp_target_update (void)
9064 : {
9065 1727 : return match_omp (EXEC_OMP_TARGET_UPDATE, OMP_TARGET_UPDATE_CLAUSES);
9066 : }
9067 :
9068 :
9069 : match
9070 1184 : gfc_match_omp_task (void)
9071 : {
9072 1184 : return match_omp (EXEC_OMP_TASK, OMP_TASK_CLAUSES);
9073 : }
9074 :
9075 :
9076 : match
9077 72 : gfc_match_omp_taskloop (void)
9078 : {
9079 72 : return match_omp (EXEC_OMP_TASKLOOP, OMP_TASKLOOP_CLAUSES);
9080 : }
9081 :
9082 :
9083 : match
9084 40 : gfc_match_omp_taskloop_simd (void)
9085 : {
9086 40 : return match_omp (EXEC_OMP_TASKLOOP_SIMD,
9087 40 : OMP_TASKLOOP_CLAUSES | OMP_SIMD_CLAUSES);
9088 : }
9089 :
9090 :
9091 : match
9092 149 : gfc_match_omp_taskwait (void)
9093 : {
9094 149 : if (gfc_match_omp_eos () == MATCH_YES)
9095 : {
9096 135 : new_st.op = EXEC_OMP_TASKWAIT;
9097 135 : new_st.ext.omp_clauses = NULL;
9098 135 : return MATCH_YES;
9099 : }
9100 14 : return match_omp (EXEC_OMP_TASKWAIT,
9101 14 : omp_mask (OMP_CLAUSE_DEPEND) | OMP_CLAUSE_NOWAIT);
9102 : }
9103 :
9104 :
9105 : match
9106 10 : gfc_match_omp_taskyield (void)
9107 : {
9108 10 : if (gfc_match_omp_eos () != MATCH_YES)
9109 : {
9110 0 : gfc_error ("Unexpected junk after TASKYIELD clause at %C");
9111 0 : return MATCH_ERROR;
9112 : }
9113 10 : new_st.op = EXEC_OMP_TASKYIELD;
9114 10 : new_st.ext.omp_clauses = NULL;
9115 10 : return MATCH_YES;
9116 : }
9117 :
9118 :
9119 : match
9120 223 : gfc_match_omp_teams (void)
9121 : {
9122 223 : return match_omp (EXEC_OMP_TEAMS, OMP_TEAMS_CLAUSES);
9123 : }
9124 :
9125 :
9126 : match
9127 22 : gfc_match_omp_teams_distribute (void)
9128 : {
9129 22 : return match_omp (EXEC_OMP_TEAMS_DISTRIBUTE,
9130 22 : OMP_TEAMS_CLAUSES | OMP_DISTRIBUTE_CLAUSES);
9131 : }
9132 :
9133 :
9134 : match
9135 41 : gfc_match_omp_teams_distribute_parallel_do (void)
9136 : {
9137 41 : return match_omp (EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO,
9138 41 : (OMP_TEAMS_CLAUSES | OMP_DISTRIBUTE_CLAUSES
9139 41 : | OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES)
9140 41 : & ~(omp_mask (OMP_CLAUSE_ORDERED)
9141 41 : | OMP_CLAUSE_LINEAR | OMP_CLAUSE_NOWAIT));
9142 : }
9143 :
9144 :
9145 : match
9146 63 : gfc_match_omp_teams_distribute_parallel_do_simd (void)
9147 : {
9148 63 : return match_omp (EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD,
9149 63 : (OMP_TEAMS_CLAUSES | OMP_DISTRIBUTE_CLAUSES
9150 63 : | OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES
9151 63 : | OMP_SIMD_CLAUSES)
9152 63 : & ~(omp_mask (OMP_CLAUSE_ORDERED) | OMP_CLAUSE_NOWAIT));
9153 : }
9154 :
9155 :
9156 : match
9157 44 : gfc_match_omp_teams_distribute_simd (void)
9158 : {
9159 44 : return match_omp (EXEC_OMP_TEAMS_DISTRIBUTE_SIMD,
9160 44 : OMP_TEAMS_CLAUSES | OMP_DISTRIBUTE_CLAUSES
9161 44 : | OMP_SIMD_CLAUSES);
9162 : }
9163 :
9164 : match
9165 203 : gfc_match_omp_tile (void)
9166 : {
9167 203 : return match_omp (EXEC_OMP_TILE, OMP_TILE_CLAUSES);
9168 : }
9169 :
9170 : match
9171 424 : gfc_match_omp_unroll (void)
9172 : {
9173 424 : return match_omp (EXEC_OMP_UNROLL, OMP_UNROLL_CLAUSES);
9174 : }
9175 :
9176 : match
9177 39 : gfc_match_omp_workshare (void)
9178 : {
9179 39 : return match_omp (EXEC_OMP_WORKSHARE, OMP_WORKSHARE_CLAUSES);
9180 : }
9181 :
9182 :
9183 : match
9184 55 : gfc_match_omp_masked (void)
9185 : {
9186 55 : return match_omp (EXEC_OMP_MASKED, OMP_MASKED_CLAUSES);
9187 : }
9188 :
9189 : match
9190 10 : gfc_match_omp_masked_taskloop (void)
9191 : {
9192 10 : return match_omp (EXEC_OMP_MASKED_TASKLOOP,
9193 10 : OMP_MASKED_CLAUSES | OMP_TASKLOOP_CLAUSES);
9194 : }
9195 :
9196 : match
9197 16 : gfc_match_omp_masked_taskloop_simd (void)
9198 : {
9199 16 : return match_omp (EXEC_OMP_MASKED_TASKLOOP_SIMD,
9200 16 : (OMP_MASKED_CLAUSES | OMP_TASKLOOP_CLAUSES
9201 16 : | OMP_SIMD_CLAUSES));
9202 : }
9203 :
9204 : match
9205 111 : gfc_match_omp_master (void)
9206 : {
9207 111 : gfc_warning (OPT_Wdeprecated_openmp,
9208 : "%<master%> construct at %C deprecated since OpenMP 5.1, "
9209 : "use %<masked%>");
9210 111 : if (gfc_match_omp_eos () != MATCH_YES)
9211 : {
9212 1 : gfc_error ("Unexpected junk after $OMP MASTER statement at %C");
9213 1 : return MATCH_ERROR;
9214 : }
9215 110 : new_st.op = EXEC_OMP_MASTER;
9216 110 : new_st.ext.omp_clauses = NULL;
9217 110 : return MATCH_YES;
9218 : }
9219 :
9220 : match
9221 16 : gfc_match_omp_master_taskloop (void)
9222 : {
9223 16 : gfc_warning (OPT_Wdeprecated_openmp,
9224 : "%<master%> construct at %C deprecated since OpenMP 5.1, "
9225 : "use %<masked%>");
9226 16 : return match_omp (EXEC_OMP_MASTER_TASKLOOP, OMP_TASKLOOP_CLAUSES);
9227 : }
9228 :
9229 : match
9230 21 : gfc_match_omp_master_taskloop_simd (void)
9231 : {
9232 21 : gfc_warning (OPT_Wdeprecated_openmp,
9233 : "%<master%> construct at %C deprecated since OpenMP 5.1, use "
9234 : "%<masked%>");
9235 21 : return match_omp (EXEC_OMP_MASTER_TASKLOOP_SIMD,
9236 21 : OMP_TASKLOOP_CLAUSES | OMP_SIMD_CLAUSES);
9237 : }
9238 :
9239 : match
9240 239 : gfc_match_omp_ordered (void)
9241 : {
9242 239 : return match_omp (EXEC_OMP_ORDERED, OMP_ORDERED_CLAUSES);
9243 : }
9244 :
9245 : match
9246 24 : gfc_match_omp_nothing (void)
9247 : {
9248 24 : if (gfc_match_omp_eos () != MATCH_YES)
9249 : {
9250 1 : gfc_error ("Unexpected junk after $OMP NOTHING statement at %C");
9251 1 : return MATCH_ERROR;
9252 : }
9253 : /* Will use ST_NONE; therefore, no EXEC_OMP_ is needed. */
9254 : return MATCH_YES;
9255 : }
9256 :
9257 : match
9258 317 : gfc_match_omp_ordered_depend (void)
9259 : {
9260 317 : return match_omp (EXEC_OMP_ORDERED, omp_mask (OMP_CLAUSE_DOACROSS));
9261 : }
9262 :
9263 :
9264 : /* omp atomic [clause-list]
9265 : - atomic-clause: read | write | update
9266 : - capture
9267 : - memory-order-clause: seq_cst | acq_rel | release | acquire | relaxed
9268 : - hint(hint-expr)
9269 : - OpenMP 5.1: compare | fail (seq_cst | acquire | relaxed ) | weak
9270 : */
9271 :
9272 : match
9273 2188 : gfc_match_omp_atomic (void)
9274 : {
9275 2188 : gfc_omp_clauses *c;
9276 2188 : locus loc = gfc_current_locus;
9277 :
9278 2188 : if (gfc_match_omp_clauses (&c, OMP_ATOMIC_CLAUSES, false, true) != MATCH_YES)
9279 : return MATCH_ERROR;
9280 :
9281 2166 : if (c->atomic_op == GFC_OMP_ATOMIC_UNSET)
9282 1013 : c->atomic_op = GFC_OMP_ATOMIC_UPDATE;
9283 :
9284 2166 : if (c->capture && c->atomic_op != GFC_OMP_ATOMIC_UPDATE)
9285 3 : gfc_error ("!$OMP ATOMIC at %L with %s clause is incompatible with "
9286 : "READ or WRITE", &loc, "CAPTURE");
9287 2166 : if (c->compare && c->atomic_op != GFC_OMP_ATOMIC_UPDATE)
9288 3 : gfc_error ("!$OMP ATOMIC at %L with %s clause is incompatible with "
9289 : "READ or WRITE", &loc, "COMPARE");
9290 2166 : if (c->fail != OMP_MEMORDER_UNSET && c->atomic_op != GFC_OMP_ATOMIC_UPDATE)
9291 2 : gfc_error ("!$OMP ATOMIC at %L with %s clause is incompatible with "
9292 : "READ or WRITE", &loc, "FAIL");
9293 2166 : if (c->weak && !c->compare)
9294 : {
9295 5 : gfc_error ("!$OMP ATOMIC at %L with %s clause requires %s clause", &loc,
9296 : "WEAK", "COMPARE");
9297 5 : c->weak = false;
9298 : }
9299 :
9300 2166 : if (c->memorder == OMP_MEMORDER_UNSET)
9301 : {
9302 1975 : gfc_namespace *prog_unit = gfc_current_ns;
9303 1975 : while (prog_unit->parent
9304 2537 : && !(prog_unit->proc_name
9305 562 : && prog_unit->proc_name->attr.flavor == FL_MODULE))
9306 562 : prog_unit = prog_unit->parent;
9307 1975 : switch (prog_unit->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
9308 : {
9309 1942 : case 0:
9310 1942 : case OMP_REQ_ATOMIC_MEM_ORDER_RELAXED:
9311 1942 : c->memorder = OMP_MEMORDER_RELAXED;
9312 1942 : break;
9313 7 : case OMP_REQ_ATOMIC_MEM_ORDER_SEQ_CST:
9314 7 : c->memorder = OMP_MEMORDER_SEQ_CST;
9315 7 : break;
9316 16 : case OMP_REQ_ATOMIC_MEM_ORDER_ACQ_REL:
9317 16 : if (c->capture)
9318 5 : c->memorder = OMP_MEMORDER_ACQ_REL;
9319 11 : else if (c->atomic_op == GFC_OMP_ATOMIC_READ)
9320 3 : c->memorder = OMP_MEMORDER_ACQUIRE;
9321 : else
9322 8 : c->memorder = OMP_MEMORDER_RELEASE;
9323 : break;
9324 5 : case OMP_REQ_ATOMIC_MEM_ORDER_ACQUIRE:
9325 5 : if (c->atomic_op == GFC_OMP_ATOMIC_WRITE)
9326 : {
9327 1 : gfc_error ("!$OMP ATOMIC WRITE at %L incompatible with "
9328 : "ACQUIRES clause implicitly provided by a "
9329 : "REQUIRES directive", &loc);
9330 1 : c->memorder = OMP_MEMORDER_SEQ_CST;
9331 : }
9332 : else
9333 4 : c->memorder = OMP_MEMORDER_ACQUIRE;
9334 : break;
9335 5 : case OMP_REQ_ATOMIC_MEM_ORDER_RELEASE:
9336 5 : if (c->atomic_op == GFC_OMP_ATOMIC_READ)
9337 : {
9338 1 : gfc_error ("!$OMP ATOMIC READ at %L incompatible with "
9339 : "RELEASE clause implicitly provided by a "
9340 : "REQUIRES directive", &loc);
9341 1 : c->memorder = OMP_MEMORDER_SEQ_CST;
9342 : }
9343 : else
9344 4 : c->memorder = OMP_MEMORDER_RELEASE;
9345 : break;
9346 0 : default:
9347 0 : gcc_unreachable ();
9348 : }
9349 : }
9350 : else
9351 191 : switch (c->atomic_op)
9352 : {
9353 31 : case GFC_OMP_ATOMIC_READ:
9354 31 : if (c->memorder == OMP_MEMORDER_RELEASE)
9355 : {
9356 1 : gfc_error ("!$OMP ATOMIC READ at %L incompatible with "
9357 : "RELEASE clause", &loc);
9358 1 : c->memorder = OMP_MEMORDER_SEQ_CST;
9359 : }
9360 30 : else if (c->memorder == OMP_MEMORDER_ACQ_REL)
9361 1 : c->memorder = OMP_MEMORDER_ACQUIRE;
9362 : break;
9363 37 : case GFC_OMP_ATOMIC_WRITE:
9364 37 : if (c->memorder == OMP_MEMORDER_ACQUIRE)
9365 : {
9366 1 : gfc_error ("!$OMP ATOMIC WRITE at %L incompatible with "
9367 : "ACQUIRE clause", &loc);
9368 1 : c->memorder = OMP_MEMORDER_SEQ_CST;
9369 : }
9370 36 : else if (c->memorder == OMP_MEMORDER_ACQ_REL)
9371 3 : c->memorder = OMP_MEMORDER_RELEASE;
9372 : break;
9373 : default:
9374 : break;
9375 : }
9376 2166 : gfc_error_check ();
9377 2166 : new_st.ext.omp_clauses = c;
9378 2166 : new_st.op = EXEC_OMP_ATOMIC;
9379 2166 : return MATCH_YES;
9380 : }
9381 :
9382 :
9383 : /* acc atomic [ read | write | update | capture] */
9384 :
9385 : match
9386 552 : gfc_match_oacc_atomic (void)
9387 : {
9388 552 : gfc_omp_clauses *c = gfc_get_omp_clauses ();
9389 552 : c->atomic_op = GFC_OMP_ATOMIC_UPDATE;
9390 552 : c->memorder = OMP_MEMORDER_RELAXED;
9391 552 : gfc_gobble_whitespace ();
9392 552 : if (gfc_match ("update") == MATCH_YES)
9393 : ;
9394 373 : else if (gfc_match ("read") == MATCH_YES)
9395 17 : c->atomic_op = GFC_OMP_ATOMIC_READ;
9396 356 : else if (gfc_match ("write") == MATCH_YES)
9397 13 : c->atomic_op = GFC_OMP_ATOMIC_WRITE;
9398 343 : else if (gfc_match ("capture") == MATCH_YES)
9399 319 : c->capture = true;
9400 552 : gfc_gobble_whitespace ();
9401 552 : if (gfc_match_omp_eos () != MATCH_YES)
9402 : {
9403 9 : gfc_error ("Unexpected junk after !$ACC ATOMIC statement at %C");
9404 9 : gfc_free_omp_clauses (c);
9405 9 : return MATCH_ERROR;
9406 : }
9407 543 : new_st.ext.omp_clauses = c;
9408 543 : new_st.op = EXEC_OACC_ATOMIC;
9409 543 : return MATCH_YES;
9410 : }
9411 :
9412 :
9413 : match
9414 614 : gfc_match_omp_barrier (void)
9415 : {
9416 614 : if (gfc_match_omp_eos () != MATCH_YES)
9417 : {
9418 0 : gfc_error ("Unexpected junk after $OMP BARRIER statement at %C");
9419 0 : return MATCH_ERROR;
9420 : }
9421 614 : new_st.op = EXEC_OMP_BARRIER;
9422 614 : new_st.ext.omp_clauses = NULL;
9423 614 : return MATCH_YES;
9424 : }
9425 :
9426 :
9427 : match
9428 188 : gfc_match_omp_taskgroup (void)
9429 : {
9430 188 : return match_omp (EXEC_OMP_TASKGROUP, OMP_TASKGROUP_CLAUSES);
9431 : }
9432 :
9433 :
9434 : static enum gfc_omp_cancel_kind
9435 502 : gfc_match_omp_cancel_kind (void)
9436 : {
9437 502 : if (gfc_match (" , ") != MATCH_YES
9438 502 : && gfc_match_space () != MATCH_YES)
9439 : return OMP_CANCEL_UNKNOWN;
9440 502 : if (gfc_match ("parallel") == MATCH_YES)
9441 : return OMP_CANCEL_PARALLEL;
9442 352 : if (gfc_match ("sections") == MATCH_YES)
9443 : return OMP_CANCEL_SECTIONS;
9444 253 : if (gfc_match ("do") == MATCH_YES)
9445 : return OMP_CANCEL_DO;
9446 123 : if (gfc_match ("taskgroup") == MATCH_YES)
9447 121 : return OMP_CANCEL_TASKGROUP;
9448 : return OMP_CANCEL_UNKNOWN;
9449 : }
9450 :
9451 :
9452 : match
9453 324 : gfc_match_omp_cancel (void)
9454 : {
9455 324 : gfc_omp_clauses *c;
9456 324 : enum gfc_omp_cancel_kind kind = gfc_match_omp_cancel_kind ();
9457 324 : if (kind == OMP_CANCEL_UNKNOWN)
9458 : return MATCH_ERROR;
9459 324 : if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_IF), false) != MATCH_YES)
9460 : return MATCH_ERROR;
9461 321 : c->cancel = kind;
9462 321 : new_st.op = EXEC_OMP_CANCEL;
9463 321 : new_st.ext.omp_clauses = c;
9464 321 : return MATCH_YES;
9465 : }
9466 :
9467 :
9468 : match
9469 178 : gfc_match_omp_cancellation_point (void)
9470 : {
9471 178 : gfc_omp_clauses *c;
9472 178 : enum gfc_omp_cancel_kind kind = gfc_match_omp_cancel_kind ();
9473 178 : if (kind == OMP_CANCEL_UNKNOWN)
9474 : {
9475 2 : gfc_error ("Expected construct-type PARALLEL, SECTIONS, DO or TASKGROUP "
9476 : "in $OMP CANCELLATION POINT statement at %C");
9477 2 : return MATCH_ERROR;
9478 : }
9479 176 : if (gfc_match_omp_eos () != MATCH_YES)
9480 : {
9481 0 : gfc_error ("Unexpected junk after $OMP CANCELLATION POINT statement "
9482 : "at %C");
9483 0 : return MATCH_ERROR;
9484 : }
9485 176 : c = gfc_get_omp_clauses ();
9486 176 : c->cancel = kind;
9487 176 : new_st.op = EXEC_OMP_CANCELLATION_POINT;
9488 176 : new_st.ext.omp_clauses = c;
9489 176 : return MATCH_YES;
9490 : }
9491 :
9492 :
9493 : match
9494 2743 : gfc_match_omp_end_nowait (void)
9495 : {
9496 2743 : bool nowait = false;
9497 2743 : if (gfc_match ("% nowait ") == MATCH_YES
9498 2743 : || gfc_match (" , nowait ") == MATCH_YES)
9499 : nowait = true;
9500 2743 : if (gfc_match_omp_eos () != MATCH_YES)
9501 : {
9502 4 : if (nowait)
9503 3 : gfc_error ("Unexpected junk after NOWAIT clause at %C");
9504 : else
9505 1 : gfc_error ("Unexpected junk at %C");
9506 : return MATCH_ERROR;
9507 : }
9508 2739 : new_st.op = EXEC_OMP_END_NOWAIT;
9509 2739 : new_st.ext.omp_bool = nowait;
9510 2739 : return MATCH_YES;
9511 : }
9512 :
9513 :
9514 : match
9515 570 : gfc_match_omp_end_single (void)
9516 : {
9517 570 : gfc_omp_clauses *c;
9518 570 : if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_COPYPRIVATE)
9519 : | OMP_CLAUSE_NOWAIT, false)
9520 : != MATCH_YES)
9521 : return MATCH_ERROR;
9522 570 : new_st.op = EXEC_OMP_END_SINGLE;
9523 570 : new_st.ext.omp_clauses = c;
9524 570 : return MATCH_YES;
9525 : }
9526 :
9527 :
9528 : static bool
9529 37154 : oacc_is_loop (gfc_code *code)
9530 : {
9531 37154 : return code->op == EXEC_OACC_PARALLEL_LOOP
9532 : || code->op == EXEC_OACC_KERNELS_LOOP
9533 20099 : || code->op == EXEC_OACC_SERIAL_LOOP
9534 13457 : || code->op == EXEC_OACC_LOOP;
9535 : }
9536 :
9537 : static bool
9538 5974 : resolve_scalar_int_expr (gfc_expr *expr, const char *clause)
9539 : {
9540 5974 : if (!gfc_resolve_expr (expr)
9541 5974 : || expr->ts.type != BT_INTEGER
9542 11879 : || expr->rank != 0)
9543 : {
9544 87 : gfc_error ("%s clause at %L requires a scalar INTEGER expression",
9545 : clause, &expr->where);
9546 87 : return false;
9547 : }
9548 : return true;
9549 : }
9550 :
9551 : /* Require that EXPR is a scalar constant integer expression; it shall be a
9552 : positive number: If WARN is true, a warning is printed if constant and
9553 : not positive. If WARN is false, an error is printed if it is either not
9554 : constant or not positive. CLAUSE is used in the diagnostic output. */
9555 :
9556 : static void
9557 4495 : resolve_positive_int_expr (gfc_expr *expr, const char *clause, bool warn)
9558 : {
9559 4495 : if (!resolve_scalar_int_expr (expr, clause))
9560 : return;
9561 4460 : if (warn
9562 3664 : && expr->expr_type == EXPR_CONSTANT
9563 3265 : && mpz_sgn (expr->value.integer) <= 0)
9564 30 : gfc_warning ((flag_openmp || flag_openmp_simd) ? OPT_Wopenmp : 0,
9565 : "INTEGER expression of %s clause at %L must be positive",
9566 : clause, &expr->where);
9567 : else if (!warn
9568 796 : && (expr->expr_type != EXPR_CONSTANT
9569 781 : || mpz_sgn (expr->value.integer) <= 0))
9570 36 : gfc_error ("INTEGER expression of %s clause at %L must be positive and "
9571 : "constant", clause, &expr->where);
9572 : }
9573 :
9574 : /* Require that EXPR is a scalar constant integer expression; it shall be a
9575 : nonnegative number: If WARN is true, a warning is printed if constant and
9576 : negative. If WARN is false, an error is printed if it is either not constant
9577 : or negative. CLAUSE is used in the diagnostic output. */
9578 :
9579 : static void
9580 91 : resolve_nonnegative_int_expr (gfc_expr *expr, const char *clause, bool warn)
9581 : {
9582 91 : if (!resolve_scalar_int_expr (expr, clause))
9583 : return;
9584 84 : if (warn
9585 84 : && expr->expr_type == EXPR_CONSTANT
9586 32 : && mpz_sgn (expr->value.integer) < 0)
9587 8 : gfc_warning ((flag_openmp || flag_openmp_simd) ? OPT_Wopenmp : 0,
9588 : "INTEGER expression of %s clause at %L must be non-negative",
9589 : clause, &expr->where);
9590 : else if (!warn
9591 0 : && (expr->expr_type != EXPR_CONSTANT
9592 0 : || mpz_sgn (expr->value.integer) < 0))
9593 0 : gfc_error ("INTEGER expression of %s clause at %L must be non-negtive and "
9594 : "constant", clause, &expr->where);
9595 : }
9596 :
9597 : /* Emits error when symbol is pointer, cray pointer or cray pointee
9598 : of derived of polymorphic type. */
9599 :
9600 : static void
9601 98 : check_symbol_not_pointer (gfc_symbol *sym, locus loc, const char *name)
9602 : {
9603 98 : if (sym->ts.type == BT_DERIVED && sym->attr.cray_pointer)
9604 0 : gfc_error ("Cray pointer object %qs of derived type in %s clause at %L",
9605 : sym->name, name, &loc);
9606 98 : if (sym->ts.type == BT_DERIVED && sym->attr.cray_pointee)
9607 0 : gfc_error ("Cray pointee object %qs of derived type in %s clause at %L",
9608 : sym->name, name, &loc);
9609 :
9610 98 : if ((sym->ts.type == BT_ASSUMED && sym->attr.pointer)
9611 98 : || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
9612 0 : && CLASS_DATA (sym)->attr.pointer))
9613 0 : gfc_error ("POINTER object %qs of polymorphic type in %s clause at %L",
9614 : sym->name, name, &loc);
9615 98 : if ((sym->ts.type == BT_ASSUMED && sym->attr.cray_pointer)
9616 98 : || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
9617 0 : && CLASS_DATA (sym)->attr.cray_pointer))
9618 0 : gfc_error ("Cray pointer object %qs of polymorphic type in %s clause at %L",
9619 : sym->name, name, &loc);
9620 98 : if ((sym->ts.type == BT_ASSUMED && sym->attr.cray_pointee)
9621 98 : || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
9622 0 : && CLASS_DATA (sym)->attr.cray_pointee))
9623 0 : gfc_error ("Cray pointee object %qs of polymorphic type in %s clause at %L",
9624 : sym->name, name, &loc);
9625 98 : }
9626 :
9627 : /* Emits error when symbol represents assumed size/rank array. */
9628 :
9629 : static void
9630 14844 : check_array_not_assumed (gfc_symbol *sym, locus loc, const char *name)
9631 : {
9632 14844 : if (sym->as && sym->as->type == AS_ASSUMED_SIZE)
9633 13 : gfc_error ("Assumed size array %qs in %s clause at %L",
9634 : sym->name, name, &loc);
9635 14844 : if (sym->as && sym->as->type == AS_ASSUMED_RANK)
9636 11 : gfc_error ("Assumed rank array %qs in %s clause at %L",
9637 : sym->name, name, &loc);
9638 14844 : }
9639 :
9640 : static void
9641 5850 : resolve_oacc_data_clauses (gfc_symbol *sym, locus loc, const char *name)
9642 : {
9643 0 : check_array_not_assumed (sym, loc, name);
9644 0 : }
9645 :
9646 : static void
9647 65 : resolve_oacc_deviceptr_clause (gfc_symbol *sym, locus loc, const char *name)
9648 : {
9649 65 : if (sym->attr.pointer
9650 64 : || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
9651 0 : && CLASS_DATA (sym)->attr.class_pointer))
9652 1 : gfc_error ("POINTER object %qs in %s clause at %L",
9653 : sym->name, name, &loc);
9654 65 : if (sym->attr.cray_pointer
9655 63 : || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
9656 0 : && CLASS_DATA (sym)->attr.cray_pointer))
9657 2 : gfc_error ("Cray pointer object %qs in %s clause at %L",
9658 : sym->name, name, &loc);
9659 65 : if (sym->attr.cray_pointee
9660 63 : || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
9661 0 : && CLASS_DATA (sym)->attr.cray_pointee))
9662 2 : gfc_error ("Cray pointee object %qs in %s clause at %L",
9663 : sym->name, name, &loc);
9664 65 : if (sym->attr.allocatable
9665 64 : || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
9666 0 : && CLASS_DATA (sym)->attr.allocatable))
9667 1 : gfc_error ("ALLOCATABLE object %qs in %s clause at %L",
9668 : sym->name, name, &loc);
9669 65 : if (sym->attr.value)
9670 1 : gfc_error ("VALUE object %qs in %s clause at %L",
9671 : sym->name, name, &loc);
9672 65 : check_array_not_assumed (sym, loc, name);
9673 65 : }
9674 :
9675 :
9676 : struct resolve_omp_udr_callback_data
9677 : {
9678 : gfc_symbol *sym1, *sym2;
9679 : };
9680 :
9681 :
9682 : static int
9683 1413 : resolve_omp_udr_callback (gfc_expr **e, int *, void *data)
9684 : {
9685 1413 : struct resolve_omp_udr_callback_data *rcd
9686 : = (struct resolve_omp_udr_callback_data *) data;
9687 1413 : if ((*e)->expr_type == EXPR_VARIABLE
9688 801 : && ((*e)->symtree->n.sym == rcd->sym1
9689 255 : || (*e)->symtree->n.sym == rcd->sym2))
9690 : {
9691 801 : gfc_ref *ref = gfc_get_ref ();
9692 801 : ref->type = REF_ARRAY;
9693 801 : ref->u.ar.where = (*e)->where;
9694 801 : ref->u.ar.as = (*e)->symtree->n.sym->as;
9695 801 : ref->u.ar.type = AR_FULL;
9696 801 : ref->u.ar.dimen = 0;
9697 801 : ref->next = (*e)->ref;
9698 801 : (*e)->ref = ref;
9699 : }
9700 1413 : return 0;
9701 : }
9702 :
9703 :
9704 : static int
9705 3008 : resolve_omp_udr_callback2 (gfc_expr **e, int *, void *)
9706 : {
9707 3008 : if ((*e)->expr_type == EXPR_FUNCTION
9708 360 : && (*e)->value.function.isym == NULL)
9709 : {
9710 174 : gfc_symbol *sym = (*e)->symtree->n.sym;
9711 174 : if (!sym->attr.intrinsic
9712 174 : && sym->attr.if_source == IFSRC_UNKNOWN)
9713 4 : gfc_error ("Implicitly declared function %s used in "
9714 : "!$OMP DECLARE REDUCTION at %L", sym->name, &(*e)->where);
9715 : }
9716 3008 : return 0;
9717 : }
9718 :
9719 :
9720 : static gfc_code *
9721 802 : resolve_omp_udr_clause (gfc_omp_namelist *n, gfc_namespace *ns,
9722 : gfc_symbol *sym1, gfc_symbol *sym2)
9723 : {
9724 802 : gfc_code *copy;
9725 802 : gfc_symbol sym1_copy, sym2_copy;
9726 :
9727 802 : if (ns->code->op == EXEC_ASSIGN)
9728 : {
9729 630 : copy = gfc_get_code (EXEC_ASSIGN);
9730 630 : copy->expr1 = gfc_copy_expr (ns->code->expr1);
9731 630 : copy->expr2 = gfc_copy_expr (ns->code->expr2);
9732 : }
9733 : else
9734 : {
9735 172 : copy = gfc_get_code (EXEC_CALL);
9736 172 : copy->symtree = ns->code->symtree;
9737 172 : copy->ext.actual = gfc_copy_actual_arglist (ns->code->ext.actual);
9738 : }
9739 802 : copy->loc = ns->code->loc;
9740 802 : sym1_copy = *sym1;
9741 802 : sym2_copy = *sym2;
9742 802 : *sym1 = *n->sym;
9743 802 : *sym2 = *n->sym;
9744 802 : sym1->name = sym1_copy.name;
9745 802 : sym2->name = sym2_copy.name;
9746 802 : ns->proc_name = ns->parent->proc_name;
9747 802 : if (n->sym->attr.dimension)
9748 : {
9749 348 : struct resolve_omp_udr_callback_data rcd;
9750 348 : rcd.sym1 = sym1;
9751 348 : rcd.sym2 = sym2;
9752 348 : gfc_code_walker (©, gfc_dummy_code_callback,
9753 : resolve_omp_udr_callback, &rcd);
9754 : }
9755 802 : gfc_resolve_code (copy, gfc_current_ns);
9756 802 : if (copy->op == EXEC_CALL && copy->resolved_isym == NULL)
9757 : {
9758 172 : gfc_symbol *sym = copy->resolved_sym;
9759 172 : if (sym
9760 170 : && !sym->attr.intrinsic
9761 170 : && sym->attr.if_source == IFSRC_UNKNOWN)
9762 4 : gfc_error ("Implicitly declared subroutine %s used in "
9763 : "!$OMP DECLARE REDUCTION at %L", sym->name,
9764 : ©->loc);
9765 : }
9766 802 : gfc_code_walker (©, gfc_dummy_code_callback,
9767 : resolve_omp_udr_callback2, NULL);
9768 802 : *sym1 = sym1_copy;
9769 802 : *sym2 = sym2_copy;
9770 802 : return copy;
9771 : }
9772 :
9773 : /* Assume that a constant expression in the range 1 (omp_default_mem_alloc)
9774 : to GOMP_OMP_PREDEF_ALLOC_MAX, or GOMP_OMPX_PREDEF_ALLOC_MIN to
9775 : GOMP_OMPX_PREDEF_ALLOC_MAX is fine. The original symbol name is already
9776 : lost during matching via gfc_match_expr. */
9777 : static bool
9778 130 : is_predefined_allocator (gfc_expr *expr)
9779 : {
9780 130 : return (gfc_resolve_expr (expr)
9781 129 : && expr->rank == 0
9782 124 : && expr->ts.type == BT_INTEGER
9783 119 : && expr->ts.kind == gfc_c_intptr_kind
9784 114 : && expr->expr_type == EXPR_CONSTANT
9785 239 : && ((mpz_sgn (expr->value.integer) > 0
9786 107 : && mpz_cmp_si (expr->value.integer,
9787 : GOMP_OMP_PREDEF_ALLOC_MAX) <= 0)
9788 4 : || (mpz_cmp_si (expr->value.integer,
9789 : GOMP_OMPX_PREDEF_ALLOC_MIN) >= 0
9790 1 : && mpz_cmp_si (expr->value.integer,
9791 130 : GOMP_OMPX_PREDEF_ALLOC_MAX) <= 0)));
9792 : }
9793 :
9794 : /* Resolve declarative ALLOCATE statement. Note: Common block vars only appear
9795 : as /block/ not individual, which is ensured during parsing. */
9796 :
9797 : void
9798 62 : gfc_resolve_omp_allocate (gfc_namespace *ns, gfc_omp_namelist *list)
9799 : {
9800 278 : for (gfc_omp_namelist *n = list; n; n = n->next)
9801 : {
9802 216 : if (n->sym->attr.result || n->sym->result == n->sym)
9803 : {
9804 1 : gfc_error ("Unexpected function-result variable %qs at %L in "
9805 : "declarative !$OMP ALLOCATE", n->sym->name, &n->where);
9806 30 : continue;
9807 : }
9808 215 : if (ns->omp_allocate->sym->attr.proc_pointer)
9809 : {
9810 0 : gfc_error ("Procedure pointer %qs not supported with !$OMP "
9811 : "ALLOCATE at %L", n->sym->name, &n->where);
9812 0 : continue;
9813 : }
9814 215 : if (n->sym->attr.flavor != FL_VARIABLE)
9815 : {
9816 3 : gfc_error ("Argument %qs at %L to declarative !$OMP ALLOCATE "
9817 : "directive must be a variable", n->sym->name,
9818 : &n->where);
9819 3 : continue;
9820 : }
9821 212 : if (ns != n->sym->ns || n->sym->attr.use_assoc || n->sym->attr.imported)
9822 : {
9823 8 : gfc_error ("Argument %qs at %L to declarative !$OMP ALLOCATE shall be"
9824 : " in the same scope as the variable declaration",
9825 : n->sym->name, &n->where);
9826 8 : continue;
9827 : }
9828 204 : if (n->sym->attr.dummy)
9829 : {
9830 3 : gfc_error ("Unexpected dummy argument %qs as argument at %L to "
9831 : "declarative !$OMP ALLOCATE", n->sym->name, &n->where);
9832 3 : continue;
9833 : }
9834 201 : if (n->sym->attr.codimension)
9835 : {
9836 0 : gfc_error ("Unexpected coarray argument %qs as argument at %L to "
9837 : "declarative !$OMP ALLOCATE", n->sym->name, &n->where);
9838 0 : continue;
9839 : }
9840 201 : if (n->sym->attr.omp_allocate)
9841 : {
9842 5 : if (n->sym->attr.in_common)
9843 : {
9844 1 : gfc_error ("Duplicated common block %</%s/%> in !$OMP ALLOCATE "
9845 1 : "at %L", n->sym->common_head->name, &n->where);
9846 3 : while (n->next && n->next->sym
9847 3 : && n->sym->common_head == n->next->sym->common_head)
9848 : n = n->next;
9849 : }
9850 : else
9851 4 : gfc_error ("Duplicated variable %qs in !$OMP ALLOCATE at %L",
9852 : n->sym->name, &n->where);
9853 5 : continue;
9854 : }
9855 : /* For 'equivalence(a,b)', a 'union_type {<type> a,b} equiv.0' is created
9856 : with a value expression for 'a' as 'equiv.0.a' (likewise for b); while
9857 : this can be handled, EQUIVALENCE is marked as obsolescent since Fortran
9858 : 2018 and also not widely used. However, it could be supported,
9859 : if needed. */
9860 196 : if (n->sym->attr.in_equivalence)
9861 : {
9862 2 : gfc_error ("Sorry, EQUIVALENCE object %qs not supported with !$OMP "
9863 : "ALLOCATE at %L", n->sym->name, &n->where);
9864 2 : continue;
9865 : }
9866 : /* Similar for Cray pointer/pointee - they could be implemented but as
9867 : common vendor extension but nowadays rarely used and requiring
9868 : -fcray-pointer, there is no need to support them. */
9869 194 : if (n->sym->attr.cray_pointer || n->sym->attr.cray_pointee)
9870 : {
9871 2 : gfc_error ("Sorry, Cray pointers and pointees such as %qs are not "
9872 : "supported with !$OMP ALLOCATE at %L",
9873 : n->sym->name, &n->where);
9874 2 : continue;
9875 : }
9876 192 : n->sym->attr.omp_allocate = 1;
9877 192 : if ((n->sym->ts.type == BT_CLASS && n->sym->attr.class_ok
9878 0 : && CLASS_DATA (n->sym)->attr.allocatable)
9879 192 : || (n->sym->ts.type != BT_CLASS && n->sym->attr.allocatable))
9880 1 : gfc_error ("Unexpected allocatable variable %qs at %L in declarative "
9881 : "!$OMP ALLOCATE directive", n->sym->name, &n->where);
9882 191 : else if ((n->sym->ts.type == BT_CLASS && n->sym->attr.class_ok
9883 0 : && CLASS_DATA (n->sym)->attr.class_pointer)
9884 191 : || (n->sym->ts.type != BT_CLASS && n->sym->attr.pointer))
9885 1 : gfc_error ("Unexpected pointer variable %qs at %L in declarative "
9886 : "!$OMP ALLOCATE directive", n->sym->name, &n->where);
9887 192 : HOST_WIDE_INT alignment = 0;
9888 198 : if (n->u.align
9889 192 : && (!gfc_resolve_expr (n->u.align)
9890 27 : || n->u.align->ts.type != BT_INTEGER
9891 26 : || n->u.align->rank != 0
9892 24 : || n->u.align->expr_type != EXPR_CONSTANT
9893 23 : || gfc_extract_hwi (n->u.align, &alignment)
9894 23 : || !pow2p_hwi (alignment)))
9895 : {
9896 6 : gfc_error ("ALIGN requires a scalar positive constant integer "
9897 : "alignment expression at %L that is a power of two",
9898 6 : &n->u.align->where);
9899 6 : while (n->sym->attr.in_common && n->next && n->next->sym
9900 6 : && n->sym->common_head == n->next->sym->common_head)
9901 : n = n->next;
9902 6 : continue;
9903 : }
9904 186 : if (n->sym->attr.in_common || n->sym->attr.save || n->sym->ns->save_all
9905 63 : || (n->sym->ns->proc_name
9906 63 : && (n->sym->ns->proc_name->attr.flavor == FL_PROGRAM
9907 55 : || n->sym->ns->proc_name->attr.flavor == FL_MODULE
9908 55 : || n->sym->ns->proc_name->attr.flavor == FL_BLOCK_DATA)))
9909 : {
9910 131 : bool com = n->sym->attr.in_common;
9911 131 : if (!n->u2.allocator)
9912 1 : gfc_error ("An ALLOCATOR clause is required as the list item "
9913 : "%<%s%s%s%> at %L has the SAVE attribute", com ? "/" : "",
9914 0 : com ? n->sym->common_head->name : n->sym->name,
9915 : com ? "/" : "", &n->where);
9916 130 : else if (!is_predefined_allocator (n->u2.allocator))
9917 24 : gfc_error ("Predefined allocator required in ALLOCATOR clause at %L"
9918 : " as the list item %<%s%s%s%> at %L has the SAVE attribute",
9919 24 : &n->u2.allocator->where, com ? "/" : "",
9920 24 : com ? n->sym->common_head->name : n->sym->name,
9921 : com ? "/" : "", &n->where);
9922 : /* Static variables may not use omp_cgroup_mem_alloc (6),
9923 : omp_pteam_mem_alloc (7), or omp_thread_mem_alloc (8). */
9924 106 : else if (mpz_cmp_si (n->u2.allocator->value.integer,
9925 : 6 /* cgroup */) >= 0
9926 34 : && mpz_cmp_si (n->u2.allocator->value.integer,
9927 : 8 /* thread */) <= 0)
9928 : {
9929 33 : STATIC_ASSERT (GOMP_OMP_PREDEF_ALLOC_CGROUP == 6);
9930 33 : STATIC_ASSERT (GOMP_OMP_PREDEF_ALLOC_PTEAM == 7);
9931 33 : STATIC_ASSERT (GOMP_OMP_PREDEF_ALLOC_THREAD == 8);
9932 33 : const char *alloc_name[] = {"omp_cgroup_mem_alloc",
9933 : "omp_pteam_mem_alloc",
9934 : "omp_thread_mem_alloc" };
9935 33 : gfc_error ("Predefined allocator %qs in ALLOCATOR clause at %L, "
9936 : "used for list item %<%s%s%s%> at %L, may not be used"
9937 : " for static variables",
9938 33 : alloc_name[mpz_get_ui (n->u2.allocator->value.integer)
9939 33 : - 6 /* cgroup */], &n->u2.allocator->where,
9940 : com ? "/" : "",
9941 33 : com ? n->sym->common_head->name : n->sym->name,
9942 : com ? "/" : "", &n->where);
9943 : }
9944 67 : while (n->sym->attr.in_common && n->next && n->next->sym
9945 186 : && n->sym->common_head == n->next->sym->common_head)
9946 : n = n->next;
9947 : }
9948 55 : else if (n->u2.allocator
9949 55 : && (!gfc_resolve_expr (n->u2.allocator)
9950 20 : || n->u2.allocator->ts.type != BT_INTEGER
9951 19 : || n->u2.allocator->rank != 0
9952 18 : || n->u2.allocator->ts.kind != gfc_c_intptr_kind))
9953 3 : gfc_error ("Expected integer expression of the "
9954 : "%<omp_allocator_handle_kind%> kind at %L",
9955 3 : &n->u2.allocator->where);
9956 : }
9957 62 : }
9958 :
9959 : /* Resolve ASSUME's and ASSUMES' assumption clauses. Note that absent/contains
9960 : is handled during parse time in omp_verify_merge_absent_contains. */
9961 :
9962 : void
9963 34 : gfc_resolve_omp_assumptions (gfc_omp_assumptions *assume)
9964 : {
9965 54 : for (gfc_expr_list *el = assume->holds; el; el = el->next)
9966 20 : if (!gfc_resolve_expr (el->expr)
9967 20 : || el->expr->ts.type != BT_LOGICAL
9968 38 : || el->expr->rank != 0)
9969 4 : gfc_error ("HOLDS expression at %L must be a scalar logical expression",
9970 4 : &el->expr->where);
9971 34 : }
9972 :
9973 :
9974 : /* Resolve the OpenMP ALLOCATE clauses. */
9975 :
9976 : static void
9977 33190 : resolve_omp_allocate_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
9978 : gfc_namespace *ns)
9979 : {
9980 33190 : gfc_omp_namelist *n;
9981 33190 : enum gfc_omp_list_type list;
9982 :
9983 33190 : if (!omp_clauses->lists[OMP_LIST_ALLOCATE])
9984 : return;
9985 795 : for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; n = n->next)
9986 : {
9987 515 : if (n->u2.allocator
9988 515 : && (!gfc_resolve_expr (n->u2.allocator)
9989 290 : || n->u2.allocator->ts.type != BT_INTEGER
9990 288 : || n->u2.allocator->rank != 0
9991 287 : || n->u2.allocator->ts.kind != gfc_c_intptr_kind))
9992 : {
9993 8 : gfc_error ("Expected integer expression of the "
9994 : "%<omp_allocator_handle_kind%> kind at %L",
9995 8 : &n->u2.allocator->where);
9996 28 : break;
9997 : }
9998 507 : if (!n->u.align)
9999 399 : continue;
10000 108 : HOST_WIDE_INT alignment = 0;
10001 108 : if (!gfc_resolve_expr (n->u.align)
10002 108 : || n->u.align->ts.type != BT_INTEGER
10003 105 : || n->u.align->rank != 0
10004 102 : || n->u.align->expr_type != EXPR_CONSTANT
10005 99 : || gfc_extract_hwi (n->u.align, &alignment)
10006 99 : || alignment <= 0
10007 207 : || !pow2p_hwi (alignment))
10008 : {
10009 12 : gfc_error ("ALIGN requires a scalar positive constant integer "
10010 : "alignment expression at %L that is a power of two",
10011 12 : &n->u.align->where);
10012 12 : break;
10013 : }
10014 : }
10015 :
10016 : /* Check for 2 things here.
10017 : 1. There is no duplication of variable in allocate clause.
10018 : 2. Variable in allocate clause are also present in some
10019 : privatization clase (non-composite case). */
10020 815 : for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; n = n->next)
10021 515 : if (n->sym)
10022 489 : n->sym->mark = 0;
10023 :
10024 : gfc_omp_namelist *prev = NULL;
10025 815 : for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; )
10026 : {
10027 515 : if (n->sym == NULL)
10028 : {
10029 26 : n = n->next;
10030 26 : continue;
10031 : }
10032 489 : if (n->sym->mark == 1)
10033 : {
10034 3 : gfc_warning (OPT_Wopenmp, "%qs appears more than once in "
10035 : "%<allocate%> at %L" , n->sym->name, &n->where);
10036 : /* We have already seen this variable so it is a duplicate.
10037 : Remove it. */
10038 3 : if (prev != NULL && prev->next == n)
10039 : {
10040 3 : prev->next = n->next;
10041 3 : n->next = NULL;
10042 3 : gfc_free_omp_namelist (n, OMP_LIST_ALLOCATE);
10043 3 : n = prev->next;
10044 : }
10045 3 : continue;
10046 : }
10047 486 : n->sym->mark = 1;
10048 486 : prev = n;
10049 486 : n = n->next;
10050 : }
10051 :
10052 : /* Non-composite constructs. */
10053 300 : if (code && code->op < EXEC_OMP_DO_SIMD)
10054 : {
10055 4760 : for (list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
10056 4641 : list = gfc_omp_list_type (list + 1))
10057 4641 : switch (list)
10058 : {
10059 1071 : case OMP_LIST_PRIVATE:
10060 1071 : case OMP_LIST_FIRSTPRIVATE:
10061 1071 : case OMP_LIST_LASTPRIVATE:
10062 1071 : case OMP_LIST_REDUCTION:
10063 1071 : case OMP_LIST_REDUCTION_INSCAN:
10064 1071 : case OMP_LIST_REDUCTION_TASK:
10065 1071 : case OMP_LIST_IN_REDUCTION:
10066 1071 : case OMP_LIST_TASK_REDUCTION:
10067 1071 : case OMP_LIST_LINEAR:
10068 1370 : for (n = omp_clauses->lists[list]; n; n = n->next)
10069 299 : n->sym->mark = 0;
10070 : break;
10071 : default:
10072 : break;
10073 : }
10074 :
10075 410 : for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; n = n->next)
10076 291 : if (n->sym->mark == 1)
10077 4 : gfc_error ("%qs specified in %<allocate%> clause at %L but not "
10078 : "in an explicit privatization clause",
10079 : n->sym->name, &n->where);
10080 : }
10081 71 : if (!(code
10082 300 : && (code->op == EXEC_OMP_ALLOCATORS || code->op == EXEC_OMP_ALLOCATE)
10083 73 : && code->block
10084 72 : && code->block->next
10085 71 : && code->block->next->op == EXEC_ALLOCATE))
10086 : return;
10087 :
10088 68 : if (code->op == EXEC_OMP_ALLOCATE)
10089 49 : gfc_warning (OPT_Wdeprecated_openmp,
10090 : "The use of one or more %<allocate%> directives with "
10091 : "an associated %<allocate%> statement at %L is "
10092 : "deprecated since OpenMP 5.2, use an %<allocators%> "
10093 : "directive", &code->loc);
10094 68 : gfc_alloc *a;
10095 68 : gfc_omp_namelist *n_null = NULL;
10096 68 : bool missing_allocator = false;
10097 68 : gfc_symbol *missing_allocator_sym = NULL;
10098 161 : for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; n = n->next)
10099 : {
10100 93 : if (n->u2.allocator == NULL)
10101 : {
10102 77 : if (!missing_allocator_sym)
10103 59 : missing_allocator_sym = n->sym;
10104 : missing_allocator = true;
10105 : }
10106 93 : if (n->sym == NULL)
10107 : {
10108 26 : n_null = n;
10109 26 : continue;
10110 : }
10111 67 : if (n->sym->attr.codimension)
10112 2 : gfc_error ("Unexpected coarray %qs in %<allocate%> at %L",
10113 : n->sym->name, &n->where);
10114 103 : for (a = code->block->next->ext.alloc.list; a; a = a->next)
10115 101 : if (a->expr->expr_type == EXPR_VARIABLE
10116 101 : && a->expr->symtree->n.sym == n->sym)
10117 : {
10118 65 : gfc_ref *ref;
10119 82 : for (ref = a->expr->ref; ref; ref = ref->next)
10120 17 : if (ref->type == REF_COMPONENT)
10121 : break;
10122 : if (ref == NULL)
10123 : break;
10124 : }
10125 67 : if (a == NULL)
10126 2 : gfc_error ("%qs specified in %<allocate%> at %L but not "
10127 : "in the associated ALLOCATE statement",
10128 2 : n->sym->name, &n->where);
10129 : }
10130 : /* If there is an ALLOCATE directive without list argument, a
10131 : namelist with its allocator/align clauses and n->sym = NULL is
10132 : created during parsing; here, we add all not otherwise specified
10133 : items from the Fortran allocate to that list.
10134 : For an ALLOCATORS directive, not listed items use the normal
10135 : Fortran way.
10136 : The behavior of an ALLOCATE directive that does not list all
10137 : arguments but there is no directive without list argument is not
10138 : well specified. Thus, we reject such code below. In OpenMP 5.2
10139 : the executable ALLOCATE directive is deprecated and in 6.0
10140 : deleted such that no spec clarification is to be expected. */
10141 125 : for (a = code->block->next->ext.alloc.list; a; a = a->next)
10142 89 : if (a->expr->expr_type == EXPR_VARIABLE)
10143 : {
10144 154 : for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; n = n->next)
10145 122 : if (a->expr->symtree->n.sym == n->sym)
10146 : {
10147 57 : gfc_ref *ref;
10148 72 : for (ref = a->expr->ref; ref; ref = ref->next)
10149 15 : if (ref->type == REF_COMPONENT)
10150 : break;
10151 : if (ref == NULL)
10152 : break;
10153 : }
10154 89 : if (n == NULL && n_null == NULL)
10155 : {
10156 : /* OK for ALLOCATORS but for ALLOCATE: Unspecified whether
10157 : that should use the default allocator of OpenMP or the
10158 : Fortran allocator. Thus, just reject it. */
10159 7 : if (code->op == EXEC_OMP_ALLOCATE)
10160 1 : gfc_error ("%qs listed in %<allocate%> statement at %L "
10161 : "but it is neither explicitly in listed in "
10162 : "the %<!$OMP ALLOCATE%> directive nor exists"
10163 : " a directive without argument list",
10164 1 : a->expr->symtree->n.sym->name,
10165 : &a->expr->where);
10166 : break;
10167 : }
10168 82 : if (n == NULL)
10169 : {
10170 25 : if (a->expr->symtree->n.sym->attr.codimension)
10171 1 : gfc_error ("Unexpected coarray %qs in %<allocate%> at "
10172 : "%L, implicitly listed in %<!$OMP ALLOCATE%>"
10173 : " at %L", a->expr->symtree->n.sym->name,
10174 : &a->expr->where, &n_null->where);
10175 : break;
10176 : }
10177 : }
10178 68 : gfc_namespace *prog_unit = ns;
10179 87 : while (prog_unit->parent)
10180 : prog_unit = prog_unit->parent;
10181 : gfc_namespace *fn_ns = ns;
10182 72 : while (fn_ns)
10183 : {
10184 70 : if (ns->proc_name
10185 70 : && (ns->proc_name->attr.subroutine
10186 6 : || ns->proc_name->attr.function))
10187 : break;
10188 4 : fn_ns = fn_ns->parent;
10189 : }
10190 68 : if (missing_allocator
10191 58 : && !(prog_unit->omp_requires & OMP_REQ_DYNAMIC_ALLOCATORS)
10192 58 : && ((fn_ns && fn_ns->proc_name->attr.omp_declare_target)
10193 55 : || omp_clauses->contained_in_target_construct))
10194 : {
10195 6 : if (code->op == EXEC_OMP_ALLOCATORS)
10196 2 : gfc_error ("ALLOCATORS directive at %L inside a target region "
10197 : "must specify an ALLOCATOR modifier for %qs",
10198 : &code->loc, missing_allocator_sym->name);
10199 4 : else if (missing_allocator_sym)
10200 2 : gfc_error ("ALLOCATE directive at %L inside a target region "
10201 : "must specify an ALLOCATOR clause for %qs",
10202 : &code->loc, missing_allocator_sym->name);
10203 : else
10204 2 : gfc_error ("ALLOCATE directive at %L inside a target region "
10205 : "must specify an ALLOCATOR clause", &code->loc);
10206 : }
10207 : }
10208 :
10209 :
10210 : /* Diagnose list items that appear multiple times in OpenMP or OpenACC clauses,
10211 : unless permitted by the specification. */
10212 :
10213 : static void
10214 33190 : check_omp_clauses_dupl_syms (gfc_code *code, gfc_omp_clauses *omp_clauses,
10215 : bool openacc)
10216 : {
10217 33190 : gfc_omp_namelist *n;
10218 33190 : enum gfc_omp_list_type list;
10219 :
10220 : /* Check that no symbol appears on multiple clauses, except that
10221 : a symbol can appear on both firstprivate and lastprivate. */
10222 1327600 : for (list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
10223 1294410 : list = gfc_omp_list_type (list + 1))
10224 1340291 : for (n = omp_clauses->lists[list]; n; n = n->next)
10225 : {
10226 45881 : if (!n->sym) /* omp_all_memory. */
10227 47 : continue;
10228 45834 : n->sym->mark = 0;
10229 45834 : n->sym->comp_mark = 0;
10230 45834 : n->sym->data_mark = 0;
10231 45834 : n->sym->dev_mark = 0;
10232 45834 : n->sym->gen_mark = 0;
10233 45834 : n->sym->reduc_mark = 0;
10234 : }
10235 1327600 : for (list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
10236 1294410 : list = gfc_omp_list_type (list + 1))
10237 1294410 : if (list != OMP_LIST_FIRSTPRIVATE
10238 1294410 : && list != OMP_LIST_LASTPRIVATE
10239 1294410 : && list != OMP_LIST_ALIGNED
10240 1194840 : && list != OMP_LIST_DEPEND
10241 1194840 : && list != OMP_LIST_FROM
10242 1128460 : && list != OMP_LIST_TO
10243 1128460 : && list != OMP_LIST_INTEROP
10244 1062080 : && (list != OMP_LIST_REDUCTION || !openacc)
10245 1049085 : && list != OMP_LIST_ALLOCATE)
10246 1050861 : for (n = omp_clauses->lists[list]; n; n = n->next)
10247 : {
10248 34966 : bool component_ref_p = false;
10249 :
10250 : /* Allow multiple components of the same (e.g. derived-type)
10251 : variable here. Duplicate components are detected elsewhere. */
10252 34966 : if (n->expr && n->expr->expr_type == EXPR_VARIABLE)
10253 16021 : for (gfc_ref *ref = n->expr->ref; ref; ref = ref->next)
10254 9744 : if (ref->type == REF_COMPONENT)
10255 3197 : component_ref_p = true;
10256 34966 : if ((list == OMP_LIST_IS_DEVICE_PTR
10257 34966 : || list == OMP_LIST_HAS_DEVICE_ADDR)
10258 314 : && !component_ref_p)
10259 : {
10260 314 : if (n->sym->gen_mark
10261 312 : || n->sym->dev_mark
10262 311 : || n->sym->reduc_mark
10263 311 : || n->sym->mark)
10264 5 : gfc_error ("Symbol %qs present on multiple clauses at %L",
10265 : n->sym->name, &n->where);
10266 : else
10267 309 : n->sym->dev_mark = 1;
10268 : }
10269 34652 : else if ((list == OMP_LIST_USE_DEVICE_PTR
10270 34652 : || list == OMP_LIST_USE_DEVICE_ADDR
10271 34652 : || list == OMP_LIST_PRIVATE
10272 : || list == OMP_LIST_SHARED)
10273 12861 : && !component_ref_p)
10274 : {
10275 12861 : if (n->sym->gen_mark || n->sym->dev_mark || n->sym->reduc_mark)
10276 13 : gfc_error ("Symbol %qs present on multiple clauses at %L",
10277 : n->sym->name, &n->where);
10278 : else
10279 : {
10280 12848 : n->sym->gen_mark = 1;
10281 : /* Set both generic and device bits if we have
10282 : use_device_*(x) or shared(x). This allows us to diagnose
10283 : "map(x) private(x)" below. */
10284 12848 : if (list != OMP_LIST_PRIVATE)
10285 3456 : n->sym->dev_mark = 1;
10286 : }
10287 : }
10288 21791 : else if ((list == OMP_LIST_REDUCTION
10289 21791 : || list == OMP_LIST_REDUCTION_TASK
10290 19329 : || list == OMP_LIST_REDUCTION_INSCAN
10291 19329 : || list == OMP_LIST_IN_REDUCTION
10292 19116 : || list == OMP_LIST_TASK_REDUCTION)
10293 2675 : && !component_ref_p)
10294 : {
10295 : /* Attempts to mix reduction types are diagnosed below. */
10296 2675 : if (n->sym->gen_mark || n->sym->dev_mark)
10297 2 : gfc_error ("Symbol %qs present on multiple clauses at %L",
10298 : n->sym->name, &n->where);
10299 2675 : n->sym->reduc_mark = 1;
10300 : }
10301 19116 : else if ((!component_ref_p && n->sym->comp_mark)
10302 19115 : || (component_ref_p && n->sym->mark))
10303 : {
10304 42 : if (openacc)
10305 3 : gfc_error ("Symbol %qs has mixed component and non-component "
10306 3 : "accesses at %L", n->sym->name, &n->where);
10307 : }
10308 19074 : else if ((openacc || list != OMP_LIST_MAP) && n->sym->mark)
10309 88 : gfc_error ("Symbol %qs present on multiple clauses at %L",
10310 : n->sym->name, &n->where);
10311 : else
10312 : {
10313 18986 : if (component_ref_p)
10314 2473 : n->sym->comp_mark = 1;
10315 : else
10316 16513 : n->sym->mark = 1;
10317 : }
10318 : }
10319 :
10320 : /* Detect specifically the case where we have "map(x) private(x)" and raise
10321 : an error. If we have "...simd" combined directives though, the "private"
10322 : applies to the simd part, so this is permitted though. */
10323 42590 : for (n = omp_clauses->lists[OMP_LIST_PRIVATE]; n; n = n->next)
10324 9400 : if (n->sym->mark
10325 6 : && n->sym->gen_mark
10326 6 : && !n->sym->dev_mark
10327 6 : && !n->sym->reduc_mark
10328 5 : && code->op != EXEC_OMP_TARGET_SIMD
10329 : && code->op != EXEC_OMP_TARGET_PARALLEL_DO_SIMD
10330 : && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD
10331 : && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD)
10332 1 : gfc_error ("Symbol %qs present on multiple clauses at %L",
10333 : n->sym->name, &n->where);
10334 :
10335 : gcc_assert (OMP_LIST_LASTPRIVATE == OMP_LIST_FIRSTPRIVATE + 1);
10336 99570 : for (list = OMP_LIST_FIRSTPRIVATE; list <= OMP_LIST_LASTPRIVATE;
10337 66380 : list = gfc_omp_list_type (list + 1))
10338 70607 : for (n = omp_clauses->lists[list]; n; n = n->next)
10339 4227 : if (n->sym->data_mark || n->sym->gen_mark || n->sym->dev_mark)
10340 : {
10341 9 : gfc_error ("Symbol %qs present on multiple clauses at %L",
10342 : n->sym->name, &n->where);
10343 9 : n->sym->data_mark = n->sym->gen_mark = n->sym->dev_mark = 0;
10344 : }
10345 4218 : else if (n->sym->mark
10346 18 : && code->op != EXEC_OMP_TARGET_TEAMS
10347 : && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE
10348 : && code->op != EXEC_OMP_TARGET_TEAMS_LOOP
10349 : && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD
10350 : && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO
10351 : && code->op != EXEC_OMP_TARGET_PARALLEL
10352 : && code->op != EXEC_OMP_TARGET_PARALLEL_DO
10353 : && code->op != EXEC_OMP_TARGET_PARALLEL_LOOP
10354 : && code->op != EXEC_OMP_TARGET_PARALLEL_DO_SIMD
10355 : && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD)
10356 7 : gfc_error ("Symbol %qs present on both data and map clauses "
10357 : "at %L", n->sym->name, &n->where);
10358 :
10359 35109 : for (n = omp_clauses->lists[OMP_LIST_FIRSTPRIVATE]; n; n = n->next)
10360 : {
10361 1919 : if (n->sym->data_mark || n->sym->gen_mark || n->sym->dev_mark)
10362 7 : gfc_error ("Symbol %qs present on multiple clauses at %L",
10363 : n->sym->name, &n->where);
10364 : else
10365 1912 : n->sym->data_mark = 1;
10366 : }
10367 :
10368 : /* LASTPRIVATE clauses. */
10369 35498 : for (n = omp_clauses->lists[OMP_LIST_LASTPRIVATE]; n; n = n->next)
10370 2308 : n->sym->data_mark = 0;
10371 35498 : for (n = omp_clauses->lists[OMP_LIST_LASTPRIVATE]; n; n = n->next)
10372 : {
10373 2308 : if (n->sym->data_mark || n->sym->gen_mark || n->sym->dev_mark)
10374 0 : gfc_error ("Symbol %qs present on multiple clauses at %L",
10375 : n->sym->name, &n->where);
10376 : else
10377 2308 : n->sym->data_mark = 1;
10378 : }
10379 :
10380 : /* ALIGNED clauses. */
10381 33340 : for (n = omp_clauses->lists[OMP_LIST_ALIGNED]; n; n = n->next)
10382 150 : n->sym->mark = 0;
10383 :
10384 33340 : for (n = omp_clauses->lists[OMP_LIST_ALIGNED]; n; n = n->next)
10385 : {
10386 150 : if (n->sym->mark)
10387 0 : gfc_error ("Symbol %qs present on multiple clauses at %L",
10388 : n->sym->name, &n->where);
10389 : else
10390 150 : n->sym->mark = 1;
10391 : }
10392 :
10393 : /* FROM and TO clauses. */
10394 33960 : for (n = omp_clauses->lists[OMP_LIST_TO]; n; n = n->next)
10395 770 : n->sym->mark = 0;
10396 34225 : for (n = omp_clauses->lists[OMP_LIST_FROM]; n; n = n->next)
10397 1035 : if (n->expr == NULL)
10398 1017 : n->sym->mark = 1;
10399 33960 : for (n = omp_clauses->lists[OMP_LIST_TO]; n; n = n->next)
10400 : {
10401 770 : if (n->expr == NULL && n->sym->mark)
10402 0 : gfc_error ("Symbol %qs present on both FROM and TO clauses at %L",
10403 : n->sym->name, &n->where);
10404 : else
10405 770 : n->sym->mark = 1;
10406 : }
10407 :
10408 : /* OpenACC reductions. */
10409 33190 : if (openacc)
10410 : {
10411 15131 : for (n = omp_clauses->lists[OMP_LIST_REDUCTION]; n; n = n->next)
10412 2136 : n->sym->mark = 0;
10413 15131 : for (n = omp_clauses->lists[OMP_LIST_REDUCTION]; n; n = n->next)
10414 : {
10415 2136 : if (n->sym->mark)
10416 0 : gfc_error ("Symbol %qs present on multiple clauses at %L",
10417 : n->sym->name, &n->where);
10418 : else
10419 2136 : n->sym->mark = 1;
10420 :
10421 : /* OpenACC does not support reductions on arrays. */
10422 2136 : if (n->sym->as)
10423 71 : gfc_error ("Array %qs is not permitted in reduction at %L",
10424 : n->sym->name, &n->where);
10425 : }
10426 : }
10427 33190 : }
10428 :
10429 : /* OpenMP/OpenACC: Resolve the list item of a MAP, TO, FROM, CACHE, AFFINITY
10430 : or DEPEND clause. */
10431 :
10432 : static void
10433 20963 : resolve_omp_clauses_aff_dep_map_cache (gfc_code *code,
10434 : gfc_omp_namelist *n,
10435 : const char *name,
10436 : enum gfc_omp_list_type list,
10437 : gfc_omp_clauses *omp_clauses,
10438 : bool openacc)
10439 : {
10440 20963 : gcc_checking_assert (list == OMP_LIST_AFFINITY || list == OMP_LIST_DEPEND
10441 : || list == OMP_LIST_MAP || list == OMP_LIST_TO
10442 : || list == OMP_LIST_FROM || list == OMP_LIST_CACHE);
10443 :
10444 20963 : if (list != OMP_LIST_CACHE && n->u2.ns && !n->u2.ns->resolved)
10445 : {
10446 109 : n->u2.ns->resolved = 1;
10447 109 : for (gfc_symbol *sym = n->u2.ns->omp_affinity_iterators;
10448 235 : sym; sym = sym->tlink)
10449 : {
10450 126 : gfc_constructor *c;
10451 126 : c = gfc_constructor_first (sym->value->value.constructor);
10452 126 : if (!gfc_resolve_expr (c->expr)
10453 126 : || c->expr->ts.type != BT_INTEGER
10454 250 : || c->expr->rank != 0)
10455 2 : gfc_error ("Scalar integer expression for range begin expected "
10456 2 : "at %L", &c->expr->where);
10457 126 : c = gfc_constructor_next (c);
10458 126 : if (!gfc_resolve_expr (c->expr)
10459 126 : || c->expr->ts.type != BT_INTEGER
10460 250 : || c->expr->rank != 0)
10461 2 : gfc_error ("Scalar integer expression for range end expected at %L",
10462 2 : &c->expr->where);
10463 126 : c = gfc_constructor_next (c);
10464 126 : if (c && (!gfc_resolve_expr (c->expr)
10465 16 : || c->expr->ts.type != BT_INTEGER
10466 14 : || c->expr->rank != 0))
10467 2 : gfc_error ("Scalar integer expression for range step expected "
10468 2 : "at %L", &c->expr->where);
10469 124 : else if (c
10470 14 : && c->expr->expr_type == EXPR_CONSTANT
10471 12 : && mpz_cmp_si (c->expr->value.integer, 0) == 0)
10472 2 : gfc_error ("Nonzero range step expected at %L", &c->expr->where);
10473 : }
10474 : }
10475 20862 : if (list == OMP_LIST_DEPEND)
10476 : {
10477 1964 : if (n->u.depend_doacross_op == OMP_DEPEND_SINK_FIRST
10478 : || n->u.depend_doacross_op == OMP_DOACROSS_SINK_FIRST
10479 1964 : || n->u.depend_doacross_op == OMP_DOACROSS_SINK)
10480 : {
10481 1233 : if (omp_clauses->doacross_source)
10482 : {
10483 0 : gfc_error ("Dependence-type SINK used together with SOURCE on "
10484 : "the same construct at %L", &n->where);
10485 0 : omp_clauses->doacross_source = false;
10486 : }
10487 1233 : else if (n->expr)
10488 : {
10489 571 : if (!gfc_resolve_expr (n->expr)
10490 571 : || n->expr->ts.type != BT_INTEGER
10491 1142 : || n->expr->rank != 0)
10492 0 : gfc_error ("SINK addend not a constant integer at %L",
10493 : &n->where);
10494 : }
10495 1233 : if (n->sym == NULL
10496 4 : && (n->expr == NULL
10497 3 : || mpz_cmp_si (n->expr->value.integer, -1) != 0))
10498 2 : gfc_error ("omp_cur_iteration at %L requires %<-1%> as "
10499 : "logical offset", &n->where);
10500 : return;
10501 : }
10502 731 : if (n->u.depend_doacross_op == OMP_DEPEND_DEPOBJ
10503 38 : && !n->expr
10504 22 : && (n->sym->ts.type != BT_INTEGER
10505 22 : || n->sym->ts.kind != 2 * gfc_index_integer_kind
10506 22 : || n->sym->attr.dimension))
10507 0 : gfc_error ("Locator %qs at %L in DEPEND clause of depobj type shall be "
10508 : "a scalar integer of OMP_DEPEND_KIND kind",
10509 : n->sym->name, &n->where);
10510 731 : else if (n->u.depend_doacross_op == OMP_DEPEND_DEPOBJ
10511 38 : && n->expr
10512 747 : && (!gfc_resolve_expr (n->expr)
10513 16 : || n->expr->ts.type != BT_INTEGER
10514 16 : || n->expr->ts.kind != 2 * gfc_index_integer_kind
10515 16 : || n->expr->rank != 0))
10516 0 : gfc_error ("Locator at %L in DEPEND clause of depobj type shall be a "
10517 0 : "scalar integer of OMP_DEPEND_KIND kind", &n->expr->where);
10518 : }
10519 19730 : gfc_ref *lastref = NULL, *lastslice = NULL;
10520 19730 : bool resolved = false;
10521 19730 : if (n->expr)
10522 : {
10523 6546 : lastref = n->expr->ref;
10524 6546 : resolved = gfc_resolve_expr (n->expr);
10525 :
10526 : /* Look through component refs to find last array reference. */
10527 6546 : if (resolved)
10528 : {
10529 16585 : for (gfc_ref *ref = n->expr->ref; ref; ref = ref->next)
10530 10057 : if (ref->type == REF_COMPONENT
10531 : || ref->type == REF_SUBSTRING
10532 10057 : || ref->type == REF_INQUIRY)
10533 : lastref = ref;
10534 6799 : else if (ref->type == REF_ARRAY)
10535 : {
10536 14290 : for (int i = 0; i < ref->u.ar.dimen; i++)
10537 7491 : if (ref->u.ar.dimen_type[i] == DIMEN_RANGE)
10538 6277 : lastslice = ref;
10539 : lastref = ref;
10540 : }
10541 :
10542 : /* The "!$acc cache" directive allows rectangular subarrays to be
10543 : specified, with some restrictions on the form of bounds (not
10544 : implemented). Only raise an error here if we're really sure the
10545 : array isn't contiguous. An expression such as arr(-n:n,-n:n)
10546 : could be contiguous even if it looks like it may not be. */
10547 6528 : if (code
10548 6502 : && code->op != EXEC_OACC_UPDATE
10549 5720 : && list != OMP_LIST_CACHE
10550 5720 : && list != OMP_LIST_DEPEND
10551 5398 : && !gfc_is_simply_contiguous (n->expr, false, true)
10552 1517 : && gfc_is_not_contiguous (n->expr)
10553 6541 : && !(lastslice && (lastslice->next
10554 3 : || lastslice->type != REF_ARRAY)))
10555 3 : gfc_error ("Array is not contiguous at %L", &n->where);
10556 : }
10557 : }
10558 19730 : if (list == OMP_LIST_MAP
10559 17058 : && (n->sym->attr.omp_groupprivate
10560 17057 : || n->sym->attr.omp_declare_target_local))
10561 2 : gfc_error ("%qs argument to MAP clause at %L must not be a device-local "
10562 : "variable, including GROUPPRIVATE", n->sym->name, &n->where);
10563 19730 : if (openacc
10564 19730 : && list == OMP_LIST_MAP
10565 9571 : && (n->u.map.op == OMP_MAP_ATTACH || n->u.map.op == OMP_MAP_DETACH))
10566 : {
10567 117 : symbol_attribute attr;
10568 117 : if (n->expr)
10569 99 : attr = gfc_expr_attr (n->expr);
10570 : else
10571 18 : attr = n->sym->attr;
10572 117 : if (!attr.pointer && !attr.allocatable)
10573 7 : gfc_error ("%qs clause argument must be ALLOCATABLE or a POINTER at %L",
10574 7 : (n->u.map.op == OMP_MAP_ATTACH) ? "attach" : "detach",
10575 : &n->where);
10576 : }
10577 19730 : if (lastref
10578 13196 : || (n->expr && (!resolved || n->expr->expr_type != EXPR_VARIABLE)))
10579 : {
10580 6546 : if (!lastslice && lastref && lastref->type == REF_SUBSTRING)
10581 11 : gfc_error ("Unexpected substring reference in %s clause at %L",
10582 : name, &n->where);
10583 6535 : else if (!lastslice && lastref && lastref->type == REF_INQUIRY)
10584 : {
10585 12 : gcc_assert (lastref->u.i == INQUIRY_RE || lastref->u.i == INQUIRY_IM);
10586 12 : gfc_error ("Unexpected complex-parts designator reference in %s "
10587 : "clause at %L", name, &n->where);
10588 : }
10589 6523 : else if (!resolved
10590 6505 : || n->expr->expr_type != EXPR_VARIABLE
10591 6493 : || (lastslice
10592 5615 : && (lastslice->next || lastslice->type != REF_ARRAY)))
10593 46 : gfc_error ("%qs in %s clause at %L is not a proper array section",
10594 46 : n->sym->name, name, &n->where);
10595 : else if (lastslice)
10596 : {
10597 : int i;
10598 : gfc_array_ref *ar = &lastslice->u.ar;
10599 11873 : for (i = 0; i < ar->dimen; i++)
10600 6275 : if (ar->stride[i] && code && code->op != EXEC_OACC_UPDATE)
10601 : {
10602 1 : gfc_error ("Stride should not be specified for array section "
10603 : "in %s clause at %L", name, &n->where);
10604 1 : break;
10605 : }
10606 6274 : else if (ar->dimen_type[i] != DIMEN_ELEMENT
10607 6274 : && ar->dimen_type[i] != DIMEN_RANGE)
10608 : {
10609 0 : gfc_error ("%qs in %s clause at %L is not a proper array "
10610 0 : "section", n->sym->name, name, &n->where);
10611 0 : break;
10612 : }
10613 6274 : else if ((list == OMP_LIST_DEPEND || list == OMP_LIST_AFFINITY)
10614 161 : && ar->start[i]
10615 133 : && ar->start[i]->expr_type == EXPR_CONSTANT
10616 97 : && ar->end[i]
10617 72 : && ar->end[i]->expr_type == EXPR_CONSTANT
10618 72 : && mpz_cmp (ar->start[i]->value.integer,
10619 72 : ar->end[i]->value.integer) > 0)
10620 : {
10621 0 : gfc_error ("%qs in %s clause at %L is a zero size array "
10622 0 : "section", n->sym->name,
10623 : list == OMP_LIST_DEPEND ? "DEPEND" : "AFFINITY",
10624 : &n->where);
10625 0 : break;
10626 : }
10627 : }
10628 : }
10629 13184 : else if (openacc)
10630 : {
10631 5915 : if (list == OMP_LIST_MAP && n->u.map.op == OMP_MAP_FORCE_DEVICEPTR)
10632 65 : resolve_oacc_deviceptr_clause (n->sym, n->where, name);
10633 : else
10634 5850 : resolve_oacc_data_clauses (n->sym, n->where, name);
10635 : }
10636 7269 : else if (list != OMP_LIST_DEPEND
10637 6775 : && n->sym->as
10638 3340 : && n->sym->as->type == AS_ASSUMED_SIZE)
10639 5 : gfc_error ("Assumed size array %qs in %s clause at %L",
10640 : n->sym->name, name, &n->where);
10641 19730 : if (code && list == OMP_LIST_MAP && !openacc)
10642 7442 : switch (code->op)
10643 : {
10644 6161 : case EXEC_OMP_TARGET:
10645 6161 : case EXEC_OMP_TARGET_PARALLEL:
10646 6161 : case EXEC_OMP_TARGET_PARALLEL_DO:
10647 6161 : case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
10648 6161 : case EXEC_OMP_TARGET_PARALLEL_LOOP:
10649 6161 : case EXEC_OMP_TARGET_SIMD:
10650 6161 : case EXEC_OMP_TARGET_TEAMS:
10651 6161 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
10652 6161 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
10653 6161 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
10654 6161 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
10655 6161 : case EXEC_OMP_TARGET_TEAMS_LOOP:
10656 6161 : case EXEC_OMP_TARGET_DATA:
10657 6161 : switch (n->u.map.op)
10658 : {
10659 : case OMP_MAP_TO:
10660 : case OMP_MAP_ALWAYS_TO:
10661 : case OMP_MAP_PRESENT_TO:
10662 : case OMP_MAP_ALWAYS_PRESENT_TO:
10663 : case OMP_MAP_FROM:
10664 : case OMP_MAP_ALWAYS_FROM:
10665 : case OMP_MAP_PRESENT_FROM:
10666 : case OMP_MAP_ALWAYS_PRESENT_FROM:
10667 : case OMP_MAP_TOFROM:
10668 : case OMP_MAP_ALWAYS_TOFROM:
10669 : case OMP_MAP_PRESENT_TOFROM:
10670 : case OMP_MAP_ALWAYS_PRESENT_TOFROM:
10671 : case OMP_MAP_ALLOC:
10672 : case OMP_MAP_PRESENT_ALLOC:
10673 : break;
10674 2 : default:
10675 2 : gfc_error ("TARGET%s with map-type other than TO, "
10676 : "FROM, TOFROM, or ALLOC on MAP clause "
10677 : "at %L",
10678 : code->op == EXEC_OMP_TARGET_DATA
10679 : ? " DATA" : "", &n->where);
10680 2 : break;
10681 : }
10682 : break;
10683 701 : case EXEC_OMP_TARGET_ENTER_DATA:
10684 701 : switch (n->u.map.op)
10685 : {
10686 : case OMP_MAP_TO:
10687 : case OMP_MAP_ALWAYS_TO:
10688 : case OMP_MAP_PRESENT_TO:
10689 : case OMP_MAP_ALWAYS_PRESENT_TO:
10690 : case OMP_MAP_ALLOC:
10691 : case OMP_MAP_PRESENT_ALLOC:
10692 : break;
10693 181 : case OMP_MAP_TOFROM:
10694 181 : n->u.map.op = OMP_MAP_TO;
10695 181 : break;
10696 3 : case OMP_MAP_ALWAYS_TOFROM:
10697 3 : n->u.map.op = OMP_MAP_ALWAYS_TO;
10698 3 : break;
10699 2 : case OMP_MAP_PRESENT_TOFROM:
10700 2 : n->u.map.op = OMP_MAP_PRESENT_TO;
10701 2 : break;
10702 2 : case OMP_MAP_ALWAYS_PRESENT_TOFROM:
10703 2 : n->u.map.op = OMP_MAP_ALWAYS_PRESENT_TO;
10704 2 : break;
10705 2 : default:
10706 2 : gfc_error ("TARGET ENTER DATA with map-type other "
10707 : "than TO, TOFROM or ALLOC on MAP clause "
10708 : "at %L", &n->where);
10709 2 : break;
10710 : }
10711 : break;
10712 580 : case EXEC_OMP_TARGET_EXIT_DATA:
10713 580 : switch (n->u.map.op)
10714 : {
10715 : case OMP_MAP_FROM:
10716 : case OMP_MAP_ALWAYS_FROM:
10717 : case OMP_MAP_PRESENT_FROM:
10718 : case OMP_MAP_ALWAYS_PRESENT_FROM:
10719 : case OMP_MAP_RELEASE:
10720 : case OMP_MAP_DELETE:
10721 : break;
10722 134 : case OMP_MAP_TOFROM:
10723 134 : n->u.map.op = OMP_MAP_FROM;
10724 134 : break;
10725 1 : case OMP_MAP_ALWAYS_TOFROM:
10726 1 : n->u.map.op = OMP_MAP_ALWAYS_FROM;
10727 1 : break;
10728 0 : case OMP_MAP_PRESENT_TOFROM:
10729 0 : n->u.map.op = OMP_MAP_PRESENT_FROM;
10730 0 : break;
10731 0 : case OMP_MAP_ALWAYS_PRESENT_TOFROM:
10732 0 : n->u.map.op = OMP_MAP_ALWAYS_PRESENT_FROM;
10733 0 : break;
10734 2 : default:
10735 2 : gfc_error ("TARGET EXIT DATA with map-type other "
10736 : "than FROM, TOFROM, RELEASE, or DELETE on "
10737 : "MAP clause at %L", &n->where);
10738 2 : break;
10739 : }
10740 : break;
10741 : default:
10742 : break;
10743 : }
10744 19730 : if (list == OMP_LIST_MAP || list == OMP_LIST_TO || list == OMP_LIST_FROM)
10745 : {
10746 18863 : gfc_typespec *ts = n->expr ? &n->expr->ts : &n->sym->ts;
10747 :
10748 18863 : if (ts->type == BT_DERIVED || ts->type == BT_CLASS)
10749 : {
10750 10 : const char *mapper_id = (n->u3.udm
10751 1002 : ? n->u3.udm->requested_mapper_id : "");
10752 1002 : gfc_omp_udm *udm = gfc_find_omp_udm (gfc_current_ns, mapper_id, ts);
10753 1002 : if (mapper_id[0] != '\0' && !udm)
10754 1 : gfc_error ("User-defined mapper %qs not found at %L",
10755 : mapper_id, &n->where);
10756 997 : else if (udm)
10757 : {
10758 27 : if (!n->u3.udm)
10759 : {
10760 18 : gcc_assert (mapper_id[0] == '\0');
10761 18 : n->u3.udm = gfc_get_omp_namelist_udm ();
10762 18 : n->u3.udm->requested_mapper_id = mapper_id;
10763 : }
10764 27 : n->u3.udm->resolved_udm = udm;
10765 : }
10766 : }
10767 : }
10768 :
10769 19730 : if (list != OMP_LIST_DEPEND)
10770 : {
10771 18999 : n->sym->attr.referenced = 1;
10772 18999 : if (n->sym->attr.threadprivate)
10773 1 : gfc_error ("THREADPRIVATE object %qs in %s clause at %L",
10774 : n->sym->name, name, &n->where);
10775 18999 : if (n->sym->attr.cray_pointee)
10776 14 : gfc_error ("Cray pointee %qs in %s clause at %L",
10777 : n->sym->name, name, &n->where);
10778 : }
10779 : }
10780 :
10781 : /* OpenMP directive resolving routines. */
10782 :
10783 : static void
10784 33190 : resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
10785 : gfc_namespace *ns, bool openacc = false)
10786 : {
10787 33190 : gfc_omp_namelist *n, *last;
10788 33190 : gfc_expr_list *el;
10789 33190 : enum gfc_omp_list_type list;
10790 33190 : int ifc;
10791 33190 : bool if_without_mod = false;
10792 33190 : gfc_omp_linear_op linear_op = OMP_LINEAR_DEFAULT;
10793 33190 : static const char *clause_names[]
10794 : = { "PRIVATE", "FIRSTPRIVATE", "LASTPRIVATE", "COPYPRIVATE", "SHARED",
10795 : "COPYIN", "UNIFORM", "AFFINITY", "ALIGNED", "LINEAR", "DEPEND", "MAP",
10796 : "TO", "FROM", "INCLUSIVE", "EXCLUSIVE",
10797 : "REDUCTION", "REDUCTION" /*inscan*/, "REDUCTION" /*task*/,
10798 : "IN_REDUCTION", "TASK_REDUCTION",
10799 : "DEVICE_RESIDENT", "LINK", "LOCAL", "USE_DEVICE",
10800 : "CACHE", "IS_DEVICE_PTR", "USE_DEVICE_PTR", "USE_DEVICE_ADDR",
10801 : "NONTEMPORAL", "ALLOCATE", "HAS_DEVICE_ADDR", "ENTER",
10802 : "USES_ALLOCATORS", "INIT", "USE", "DESTROY", "INTEROP", "ADJUST_ARGS" };
10803 33190 : STATIC_ASSERT (ARRAY_SIZE (clause_names) == OMP_LIST_NUM);
10804 :
10805 33190 : if (omp_clauses == NULL)
10806 : return;
10807 :
10808 33190 : if (ns == NULL)
10809 32705 : ns = gfc_current_ns;
10810 :
10811 33190 : check_omp_clauses_dupl_syms (code, omp_clauses, openacc);
10812 :
10813 33190 : if (omp_clauses->orderedc && omp_clauses->orderedc < omp_clauses->collapse)
10814 0 : gfc_error ("ORDERED clause parameter is less than COLLAPSE at %L",
10815 : &code->loc);
10816 33190 : if (omp_clauses->order_concurrent && omp_clauses->ordered)
10817 4 : gfc_error ("ORDER clause must not be used together with ORDERED at %L",
10818 : &code->loc);
10819 33190 : if (omp_clauses->if_expr)
10820 : {
10821 1299 : gfc_expr *expr = omp_clauses->if_expr;
10822 1299 : if (!gfc_resolve_expr (expr)
10823 1299 : || expr->ts.type != BT_LOGICAL || expr->rank != 0)
10824 16 : gfc_error ("IF clause at %L requires a scalar LOGICAL expression",
10825 : &expr->where);
10826 : if_without_mod = true;
10827 : }
10828 365090 : for (ifc = 0; ifc < OMP_IF_LAST; ifc++)
10829 331900 : if (omp_clauses->if_exprs[ifc])
10830 : {
10831 141 : gfc_expr *expr = omp_clauses->if_exprs[ifc];
10832 141 : bool ok = true;
10833 141 : if (!gfc_resolve_expr (expr)
10834 141 : || expr->ts.type != BT_LOGICAL || expr->rank != 0)
10835 0 : gfc_error ("IF clause at %L requires a scalar LOGICAL expression",
10836 : &expr->where);
10837 141 : else if (if_without_mod)
10838 : {
10839 1 : gfc_error ("IF clause without modifier at %L used together with "
10840 : "IF clauses with modifiers",
10841 1 : &omp_clauses->if_expr->where);
10842 1 : if_without_mod = false;
10843 : }
10844 : else
10845 140 : switch (code->op)
10846 : {
10847 13 : case EXEC_OMP_CANCEL:
10848 13 : ok = ifc == OMP_IF_CANCEL;
10849 13 : break;
10850 :
10851 16 : case EXEC_OMP_PARALLEL:
10852 16 : case EXEC_OMP_PARALLEL_DO:
10853 16 : case EXEC_OMP_PARALLEL_LOOP:
10854 16 : case EXEC_OMP_PARALLEL_MASKED:
10855 16 : case EXEC_OMP_PARALLEL_MASTER:
10856 16 : case EXEC_OMP_PARALLEL_SECTIONS:
10857 16 : case EXEC_OMP_PARALLEL_WORKSHARE:
10858 16 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
10859 16 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
10860 16 : ok = ifc == OMP_IF_PARALLEL;
10861 16 : break;
10862 :
10863 28 : case EXEC_OMP_PARALLEL_DO_SIMD:
10864 28 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
10865 28 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
10866 28 : ok = ifc == OMP_IF_PARALLEL || ifc == OMP_IF_SIMD;
10867 28 : break;
10868 :
10869 8 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
10870 8 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
10871 8 : ok = ifc == OMP_IF_PARALLEL || ifc == OMP_IF_TASKLOOP;
10872 8 : break;
10873 :
10874 12 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
10875 12 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
10876 12 : ok = (ifc == OMP_IF_PARALLEL
10877 12 : || ifc == OMP_IF_TASKLOOP
10878 : || ifc == OMP_IF_SIMD);
10879 : break;
10880 :
10881 0 : case EXEC_OMP_SIMD:
10882 0 : case EXEC_OMP_DO_SIMD:
10883 0 : case EXEC_OMP_DISTRIBUTE_SIMD:
10884 0 : case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
10885 0 : ok = ifc == OMP_IF_SIMD;
10886 0 : break;
10887 :
10888 1 : case EXEC_OMP_TASK:
10889 1 : ok = ifc == OMP_IF_TASK;
10890 1 : break;
10891 :
10892 5 : case EXEC_OMP_TASKLOOP:
10893 5 : case EXEC_OMP_MASKED_TASKLOOP:
10894 5 : case EXEC_OMP_MASTER_TASKLOOP:
10895 5 : ok = ifc == OMP_IF_TASKLOOP;
10896 5 : break;
10897 :
10898 20 : case EXEC_OMP_TASKLOOP_SIMD:
10899 20 : case EXEC_OMP_MASKED_TASKLOOP_SIMD:
10900 20 : case EXEC_OMP_MASTER_TASKLOOP_SIMD:
10901 20 : ok = ifc == OMP_IF_TASKLOOP || ifc == OMP_IF_SIMD;
10902 20 : break;
10903 :
10904 5 : case EXEC_OMP_TARGET:
10905 5 : case EXEC_OMP_TARGET_TEAMS:
10906 5 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
10907 5 : case EXEC_OMP_TARGET_TEAMS_LOOP:
10908 5 : ok = ifc == OMP_IF_TARGET;
10909 5 : break;
10910 :
10911 4 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
10912 4 : case EXEC_OMP_TARGET_SIMD:
10913 4 : ok = ifc == OMP_IF_TARGET || ifc == OMP_IF_SIMD;
10914 4 : break;
10915 :
10916 2 : case EXEC_OMP_TARGET_DATA:
10917 2 : ok = ifc == OMP_IF_TARGET_DATA;
10918 2 : break;
10919 :
10920 2 : case EXEC_OMP_TARGET_UPDATE:
10921 2 : ok = ifc == OMP_IF_TARGET_UPDATE;
10922 2 : break;
10923 :
10924 2 : case EXEC_OMP_TARGET_ENTER_DATA:
10925 2 : ok = ifc == OMP_IF_TARGET_ENTER_DATA;
10926 2 : break;
10927 :
10928 2 : case EXEC_OMP_TARGET_EXIT_DATA:
10929 2 : ok = ifc == OMP_IF_TARGET_EXIT_DATA;
10930 2 : break;
10931 :
10932 10 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
10933 10 : case EXEC_OMP_TARGET_PARALLEL:
10934 10 : case EXEC_OMP_TARGET_PARALLEL_DO:
10935 10 : case EXEC_OMP_TARGET_PARALLEL_LOOP:
10936 10 : ok = ifc == OMP_IF_TARGET || ifc == OMP_IF_PARALLEL;
10937 10 : break;
10938 :
10939 10 : case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
10940 10 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
10941 10 : ok = (ifc == OMP_IF_TARGET
10942 10 : || ifc == OMP_IF_PARALLEL
10943 : || ifc == OMP_IF_SIMD);
10944 : break;
10945 :
10946 : default:
10947 : ok = false;
10948 : break;
10949 : }
10950 119 : if (!ok)
10951 : {
10952 2 : static const char *ifs[] = {
10953 : "CANCEL",
10954 : "PARALLEL",
10955 : "SIMD",
10956 : "TASK",
10957 : "TASKLOOP",
10958 : "TARGET",
10959 : "TARGET DATA",
10960 : "TARGET UPDATE",
10961 : "TARGET ENTER DATA",
10962 : "TARGET EXIT DATA"
10963 : };
10964 2 : gfc_error ("IF clause modifier %s at %L not appropriate for "
10965 : "the current OpenMP construct", ifs[ifc], &expr->where);
10966 : }
10967 : }
10968 :
10969 33190 : if (omp_clauses->self_expr)
10970 : {
10971 177 : gfc_expr *expr = omp_clauses->self_expr;
10972 177 : if (!gfc_resolve_expr (expr)
10973 177 : || expr->ts.type != BT_LOGICAL || expr->rank != 0)
10974 6 : gfc_error ("SELF clause at %L requires a scalar LOGICAL expression",
10975 : &expr->where);
10976 : }
10977 :
10978 33190 : if (omp_clauses->final_expr)
10979 : {
10980 64 : gfc_expr *expr = omp_clauses->final_expr;
10981 64 : if (!gfc_resolve_expr (expr)
10982 64 : || expr->ts.type != BT_LOGICAL || expr->rank != 0)
10983 0 : gfc_error ("FINAL clause at %L requires a scalar LOGICAL expression",
10984 : &expr->where);
10985 : }
10986 33190 : if (omp_clauses->novariants)
10987 : {
10988 9 : gfc_expr *expr = omp_clauses->novariants;
10989 18 : if (!gfc_resolve_expr (expr) || expr->ts.type != BT_LOGICAL
10990 17 : || expr->rank != 0)
10991 1 : gfc_error (
10992 : "NOVARIANTS clause at %L requires a scalar LOGICAL expression",
10993 : &expr->where);
10994 33190 : if_without_mod = true;
10995 : }
10996 33190 : if (omp_clauses->nocontext)
10997 : {
10998 12 : gfc_expr *expr = omp_clauses->nocontext;
10999 24 : if (!gfc_resolve_expr (expr) || expr->ts.type != BT_LOGICAL
11000 23 : || expr->rank != 0)
11001 1 : gfc_error (
11002 : "NOCONTEXT clause at %L requires a scalar LOGICAL expression",
11003 : &expr->where);
11004 33190 : if_without_mod = true;
11005 : }
11006 :
11007 34206 : for (el = omp_clauses->num_threads_list; el; el = el->next)
11008 1016 : resolve_positive_int_expr (el->expr, "NUM_THREADS", true);
11009 :
11010 33190 : if (omp_clauses->dyn_groupprivate)
11011 14 : resolve_nonnegative_int_expr (omp_clauses->dyn_groupprivate,
11012 : "DYN_GROUPPRIVATE", true);
11013 33190 : if (omp_clauses->chunk_size)
11014 : {
11015 510 : gfc_expr *expr = omp_clauses->chunk_size;
11016 510 : if (!gfc_resolve_expr (expr)
11017 510 : || expr->ts.type != BT_INTEGER || expr->rank != 0)
11018 0 : gfc_error ("SCHEDULE clause's chunk_size at %L requires "
11019 : "a scalar INTEGER expression", &expr->where);
11020 510 : else if (expr->expr_type == EXPR_CONSTANT
11021 : && expr->ts.type == BT_INTEGER
11022 485 : && mpz_sgn (expr->value.integer) <= 0)
11023 2 : gfc_warning (OPT_Wopenmp, "INTEGER expression of SCHEDULE clause's "
11024 : "chunk_size at %L must be positive", &expr->where);
11025 : }
11026 33190 : if (omp_clauses->sched_kind != OMP_SCHED_NONE
11027 891 : && omp_clauses->sched_nonmonotonic)
11028 : {
11029 34 : if (omp_clauses->sched_monotonic)
11030 2 : gfc_error ("Both MONOTONIC and NONMONOTONIC schedule modifiers "
11031 : "specified at %L", &code->loc);
11032 32 : else if (omp_clauses->ordered)
11033 4 : gfc_error ("NONMONOTONIC schedule modifier specified with ORDERED "
11034 : "clause at %L", &code->loc);
11035 : }
11036 :
11037 33190 : if (omp_clauses->depobj
11038 33190 : && (!gfc_resolve_expr (omp_clauses->depobj)
11039 118 : || omp_clauses->depobj->ts.type != BT_INTEGER
11040 117 : || omp_clauses->depobj->ts.kind != 2 * gfc_index_integer_kind
11041 116 : || omp_clauses->depobj->rank != 0))
11042 4 : gfc_error ("DEPOBJ in DEPOBJ construct at %L shall be a scalar integer "
11043 4 : "of OMP_DEPEND_KIND kind", &omp_clauses->depobj->where);
11044 :
11045 : /* Check that list items are variables. */
11046 1327600 : for (list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
11047 1294410 : list = gfc_omp_list_type (list + 1))
11048 1340291 : for (n = omp_clauses->lists[list]; n; n = n->next)
11049 : {
11050 45881 : if (!n->sym) /* omp_all_memory. */
11051 47 : continue;
11052 45834 : if (n->sym->attr.flavor == FL_VARIABLE
11053 277 : || n->sym->attr.proc_pointer
11054 236 : || (!code
11055 0 : && !ns->omp_udm_ns
11056 0 : && (!n->sym->attr.dummy || n->sym->ns != ns)))
11057 : {
11058 45598 : if (!code
11059 322 : && !ns->omp_udm_ns
11060 277 : && (!n->sym->attr.dummy || n->sym->ns != ns))
11061 0 : gfc_error ("Variable %qs is not a dummy argument at %L",
11062 : n->sym->name, &n->where);
11063 45598 : continue;
11064 : }
11065 236 : if (n->sym->attr.flavor == FL_PROCEDURE
11066 153 : && n->sym->result == n->sym
11067 138 : && n->sym->attr.function)
11068 : {
11069 138 : if (ns->proc_name == n->sym
11070 44 : || (ns->parent && ns->parent->proc_name == n->sym))
11071 101 : continue;
11072 37 : if (ns->proc_name->attr.entry_master)
11073 : {
11074 32 : gfc_entry_list *el = ns->entries;
11075 51 : for (; el; el = el->next)
11076 51 : if (el->sym == n->sym)
11077 : break;
11078 32 : if (el)
11079 32 : continue;
11080 : }
11081 5 : if (ns->parent
11082 3 : && ns->parent->proc_name->attr.entry_master)
11083 : {
11084 2 : gfc_entry_list *el = ns->parent->entries;
11085 3 : for (; el; el = el->next)
11086 3 : if (el->sym == n->sym)
11087 : break;
11088 2 : if (el)
11089 2 : continue;
11090 : }
11091 : }
11092 101 : if (list == OMP_LIST_MAP
11093 18 : && n->sym->attr.flavor == FL_PARAMETER)
11094 : {
11095 : /* OpenACC since 3.4 permits for Fortran named constants, but
11096 : permits removing then as optimization is not needed and such
11097 : ignore them. Likewise below for FIRSTPRIVATE. */
11098 12 : if (openacc)
11099 10 : gfc_warning (OPT_Wsurprising, "Clause for object %qs at %L is "
11100 : "ignored as parameters need not be copied",
11101 : n->sym->name, &n->where);
11102 : else
11103 2 : gfc_error ("Object %qs is not a variable at %L; parameters"
11104 : " cannot be and need not be mapped", n->sym->name,
11105 : &n->where);
11106 : }
11107 89 : else if (openacc && n->sym->attr.flavor == FL_PARAMETER)
11108 9 : gfc_warning (OPT_Wsurprising, "Clause for object %qs at %L is ignored"
11109 : " as it is a parameter", n->sym->name, &n->where);
11110 80 : else if (list != OMP_LIST_USES_ALLOCATORS)
11111 30 : gfc_error ("Object %qs is not a variable at %L", n->sym->name,
11112 : &n->where);
11113 : }
11114 :
11115 33190 : if (omp_clauses->lists[OMP_LIST_REDUCTION_INSCAN])
11116 : {
11117 69 : locus *loc = &omp_clauses->lists[OMP_LIST_REDUCTION_INSCAN]->where;
11118 69 : if (code->op != EXEC_OMP_DO
11119 : && code->op != EXEC_OMP_SIMD
11120 : && code->op != EXEC_OMP_DO_SIMD
11121 : && code->op != EXEC_OMP_PARALLEL_DO
11122 : && code->op != EXEC_OMP_PARALLEL_DO_SIMD)
11123 23 : gfc_error ("%<inscan%> REDUCTION clause on construct other than DO, "
11124 : "SIMD, DO SIMD, PARALLEL DO, PARALLEL DO SIMD at %L",
11125 : loc);
11126 69 : if (omp_clauses->ordered)
11127 2 : gfc_error ("ORDERED clause specified together with %<inscan%> "
11128 : "REDUCTION clause at %L", loc);
11129 69 : if (omp_clauses->sched_kind != OMP_SCHED_NONE)
11130 3 : gfc_error ("SCHEDULE clause specified together with %<inscan%> "
11131 : "REDUCTION clause at %L", loc);
11132 : }
11133 :
11134 33190 : if (code
11135 32908 : && code->op == EXEC_OMP_INTEROP
11136 63 : && omp_clauses->lists[OMP_LIST_DEPEND])
11137 : {
11138 12 : if (!omp_clauses->lists[OMP_LIST_INIT]
11139 5 : && !omp_clauses->lists[OMP_LIST_USE]
11140 1 : && !omp_clauses->lists[OMP_LIST_DESTROY])
11141 : {
11142 1 : gfc_error ("DEPEND clause at %L requires action clause with "
11143 : "%<targetsync%> interop-type",
11144 : &omp_clauses->lists[OMP_LIST_DEPEND]->where);
11145 : }
11146 22 : for (n = omp_clauses->lists[OMP_LIST_INIT]; n; n = n->next)
11147 12 : if (!n->u.init.targetsync)
11148 : {
11149 2 : gfc_error ("DEPEND clause at %L requires %<targetsync%> "
11150 : "interop-type, lacking it for %qs at %L",
11151 2 : &omp_clauses->lists[OMP_LIST_DEPEND]->where,
11152 2 : n->sym->name, &n->where);
11153 2 : break;
11154 : }
11155 : }
11156 32908 : if (code && (code->op == EXEC_OMP_INTEROP || code->op == EXEC_OMP_DISPATCH))
11157 1085 : for (list = OMP_LIST_INIT; list <= OMP_LIST_INTEROP;
11158 868 : list = gfc_omp_list_type (list + 1))
11159 1123 : for (n = omp_clauses->lists[list]; n; n = n->next)
11160 : {
11161 255 : if (n->sym->ts.type != BT_INTEGER
11162 252 : || n->sym->ts.kind != gfc_index_integer_kind
11163 248 : || n->sym->attr.dimension
11164 243 : || n->sym->attr.flavor != FL_VARIABLE)
11165 16 : gfc_error ("%qs at %L in %qs clause must be a scalar integer "
11166 : "variable of %<omp_interop_kind%> kind", n->sym->name,
11167 : &n->where, clause_names[list]);
11168 255 : if (list != OMP_LIST_USE && list != OMP_LIST_INTEROP
11169 109 : && n->sym->attr.intent == INTENT_IN)
11170 2 : gfc_error ("%qs at %L in %qs clause must be definable",
11171 : n->sym->name, &n->where, clause_names[list]);
11172 : }
11173 :
11174 33190 : resolve_omp_allocate_clauses (code, omp_clauses, ns);
11175 :
11176 33190 : bool has_inscan = false, has_notinscan = false;
11177 1360790 : for (enum gfc_omp_list_type list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
11178 1294410 : list = gfc_omp_list_type (list + 1))
11179 1294410 : if ((n = omp_clauses->lists[list]) != NULL)
11180 : {
11181 29339 : const char *name = clause_names[list];
11182 :
11183 29339 : switch (list)
11184 : {
11185 : case OMP_LIST_COPYIN:
11186 267 : for (; n != NULL; n = n->next)
11187 : {
11188 170 : if (!n->sym->attr.threadprivate)
11189 0 : gfc_error ("Non-THREADPRIVATE object %qs in COPYIN clause"
11190 : " at %L", n->sym->name, &n->where);
11191 : }
11192 : break;
11193 83 : case OMP_LIST_COPYPRIVATE:
11194 83 : if (omp_clauses->nowait)
11195 6 : gfc_error ("NOWAIT clause must not be used with COPYPRIVATE "
11196 : "clause at %L", &n->where);
11197 376 : for (; n != NULL; n = n->next)
11198 : {
11199 293 : if (n->sym->as && n->sym->as->type == AS_ASSUMED_SIZE)
11200 0 : gfc_error ("Assumed size array %qs in COPYPRIVATE clause "
11201 : "at %L", n->sym->name, &n->where);
11202 293 : if (n->sym->attr.pointer && n->sym->attr.intent == INTENT_IN)
11203 1 : gfc_error ("INTENT(IN) POINTER %qs in COPYPRIVATE clause "
11204 : "at %L", n->sym->name, &n->where);
11205 : }
11206 : break;
11207 : case OMP_LIST_SHARED:
11208 2604 : for (; n != NULL; n = n->next)
11209 : {
11210 1642 : if (n->sym->attr.threadprivate)
11211 0 : gfc_error ("THREADPRIVATE object %qs in SHARED clause at "
11212 : "%L", n->sym->name, &n->where);
11213 1642 : if (n->sym->attr.cray_pointee)
11214 1 : gfc_error ("Cray pointee %qs in SHARED clause at %L",
11215 : n->sym->name, &n->where);
11216 1642 : if (n->sym->attr.associate_var)
11217 8 : gfc_error ("Associate name %qs in SHARED clause at %L",
11218 8 : n->sym->attr.select_type_temporary
11219 4 : ? n->sym->assoc->target->symtree->n.sym->name
11220 : : n->sym->name, &n->where);
11221 1642 : if (omp_clauses->detach
11222 1 : && n->sym == omp_clauses->detach->symtree->n.sym)
11223 1 : gfc_error ("DETACH event handle %qs in SHARED clause at %L",
11224 : n->sym->name, &n->where);
11225 : }
11226 : break;
11227 : case OMP_LIST_ALIGNED:
11228 256 : for (; n != NULL; n = n->next)
11229 : {
11230 150 : if (!n->sym->attr.pointer
11231 45 : && !n->sym->attr.allocatable
11232 30 : && !n->sym->attr.cray_pointer
11233 18 : && (n->sym->ts.type != BT_DERIVED
11234 18 : || (n->sym->ts.u.derived->from_intmod
11235 : != INTMOD_ISO_C_BINDING)
11236 18 : || (n->sym->ts.u.derived->intmod_sym_id
11237 : != ISOCBINDING_PTR)))
11238 0 : gfc_error ("%qs in ALIGNED clause must be POINTER, "
11239 : "ALLOCATABLE, Cray pointer or C_PTR at %L",
11240 : n->sym->name, &n->where);
11241 150 : else if (n->expr)
11242 : {
11243 147 : if (!gfc_resolve_expr (n->expr)
11244 147 : || n->expr->ts.type != BT_INTEGER
11245 146 : || n->expr->rank != 0
11246 146 : || n->expr->expr_type != EXPR_CONSTANT
11247 292 : || mpz_sgn (n->expr->value.integer) <= 0)
11248 4 : gfc_error ("%qs in ALIGNED clause at %L requires a scalar"
11249 : " positive constant integer alignment "
11250 4 : "expression", n->sym->name, &n->where);
11251 : }
11252 : }
11253 : break;
11254 : case OMP_LIST_AFFINITY:
11255 : case OMP_LIST_DEPEND:
11256 : case OMP_LIST_MAP:
11257 : case OMP_LIST_TO:
11258 : case OMP_LIST_FROM:
11259 : case OMP_LIST_CACHE:
11260 33236 : for (; n != NULL; n = n->next)
11261 20963 : resolve_omp_clauses_aff_dep_map_cache (code, n, name, list,
11262 : omp_clauses, openacc);
11263 : break;
11264 : case OMP_LIST_IS_DEVICE_PTR:
11265 : last = NULL;
11266 377 : for (n = omp_clauses->lists[list]; n != NULL; )
11267 : {
11268 257 : if ((n->sym->ts.type != BT_DERIVED
11269 71 : || !n->sym->ts.u.derived->ts.is_iso_c
11270 71 : || (n->sym->ts.u.derived->intmod_sym_id
11271 : != ISOCBINDING_PTR))
11272 187 : && code->op == EXEC_OMP_DISPATCH)
11273 : /* Non-TARGET (i.e. DISPATCH) requires a C_PTR. */
11274 3 : gfc_error ("List item %qs in %s clause at %L must be of "
11275 : "TYPE(C_PTR)", n->sym->name, name, &n->where);
11276 254 : else if (n->sym->ts.type != BT_DERIVED
11277 70 : || !n->sym->ts.u.derived->ts.is_iso_c
11278 70 : || (n->sym->ts.u.derived->intmod_sym_id
11279 : != ISOCBINDING_PTR))
11280 : {
11281 : /* For TARGET, non-C_PTR are deprecated and handled as
11282 : has_device_addr. */
11283 184 : gfc_warning (OPT_Wdeprecated_openmp,
11284 : "Non-C_PTR type argument at %L is deprecated, "
11285 : "use HAS_DEVICE_ADDR", &n->where);
11286 184 : gfc_omp_namelist *n2 = n;
11287 184 : n = n->next;
11288 184 : if (last)
11289 0 : last->next = n;
11290 : else
11291 184 : omp_clauses->lists[list] = n;
11292 184 : n2->next = omp_clauses->lists[OMP_LIST_HAS_DEVICE_ADDR];
11293 184 : omp_clauses->lists[OMP_LIST_HAS_DEVICE_ADDR] = n2;
11294 184 : continue;
11295 184 : }
11296 73 : last = n;
11297 73 : n = n->next;
11298 : }
11299 : break;
11300 : case OMP_LIST_HAS_DEVICE_ADDR:
11301 : case OMP_LIST_USE_DEVICE_ADDR:
11302 : break;
11303 : case OMP_LIST_USE_DEVICE_PTR:
11304 : /* Non-C_PTR are deprecated and handled as use_device_ADDR. */
11305 : last = NULL;
11306 475 : for (n = omp_clauses->lists[list]; n != NULL; )
11307 : {
11308 312 : gfc_omp_namelist *n2 = n;
11309 312 : if (n->sym->ts.type != BT_DERIVED
11310 18 : || !n->sym->ts.u.derived->ts.is_iso_c)
11311 : {
11312 294 : gfc_warning (OPT_Wdeprecated_openmp,
11313 : "Non-C_PTR type argument at %L is "
11314 : "deprecated, use USE_DEVICE_ADDR", &n->where);
11315 294 : n = n->next;
11316 294 : if (last)
11317 0 : last->next = n;
11318 : else
11319 294 : omp_clauses->lists[list] = n;
11320 294 : n2->next = omp_clauses->lists[OMP_LIST_USE_DEVICE_ADDR];
11321 294 : omp_clauses->lists[OMP_LIST_USE_DEVICE_ADDR] = n2;
11322 294 : continue;
11323 : }
11324 18 : last = n;
11325 18 : n = n->next;
11326 : }
11327 : break;
11328 65 : case OMP_LIST_USES_ALLOCATORS:
11329 65 : {
11330 65 : if (n != NULL
11331 65 : && n->u.memspace_sym
11332 20 : && (n->u.memspace_sym->attr.flavor != FL_PARAMETER
11333 18 : || n->u.memspace_sym->ts.type != BT_INTEGER
11334 18 : || n->u.memspace_sym->ts.kind != gfc_c_intptr_kind
11335 18 : || n->u.memspace_sym->attr.dimension
11336 18 : || (!startswith (n->u.memspace_sym->name, "omp_")
11337 0 : && !startswith (n->u.memspace_sym->name, "ompx_"))
11338 18 : || !endswith (n->u.memspace_sym->name, "_mem_space")))
11339 3 : gfc_error ("Memspace %qs at %L in USES_ALLOCATORS must be "
11340 : "a predefined memory space",
11341 : n->u.memspace_sym->name, &n->where);
11342 180 : for (; n != NULL; n = n->next)
11343 : {
11344 122 : if (n->sym->ts.type != BT_INTEGER
11345 121 : || n->sym->ts.kind != gfc_c_intptr_kind
11346 120 : || n->sym->attr.dimension)
11347 3 : gfc_error ("Allocator %qs at %L in USES_ALLOCATORS must "
11348 : "be a scalar integer of kind "
11349 : "%<omp_allocator_handle_kind%>", n->sym->name,
11350 : &n->where);
11351 119 : else if (n->sym->attr.flavor != FL_VARIABLE
11352 50 : && strcmp (n->sym->name, "omp_null_allocator") != 0
11353 165 : && ((!startswith (n->sym->name, "omp_")
11354 1 : && !startswith (n->sym->name, "ompx_"))
11355 45 : || !endswith (n->sym->name, "_mem_alloc")))
11356 2 : gfc_error ("Allocator %qs at %L in USES_ALLOCATORS must "
11357 : "either a variable or a predefined allocator",
11358 : n->sym->name, &n->where);
11359 117 : else if ((n->u.memspace_sym || n->u2.traits_sym)
11360 61 : && n->sym->attr.flavor != FL_VARIABLE)
11361 3 : gfc_error ("A memory space or traits array may not be "
11362 : "specified for predefined allocator %qs at %L",
11363 : n->sym->name, &n->where);
11364 122 : if (n->u2.traits_sym
11365 50 : && (n->u2.traits_sym->attr.flavor != FL_PARAMETER
11366 47 : || !n->u2.traits_sym->attr.dimension
11367 45 : || n->u2.traits_sym->as->rank != 1
11368 45 : || n->u2.traits_sym->ts.type != BT_DERIVED
11369 43 : || strcmp (n->u2.traits_sym->ts.u.derived->name,
11370 : "omp_alloctrait") != 0))
11371 : {
11372 7 : gfc_error ("Traits array %qs in USES_ALLOCATORS %L must "
11373 : "be a one-dimensional named constant array of "
11374 : "type %<omp_alloctrait%>",
11375 : n->u2.traits_sym->name, &n->where);
11376 7 : break;
11377 : }
11378 : }
11379 : break;
11380 : }
11381 : default:
11382 34820 : for (; n != NULL; n = n->next)
11383 : {
11384 20405 : if (n->sym == NULL)
11385 : {
11386 26 : gcc_assert (code->op == EXEC_OMP_ALLOCATORS
11387 : || code->op == EXEC_OMP_ALLOCATE);
11388 26 : continue;
11389 : }
11390 20379 : bool bad = false;
11391 20379 : bool is_reduction = (list == OMP_LIST_REDUCTION
11392 : || list == OMP_LIST_REDUCTION_INSCAN
11393 : || list == OMP_LIST_REDUCTION_TASK
11394 : || list == OMP_LIST_IN_REDUCTION
11395 20379 : || list == OMP_LIST_TASK_REDUCTION);
11396 20379 : if (list == OMP_LIST_REDUCTION_INSCAN)
11397 : has_inscan = true;
11398 20307 : else if (is_reduction)
11399 4739 : has_notinscan = true;
11400 20379 : if (has_inscan && has_notinscan && is_reduction)
11401 : {
11402 3 : gfc_error ("%<inscan%> and non-%<inscan%> %<reduction%> "
11403 : "clauses on the same construct at %L",
11404 : &n->where);
11405 3 : break;
11406 : }
11407 20376 : if (n->sym->attr.threadprivate)
11408 1 : gfc_error ("THREADPRIVATE object %qs in %s clause at %L",
11409 : n->sym->name, name, &n->where);
11410 20376 : if (n->sym->attr.cray_pointee)
11411 14 : gfc_error ("Cray pointee %qs in %s clause at %L",
11412 : n->sym->name, name, &n->where);
11413 20376 : if (n->sym->attr.associate_var)
11414 22 : gfc_error ("Associate name %qs in %s clause at %L",
11415 22 : n->sym->attr.select_type_temporary
11416 4 : ? n->sym->assoc->target->symtree->n.sym->name
11417 : : n->sym->name, name, &n->where);
11418 20376 : if (list != OMP_LIST_PRIVATE && is_reduction)
11419 : {
11420 4808 : if (n->sym->attr.proc_pointer)
11421 1 : gfc_error ("Procedure pointer %qs in %s clause at %L",
11422 : n->sym->name, name, &n->where);
11423 4808 : if (n->sym->attr.pointer)
11424 3 : gfc_error ("POINTER object %qs in %s clause at %L",
11425 : n->sym->name, name, &n->where);
11426 4808 : if (n->sym->attr.cray_pointer)
11427 5 : gfc_error ("Cray pointer %qs in %s clause at %L",
11428 : n->sym->name, name, &n->where);
11429 : }
11430 20376 : if (code
11431 20376 : && (oacc_is_loop (code)
11432 : || code->op == EXEC_OACC_PARALLEL
11433 : || code->op == EXEC_OACC_SERIAL))
11434 8741 : check_array_not_assumed (n->sym, n->where, name);
11435 11635 : else if (list != OMP_LIST_UNIFORM
11436 11518 : && n->sym->as && n->sym->as->type == AS_ASSUMED_SIZE)
11437 2 : gfc_error ("Assumed size array %qs in %s clause at %L",
11438 : n->sym->name, name, &n->where);
11439 20376 : if (n->sym->attr.in_namelist && !is_reduction)
11440 0 : gfc_error ("Variable %qs in %s clause is used in "
11441 : "NAMELIST statement at %L",
11442 : n->sym->name, name, &n->where);
11443 20376 : if (n->sym->attr.pointer && n->sym->attr.intent == INTENT_IN)
11444 3 : switch (list)
11445 : {
11446 3 : case OMP_LIST_PRIVATE:
11447 3 : case OMP_LIST_LASTPRIVATE:
11448 3 : case OMP_LIST_LINEAR:
11449 : /* case OMP_LIST_REDUCTION: */
11450 3 : gfc_error ("INTENT(IN) POINTER %qs in %s clause at %L",
11451 : n->sym->name, name, &n->where);
11452 3 : break;
11453 : default:
11454 : break;
11455 : }
11456 20376 : if (omp_clauses->detach
11457 3 : && (list == OMP_LIST_PRIVATE
11458 : || list == OMP_LIST_FIRSTPRIVATE
11459 : || list == OMP_LIST_LASTPRIVATE)
11460 3 : && n->sym == omp_clauses->detach->symtree->n.sym)
11461 1 : gfc_error ("DETACH event handle %qs in %s clause at %L",
11462 : n->sym->name, name, &n->where);
11463 :
11464 20376 : if (!openacc
11465 20376 : && (list == OMP_LIST_PRIVATE
11466 20376 : || list == OMP_LIST_FIRSTPRIVATE)
11467 4714 : && ((n->sym->ts.type == BT_DERIVED
11468 158 : && n->sym->ts.u.derived->attr.alloc_comp)
11469 4604 : || n->sym->ts.type == BT_CLASS))
11470 170 : switch (code->op)
11471 : {
11472 8 : case EXEC_OMP_TARGET:
11473 8 : case EXEC_OMP_TARGET_PARALLEL:
11474 8 : case EXEC_OMP_TARGET_PARALLEL_DO:
11475 8 : case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
11476 8 : case EXEC_OMP_TARGET_PARALLEL_LOOP:
11477 8 : case EXEC_OMP_TARGET_SIMD:
11478 8 : case EXEC_OMP_TARGET_TEAMS:
11479 8 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
11480 8 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
11481 8 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
11482 8 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
11483 8 : case EXEC_OMP_TARGET_TEAMS_LOOP:
11484 8 : if (n->sym->ts.type == BT_DERIVED
11485 2 : && n->sym->ts.u.derived->attr.alloc_comp)
11486 3 : gfc_error ("Sorry, list item %qs at %L with allocatable"
11487 : " components is not yet supported in %s "
11488 : "clause", n->sym->name, &n->where,
11489 : list == OMP_LIST_PRIVATE ? "PRIVATE"
11490 : : "FIRSTPRIVATE");
11491 : else
11492 9 : gfc_error ("Polymorphic list item %qs at %L in %s "
11493 : "clause has unspecified behavior and "
11494 : "unsupported", n->sym->name, &n->where,
11495 : list == OMP_LIST_PRIVATE ? "PRIVATE"
11496 : : "FIRSTPRIVATE");
11497 : break;
11498 : default:
11499 : break;
11500 : }
11501 :
11502 20376 : switch (list)
11503 : {
11504 104 : case OMP_LIST_REDUCTION_TASK:
11505 104 : if (code
11506 104 : && (code->op == EXEC_OMP_LOOP
11507 : || code->op == EXEC_OMP_TASKLOOP
11508 : || code->op == EXEC_OMP_TASKLOOP_SIMD
11509 : || code->op == EXEC_OMP_MASKED_TASKLOOP
11510 : || code->op == EXEC_OMP_MASKED_TASKLOOP_SIMD
11511 : || code->op == EXEC_OMP_MASTER_TASKLOOP
11512 : || code->op == EXEC_OMP_MASTER_TASKLOOP_SIMD
11513 : || code->op == EXEC_OMP_PARALLEL_LOOP
11514 : || code->op == EXEC_OMP_PARALLEL_MASKED_TASKLOOP
11515 : || code->op == EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD
11516 : || code->op == EXEC_OMP_PARALLEL_MASTER_TASKLOOP
11517 : || code->op == EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD
11518 : || code->op == EXEC_OMP_TARGET_PARALLEL_LOOP
11519 : || code->op == EXEC_OMP_TARGET_TEAMS_LOOP
11520 : || code->op == EXEC_OMP_TEAMS
11521 : || code->op == EXEC_OMP_TEAMS_DISTRIBUTE
11522 : || code->op == EXEC_OMP_TEAMS_LOOP))
11523 : {
11524 17 : gfc_error ("Only DEFAULT permitted as reduction-"
11525 : "modifier in REDUCTION clause at %L",
11526 : &n->where);
11527 17 : break;
11528 : }
11529 4791 : gcc_fallthrough ();
11530 4791 : case OMP_LIST_REDUCTION:
11531 4791 : case OMP_LIST_IN_REDUCTION:
11532 4791 : case OMP_LIST_TASK_REDUCTION:
11533 4791 : case OMP_LIST_REDUCTION_INSCAN:
11534 4791 : switch (n->u.reduction_op)
11535 : {
11536 2656 : case OMP_REDUCTION_PLUS:
11537 2656 : case OMP_REDUCTION_TIMES:
11538 2656 : case OMP_REDUCTION_MINUS:
11539 2656 : if (!gfc_numeric_ts (&n->sym->ts))
11540 : bad = true;
11541 : break;
11542 1112 : case OMP_REDUCTION_AND:
11543 1112 : case OMP_REDUCTION_OR:
11544 1112 : case OMP_REDUCTION_EQV:
11545 1112 : case OMP_REDUCTION_NEQV:
11546 1112 : if (n->sym->ts.type != BT_LOGICAL)
11547 : bad = true;
11548 : break;
11549 480 : case OMP_REDUCTION_MAX:
11550 480 : case OMP_REDUCTION_MIN:
11551 480 : if (n->sym->ts.type != BT_INTEGER
11552 212 : && n->sym->ts.type != BT_REAL)
11553 : bad = true;
11554 : break;
11555 192 : case OMP_REDUCTION_IAND:
11556 192 : case OMP_REDUCTION_IOR:
11557 192 : case OMP_REDUCTION_IEOR:
11558 192 : if (n->sym->ts.type != BT_INTEGER)
11559 : bad = true;
11560 : break;
11561 : case OMP_REDUCTION_USER:
11562 : bad = true;
11563 : break;
11564 : default:
11565 : break;
11566 : }
11567 : if (!bad)
11568 4216 : n->u2.udr = NULL;
11569 : else
11570 : {
11571 575 : const char *udr_name = NULL;
11572 575 : if (n->u2.udr)
11573 : {
11574 471 : udr_name = n->u2.udr->udr->name;
11575 471 : n->u2.udr->udr
11576 942 : = gfc_find_omp_udr (NULL, udr_name,
11577 471 : &n->sym->ts);
11578 471 : if (n->u2.udr->udr == NULL)
11579 : {
11580 0 : free (n->u2.udr);
11581 0 : n->u2.udr = NULL;
11582 : }
11583 : }
11584 575 : if (n->u2.udr == NULL)
11585 : {
11586 104 : if (udr_name == NULL)
11587 104 : switch (n->u.reduction_op)
11588 : {
11589 50 : case OMP_REDUCTION_PLUS:
11590 50 : case OMP_REDUCTION_TIMES:
11591 50 : case OMP_REDUCTION_MINUS:
11592 50 : case OMP_REDUCTION_AND:
11593 50 : case OMP_REDUCTION_OR:
11594 50 : case OMP_REDUCTION_EQV:
11595 50 : case OMP_REDUCTION_NEQV:
11596 50 : udr_name = gfc_op2string ((gfc_intrinsic_op)
11597 : n->u.reduction_op);
11598 50 : break;
11599 : case OMP_REDUCTION_MAX:
11600 : udr_name = "max";
11601 : break;
11602 9 : case OMP_REDUCTION_MIN:
11603 9 : udr_name = "min";
11604 9 : break;
11605 12 : case OMP_REDUCTION_IAND:
11606 12 : udr_name = "iand";
11607 12 : break;
11608 12 : case OMP_REDUCTION_IOR:
11609 12 : udr_name = "ior";
11610 12 : break;
11611 9 : case OMP_REDUCTION_IEOR:
11612 9 : udr_name = "ieor";
11613 9 : break;
11614 0 : default:
11615 0 : gcc_unreachable ();
11616 : }
11617 104 : gfc_error ("!$OMP DECLARE REDUCTION %s not found "
11618 : "for type %s at %L", udr_name,
11619 104 : gfc_typename (&n->sym->ts), &n->where);
11620 : }
11621 : else
11622 : {
11623 471 : gfc_omp_udr *udr = n->u2.udr->udr;
11624 471 : n->u.reduction_op = OMP_REDUCTION_USER;
11625 471 : n->u2.udr->combiner
11626 942 : = resolve_omp_udr_clause (n, udr->combiner_ns,
11627 471 : udr->omp_out,
11628 471 : udr->omp_in);
11629 471 : if (udr->initializer_ns)
11630 331 : n->u2.udr->initializer
11631 331 : = resolve_omp_udr_clause (n,
11632 : udr->initializer_ns,
11633 331 : udr->omp_priv,
11634 331 : udr->omp_orig);
11635 : }
11636 : }
11637 : break;
11638 887 : case OMP_LIST_LINEAR:
11639 887 : if (code)
11640 : {
11641 727 : bool is_worksharing_for = false;
11642 727 : switch (code->op)
11643 : {
11644 54 : case EXEC_OMP_DO:
11645 54 : case EXEC_OMP_PARALLEL_DO:
11646 54 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
11647 54 : case EXEC_OMP_TARGET_PARALLEL_DO:
11648 54 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
11649 54 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
11650 54 : is_worksharing_for = true;
11651 54 : break;
11652 : default:
11653 : break;
11654 : }
11655 :
11656 54 : if (is_worksharing_for
11657 54 : && (n->sym->attr.dimension
11658 53 : || n->sym->attr.allocatable))
11659 : {
11660 1 : if (n->sym->attr.allocatable)
11661 0 : gfc_error ("Sorry, ALLOCATABLE object %qs in "
11662 : "LINEAR clause on worksharing-loop "
11663 : "construct at %L is not yet supported",
11664 : n->sym->name, &n->where);
11665 : else
11666 1 : gfc_error ("Sorry, array %qs in LINEAR clause "
11667 : "on worksharing-loop construct at %L "
11668 : "is not yet supported",
11669 : n->sym->name, &n->where);
11670 : break;
11671 : }
11672 : }
11673 :
11674 726 : if (code
11675 726 : && n->u.linear.op != OMP_LINEAR_DEFAULT
11676 23 : && n->u.linear.op != linear_op)
11677 : {
11678 23 : if (n->u.linear.old_modifier)
11679 : {
11680 9 : gfc_error ("LINEAR clause modifier used on DO or "
11681 : "SIMD construct at %L", &n->where);
11682 9 : linear_op = n->u.linear.op;
11683 : }
11684 14 : else if (n->u.linear.op != OMP_LINEAR_VAL)
11685 : {
11686 6 : gfc_error ("LINEAR clause modifier other than VAL "
11687 : "used on DO or SIMD construct at %L",
11688 : &n->where);
11689 6 : linear_op = n->u.linear.op;
11690 : }
11691 : }
11692 863 : else if (n->u.linear.op != OMP_LINEAR_REF
11693 813 : && n->sym->ts.type != BT_INTEGER)
11694 1 : gfc_error ("LINEAR variable %qs must be INTEGER "
11695 : "at %L", n->sym->name, &n->where);
11696 862 : else if ((n->u.linear.op == OMP_LINEAR_REF
11697 812 : || n->u.linear.op == OMP_LINEAR_UVAL)
11698 61 : && n->sym->attr.value)
11699 0 : gfc_error ("LINEAR dummy argument %qs with VALUE "
11700 : "attribute with %s modifier at %L",
11701 : n->sym->name,
11702 : n->u.linear.op == OMP_LINEAR_REF
11703 : ? "REF" : "UVAL", &n->where);
11704 862 : else if (n->expr)
11705 : {
11706 843 : gfc_expr *expr = n->expr;
11707 843 : if (!gfc_resolve_expr (expr)
11708 843 : || expr->ts.type != BT_INTEGER
11709 1686 : || expr->rank != 0)
11710 0 : gfc_error ("%qs in LINEAR clause at %L requires "
11711 : "a scalar integer linear-step expression",
11712 0 : n->sym->name, &n->where);
11713 843 : else if (!code && expr->expr_type != EXPR_CONSTANT)
11714 : {
11715 11 : if (expr->expr_type == EXPR_VARIABLE
11716 7 : && expr->symtree->n.sym->attr.dummy
11717 6 : && expr->symtree->n.sym->ns == ns)
11718 : {
11719 6 : gfc_omp_namelist *n2;
11720 6 : for (n2 = omp_clauses->lists[OMP_LIST_UNIFORM];
11721 6 : n2; n2 = n2->next)
11722 6 : if (n2->sym == expr->symtree->n.sym)
11723 : break;
11724 6 : if (n2)
11725 : break;
11726 : }
11727 5 : gfc_error ("%qs in LINEAR clause at %L requires "
11728 : "a constant integer linear-step "
11729 : "expression or dummy argument "
11730 : "specified in UNIFORM clause",
11731 5 : n->sym->name, &n->where);
11732 : }
11733 : }
11734 : break;
11735 : /* Workaround for PR middle-end/26316, nothing really needs
11736 : to be done here for OMP_LIST_PRIVATE. */
11737 9400 : case OMP_LIST_PRIVATE:
11738 9400 : gcc_assert (code && code->op != EXEC_NOP);
11739 : break;
11740 98 : case OMP_LIST_USE_DEVICE:
11741 98 : if (n->sym->attr.allocatable
11742 98 : || (n->sym->ts.type == BT_CLASS && CLASS_DATA (n->sym)
11743 0 : && CLASS_DATA (n->sym)->attr.allocatable))
11744 0 : gfc_error ("ALLOCATABLE object %qs in %s clause at %L",
11745 : n->sym->name, name, &n->where);
11746 98 : if (n->sym->ts.type == BT_CLASS
11747 0 : && CLASS_DATA (n->sym)
11748 0 : && CLASS_DATA (n->sym)->attr.class_pointer)
11749 0 : gfc_error ("POINTER object %qs of polymorphic type in "
11750 : "%s clause at %L", n->sym->name, name,
11751 : &n->where);
11752 98 : if (n->sym->attr.cray_pointer)
11753 2 : gfc_error ("Cray pointer object %qs in %s clause at %L",
11754 : n->sym->name, name, &n->where);
11755 96 : else if (n->sym->attr.cray_pointee)
11756 2 : gfc_error ("Cray pointee object %qs in %s clause at %L",
11757 : n->sym->name, name, &n->where);
11758 94 : else if (n->sym->attr.flavor == FL_VARIABLE
11759 93 : && !n->sym->as
11760 54 : && !n->sym->attr.pointer)
11761 13 : gfc_error ("%s clause variable %qs at %L is neither "
11762 : "a POINTER nor an array", name,
11763 : n->sym->name, &n->where);
11764 : /* FALLTHRU */
11765 98 : case OMP_LIST_DEVICE_RESIDENT:
11766 98 : check_symbol_not_pointer (n->sym, n->where, name);
11767 98 : check_array_not_assumed (n->sym, n->where, name);
11768 98 : break;
11769 : default:
11770 : break;
11771 : }
11772 : }
11773 : break;
11774 : }
11775 : }
11776 : /* OpenMP 5.1: use_device_ptr acts like use_device_addr, except for
11777 : type(c_ptr). */
11778 33190 : if (omp_clauses->lists[OMP_LIST_USE_DEVICE_PTR])
11779 : {
11780 9 : gfc_omp_namelist *n_prev, *n_next, *n_addr;
11781 9 : n_addr = omp_clauses->lists[OMP_LIST_USE_DEVICE_ADDR];
11782 28 : for (; n_addr && n_addr->next; n_addr = n_addr->next)
11783 : ;
11784 : n_prev = NULL;
11785 : n = omp_clauses->lists[OMP_LIST_USE_DEVICE_PTR];
11786 27 : while (n)
11787 : {
11788 18 : n_next = n->next;
11789 18 : if (n->sym->ts.type != BT_DERIVED
11790 18 : || n->sym->ts.u.derived->ts.f90_type != BT_VOID)
11791 : {
11792 0 : n->next = NULL;
11793 0 : if (n_addr)
11794 0 : n_addr->next = n;
11795 : else
11796 0 : omp_clauses->lists[OMP_LIST_USE_DEVICE_ADDR] = n;
11797 0 : n_addr = n;
11798 0 : if (n_prev)
11799 0 : n_prev->next = n_next;
11800 : else
11801 0 : omp_clauses->lists[OMP_LIST_USE_DEVICE_PTR] = n_next;
11802 : }
11803 : else
11804 : n_prev = n;
11805 18 : n = n_next;
11806 : }
11807 : }
11808 33190 : if (omp_clauses->safelen_expr)
11809 93 : resolve_positive_int_expr (omp_clauses->safelen_expr, "SAFELEN", false);
11810 33190 : if (omp_clauses->simdlen_expr)
11811 143 : resolve_positive_int_expr (omp_clauses->simdlen_expr, "SIMDLEN", false);
11812 33190 : if (omp_clauses->simdlen_divisor
11813 33190 : && (!gfc_resolve_expr (omp_clauses->simdlen_divisor)
11814 11 : || omp_clauses->simdlen_divisor->ts.type != BT_INTEGER
11815 11 : || omp_clauses->simdlen_divisor->rank != 0
11816 11 : || omp_clauses->simdlen_divisor->expr_type != EXPR_CONSTANT
11817 10 : || mpz_sgn (omp_clauses->simdlen_divisor->value.integer) <= 0))
11818 2 : gfc_error ("Divisor expression at %L of the SCALED modifier to SIMDLEN must"
11819 : " be a positive scalar constant integer expression",
11820 2 : &omp_clauses->simdlen_divisor->where);
11821 : /* Check that safelen >= simdlen * scaled; however, scaled is
11822 : unknown, hence, assume scaled == 1 as conservative estimate.
11823 : we need to repeat some const check as the program still continues
11824 : after the error diagnostic above. */
11825 33190 : if (omp_clauses->safelen_expr && omp_clauses->simdlen_expr
11826 36 : && omp_clauses->safelen_expr->expr_type == EXPR_CONSTANT
11827 36 : && omp_clauses->simdlen_expr->expr_type == EXPR_CONSTANT
11828 36 : && omp_clauses->safelen_expr->rank == 0
11829 36 : && omp_clauses->simdlen_expr->rank == 0
11830 36 : && omp_clauses->safelen_expr->ts.type == BT_INTEGER
11831 36 : && omp_clauses->simdlen_expr->ts.type == BT_INTEGER
11832 36 : && mpz_cmp (omp_clauses->safelen_expr->value.integer,
11833 36 : omp_clauses->simdlen_expr->value.integer) < 0)
11834 0 : gfc_error ("SIMDLEN at %L must be smaller or equal to SAFELEN at %L",
11835 : &omp_clauses->simdlen_expr->where,
11836 : &omp_clauses->safelen_expr->where);
11837 33388 : for (el = omp_clauses->num_teams_list; el; el = el->next)
11838 198 : resolve_positive_int_expr (el->expr, "NUM_TEAMS", true);
11839 33190 : if (omp_clauses->num_teams_list
11840 157 : && omp_clauses->num_teams_list->next
11841 34 : && !omp_clauses->num_teams_dims
11842 27 : && omp_clauses->num_teams_list->expr->expr_type == EXPR_CONSTANT
11843 13 : && omp_clauses->num_teams_list->next->expr->expr_type == EXPR_CONSTANT
11844 13 : && mpz_cmp (omp_clauses->num_teams_list->expr->value.integer,
11845 13 : omp_clauses->num_teams_list->next->expr->value.integer) > 0)
11846 2 : gfc_warning (OPT_Wopenmp, "NUM_TEAMS lower bound at %L larger than upper "
11847 : "bound at %L", &omp_clauses->num_teams_list->expr->where,
11848 : &omp_clauses->num_teams_list->next->expr->where);
11849 33190 : if (omp_clauses->device)
11850 334 : resolve_scalar_int_expr (omp_clauses->device, "DEVICE");
11851 33190 : if (omp_clauses->filter)
11852 42 : resolve_nonnegative_int_expr (omp_clauses->filter, "FILTER", true);
11853 33190 : if (omp_clauses->hint)
11854 : {
11855 47 : if (!gfc_resolve_expr (omp_clauses->hint)
11856 47 : || omp_clauses->hint->rank != 0
11857 47 : || omp_clauses->hint->ts.type != BT_INTEGER
11858 45 : || omp_clauses->hint->expr_type != EXPR_CONSTANT
11859 90 : || mpz_sgn (omp_clauses->hint->value.integer) < 0)
11860 5 : gfc_error ("Value of HINT clause at %L shall be a valid "
11861 5 : "constant hint expression", &omp_clauses->hint->where);
11862 : }
11863 33190 : if (omp_clauses->priority)
11864 35 : resolve_nonnegative_int_expr (omp_clauses->priority, "PRIORITY", true);
11865 33190 : if (omp_clauses->dist_chunk_size)
11866 : {
11867 83 : gfc_expr *expr = omp_clauses->dist_chunk_size;
11868 83 : if (!gfc_resolve_expr (expr)
11869 83 : || expr->ts.type != BT_INTEGER || expr->rank != 0)
11870 0 : gfc_error ("DIST_SCHEDULE clause's chunk_size at %L requires "
11871 : "a scalar INTEGER expression", &expr->where);
11872 : }
11873 33316 : for (el = omp_clauses->thread_limit_list; el; el = el->next)
11874 126 : resolve_positive_int_expr (el->expr, "THREAD_LIMIT", true);
11875 33190 : if (omp_clauses->grainsize)
11876 34 : resolve_positive_int_expr (omp_clauses->grainsize, "GRAINSIZE", true);
11877 33190 : if (omp_clauses->num_tasks)
11878 26 : resolve_positive_int_expr (omp_clauses->num_tasks, "NUM_TASKS", true);
11879 33190 : if (omp_clauses->grainsize && omp_clauses->num_tasks)
11880 1 : gfc_error ("%<GRAINSIZE%> clause at %L must not be used together with "
11881 : "%<NUM_TASKS%> clause", &omp_clauses->grainsize->where);
11882 33190 : if (omp_clauses->lists[OMP_LIST_REDUCTION] && omp_clauses->nogroup)
11883 1 : gfc_error ("%<REDUCTION%> clause at %L must not be used together with "
11884 : "%<NOGROUP%> clause",
11885 : &omp_clauses->lists[OMP_LIST_REDUCTION]->where);
11886 33190 : if (omp_clauses->full && omp_clauses->partial)
11887 0 : gfc_error ("%<FULL%> clause at %C must not be used together with "
11888 : "%<PARTIAL%> clause");
11889 33190 : if (omp_clauses->async)
11890 610 : if (omp_clauses->async_expr)
11891 610 : resolve_scalar_int_expr (omp_clauses->async_expr, "ASYNC");
11892 33190 : if (omp_clauses->device_num_expr)
11893 105 : resolve_scalar_int_expr (omp_clauses->device_num_expr, "DEVICE_NUM");
11894 33190 : if (code && code->op == EXEC_OACC_SET
11895 121 : && !omp_clauses->device_num_expr
11896 52 : && !omp_clauses->oacc_device_type_present)
11897 2 : gfc_error ("At least one of the clauses %<DEVICE_TYPE%> and %<DEVICE_NUM%> "
11898 : "should be present in %<SET%> directive at %L", &code->loc);
11899 33190 : if (omp_clauses->num_gangs_expr)
11900 682 : resolve_positive_int_expr (omp_clauses->num_gangs_expr, "NUM_GANGS", true);
11901 33190 : if (omp_clauses->num_workers_expr)
11902 599 : resolve_positive_int_expr (omp_clauses->num_workers_expr, "NUM_WORKERS",
11903 : true);
11904 33190 : if (omp_clauses->vector_length_expr)
11905 569 : resolve_positive_int_expr (omp_clauses->vector_length_expr,
11906 : "VECTOR_LENGTH", true);
11907 33190 : if (omp_clauses->gang_num_expr)
11908 114 : resolve_positive_int_expr (omp_clauses->gang_num_expr, "GANG", true);
11909 33190 : if (omp_clauses->gang_static_expr)
11910 94 : resolve_positive_int_expr (omp_clauses->gang_static_expr, "GANG", true);
11911 33190 : if (omp_clauses->worker_expr)
11912 101 : resolve_positive_int_expr (omp_clauses->worker_expr, "WORKER", true);
11913 33190 : if (omp_clauses->vector_expr)
11914 132 : resolve_positive_int_expr (omp_clauses->vector_expr, "VECTOR", true);
11915 33529 : for (el = omp_clauses->wait_list; el; el = el->next)
11916 339 : resolve_scalar_int_expr (el->expr, "WAIT");
11917 33190 : if (omp_clauses->collapse && omp_clauses->tile_list)
11918 4 : gfc_error ("Incompatible use of TILE and COLLAPSE at %L", &code->loc);
11919 33190 : if (omp_clauses->message)
11920 : {
11921 58 : gfc_expr *expr = omp_clauses->message;
11922 58 : if (!gfc_resolve_expr (expr)
11923 58 : || expr->ts.kind != gfc_default_character_kind
11924 113 : || expr->ts.type != BT_CHARACTER || expr->rank != 0)
11925 4 : gfc_error ("MESSAGE clause at %L requires a scalar default-kind "
11926 : "CHARACTER expression", &expr->where);
11927 : }
11928 33190 : if (!openacc
11929 33190 : && code
11930 19913 : && omp_clauses->lists[OMP_LIST_MAP] == NULL
11931 16116 : && omp_clauses->lists[OMP_LIST_USE_DEVICE_PTR] == NULL
11932 16113 : && omp_clauses->lists[OMP_LIST_USE_DEVICE_ADDR] == NULL)
11933 : {
11934 16090 : const char *p = NULL;
11935 16090 : switch (code->op)
11936 : {
11937 1 : case EXEC_OMP_TARGET_ENTER_DATA: p = "TARGET ENTER DATA"; break;
11938 1 : case EXEC_OMP_TARGET_EXIT_DATA: p = "TARGET EXIT DATA"; break;
11939 : default: break;
11940 : }
11941 16090 : if (code->op == EXEC_OMP_TARGET_DATA)
11942 1 : gfc_error ("TARGET DATA must contain at least one MAP, USE_DEVICE_PTR, "
11943 : "or USE_DEVICE_ADDR clause at %L", &code->loc);
11944 16089 : else if (p)
11945 2 : gfc_error ("%s must contain at least one MAP clause at %L",
11946 : p, &code->loc);
11947 : }
11948 33190 : if (omp_clauses->sizes_list)
11949 : {
11950 : gfc_expr_list *el;
11951 572 : for (el = omp_clauses->sizes_list; el; el = el->next)
11952 377 : resolve_positive_int_expr (el->expr, "SIZES", false);
11953 : }
11954 :
11955 33190 : if (!openacc && omp_clauses->detach)
11956 : {
11957 125 : if (!gfc_resolve_expr (omp_clauses->detach)
11958 125 : || omp_clauses->detach->ts.type != BT_INTEGER
11959 124 : || omp_clauses->detach->ts.kind != gfc_c_intptr_kind
11960 248 : || omp_clauses->detach->rank != 0)
11961 3 : gfc_error ("%qs at %L should be a scalar of type "
11962 : "integer(kind=omp_event_handle_kind)",
11963 3 : omp_clauses->detach->symtree->n.sym->name,
11964 3 : &omp_clauses->detach->where);
11965 122 : else if (omp_clauses->detach->symtree->n.sym->attr.dimension > 0)
11966 1 : gfc_error ("The event handle at %L must not be an array element",
11967 : &omp_clauses->detach->where);
11968 121 : else if (omp_clauses->detach->symtree->n.sym->ts.type == BT_DERIVED
11969 120 : || omp_clauses->detach->symtree->n.sym->ts.type == BT_CLASS)
11970 1 : gfc_error ("The event handle at %L must not be part of "
11971 : "a derived type or class", &omp_clauses->detach->where);
11972 :
11973 125 : if (omp_clauses->mergeable)
11974 2 : gfc_error ("%<DETACH%> clause at %L must not be used together with "
11975 2 : "%<MERGEABLE%> clause", &omp_clauses->detach->where);
11976 : }
11977 :
11978 : if (openacc
11979 12995 : && code->op == EXEC_OACC_HOST_DATA
11980 60 : && omp_clauses->lists[OMP_LIST_USE_DEVICE] == NULL)
11981 1 : gfc_error ("%<host_data%> construct at %L requires %<use_device%> clause",
11982 : &code->loc);
11983 :
11984 33190 : if (omp_clauses->assume)
11985 18 : gfc_resolve_omp_assumptions (omp_clauses->assume);
11986 : }
11987 :
11988 :
11989 : /* Return true if SYM is ever referenced in EXPR except in the SE node. */
11990 :
11991 : static bool
11992 5008 : expr_references_sym (gfc_expr *e, gfc_symbol *s, gfc_expr *se)
11993 : {
11994 6641 : gfc_actual_arglist *arg;
11995 6641 : if (e == NULL || e == se)
11996 : return false;
11997 5386 : switch (e->expr_type)
11998 : {
11999 3133 : case EXPR_CONSTANT:
12000 3133 : case EXPR_NULL:
12001 3133 : case EXPR_VARIABLE:
12002 3133 : case EXPR_STRUCTURE:
12003 3133 : case EXPR_ARRAY:
12004 3133 : if (e->symtree != NULL
12005 1157 : && e->symtree->n.sym == s)
12006 470 : return true;
12007 : return false;
12008 0 : case EXPR_SUBSTRING:
12009 0 : if (e->ref != NULL
12010 0 : && (expr_references_sym (e->ref->u.ss.start, s, se)
12011 0 : || expr_references_sym (e->ref->u.ss.end, s, se)))
12012 0 : return true;
12013 : return false;
12014 1742 : case EXPR_OP:
12015 1742 : if (expr_references_sym (e->value.op.op2, s, se))
12016 : return true;
12017 1633 : return expr_references_sym (e->value.op.op1, s, se);
12018 511 : case EXPR_FUNCTION:
12019 896 : for (arg = e->value.function.actual; arg; arg = arg->next)
12020 586 : if (expr_references_sym (arg->expr, s, se))
12021 : return true;
12022 : return false;
12023 0 : default:
12024 0 : gcc_unreachable ();
12025 : }
12026 : }
12027 :
12028 :
12029 : /* If EXPR is a conversion function that widens the type
12030 : if WIDENING is true or narrows the type if NARROW is true,
12031 : return the inner expression, otherwise return NULL. */
12032 :
12033 : static gfc_expr *
12034 5928 : is_conversion (gfc_expr *expr, bool narrowing, bool widening)
12035 : {
12036 5928 : gfc_typespec *ts1, *ts2;
12037 :
12038 5928 : if (expr->expr_type != EXPR_FUNCTION
12039 917 : || expr->value.function.isym == NULL
12040 894 : || expr->value.function.esym != NULL
12041 894 : || expr->value.function.isym->id != GFC_ISYM_CONVERSION
12042 388 : || (!narrowing && !widening))
12043 : return NULL;
12044 :
12045 388 : if (narrowing && widening)
12046 267 : return expr->value.function.actual->expr;
12047 :
12048 121 : if (widening)
12049 : {
12050 121 : ts1 = &expr->ts;
12051 121 : ts2 = &expr->value.function.actual->expr->ts;
12052 : }
12053 : else
12054 : {
12055 0 : ts1 = &expr->value.function.actual->expr->ts;
12056 0 : ts2 = &expr->ts;
12057 : }
12058 :
12059 121 : if (ts1->type > ts2->type
12060 49 : || (ts1->type == ts2->type && ts1->kind > ts2->kind))
12061 121 : return expr->value.function.actual->expr;
12062 :
12063 : return NULL;
12064 : }
12065 :
12066 : static bool
12067 6883 : is_scalar_intrinsic_expr (gfc_expr *expr, bool must_be_var, bool conv_ok)
12068 : {
12069 6883 : if (must_be_var
12070 4034 : && (expr->expr_type != EXPR_VARIABLE || !expr->symtree))
12071 : {
12072 37 : if (!conv_ok)
12073 : return false;
12074 37 : gfc_expr *conv = is_conversion (expr, true, true);
12075 37 : if (!conv)
12076 : return false;
12077 36 : if (conv->expr_type != EXPR_VARIABLE || !conv->symtree)
12078 : return false;
12079 : }
12080 6880 : return (expr->rank == 0
12081 6876 : && !gfc_is_coindexed (expr)
12082 13756 : && (expr->ts.type == BT_INTEGER
12083 1522 : || expr->ts.type == BT_REAL
12084 590 : || expr->ts.type == BT_COMPLEX
12085 572 : || expr->ts.type == BT_LOGICAL));
12086 : }
12087 :
12088 : static void
12089 2710 : resolve_omp_atomic (gfc_code *code)
12090 : {
12091 2710 : gfc_code *atomic_code = code->block;
12092 2710 : gfc_symbol *var;
12093 2710 : gfc_expr *stmt_expr2, *capt_expr2;
12094 2710 : gfc_omp_atomic_op aop
12095 2710 : = (gfc_omp_atomic_op) (atomic_code->ext.omp_clauses->atomic_op
12096 : & GFC_OMP_ATOMIC_MASK);
12097 2710 : gfc_code *stmt = NULL, *capture_stmt = NULL, *tailing_stmt = NULL;
12098 2710 : gfc_expr *comp_cond = NULL;
12099 2710 : locus *loc = NULL;
12100 :
12101 2710 : code = code->block->next;
12102 : /* resolve_blocks asserts this is initially EXEC_ASSIGN or EXEC_IF
12103 : If it changed to EXEC_NOP, assume an error has been emitted already. */
12104 2710 : if (code->op == EXEC_NOP)
12105 : return;
12106 :
12107 2709 : if (atomic_code->ext.omp_clauses->compare
12108 157 : && atomic_code->ext.omp_clauses->capture)
12109 : {
12110 : /* Must be either "if (x == e) then; x = d; else; v = x; end if"
12111 : or "v = expr" followed/preceded by
12112 : "if (x == e) then; x = d; end if" or "if (x == e) x = d". */
12113 103 : gfc_code *next = code;
12114 103 : if (code->op == EXEC_ASSIGN)
12115 : {
12116 19 : capture_stmt = code;
12117 19 : next = code->next;
12118 : }
12119 103 : if (next->op == EXEC_IF
12120 103 : && next->block
12121 103 : && next->block->op == EXEC_IF
12122 103 : && next->block->next
12123 102 : && next->block->next->op == EXEC_ASSIGN)
12124 : {
12125 102 : comp_cond = next->block->expr1;
12126 102 : stmt = next->block->next;
12127 102 : if (stmt->next)
12128 : {
12129 0 : loc = &stmt->loc;
12130 0 : goto unexpected;
12131 : }
12132 : }
12133 1 : else if (capture_stmt)
12134 : {
12135 0 : gfc_error ("Expected IF at %L in atomic compare capture",
12136 : &next->loc);
12137 0 : return;
12138 : }
12139 103 : if (stmt && !capture_stmt && next->block->block)
12140 : {
12141 64 : if (next->block->block->expr1)
12142 : {
12143 0 : gfc_error ("Expected ELSE at %L in atomic compare capture",
12144 : &next->block->block->expr1->where);
12145 0 : return;
12146 : }
12147 64 : if (!code->block->block->next
12148 64 : || code->block->block->next->op != EXEC_ASSIGN)
12149 : {
12150 0 : loc = (code->block->block->next ? &code->block->block->next->loc
12151 : : &code->block->block->loc);
12152 0 : goto unexpected;
12153 : }
12154 64 : capture_stmt = code->block->block->next;
12155 64 : if (capture_stmt->next)
12156 : {
12157 0 : loc = &capture_stmt->next->loc;
12158 0 : goto unexpected;
12159 : }
12160 : }
12161 103 : if (stmt && !capture_stmt && next->next->op == EXEC_ASSIGN)
12162 : capture_stmt = next->next;
12163 84 : else if (!capture_stmt)
12164 : {
12165 1 : loc = &code->loc;
12166 1 : goto unexpected;
12167 : }
12168 : }
12169 2606 : else if (atomic_code->ext.omp_clauses->compare)
12170 : {
12171 : /* Must be: "if (x == e) then; x = d; end if" or "if (x == e) x = d". */
12172 54 : if (code->op == EXEC_IF
12173 54 : && code->block
12174 54 : && code->block->op == EXEC_IF
12175 54 : && code->block->next
12176 52 : && code->block->next->op == EXEC_ASSIGN)
12177 : {
12178 52 : comp_cond = code->block->expr1;
12179 52 : stmt = code->block->next;
12180 52 : if (stmt->next || code->block->block)
12181 : {
12182 0 : loc = stmt->next ? &stmt->next->loc : &code->block->block->loc;
12183 0 : goto unexpected;
12184 : }
12185 : }
12186 : else
12187 : {
12188 2 : loc = &code->loc;
12189 2 : goto unexpected;
12190 : }
12191 : }
12192 2552 : else if (atomic_code->ext.omp_clauses->capture)
12193 : {
12194 : /* Must be: "v = x" followed/preceded by "x = ...". */
12195 489 : if (code->op != EXEC_ASSIGN)
12196 0 : goto unexpected;
12197 489 : if (code->next->op != EXEC_ASSIGN)
12198 : {
12199 0 : loc = &code->next->loc;
12200 0 : goto unexpected;
12201 : }
12202 489 : gfc_expr *expr2, *expr2_next;
12203 489 : expr2 = is_conversion (code->expr2, true, true);
12204 489 : if (expr2 == NULL)
12205 447 : expr2 = code->expr2;
12206 489 : expr2_next = is_conversion (code->next->expr2, true, true);
12207 489 : if (expr2_next == NULL)
12208 478 : expr2_next = code->next->expr2;
12209 489 : if (code->expr1->expr_type == EXPR_VARIABLE
12210 489 : && code->next->expr1->expr_type == EXPR_VARIABLE
12211 489 : && expr2->expr_type == EXPR_VARIABLE
12212 243 : && expr2_next->expr_type == EXPR_VARIABLE)
12213 : {
12214 1 : if (code->expr1->symtree->n.sym == expr2_next->symtree->n.sym)
12215 : {
12216 : stmt = code;
12217 : capture_stmt = code->next;
12218 : }
12219 : else
12220 : {
12221 489 : capture_stmt = code;
12222 489 : stmt = code->next;
12223 : }
12224 : }
12225 488 : else if (expr2->expr_type == EXPR_VARIABLE)
12226 : {
12227 : capture_stmt = code;
12228 : stmt = code->next;
12229 : }
12230 : else
12231 : {
12232 247 : stmt = code;
12233 247 : capture_stmt = code->next;
12234 : }
12235 : /* Shall be NULL but can happen for invalid code. */
12236 489 : tailing_stmt = code->next->next;
12237 : }
12238 : else
12239 : {
12240 : /* x = ... */
12241 2063 : stmt = code;
12242 2063 : if (!atomic_code->ext.omp_clauses->compare && stmt->op != EXEC_ASSIGN)
12243 1 : goto unexpected;
12244 : /* Shall be NULL but can happen for invalid code. */
12245 2062 : tailing_stmt = code->next;
12246 : }
12247 :
12248 2705 : if (comp_cond)
12249 : {
12250 154 : if (comp_cond->expr_type != EXPR_OP
12251 154 : || (comp_cond->value.op.op != INTRINSIC_EQ
12252 : && comp_cond->value.op.op != INTRINSIC_EQ_OS
12253 : && comp_cond->value.op.op != INTRINSIC_EQV))
12254 : {
12255 0 : gfc_error ("Expected %<==%>, %<.EQ.%> or %<.EQV.%> atomic comparison "
12256 : "expression at %L", &comp_cond->where);
12257 0 : return;
12258 : }
12259 154 : if (!is_scalar_intrinsic_expr (comp_cond->value.op.op1, true, true))
12260 : {
12261 1 : gfc_error ("Expected scalar intrinsic variable at %L in atomic "
12262 1 : "comparison", &comp_cond->value.op.op1->where);
12263 1 : return;
12264 : }
12265 153 : if (!gfc_resolve_expr (comp_cond->value.op.op2))
12266 : return;
12267 153 : if (!is_scalar_intrinsic_expr (comp_cond->value.op.op2, false, false))
12268 : {
12269 0 : gfc_error ("Expected scalar intrinsic expression at %L in atomic "
12270 0 : "comparison", &comp_cond->value.op.op1->where);
12271 0 : return;
12272 : }
12273 : }
12274 :
12275 2704 : if (!is_scalar_intrinsic_expr (stmt->expr1, true, false))
12276 : {
12277 4 : gfc_error ("!$OMP ATOMIC statement must set a scalar variable of "
12278 4 : "intrinsic type at %L", &stmt->expr1->where);
12279 4 : return;
12280 : }
12281 :
12282 2700 : if (!gfc_resolve_expr (stmt->expr2))
12283 : return;
12284 2696 : if (!is_scalar_intrinsic_expr (stmt->expr2, false, false))
12285 : {
12286 0 : gfc_error ("!$OMP ATOMIC statement must assign an expression of "
12287 0 : "intrinsic type at %L", &stmt->expr2->where);
12288 0 : return;
12289 : }
12290 :
12291 2696 : if (gfc_expr_attr (stmt->expr1).allocatable)
12292 : {
12293 0 : gfc_error ("!$OMP ATOMIC with ALLOCATABLE variable at %L",
12294 0 : &stmt->expr1->where);
12295 0 : return;
12296 : }
12297 :
12298 : /* Should be diagnosed above already. */
12299 2696 : gcc_assert (tailing_stmt == NULL);
12300 :
12301 2696 : var = stmt->expr1->symtree->n.sym;
12302 2696 : stmt_expr2 = is_conversion (stmt->expr2, true, true);
12303 2696 : if (stmt_expr2 == NULL)
12304 2540 : stmt_expr2 = stmt->expr2;
12305 :
12306 2696 : switch (aop)
12307 : {
12308 506 : case GFC_OMP_ATOMIC_READ:
12309 506 : if (stmt_expr2->expr_type != EXPR_VARIABLE)
12310 0 : gfc_error ("!$OMP ATOMIC READ statement must read from a scalar "
12311 : "variable of intrinsic type at %L", &stmt_expr2->where);
12312 : return;
12313 426 : case GFC_OMP_ATOMIC_WRITE:
12314 426 : if (expr_references_sym (stmt_expr2, var, NULL))
12315 0 : gfc_error ("expr in !$OMP ATOMIC WRITE assignment var = expr "
12316 : "must be scalar and cannot reference var at %L",
12317 : &stmt_expr2->where);
12318 : return;
12319 1764 : default:
12320 1764 : break;
12321 : }
12322 :
12323 1764 : if (atomic_code->ext.omp_clauses->capture)
12324 : {
12325 588 : if (!is_scalar_intrinsic_expr (capture_stmt->expr1, true, false))
12326 : {
12327 0 : gfc_error ("!$OMP ATOMIC capture-statement must set a scalar "
12328 : "variable of intrinsic type at %L",
12329 0 : &capture_stmt->expr1->where);
12330 0 : return;
12331 : }
12332 :
12333 588 : if (!is_scalar_intrinsic_expr (capture_stmt->expr2, true, true))
12334 : {
12335 2 : gfc_error ("!$OMP ATOMIC capture-statement requires a scalar variable"
12336 2 : " of intrinsic type at %L", &capture_stmt->expr2->where);
12337 2 : return;
12338 : }
12339 586 : capt_expr2 = is_conversion (capture_stmt->expr2, true, true);
12340 586 : if (capt_expr2 == NULL)
12341 564 : capt_expr2 = capture_stmt->expr2;
12342 :
12343 586 : if (capt_expr2->symtree->n.sym != var)
12344 : {
12345 1 : gfc_error ("!$OMP ATOMIC CAPTURE capture statement reads from "
12346 : "different variable than update statement writes "
12347 : "into at %L", &capture_stmt->expr2->where);
12348 1 : return;
12349 : }
12350 : }
12351 :
12352 1761 : if (atomic_code->ext.omp_clauses->compare)
12353 : {
12354 150 : gfc_expr *var_expr;
12355 150 : if (comp_cond->value.op.op1->expr_type == EXPR_VARIABLE)
12356 : var_expr = comp_cond->value.op.op1;
12357 : else
12358 12 : var_expr = comp_cond->value.op.op1->value.function.actual->expr;
12359 150 : if (var_expr->symtree->n.sym != var)
12360 : {
12361 2 : gfc_error ("For !$OMP ATOMIC COMPARE, the first operand in comparison"
12362 : " at %L must be the variable %qs that the update statement"
12363 : " writes into at %L", &var_expr->where, var->name,
12364 2 : &stmt->expr1->where);
12365 2 : return;
12366 : }
12367 148 : if (stmt_expr2->rank != 0 || expr_references_sym (stmt_expr2, var, NULL))
12368 : {
12369 1 : gfc_error ("expr in !$OMP ATOMIC COMPARE assignment var = expr "
12370 : "must be scalar and cannot reference var at %L",
12371 : &stmt_expr2->where);
12372 1 : return;
12373 : }
12374 : }
12375 1611 : else if (atomic_code->ext.omp_clauses->capture
12376 1611 : && !expr_references_sym (stmt_expr2, var, NULL))
12377 22 : atomic_code->ext.omp_clauses->atomic_op
12378 22 : = (gfc_omp_atomic_op) (atomic_code->ext.omp_clauses->atomic_op
12379 : | GFC_OMP_ATOMIC_SWAP);
12380 1589 : else if (stmt_expr2->expr_type == EXPR_OP)
12381 : {
12382 1233 : gfc_expr *v = NULL, *e, *c;
12383 1233 : gfc_intrinsic_op op = stmt_expr2->value.op.op;
12384 1233 : gfc_intrinsic_op alt_op = INTRINSIC_NONE;
12385 :
12386 1233 : if (atomic_code->ext.omp_clauses->fail != OMP_MEMORDER_UNSET)
12387 3 : gfc_error ("!$OMP ATOMIC UPDATE at %L with FAIL clause requires either"
12388 : " the COMPARE clause or using the intrinsic MIN/MAX "
12389 : "procedure", &atomic_code->loc);
12390 1233 : switch (op)
12391 : {
12392 746 : case INTRINSIC_PLUS:
12393 746 : alt_op = INTRINSIC_MINUS;
12394 746 : break;
12395 94 : case INTRINSIC_TIMES:
12396 94 : alt_op = INTRINSIC_DIVIDE;
12397 94 : break;
12398 120 : case INTRINSIC_MINUS:
12399 120 : alt_op = INTRINSIC_PLUS;
12400 120 : break;
12401 94 : case INTRINSIC_DIVIDE:
12402 94 : alt_op = INTRINSIC_TIMES;
12403 94 : break;
12404 : case INTRINSIC_AND:
12405 : case INTRINSIC_OR:
12406 : break;
12407 43 : case INTRINSIC_EQV:
12408 43 : alt_op = INTRINSIC_NEQV;
12409 43 : break;
12410 43 : case INTRINSIC_NEQV:
12411 43 : alt_op = INTRINSIC_EQV;
12412 43 : break;
12413 1 : default:
12414 1 : gfc_error ("!$OMP ATOMIC assignment operator must be binary "
12415 : "+, *, -, /, .AND., .OR., .EQV. or .NEQV. at %L",
12416 : &stmt_expr2->where);
12417 1 : return;
12418 : }
12419 :
12420 : /* Check for var = var op expr resp. var = expr op var where
12421 : expr doesn't reference var and var op expr is mathematically
12422 : equivalent to var op (expr) resp. expr op var equivalent to
12423 : (expr) op var. We rely here on the fact that the matcher
12424 : for x op1 y op2 z where op1 and op2 have equal precedence
12425 : returns (x op1 y) op2 z. */
12426 1232 : e = stmt_expr2->value.op.op2;
12427 1232 : if (e->expr_type == EXPR_VARIABLE
12428 288 : && e->symtree != NULL
12429 288 : && e->symtree->n.sym == var)
12430 : v = e;
12431 1003 : else if ((c = is_conversion (e, false, true)) != NULL
12432 48 : && c->expr_type == EXPR_VARIABLE
12433 48 : && c->symtree != NULL
12434 1051 : && c->symtree->n.sym == var)
12435 : v = c;
12436 : else
12437 : {
12438 955 : gfc_expr **p = NULL, **q;
12439 1053 : for (q = &stmt_expr2->value.op.op1; (e = *q) != NULL; )
12440 1053 : if (e->expr_type == EXPR_VARIABLE
12441 952 : && e->symtree != NULL
12442 952 : && e->symtree->n.sym == var)
12443 : {
12444 : v = e;
12445 : break;
12446 : }
12447 101 : else if ((c = is_conversion (e, false, true)) != NULL)
12448 60 : q = &e->value.function.actual->expr;
12449 41 : else if (e->expr_type != EXPR_OP
12450 41 : || (e->value.op.op != op
12451 15 : && e->value.op.op != alt_op)
12452 38 : || e->rank != 0)
12453 : break;
12454 : else
12455 : {
12456 38 : p = q;
12457 38 : q = &e->value.op.op1;
12458 : }
12459 :
12460 955 : if (v == NULL)
12461 : {
12462 3 : gfc_error ("!$OMP ATOMIC assignment must be var = var op expr "
12463 : "or var = expr op var at %L", &stmt_expr2->where);
12464 3 : return;
12465 : }
12466 :
12467 952 : if (p != NULL)
12468 : {
12469 38 : e = *p;
12470 38 : switch (e->value.op.op)
12471 : {
12472 8 : case INTRINSIC_MINUS:
12473 8 : case INTRINSIC_DIVIDE:
12474 8 : case INTRINSIC_EQV:
12475 8 : case INTRINSIC_NEQV:
12476 8 : gfc_error ("!$OMP ATOMIC var = var op expr not "
12477 : "mathematically equivalent to var = var op "
12478 : "(expr) at %L", &stmt_expr2->where);
12479 8 : break;
12480 : default:
12481 : break;
12482 : }
12483 :
12484 : /* Canonicalize into var = var op (expr). */
12485 38 : *p = e->value.op.op2;
12486 38 : e->value.op.op2 = stmt_expr2;
12487 38 : e->ts = stmt_expr2->ts;
12488 38 : if (stmt->expr2 == stmt_expr2)
12489 26 : stmt->expr2 = stmt_expr2 = e;
12490 : else
12491 12 : stmt->expr2->value.function.actual->expr = stmt_expr2 = e;
12492 :
12493 38 : if (!gfc_compare_types (&stmt_expr2->value.op.op1->ts,
12494 : &stmt_expr2->ts))
12495 : {
12496 24 : for (p = &stmt_expr2->value.op.op1; *p != v;
12497 12 : p = &(*p)->value.function.actual->expr)
12498 : ;
12499 12 : *p = NULL;
12500 12 : gfc_free_expr (stmt_expr2->value.op.op1);
12501 12 : stmt_expr2->value.op.op1 = v;
12502 12 : gfc_convert_type (v, &stmt_expr2->ts, 2);
12503 : }
12504 : }
12505 : }
12506 :
12507 1229 : if (e->rank != 0 || expr_references_sym (stmt->expr2, var, v))
12508 : {
12509 1 : gfc_error ("expr in !$OMP ATOMIC assignment var = var op expr "
12510 : "must be scalar and cannot reference var at %L",
12511 : &stmt_expr2->where);
12512 1 : return;
12513 : }
12514 : }
12515 356 : else if (stmt_expr2->expr_type == EXPR_FUNCTION
12516 355 : && stmt_expr2->value.function.isym != NULL
12517 355 : && stmt_expr2->value.function.esym == NULL
12518 355 : && stmt_expr2->value.function.actual != NULL
12519 355 : && stmt_expr2->value.function.actual->next != NULL)
12520 : {
12521 355 : gfc_actual_arglist *arg, *var_arg;
12522 :
12523 355 : switch (stmt_expr2->value.function.isym->id)
12524 : {
12525 : case GFC_ISYM_MIN:
12526 : case GFC_ISYM_MAX:
12527 : break;
12528 147 : case GFC_ISYM_IAND:
12529 147 : case GFC_ISYM_IOR:
12530 147 : case GFC_ISYM_IEOR:
12531 147 : if (stmt_expr2->value.function.actual->next->next != NULL)
12532 : {
12533 0 : gfc_error ("!$OMP ATOMIC assignment intrinsic IAND, IOR "
12534 : "or IEOR must have two arguments at %L",
12535 : &stmt_expr2->where);
12536 0 : return;
12537 : }
12538 : break;
12539 1 : default:
12540 1 : gfc_error ("!$OMP ATOMIC assignment intrinsic must be "
12541 : "MIN, MAX, IAND, IOR or IEOR at %L",
12542 : &stmt_expr2->where);
12543 1 : return;
12544 : }
12545 :
12546 : var_arg = NULL;
12547 1088 : for (arg = stmt_expr2->value.function.actual; arg; arg = arg->next)
12548 : {
12549 741 : gfc_expr *e = NULL;
12550 741 : if (arg == stmt_expr2->value.function.actual
12551 387 : || (var_arg == NULL && arg->next == NULL))
12552 : {
12553 527 : e = is_conversion (arg->expr, false, true);
12554 527 : if (!e)
12555 514 : e = arg->expr;
12556 527 : if (e->expr_type == EXPR_VARIABLE
12557 453 : && e->symtree != NULL
12558 453 : && e->symtree->n.sym == var)
12559 741 : var_arg = arg;
12560 : }
12561 741 : if ((!var_arg || !e) && expr_references_sym (arg->expr, var, NULL))
12562 : {
12563 7 : gfc_error ("!$OMP ATOMIC intrinsic arguments except one must "
12564 : "not reference %qs at %L",
12565 : var->name, &arg->expr->where);
12566 7 : return;
12567 : }
12568 734 : if (arg->expr->rank != 0)
12569 : {
12570 0 : gfc_error ("!$OMP ATOMIC intrinsic arguments must be scalar "
12571 : "at %L", &arg->expr->where);
12572 0 : return;
12573 : }
12574 : }
12575 :
12576 347 : if (var_arg == NULL)
12577 : {
12578 1 : gfc_error ("First or last !$OMP ATOMIC intrinsic argument must "
12579 : "be %qs at %L", var->name, &stmt_expr2->where);
12580 1 : return;
12581 : }
12582 :
12583 346 : if (var_arg != stmt_expr2->value.function.actual)
12584 : {
12585 : /* Canonicalize, so that var comes first. */
12586 172 : gcc_assert (var_arg->next == NULL);
12587 : for (arg = stmt_expr2->value.function.actual;
12588 185 : arg->next != var_arg; arg = arg->next)
12589 : ;
12590 172 : var_arg->next = stmt_expr2->value.function.actual;
12591 172 : stmt_expr2->value.function.actual = var_arg;
12592 172 : arg->next = NULL;
12593 : }
12594 : }
12595 : else
12596 1 : gfc_error ("!$OMP ATOMIC assignment must have an operator or "
12597 : "intrinsic on right hand side at %L", &stmt_expr2->where);
12598 : return;
12599 :
12600 4 : unexpected:
12601 4 : gfc_error ("unexpected !$OMP ATOMIC expression at %L",
12602 : loc ? loc : &code->loc);
12603 4 : return;
12604 : }
12605 :
12606 :
12607 : static struct fortran_omp_context
12608 : {
12609 : gfc_code *code;
12610 : hash_set<gfc_symbol *> *sharing_clauses;
12611 : hash_set<gfc_symbol *> *private_iterators;
12612 : struct fortran_omp_context *previous;
12613 : bool is_openmp;
12614 : } *omp_current_ctx;
12615 : static gfc_code *omp_current_do_code;
12616 : static int omp_current_do_collapse;
12617 :
12618 : /* Forward declaration for mutually recursive functions. */
12619 : static gfc_code *
12620 : find_nested_loop_in_block (gfc_code *block);
12621 :
12622 : /* Return the first nested DO loop in CHAIN, or NULL if there
12623 : isn't one. Does no error checking on intervening code. */
12624 :
12625 : static gfc_code *
12626 27482 : find_nested_loop_in_chain (gfc_code *chain)
12627 : {
12628 27482 : gfc_code *code;
12629 :
12630 27482 : if (!chain)
12631 : return NULL;
12632 :
12633 31643 : for (code = chain; code; code = code->next)
12634 31222 : switch (code->op)
12635 : {
12636 : case EXEC_DO:
12637 : case EXEC_OMP_TILE:
12638 : case EXEC_OMP_UNROLL:
12639 : return code;
12640 621 : case EXEC_BLOCK:
12641 621 : if (gfc_code *c = find_nested_loop_in_block (code))
12642 : return c;
12643 : break;
12644 : default:
12645 : break;
12646 : }
12647 : return NULL;
12648 : }
12649 :
12650 : /* Return the first nested DO loop in BLOCK, or NULL if there
12651 : isn't one. Does no error checking on intervening code. */
12652 : static gfc_code *
12653 939 : find_nested_loop_in_block (gfc_code *block)
12654 : {
12655 939 : gfc_namespace *ns;
12656 939 : gcc_assert (block->op == EXEC_BLOCK);
12657 939 : ns = block->ext.block.ns;
12658 939 : gcc_assert (ns);
12659 939 : return find_nested_loop_in_chain (ns->code);
12660 : }
12661 :
12662 : void
12663 5463 : gfc_resolve_omp_do_blocks (gfc_code *code, gfc_namespace *ns)
12664 : {
12665 5463 : if (code->block->next && code->block->next->op == EXEC_DO)
12666 : {
12667 5110 : int i;
12668 :
12669 5110 : omp_current_do_code = code->block->next;
12670 5110 : if (code->ext.omp_clauses->orderedc)
12671 142 : omp_current_do_collapse = code->ext.omp_clauses->orderedc;
12672 4968 : else if (code->ext.omp_clauses->collapse)
12673 1121 : omp_current_do_collapse = code->ext.omp_clauses->collapse;
12674 3847 : else if (code->ext.omp_clauses->sizes_list)
12675 175 : omp_current_do_collapse
12676 175 : = gfc_expr_list_len (code->ext.omp_clauses->sizes_list);
12677 : else
12678 3672 : omp_current_do_collapse = 1;
12679 5110 : if (code->ext.omp_clauses->lists[OMP_LIST_REDUCTION_INSCAN])
12680 : {
12681 : /* Checking that there is a matching EXEC_OMP_SCAN in the
12682 : innermost body cannot be deferred to resolve_omp_do because
12683 : we process directives nested in the loop before we get
12684 : there. */
12685 60 : locus *loc
12686 : = &code->ext.omp_clauses->lists[OMP_LIST_REDUCTION_INSCAN]->where;
12687 60 : gfc_code *c;
12688 :
12689 80 : for (i = 1, c = omp_current_do_code;
12690 80 : i < omp_current_do_collapse; i++)
12691 : {
12692 22 : c = find_nested_loop_in_chain (c->block->next);
12693 22 : if (!c || c->op != EXEC_DO || c->block == NULL)
12694 : break;
12695 : }
12696 :
12697 : /* Skip this if we don't have enough nested loops. That
12698 : problem will be diagnosed elsewhere. */
12699 60 : if (c && c->op == EXEC_DO)
12700 : {
12701 58 : gfc_code *block = c->block ? c->block->next : NULL;
12702 58 : if (block && block->op != EXEC_OMP_SCAN)
12703 54 : while (block && block->next
12704 54 : && block->next->op != EXEC_OMP_SCAN)
12705 : block = block->next;
12706 43 : if (!block
12707 46 : || (block->op != EXEC_OMP_SCAN
12708 43 : && (!block->next || block->next->op != EXEC_OMP_SCAN)))
12709 19 : gfc_error ("With INSCAN at %L, expected loop body with "
12710 : "!$OMP SCAN between two "
12711 : "structured block sequences", loc);
12712 : else
12713 : {
12714 39 : if (block->op == EXEC_OMP_SCAN)
12715 3 : gfc_warning (OPT_Wopenmp,
12716 : "!$OMP SCAN at %L with zero executable "
12717 : "statements in preceding structured block "
12718 : "sequence", &block->loc);
12719 39 : if ((block->op == EXEC_OMP_SCAN && !block->next)
12720 38 : || (block->next && block->next->op == EXEC_OMP_SCAN
12721 36 : && !block->next->next))
12722 3 : gfc_warning (OPT_Wopenmp,
12723 : "!$OMP SCAN at %L with zero executable "
12724 : "statements in succeeding structured block "
12725 : "sequence", block->op == EXEC_OMP_SCAN
12726 1 : ? &block->loc : &block->next->loc);
12727 : }
12728 58 : if (block && block->op != EXEC_OMP_SCAN)
12729 43 : block = block->next;
12730 46 : if (block && block->op == EXEC_OMP_SCAN)
12731 : /* Mark 'omp scan' as checked; flag will be unset later. */
12732 39 : block->ext.omp_clauses->if_present = true;
12733 : }
12734 : }
12735 : }
12736 5463 : gfc_resolve_blocks (code->block, ns);
12737 5463 : omp_current_do_collapse = 0;
12738 5463 : omp_current_do_code = NULL;
12739 5463 : }
12740 :
12741 :
12742 : void
12743 6129 : gfc_resolve_omp_parallel_blocks (gfc_code *code, gfc_namespace *ns)
12744 : {
12745 6129 : struct fortran_omp_context ctx;
12746 6129 : gfc_omp_clauses *omp_clauses = code->ext.omp_clauses;
12747 6129 : gfc_omp_namelist *n;
12748 :
12749 6129 : ctx.code = code;
12750 6129 : ctx.sharing_clauses = new hash_set<gfc_symbol *>;
12751 6129 : ctx.private_iterators = new hash_set<gfc_symbol *>;
12752 6129 : ctx.previous = omp_current_ctx;
12753 6129 : ctx.is_openmp = true;
12754 6129 : omp_current_ctx = &ctx;
12755 :
12756 245160 : for (enum gfc_omp_list_type list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
12757 239031 : list = gfc_omp_list_type (list + 1))
12758 239031 : switch (list)
12759 : {
12760 61290 : case OMP_LIST_SHARED:
12761 61290 : case OMP_LIST_PRIVATE:
12762 61290 : case OMP_LIST_FIRSTPRIVATE:
12763 61290 : case OMP_LIST_LASTPRIVATE:
12764 61290 : case OMP_LIST_REDUCTION:
12765 61290 : case OMP_LIST_REDUCTION_INSCAN:
12766 61290 : case OMP_LIST_REDUCTION_TASK:
12767 61290 : case OMP_LIST_IN_REDUCTION:
12768 61290 : case OMP_LIST_TASK_REDUCTION:
12769 61290 : case OMP_LIST_LINEAR:
12770 70286 : for (n = omp_clauses->lists[list]; n; n = n->next)
12771 8996 : ctx.sharing_clauses->add (n->sym);
12772 : break;
12773 : default:
12774 : break;
12775 : }
12776 :
12777 6129 : switch (code->op)
12778 : {
12779 2375 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
12780 2375 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
12781 2375 : case EXEC_OMP_MASKED_TASKLOOP:
12782 2375 : case EXEC_OMP_MASKED_TASKLOOP_SIMD:
12783 2375 : case EXEC_OMP_MASTER_TASKLOOP:
12784 2375 : case EXEC_OMP_MASTER_TASKLOOP_SIMD:
12785 2375 : case EXEC_OMP_PARALLEL_DO:
12786 2375 : case EXEC_OMP_PARALLEL_DO_SIMD:
12787 2375 : case EXEC_OMP_PARALLEL_LOOP:
12788 2375 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
12789 2375 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
12790 2375 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
12791 2375 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
12792 2375 : case EXEC_OMP_TARGET_PARALLEL_DO:
12793 2375 : case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
12794 2375 : case EXEC_OMP_TARGET_PARALLEL_LOOP:
12795 2375 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
12796 2375 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
12797 2375 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
12798 2375 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
12799 2375 : case EXEC_OMP_TARGET_TEAMS_LOOP:
12800 2375 : case EXEC_OMP_TASKLOOP:
12801 2375 : case EXEC_OMP_TASKLOOP_SIMD:
12802 2375 : case EXEC_OMP_TEAMS_DISTRIBUTE:
12803 2375 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
12804 2375 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
12805 2375 : case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
12806 2375 : case EXEC_OMP_TEAMS_LOOP:
12807 2375 : gfc_resolve_omp_do_blocks (code, ns);
12808 2375 : break;
12809 3754 : default:
12810 3754 : gfc_resolve_blocks (code->block, ns);
12811 : }
12812 :
12813 6129 : omp_current_ctx = ctx.previous;
12814 12258 : delete ctx.sharing_clauses;
12815 12258 : delete ctx.private_iterators;
12816 6129 : }
12817 :
12818 :
12819 : /* Save and clear openmp.cc private state. */
12820 :
12821 : void
12822 303413 : gfc_omp_save_and_clear_state (struct gfc_omp_saved_state *state)
12823 : {
12824 303413 : state->ptrs[0] = omp_current_ctx;
12825 303413 : state->ptrs[1] = omp_current_do_code;
12826 303413 : state->ints[0] = omp_current_do_collapse;
12827 303413 : omp_current_ctx = NULL;
12828 303413 : omp_current_do_code = NULL;
12829 303413 : omp_current_do_collapse = 0;
12830 303413 : }
12831 :
12832 :
12833 : /* Restore openmp.cc private state from the saved state. */
12834 :
12835 : void
12836 303412 : gfc_omp_restore_state (struct gfc_omp_saved_state *state)
12837 : {
12838 303412 : omp_current_ctx = (struct fortran_omp_context *) state->ptrs[0];
12839 303412 : omp_current_do_code = (gfc_code *) state->ptrs[1];
12840 303412 : omp_current_do_collapse = state->ints[0];
12841 303412 : }
12842 :
12843 :
12844 : /* Note a DO iterator variable. This is special in !$omp parallel
12845 : construct, where they are predetermined private. */
12846 :
12847 : void
12848 33533 : gfc_resolve_do_iterator (gfc_code *code, gfc_symbol *sym, bool add_clause)
12849 : {
12850 33533 : if (omp_current_ctx == NULL)
12851 : return;
12852 :
12853 13122 : int i = omp_current_do_collapse;
12854 13122 : gfc_code *c = omp_current_do_code;
12855 :
12856 13122 : if (sym->attr.threadprivate)
12857 : return;
12858 :
12859 : /* !$omp do and !$omp parallel do iteration variable is predetermined
12860 : private just in the !$omp do resp. !$omp parallel do construct,
12861 : with no implications for the outer parallel constructs. */
12862 :
12863 17957 : while (i-- >= 1 && c)
12864 : {
12865 9511 : if (code == c)
12866 : return;
12867 4835 : c = find_nested_loop_in_chain (c->block->next);
12868 4835 : if (c && (c->op == EXEC_OMP_TILE || c->op == EXEC_OMP_UNROLL))
12869 : return;
12870 : }
12871 :
12872 : /* An openacc context may represent a data clause. Abort if so. */
12873 8446 : if (!omp_current_ctx->is_openmp && !oacc_is_loop (omp_current_ctx->code))
12874 : return;
12875 :
12876 7468 : if (omp_current_ctx->sharing_clauses->contains (sym))
12877 : return;
12878 :
12879 6466 : if (! omp_current_ctx->private_iterators->add (sym) && add_clause)
12880 : {
12881 6276 : gfc_omp_clauses *omp_clauses = omp_current_ctx->code->ext.omp_clauses;
12882 6276 : gfc_omp_namelist *p;
12883 :
12884 6276 : p = gfc_get_omp_namelist ();
12885 6276 : p->sym = sym;
12886 6276 : p->where = omp_current_ctx->code->loc;
12887 6276 : p->next = omp_clauses->lists[OMP_LIST_PRIVATE];
12888 6276 : omp_clauses->lists[OMP_LIST_PRIVATE] = p;
12889 : }
12890 : }
12891 :
12892 : static void
12893 777 : handle_local_var (gfc_symbol *sym)
12894 : {
12895 777 : if (sym->attr.flavor != FL_VARIABLE
12896 180 : || sym->as != NULL
12897 139 : || (sym->ts.type != BT_INTEGER && sym->ts.type != BT_REAL))
12898 : return;
12899 72 : gfc_resolve_do_iterator (sym->ns->code, sym, false);
12900 : }
12901 :
12902 : void
12903 351850 : gfc_resolve_omp_local_vars (gfc_namespace *ns)
12904 : {
12905 351850 : if (omp_current_ctx)
12906 471 : gfc_traverse_ns (ns, handle_local_var);
12907 351850 : }
12908 :
12909 :
12910 : /* Error checking on intervening code uses a code walker. */
12911 :
12912 : struct icode_error_state
12913 : {
12914 : const char *name;
12915 : bool errorp;
12916 : gfc_code *nested;
12917 : gfc_code *next;
12918 : };
12919 :
12920 : static int
12921 944 : icode_code_error_callback (gfc_code **codep,
12922 : int *walk_subtrees ATTRIBUTE_UNUSED, void *opaque)
12923 : {
12924 944 : gfc_code *code = *codep;
12925 944 : icode_error_state *state = (icode_error_state *)opaque;
12926 :
12927 : /* gfc_code_walker walks down CODE's next chain as well as
12928 : walking things that are actually nested in CODE. We need to
12929 : special-case traversal of outer blocks, so stop immediately if we
12930 : are heading down such a next chain. */
12931 944 : if (code == state->next)
12932 : return 1;
12933 :
12934 647 : switch (code->op)
12935 : {
12936 1 : case EXEC_DO:
12937 1 : case EXEC_DO_WHILE:
12938 1 : case EXEC_DO_CONCURRENT:
12939 1 : gfc_error ("%s cannot contain loop in intervening code at %L",
12940 : state->name, &code->loc);
12941 1 : state->errorp = true;
12942 1 : break;
12943 0 : case EXEC_CYCLE:
12944 0 : case EXEC_EXIT:
12945 : /* Errors have already been diagnosed in match_exit_cycle. */
12946 0 : state->errorp = true;
12947 0 : break;
12948 : case EXEC_OMP_ASSUME:
12949 : case EXEC_OMP_METADIRECTIVE:
12950 : /* Per OpenMP 6.0, some non-executable directives are allowed in
12951 : intervening code. */
12952 : break;
12953 477 : case EXEC_CALL:
12954 : /* Per OpenMP 5.2, the "omp_" prefix is reserved, so we don't have to
12955 : consider the possibility that some locally-bound definition
12956 : overrides the runtime routine. */
12957 477 : if (code->resolved_sym
12958 477 : && omp_runtime_api_procname (code->resolved_sym->name))
12959 : {
12960 1 : gfc_error ("%s cannot contain OpenMP API call in intervening code "
12961 : "at %L",
12962 : state->name, &code->loc);
12963 1 : state->errorp = true;
12964 : }
12965 : break;
12966 168 : default:
12967 168 : if (code->op >= EXEC_OMP_FIRST_OPENMP_EXEC
12968 168 : && code->op <= EXEC_OMP_LAST_OPENMP_EXEC)
12969 : {
12970 2 : gfc_error ("%s cannot contain OpenMP directive in intervening code "
12971 : "at %L",
12972 : state->name, &code->loc);
12973 2 : state->errorp = true;
12974 : }
12975 : }
12976 : return 0;
12977 : }
12978 :
12979 : static int
12980 1081 : icode_expr_error_callback (gfc_expr **expr,
12981 : int *walk_subtrees ATTRIBUTE_UNUSED, void *opaque)
12982 : {
12983 1081 : icode_error_state *state = (icode_error_state *)opaque;
12984 :
12985 1081 : switch ((*expr)->expr_type)
12986 : {
12987 : /* As for EXPR_CALL with "omp_"-prefixed symbols. */
12988 2 : case EXPR_FUNCTION:
12989 2 : {
12990 2 : gfc_symbol *sym = (*expr)->value.function.esym;
12991 2 : if (sym && omp_runtime_api_procname (sym->name))
12992 : {
12993 1 : gfc_error ("%s cannot contain OpenMP API call in intervening code "
12994 : "at %L",
12995 1 : state->name, &((*expr)->where));
12996 1 : state->errorp = true;
12997 : }
12998 : }
12999 :
13000 : break;
13001 : default:
13002 : break;
13003 : }
13004 :
13005 : /* FIXME: The description of canonical loop form in the OpenMP standard
13006 : also says "array expressions" are not permitted in intervening code.
13007 : That term is not defined in either the OpenMP spec or the Fortran
13008 : standard, although the latter uses it informally to refer to any
13009 : expression that is not scalar-valued. It is also apparently not the
13010 : thing GCC internally calls EXPR_ARRAY. It seems the intent of the
13011 : OpenMP restriction is to disallow elemental operations/intrinsics
13012 : (including things that are not expressions, like assignment
13013 : statements) that generate implicit loops over array operands
13014 : (even if the result is a scalar), but even if the spec said
13015 : that there is no list of all the cases that would be forbidden.
13016 : This is OpenMP issue 3326. */
13017 :
13018 1081 : return 0;
13019 : }
13020 :
13021 : static void
13022 267 : diagnose_intervening_code_errors_1 (gfc_code *chain,
13023 : struct icode_error_state *state)
13024 : {
13025 267 : gfc_code *code;
13026 1080 : for (code = chain; code; code = code->next)
13027 : {
13028 813 : if (code == state->nested)
13029 : /* Do not walk the nested loop or its body, we are only
13030 : interested in intervening code. */
13031 : ;
13032 636 : else if (code->op == EXEC_BLOCK
13033 636 : && find_nested_loop_in_block (code) == state->nested)
13034 : /* This block contains the nested loop, recurse on its
13035 : statements. */
13036 : {
13037 90 : gfc_namespace* ns = code->ext.block.ns;
13038 90 : diagnose_intervening_code_errors_1 (ns->code, state);
13039 : }
13040 : else
13041 : /* Treat the whole statement as a unit. */
13042 : {
13043 546 : gfc_code *temp = state->next;
13044 546 : state->next = code->next;
13045 546 : gfc_code_walker (&code, icode_code_error_callback,
13046 : icode_expr_error_callback, state);
13047 546 : state->next = temp;
13048 : }
13049 : }
13050 267 : }
13051 :
13052 : /* Diagnose intervening code errors in BLOCK with nested loop NESTED.
13053 : NAME is the user-friendly name of the OMP directive, used for error
13054 : messages. Returns true if any error was found. */
13055 : static bool
13056 177 : diagnose_intervening_code_errors (gfc_code *chain, const char *name,
13057 : gfc_code *nested)
13058 : {
13059 177 : struct icode_error_state state;
13060 177 : state.name = name;
13061 177 : state.errorp = false;
13062 177 : state.nested = nested;
13063 177 : state.next = NULL;
13064 0 : diagnose_intervening_code_errors_1 (chain, &state);
13065 177 : return state.errorp;
13066 : }
13067 :
13068 : /* Helper function for restructure_intervening_code: wrap CHAIN in
13069 : a marker to indicate that it is a structured block sequence. That
13070 : information will be used later on (in omp-low.cc) for error checking. */
13071 : static gfc_code *
13072 461 : make_structured_block (gfc_code *chain)
13073 : {
13074 461 : gcc_assert (chain);
13075 461 : gfc_namespace *ns = gfc_build_block_ns (gfc_current_ns);
13076 461 : gfc_code *result = gfc_get_code (EXEC_BLOCK);
13077 461 : result->op = EXEC_BLOCK;
13078 461 : result->ext.block.ns = ns;
13079 461 : result->ext.block.assoc = NULL;
13080 461 : result->loc = chain->loc;
13081 461 : ns->omp_structured_block = 1;
13082 461 : ns->code = chain;
13083 461 : return result;
13084 : }
13085 :
13086 : /* Push intervening code surrounding a loop, including nested scopes,
13087 : into the body of the loop. CHAINP is the pointer to the head of
13088 : the next-chain to scan, OUTER_LOOP is the EXEC_DO for the next outer
13089 : loop level, and COLLAPSE is the number of nested loops we need to
13090 : process.
13091 : Note that CHAINP may point at outer_loop->block->next when we
13092 : are scanning the body of a loop, but if there is an intervening block
13093 : CHAINP points into the block's chain rather than its enclosing outer
13094 : loop. This is why OUTER_LOOP is passed separately. */
13095 : static gfc_code *
13096 7213 : restructure_intervening_code (gfc_code **chainp, gfc_code *outer_loop,
13097 : int count)
13098 : {
13099 7213 : gfc_code *code;
13100 7213 : gfc_code *head = *chainp;
13101 7213 : gfc_code *tail = NULL;
13102 7213 : gfc_code *innermost_loop = NULL;
13103 :
13104 7477 : for (code = *chainp; code; code = code->next, chainp = &(*chainp)->next)
13105 : {
13106 7477 : if (code->op == EXEC_DO)
13107 : {
13108 : /* Cut CODE free from its chain, leaving the ends dangling. */
13109 7129 : *chainp = NULL;
13110 7129 : tail = code->next;
13111 7129 : code->next = NULL;
13112 :
13113 7129 : if (count == 1)
13114 : innermost_loop = code;
13115 : else
13116 2090 : innermost_loop
13117 2090 : = restructure_intervening_code (&code->block->next,
13118 : code, count - 1);
13119 : break;
13120 : }
13121 348 : else if (code->op == EXEC_BLOCK
13122 348 : && find_nested_loop_in_block (code))
13123 : {
13124 84 : gfc_namespace *ns = code->ext.block.ns;
13125 :
13126 : /* Cut CODE free from its chain, leaving the ends dangling. */
13127 84 : *chainp = NULL;
13128 84 : tail = code->next;
13129 84 : code->next = NULL;
13130 :
13131 84 : innermost_loop
13132 84 : = restructure_intervening_code (&ns->code, outer_loop,
13133 : count);
13134 :
13135 : /* At this point we have already pulled out the nested loop and
13136 : pointed outer_loop at it, and moved the intervening code that
13137 : was previously in the block into the body of innermost_loop.
13138 : Now we want to move the BLOCK itself so it wraps the entire
13139 : current body of innermost_loop. */
13140 84 : ns->code = innermost_loop->block->next;
13141 84 : innermost_loop->block->next = code;
13142 84 : break;
13143 : }
13144 : }
13145 :
13146 2174 : gcc_assert (innermost_loop);
13147 :
13148 : /* Now we have split the intervening code into two parts:
13149 : head is the start of the part before the loop/block, terminating
13150 : at *chainp, and tail is the part after it. Mark each part as
13151 : a structured block sequence, and splice the two parts around the
13152 : existing body of the innermost loop. */
13153 7213 : if (head != code)
13154 : {
13155 222 : gfc_code *block = make_structured_block (head);
13156 222 : if (innermost_loop->block->next)
13157 221 : gfc_append_code (block, innermost_loop->block->next);
13158 222 : innermost_loop->block->next = block;
13159 : }
13160 7213 : if (tail)
13161 : {
13162 239 : gfc_code *block = make_structured_block (tail);
13163 239 : if (innermost_loop->block->next)
13164 237 : gfc_append_code (innermost_loop->block->next, block);
13165 : else
13166 2 : innermost_loop->block->next = block;
13167 : }
13168 :
13169 : /* For loops, finally splice CODE into OUTER_LOOP. We already handled
13170 : relinking EXEC_BLOCK above. */
13171 7213 : if (code->op == EXEC_DO && outer_loop)
13172 7129 : outer_loop->block->next = code;
13173 :
13174 7213 : return innermost_loop;
13175 : }
13176 :
13177 : /* CODE is an OMP loop construct. Return true if VAR matches an iteration
13178 : variable outer to level DEPTH. */
13179 : static bool
13180 8126 : is_outer_iteration_variable (gfc_code *code, int depth, gfc_symbol *var)
13181 : {
13182 8126 : int i;
13183 8126 : gfc_code *do_code = code;
13184 :
13185 12653 : for (i = 1; i < depth; i++)
13186 : {
13187 5028 : do_code = find_nested_loop_in_chain (do_code->block->next);
13188 5028 : gcc_assert (do_code);
13189 5028 : if (do_code->op == EXEC_OMP_TILE || do_code->op == EXEC_OMP_UNROLL)
13190 : {
13191 51 : --i;
13192 51 : continue;
13193 : }
13194 4977 : gfc_symbol *ivar = do_code->ext.iterator->var->symtree->n.sym;
13195 4977 : if (var == ivar)
13196 : return true;
13197 : }
13198 : return false;
13199 : }
13200 :
13201 : /* Forward declaration for recursive functions. */
13202 : static gfc_code *
13203 : check_nested_loop_in_block (gfc_code *block, gfc_expr *expr, gfc_symbol *sym,
13204 : bool *bad);
13205 :
13206 : /* Like find_nested_loop_in_chain, but additionally check that EXPR
13207 : does not reference any variables bound in intervening EXEC_BLOCKs
13208 : and that SYM is not bound in such intervening blocks. Either EXPR or SYM
13209 : may be null. Sets *BAD to true if either test fails. */
13210 : static gfc_code *
13211 48337 : check_nested_loop_in_chain (gfc_code *chain, gfc_expr *expr, gfc_symbol *sym,
13212 : bool *bad)
13213 : {
13214 51941 : for (gfc_code *code = chain; code; code = code->next)
13215 : {
13216 51653 : if (code->op == EXEC_DO)
13217 : return code;
13218 4123 : else if (code->op == EXEC_OMP_TILE || code->op == EXEC_OMP_UNROLL)
13219 1682 : return check_nested_loop_in_chain (code->block->next, expr, sym, bad);
13220 2441 : else if (code->op == EXEC_BLOCK)
13221 : {
13222 807 : gfc_code *c = check_nested_loop_in_block (code, expr, sym, bad);
13223 807 : if (c)
13224 : return c;
13225 : }
13226 : }
13227 : return NULL;
13228 : }
13229 :
13230 : /* Code walker for block symtrees. It doesn't take any kind of state
13231 : argument, so use a static variable. */
13232 : static struct check_nested_loop_in_block_state_t {
13233 : gfc_expr *expr;
13234 : gfc_symbol *sym;
13235 : bool *bad;
13236 : } check_nested_loop_in_block_state;
13237 :
13238 : static void
13239 766 : check_nested_loop_in_block_symbol (gfc_symbol *sym)
13240 : {
13241 766 : if (sym == check_nested_loop_in_block_state.sym
13242 766 : || (check_nested_loop_in_block_state.expr
13243 567 : && gfc_find_sym_in_expr (sym,
13244 : check_nested_loop_in_block_state.expr)))
13245 5 : *check_nested_loop_in_block_state.bad = true;
13246 766 : }
13247 :
13248 : /* Return the first nested DO loop in BLOCK, or NULL if there
13249 : isn't one. Set *BAD to true if EXPR references any variables in BLOCK, or
13250 : SYM is bound in BLOCK. Either EXPR or SYM may be null. */
13251 : static gfc_code *
13252 807 : check_nested_loop_in_block (gfc_code *block, gfc_expr *expr,
13253 : gfc_symbol *sym, bool *bad)
13254 : {
13255 807 : gfc_namespace *ns;
13256 807 : gcc_assert (block->op == EXEC_BLOCK);
13257 807 : ns = block->ext.block.ns;
13258 807 : gcc_assert (ns);
13259 :
13260 : /* Skip the check if this block doesn't contain the nested loop, or
13261 : if we already know it's bad. */
13262 807 : gfc_code *result = check_nested_loop_in_chain (ns->code, expr, sym, bad);
13263 807 : if (result && !*bad)
13264 : {
13265 519 : check_nested_loop_in_block_state.expr = expr;
13266 519 : check_nested_loop_in_block_state.sym = sym;
13267 519 : check_nested_loop_in_block_state.bad = bad;
13268 519 : gfc_traverse_ns (ns, check_nested_loop_in_block_symbol);
13269 519 : check_nested_loop_in_block_state.expr = NULL;
13270 519 : check_nested_loop_in_block_state.sym = NULL;
13271 519 : check_nested_loop_in_block_state.bad = NULL;
13272 : }
13273 807 : return result;
13274 : }
13275 :
13276 : /* CODE is an OMP loop construct. Return true if EXPR references
13277 : any variables bound in intervening code, to level DEPTH. */
13278 : static bool
13279 22846 : expr_uses_intervening_var (gfc_code *code, int depth, gfc_expr *expr)
13280 : {
13281 22846 : int i;
13282 22846 : gfc_code *do_code = code;
13283 :
13284 58471 : for (i = 0; i < depth; i++)
13285 : {
13286 35628 : bool bad = false;
13287 35628 : do_code = check_nested_loop_in_chain (do_code->block->next,
13288 : expr, NULL, &bad);
13289 35628 : if (bad)
13290 3 : return true;
13291 : }
13292 : return false;
13293 : }
13294 :
13295 : /* CODE is an OMP loop construct. Return true if SYM is bound in
13296 : intervening code, to level DEPTH. */
13297 : static bool
13298 7625 : is_intervening_var (gfc_code *code, int depth, gfc_symbol *sym)
13299 : {
13300 7625 : int i;
13301 7625 : gfc_code *do_code = code;
13302 :
13303 19525 : for (i = 0; i < depth; i++)
13304 : {
13305 11902 : bool bad = false;
13306 11902 : do_code = check_nested_loop_in_chain (do_code->block->next,
13307 : NULL, sym, &bad);
13308 11902 : if (bad)
13309 2 : return true;
13310 : }
13311 : return false;
13312 : }
13313 :
13314 : /* CODE is an OMP loop construct. Return true if EXPR does not reference
13315 : any iteration variables outer to level DEPTH. */
13316 : static bool
13317 23925 : expr_is_invariant (gfc_code *code, int depth, gfc_expr *expr)
13318 : {
13319 23925 : int i;
13320 23925 : gfc_code *do_code = code;
13321 :
13322 37247 : for (i = 1; i < depth; i++)
13323 : {
13324 14388 : do_code = find_nested_loop_in_chain (do_code->block->next);
13325 14388 : gcc_assert (do_code);
13326 14388 : if (do_code->op == EXEC_OMP_TILE || do_code->op == EXEC_OMP_UNROLL)
13327 : {
13328 136 : --i;
13329 136 : continue;
13330 : }
13331 14252 : gfc_symbol *ivar = do_code->ext.iterator->var->symtree->n.sym;
13332 14252 : if (gfc_find_sym_in_expr (ivar, expr))
13333 : return false;
13334 : }
13335 : return true;
13336 : }
13337 :
13338 : /* CODE is an OMP loop construct. Return true if EXPR matches one of the
13339 : canonical forms for a bound expression. It may include references to
13340 : an iteration variable outer to level DEPTH; set OUTER_VARP if so. */
13341 : static bool
13342 15241 : bound_expr_is_canonical (gfc_code *code, int depth, gfc_expr *expr,
13343 : gfc_symbol **outer_varp)
13344 : {
13345 15241 : gfc_expr *expr2 = NULL;
13346 :
13347 : /* Rectangular case. */
13348 15241 : if (depth == 0 || expr_is_invariant (code, depth, expr))
13349 : return true;
13350 :
13351 : /* Any simple variable that didn't pass expr_is_invariant must be
13352 : an outer_var. */
13353 568 : if (expr->expr_type == EXPR_VARIABLE && expr->rank == 0)
13354 : {
13355 63 : *outer_varp = expr->symtree->n.sym;
13356 63 : return true;
13357 : }
13358 :
13359 : /* All other permitted forms are binary operators. */
13360 505 : if (expr->expr_type != EXPR_OP)
13361 : return false;
13362 :
13363 : /* Check for plus/minus a loop invariant expr. */
13364 503 : if (expr->value.op.op == INTRINSIC_PLUS
13365 503 : || expr->value.op.op == INTRINSIC_MINUS)
13366 : {
13367 483 : if (expr_is_invariant (code, depth, expr->value.op.op1))
13368 48 : expr2 = expr->value.op.op2;
13369 435 : else if (expr_is_invariant (code, depth, expr->value.op.op2))
13370 434 : expr2 = expr->value.op.op1;
13371 : else
13372 : return false;
13373 : }
13374 : else
13375 : expr2 = expr;
13376 :
13377 : /* Check for a product with a loop-invariant expr. */
13378 502 : if (expr2->expr_type == EXPR_OP
13379 96 : && expr2->value.op.op == INTRINSIC_TIMES)
13380 : {
13381 96 : if (expr_is_invariant (code, depth, expr2->value.op.op1))
13382 40 : expr2 = expr2->value.op.op2;
13383 56 : else if (expr_is_invariant (code, depth, expr2->value.op.op2))
13384 53 : expr2 = expr2->value.op.op1;
13385 : else
13386 : return false;
13387 : }
13388 :
13389 : /* What's left must be a reference to an outer loop variable. */
13390 499 : if (expr2->expr_type == EXPR_VARIABLE
13391 499 : && expr2->rank == 0
13392 998 : && is_outer_iteration_variable (code, depth, expr2->symtree->n.sym))
13393 : {
13394 499 : *outer_varp = expr2->symtree->n.sym;
13395 499 : return true;
13396 : }
13397 :
13398 : return false;
13399 : }
13400 :
13401 : static void
13402 5463 : resolve_omp_do (gfc_code *code)
13403 : {
13404 5463 : gfc_code *do_code, *next;
13405 5463 : int i, count, non_generated_count;
13406 5463 : gfc_omp_namelist *n;
13407 5463 : gfc_symbol *dovar;
13408 5463 : const char *name;
13409 5463 : bool is_simd = false;
13410 5463 : bool errorp = false;
13411 5463 : bool perfect_nesting_errorp = false;
13412 5463 : bool imperfect = false;
13413 :
13414 5463 : switch (code->op)
13415 : {
13416 : case EXEC_OMP_DISTRIBUTE: name = "!$OMP DISTRIBUTE"; break;
13417 55 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
13418 55 : name = "!$OMP DISTRIBUTE PARALLEL DO";
13419 55 : break;
13420 32 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
13421 32 : name = "!$OMP DISTRIBUTE PARALLEL DO SIMD";
13422 32 : is_simd = true;
13423 32 : break;
13424 50 : case EXEC_OMP_DISTRIBUTE_SIMD:
13425 50 : name = "!$OMP DISTRIBUTE SIMD";
13426 50 : is_simd = true;
13427 50 : break;
13428 1338 : case EXEC_OMP_DO: name = "!$OMP DO"; break;
13429 136 : case EXEC_OMP_DO_SIMD: name = "!$OMP DO SIMD"; is_simd = true; break;
13430 64 : case EXEC_OMP_LOOP: name = "!$OMP LOOP"; break;
13431 1220 : case EXEC_OMP_PARALLEL_DO: name = "!$OMP PARALLEL DO"; break;
13432 304 : case EXEC_OMP_PARALLEL_DO_SIMD:
13433 304 : name = "!$OMP PARALLEL DO SIMD";
13434 304 : is_simd = true;
13435 304 : break;
13436 46 : case EXEC_OMP_PARALLEL_LOOP: name = "!$OMP PARALLEL LOOP"; break;
13437 7 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
13438 7 : name = "!$OMP PARALLEL MASKED TASKLOOP";
13439 7 : break;
13440 10 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
13441 10 : name = "!$OMP PARALLEL MASKED TASKLOOP SIMD";
13442 10 : is_simd = true;
13443 10 : break;
13444 13 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
13445 13 : name = "!$OMP PARALLEL MASTER TASKLOOP";
13446 13 : break;
13447 18 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
13448 18 : name = "!$OMP PARALLEL MASTER TASKLOOP SIMD";
13449 18 : is_simd = true;
13450 18 : break;
13451 8 : case EXEC_OMP_MASKED_TASKLOOP: name = "!$OMP MASKED TASKLOOP"; break;
13452 14 : case EXEC_OMP_MASKED_TASKLOOP_SIMD:
13453 14 : name = "!$OMP MASKED TASKLOOP SIMD";
13454 14 : is_simd = true;
13455 14 : break;
13456 14 : case EXEC_OMP_MASTER_TASKLOOP: name = "!$OMP MASTER TASKLOOP"; break;
13457 19 : case EXEC_OMP_MASTER_TASKLOOP_SIMD:
13458 19 : name = "!$OMP MASTER TASKLOOP SIMD";
13459 19 : is_simd = true;
13460 19 : break;
13461 801 : case EXEC_OMP_SIMD: name = "!$OMP SIMD"; is_simd = true; break;
13462 88 : case EXEC_OMP_TARGET_PARALLEL_DO: name = "!$OMP TARGET PARALLEL DO"; break;
13463 20 : case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
13464 20 : name = "!$OMP TARGET PARALLEL DO SIMD";
13465 20 : is_simd = true;
13466 20 : break;
13467 16 : case EXEC_OMP_TARGET_PARALLEL_LOOP:
13468 16 : name = "!$OMP TARGET PARALLEL LOOP";
13469 16 : break;
13470 33 : case EXEC_OMP_TARGET_SIMD:
13471 33 : name = "!$OMP TARGET SIMD";
13472 33 : is_simd = true;
13473 33 : break;
13474 20 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
13475 20 : name = "!$OMP TARGET TEAMS DISTRIBUTE";
13476 20 : break;
13477 77 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
13478 77 : name = "!$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO";
13479 77 : break;
13480 38 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
13481 38 : name = "!$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD";
13482 38 : is_simd = true;
13483 38 : break;
13484 20 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
13485 20 : name = "!$OMP TARGET TEAMS DISTRIBUTE SIMD";
13486 20 : is_simd = true;
13487 20 : break;
13488 19 : case EXEC_OMP_TARGET_TEAMS_LOOP: name = "!$OMP TARGET TEAMS LOOP"; break;
13489 69 : case EXEC_OMP_TASKLOOP: name = "!$OMP TASKLOOP"; break;
13490 38 : case EXEC_OMP_TASKLOOP_SIMD:
13491 38 : name = "!$OMP TASKLOOP SIMD";
13492 38 : is_simd = true;
13493 38 : break;
13494 20 : case EXEC_OMP_TEAMS_DISTRIBUTE: name = "!$OMP TEAMS DISTRIBUTE"; break;
13495 39 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
13496 39 : name = "!$OMP TEAMS DISTRIBUTE PARALLEL DO";
13497 39 : break;
13498 61 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
13499 61 : name = "!$OMP TEAMS DISTRIBUTE PARALLEL DO SIMD";
13500 61 : is_simd = true;
13501 61 : break;
13502 42 : case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
13503 42 : name = "!$OMP TEAMS DISTRIBUTE SIMD";
13504 42 : is_simd = true;
13505 42 : break;
13506 48 : case EXEC_OMP_TEAMS_LOOP: name = "!$OMP TEAMS LOOP"; break;
13507 195 : case EXEC_OMP_TILE: name = "!$OMP TILE"; break;
13508 417 : case EXEC_OMP_UNROLL: name = "!$OMP UNROLL"; break;
13509 0 : default: gcc_unreachable ();
13510 : }
13511 :
13512 5463 : if (code->ext.omp_clauses)
13513 5463 : resolve_omp_clauses (code, code->ext.omp_clauses, NULL);
13514 :
13515 5463 : if (code->op == EXEC_OMP_TILE && code->ext.omp_clauses->sizes_list == NULL)
13516 0 : gfc_error ("SIZES clause is required on !$OMP TILE construct at %L",
13517 : &code->loc);
13518 :
13519 5463 : do_code = code->block->next;
13520 5463 : if (code->ext.omp_clauses->orderedc)
13521 : count = code->ext.omp_clauses->orderedc;
13522 5319 : else if (code->ext.omp_clauses->sizes_list)
13523 195 : count = gfc_expr_list_len (code->ext.omp_clauses->sizes_list);
13524 : else
13525 : {
13526 5124 : count = code->ext.omp_clauses->collapse;
13527 5124 : if (count <= 0)
13528 : count = 1;
13529 : }
13530 :
13531 5463 : non_generated_count = count;
13532 : /* While the spec defines the loop nest depth independently of the COLLAPSE
13533 : clause, in practice the middle end only pays attention to the COLLAPSE
13534 : depth and treats any further inner loops as the final-loop-body. So
13535 : here we also check canonical loop nest form only for the number of
13536 : outer loops specified by the COLLAPSE clause too. */
13537 8103 : for (i = 1; i <= count; i++)
13538 : {
13539 8103 : gfc_symbol *start_var = NULL, *end_var = NULL;
13540 : /* Parse errors are not recoverable. */
13541 8103 : if (do_code->op == EXEC_DO_WHILE)
13542 : {
13543 6 : gfc_error ("%s cannot be a DO WHILE or DO without loop control "
13544 : "at %L", name, &do_code->loc);
13545 106 : goto fail;
13546 : }
13547 8097 : if (do_code->op == EXEC_DO_CONCURRENT)
13548 : {
13549 4 : gfc_error ("%s cannot be a DO CONCURRENT loop at %L", name,
13550 : &do_code->loc);
13551 4 : goto fail;
13552 : }
13553 8093 : if (do_code->op == EXEC_OMP_TILE || do_code->op == EXEC_OMP_UNROLL)
13554 : {
13555 466 : if (do_code->op == EXEC_OMP_UNROLL)
13556 : {
13557 308 : if (!do_code->ext.omp_clauses->partial)
13558 : {
13559 53 : gfc_error ("Generated loop of UNROLL construct at %L "
13560 : "without PARTIAL clause does not have "
13561 : "canonical form", &do_code->loc);
13562 53 : goto fail;
13563 : }
13564 255 : else if (i != count)
13565 : {
13566 5 : gfc_error ("UNROLL construct at %L with PARTIAL clause "
13567 : "generates just one loop with canonical form "
13568 : "but %d loops are needed",
13569 5 : &do_code->loc, count - i + 1);
13570 5 : goto fail;
13571 : }
13572 : }
13573 158 : else if (do_code->op == EXEC_OMP_TILE)
13574 : {
13575 158 : if (do_code->ext.omp_clauses->sizes_list == NULL)
13576 : /* This should have been diagnosed earlier already. */
13577 0 : return;
13578 158 : int l = gfc_expr_list_len (do_code->ext.omp_clauses->sizes_list);
13579 158 : if (count - i + 1 > l)
13580 : {
13581 14 : gfc_error ("TILE construct at %L generates %d loops "
13582 : "with canonical form but %d loops are needed",
13583 : &do_code->loc, l, count - i + 1);
13584 14 : goto fail;
13585 : }
13586 : }
13587 394 : if (do_code->ext.omp_clauses && do_code->ext.omp_clauses->erroneous)
13588 17 : goto fail;
13589 377 : if (imperfect && !perfect_nesting_errorp)
13590 : {
13591 4 : sorry_at (gfc_get_location (&do_code->loc),
13592 : "Imperfectly nested loop using generated loops");
13593 4 : errorp = true;
13594 : }
13595 377 : if (non_generated_count == count)
13596 329 : non_generated_count = i - 1;
13597 377 : --i;
13598 377 : do_code = do_code->block->next;
13599 377 : continue;
13600 377 : }
13601 7627 : gcc_assert (do_code->op == EXEC_DO);
13602 7627 : if (do_code->ext.iterator->var->ts.type != BT_INTEGER)
13603 : {
13604 3 : gfc_error ("%s iteration variable must be of type integer at %L",
13605 : name, &do_code->loc);
13606 3 : errorp = true;
13607 : }
13608 7627 : dovar = do_code->ext.iterator->var->symtree->n.sym;
13609 7627 : if (dovar->attr.threadprivate)
13610 : {
13611 0 : gfc_error ("%s iteration variable must not be THREADPRIVATE "
13612 : "at %L", name, &do_code->loc);
13613 0 : errorp = true;
13614 : }
13615 7627 : if (code->ext.omp_clauses)
13616 305080 : for (enum gfc_omp_list_type list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
13617 297453 : list = gfc_omp_list_type (list + 1))
13618 98358 : if (!is_simd || code->ext.omp_clauses->collapse > 1
13619 297453 : ? (list != OMP_LIST_PRIVATE && list != OMP_LIST_LASTPRIVATE
13620 255450 : && list != OMP_LIST_ALLOCATE)
13621 42003 : : (list != OMP_LIST_PRIVATE && list != OMP_LIST_LASTPRIVATE
13622 42003 : && list != OMP_LIST_ALLOCATE && list != OMP_LIST_LINEAR))
13623 277882 : for (n = code->ext.omp_clauses->lists[list]; n; n = n->next)
13624 4387 : if (dovar == n->sym)
13625 : {
13626 5 : if (!is_simd || code->ext.omp_clauses->collapse > 1)
13627 4 : gfc_error ("%s iteration variable present on clause "
13628 : "other than PRIVATE, LASTPRIVATE or "
13629 : "ALLOCATE at %L", name, &do_code->loc);
13630 : else
13631 1 : gfc_error ("%s iteration variable present on clause "
13632 : "other than PRIVATE, LASTPRIVATE, ALLOCATE or "
13633 : "LINEAR at %L", name, &do_code->loc);
13634 : errorp = true;
13635 : }
13636 7627 : if (is_outer_iteration_variable (code, i, dovar))
13637 : {
13638 2 : gfc_error ("%s iteration variable used in more than one loop at %L",
13639 : name, &do_code->loc);
13640 2 : errorp = true;
13641 : }
13642 7625 : else if (is_intervening_var (code, i, dovar))
13643 : {
13644 2 : gfc_error ("%s iteration variable at %L is bound in "
13645 : "intervening code",
13646 : name, &do_code->loc);
13647 2 : errorp = true;
13648 : }
13649 7623 : else if (!bound_expr_is_canonical (code, i,
13650 7623 : do_code->ext.iterator->start,
13651 : &start_var))
13652 : {
13653 4 : gfc_error ("%s loop start expression not in canonical form at %L",
13654 : name, &do_code->loc);
13655 4 : errorp = true;
13656 : }
13657 7619 : else if (expr_uses_intervening_var (code, i,
13658 7619 : do_code->ext.iterator->start))
13659 : {
13660 1 : gfc_error ("%s loop start expression at %L uses variable bound in "
13661 : "intervening code",
13662 : name, &do_code->loc);
13663 1 : errorp = true;
13664 : }
13665 7618 : else if (!bound_expr_is_canonical (code, i,
13666 7618 : do_code->ext.iterator->end,
13667 : &end_var))
13668 : {
13669 2 : gfc_error ("%s loop end expression not in canonical form at %L",
13670 : name, &do_code->loc);
13671 2 : errorp = true;
13672 : }
13673 7616 : else if (expr_uses_intervening_var (code, i,
13674 7616 : do_code->ext.iterator->end))
13675 : {
13676 1 : gfc_error ("%s loop end expression at %L uses variable bound in "
13677 : "intervening code",
13678 : name, &do_code->loc);
13679 1 : errorp = true;
13680 : }
13681 7615 : else if (start_var && end_var && start_var != end_var)
13682 : {
13683 1 : gfc_error ("%s loop bounds reference different "
13684 : "iteration variables at %L", name, &do_code->loc);
13685 1 : errorp = true;
13686 : }
13687 7614 : else if (!expr_is_invariant (code, i, do_code->ext.iterator->step))
13688 : {
13689 3 : gfc_error ("%s loop increment not in canonical form at %L",
13690 : name, &do_code->loc);
13691 3 : errorp = true;
13692 : }
13693 7611 : else if (expr_uses_intervening_var (code, i,
13694 7611 : do_code->ext.iterator->step))
13695 : {
13696 1 : gfc_error ("%s loop increment expression at %L uses variable "
13697 : "bound in intervening code",
13698 : name, &do_code->loc);
13699 1 : errorp = true;
13700 : }
13701 7627 : if (start_var || end_var)
13702 : {
13703 528 : code->ext.omp_clauses->non_rectangular = 1;
13704 528 : if (i > non_generated_count)
13705 : {
13706 3 : sorry_at (gfc_get_location (&do_code->loc),
13707 : "Non-rectangular loops from generated loops "
13708 : "unsupported");
13709 3 : errorp = true;
13710 : }
13711 : }
13712 :
13713 : /* Only parse loop body into nested loop and intervening code if
13714 : there are supposed to be more loops in the nest to collapse. */
13715 7627 : if (i == count)
13716 : break;
13717 :
13718 2270 : next = find_nested_loop_in_chain (do_code->block->next);
13719 :
13720 2270 : if (!next)
13721 : {
13722 : /* Parse error, can't recover from this. */
13723 7 : gfc_error ("not enough DO loops for collapsed %s (level %d) at %L",
13724 : name, i, &code->loc);
13725 7 : goto fail;
13726 : }
13727 2263 : else if (next != do_code->block->next
13728 2103 : || (next->next && next->next->op != EXEC_CONTINUE))
13729 : /* Imperfectly nested loop found. */
13730 : {
13731 : /* Only diagnose violation of imperfect nesting constraints once. */
13732 177 : if (!perfect_nesting_errorp)
13733 : {
13734 176 : if (code->ext.omp_clauses->orderedc)
13735 : {
13736 3 : gfc_error ("%s inner loops must be perfectly nested with "
13737 : "ORDERED clause at %L",
13738 : name, &code->loc);
13739 3 : perfect_nesting_errorp = true;
13740 : }
13741 173 : else if (code->ext.omp_clauses->lists[OMP_LIST_REDUCTION_INSCAN])
13742 : {
13743 2 : gfc_error ("%s inner loops must be perfectly nested with "
13744 : "REDUCTION INSCAN clause at %L",
13745 : name, &code->loc);
13746 2 : perfect_nesting_errorp = true;
13747 : }
13748 171 : else if (code->op == EXEC_OMP_TILE)
13749 : {
13750 8 : gfc_error ("%s inner loops must be perfectly nested at %L",
13751 : name, &code->loc);
13752 8 : perfect_nesting_errorp = true;
13753 : }
13754 13 : if (perfect_nesting_errorp)
13755 : errorp = true;
13756 : }
13757 177 : if (diagnose_intervening_code_errors (do_code->block->next,
13758 : name, next))
13759 5 : errorp = true;
13760 : imperfect = true;
13761 : }
13762 2263 : do_code = next;
13763 : }
13764 :
13765 : /* Give up now if we found any constraint violations. */
13766 5357 : if (errorp)
13767 : {
13768 48 : fail:
13769 154 : if (code->ext.omp_clauses)
13770 154 : code->ext.omp_clauses->erroneous = 1;
13771 : return;
13772 : }
13773 :
13774 5309 : if (non_generated_count)
13775 5039 : restructure_intervening_code (&code->block->next, code,
13776 : non_generated_count);
13777 : }
13778 :
13779 : /* Resolve the context selector. In particular, SKIP_P is set to true,
13780 : the context can never be matched. */
13781 :
13782 : static void
13783 804 : gfc_resolve_omp_context_selector (gfc_omp_set_selector *oss,
13784 : bool is_metadirective, bool *skip_p)
13785 : {
13786 804 : if (skip_p)
13787 327 : *skip_p = false;
13788 1527 : for (gfc_omp_set_selector *set_selector = oss; set_selector;
13789 723 : set_selector = set_selector->next)
13790 1558 : for (gfc_omp_selector *os = set_selector->trait_selectors; os; os = os->next)
13791 : {
13792 853 : if (os->score)
13793 : {
13794 52 : if (!gfc_resolve_expr (os->score)
13795 52 : || os->score->ts.type != BT_INTEGER
13796 104 : || os->score->rank != 0)
13797 : {
13798 0 : gfc_error ("%<score%> argument must be constant integer "
13799 0 : "expression at %L", &os->score->where);
13800 0 : gfc_free_expr (os->score);
13801 0 : os->score = nullptr;
13802 : }
13803 52 : else if (os->score->expr_type == EXPR_CONSTANT
13804 52 : && mpz_sgn (os->score->value.integer) < 0)
13805 : {
13806 1 : gfc_error ("%<score%> argument must be non-negative at %L",
13807 : &os->score->where);
13808 1 : gfc_free_expr (os->score);
13809 1 : os->score = nullptr;
13810 : }
13811 : }
13812 :
13813 853 : if (os->code == OMP_TRAIT_INVALID)
13814 : break;
13815 835 : enum omp_tp_type property_kind = omp_ts_map[os->code].tp_type;
13816 835 : gfc_omp_trait_property *otp = os->properties;
13817 :
13818 835 : if (!otp)
13819 419 : continue;
13820 416 : switch (property_kind)
13821 : {
13822 148 : case OMP_TRAIT_PROPERTY_DEV_NUM_EXPR:
13823 148 : case OMP_TRAIT_PROPERTY_BOOL_EXPR:
13824 148 : if (!gfc_resolve_expr (otp->expr)
13825 147 : || (property_kind == OMP_TRAIT_PROPERTY_BOOL_EXPR
13826 133 : && otp->expr->ts.type != BT_LOGICAL)
13827 146 : || (property_kind == OMP_TRAIT_PROPERTY_DEV_NUM_EXPR
13828 14 : && otp->expr->ts.type != BT_INTEGER)
13829 146 : || otp->expr->rank != 0
13830 294 : || (!is_metadirective && otp->expr->expr_type != EXPR_CONSTANT))
13831 : {
13832 3 : if (is_metadirective)
13833 : {
13834 0 : if (property_kind == OMP_TRAIT_PROPERTY_BOOL_EXPR)
13835 0 : gfc_error ("property must be a "
13836 : "logical expression at %L",
13837 0 : &otp->expr->where);
13838 : else
13839 0 : gfc_error ("property must be an "
13840 : "integer expression at %L",
13841 0 : &otp->expr->where);
13842 : }
13843 : else
13844 : {
13845 3 : if (property_kind == OMP_TRAIT_PROPERTY_BOOL_EXPR)
13846 2 : gfc_error ("property must be a constant "
13847 : "logical expression at %L",
13848 2 : &otp->expr->where);
13849 : else
13850 1 : gfc_error ("property must be a constant "
13851 : "integer expression at %L",
13852 1 : &otp->expr->where);
13853 : }
13854 : /* Prevent later ICEs. */
13855 3 : gfc_expr *e;
13856 3 : if (property_kind == OMP_TRAIT_PROPERTY_BOOL_EXPR)
13857 2 : e = gfc_get_logical_expr (gfc_default_logical_kind,
13858 2 : &otp->expr->where, true);
13859 : else
13860 1 : e = gfc_get_int_expr (gfc_default_integer_kind,
13861 1 : &otp->expr->where, 0);
13862 3 : gfc_free_expr (otp->expr);
13863 3 : otp->expr = e;
13864 3 : continue;
13865 3 : }
13866 : /* Device number must be conforming, which includes
13867 : omp_initial_device (-1), omp_invalid_device (-4),
13868 : and omp_default_device (-5). */
13869 145 : if (property_kind == OMP_TRAIT_PROPERTY_DEV_NUM_EXPR
13870 14 : && otp->expr->expr_type == EXPR_CONSTANT
13871 5 : && mpz_sgn (otp->expr->value.integer) < 0
13872 3 : && mpz_cmp_si (otp->expr->value.integer, -1) != 0
13873 2 : && mpz_cmp_si (otp->expr->value.integer, -4) != 0
13874 1 : && mpz_cmp_si (otp->expr->value.integer, -5) != 0)
13875 1 : gfc_error ("property must be a conforming device number at %L",
13876 : &otp->expr->where);
13877 : break;
13878 : default:
13879 : break;
13880 : }
13881 : /* This only handles one specific case: User condition.
13882 : FIXME: Handle more cases by calling omp_context_selector_matches;
13883 : unfortunately, we cannot generate the tree here as, e.g., PARM_DECL
13884 : backend decl are not available at this stage - but might be used in,
13885 : e.g. user conditions. See PR122361. */
13886 413 : if (skip_p && otp
13887 149 : && os->code == OMP_TRAIT_USER_CONDITION
13888 88 : && otp->expr->expr_type == EXPR_CONSTANT
13889 14 : && otp->expr->value.logical == false)
13890 12 : *skip_p = true;
13891 : }
13892 804 : }
13893 :
13894 :
13895 : static void
13896 146 : resolve_omp_metadirective (gfc_code *code, gfc_namespace *ns)
13897 : {
13898 146 : gfc_omp_variant *variant = code->ext.omp_variants;
13899 146 : gfc_omp_variant *prev_variant = variant;
13900 :
13901 473 : while (variant)
13902 : {
13903 327 : bool skip;
13904 327 : gfc_resolve_omp_context_selector (variant->selectors, true, &skip);
13905 327 : gfc_code *variant_code = variant->code;
13906 327 : gfc_resolve_code (variant_code, ns);
13907 327 : if (skip)
13908 : {
13909 : /* The following should only be true if an error occurred
13910 : as the 'otherwise' clause should always match. */
13911 12 : if (variant == code->ext.omp_variants && !variant->next)
13912 : break;
13913 12 : gfc_omp_variant *tmp = variant;
13914 12 : if (variant == code->ext.omp_variants)
13915 11 : variant = prev_variant = code->ext.omp_variants = variant->next;
13916 : else
13917 1 : variant = prev_variant->next = variant->next;
13918 12 : gfc_free_omp_set_selector_list (tmp->selectors);
13919 12 : free (tmp);
13920 : }
13921 : else
13922 : {
13923 315 : prev_variant = variant;
13924 315 : variant = variant->next;
13925 : }
13926 : }
13927 : /* Replace metadirective by its body if only 'nothing' remains. */
13928 146 : if (!code->ext.omp_variants->next && code->ext.omp_variants->stmt == ST_NONE)
13929 : {
13930 11 : gfc_code *next = code->next;
13931 11 : gfc_code *inner = code->ext.omp_variants->code;
13932 11 : gfc_free_omp_set_selector_list (code->ext.omp_variants->selectors);
13933 11 : free (code->ext.omp_variants);
13934 11 : *code = *inner;
13935 11 : free (inner);
13936 11 : while (code->next)
13937 : code = code->next;
13938 11 : code->next = next;
13939 : }
13940 146 : }
13941 :
13942 :
13943 : static gfc_statement
13944 63 : omp_code_to_statement (gfc_code *code)
13945 : {
13946 63 : switch (code->op)
13947 : {
13948 : case EXEC_OMP_PARALLEL:
13949 : return ST_OMP_PARALLEL;
13950 0 : case EXEC_OMP_PARALLEL_MASKED:
13951 0 : return ST_OMP_PARALLEL_MASKED;
13952 0 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
13953 0 : return ST_OMP_PARALLEL_MASKED_TASKLOOP;
13954 0 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
13955 0 : return ST_OMP_PARALLEL_MASKED_TASKLOOP_SIMD;
13956 0 : case EXEC_OMP_PARALLEL_MASTER:
13957 0 : return ST_OMP_PARALLEL_MASTER;
13958 0 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
13959 0 : return ST_OMP_PARALLEL_MASTER_TASKLOOP;
13960 0 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
13961 0 : return ST_OMP_PARALLEL_MASTER_TASKLOOP_SIMD;
13962 1 : case EXEC_OMP_PARALLEL_SECTIONS:
13963 1 : return ST_OMP_PARALLEL_SECTIONS;
13964 1 : case EXEC_OMP_SECTIONS:
13965 1 : return ST_OMP_SECTIONS;
13966 1 : case EXEC_OMP_ORDERED:
13967 1 : return ST_OMP_ORDERED;
13968 1 : case EXEC_OMP_CRITICAL:
13969 1 : return ST_OMP_CRITICAL;
13970 0 : case EXEC_OMP_MASKED:
13971 0 : return ST_OMP_MASKED;
13972 0 : case EXEC_OMP_MASKED_TASKLOOP:
13973 0 : return ST_OMP_MASKED_TASKLOOP;
13974 0 : case EXEC_OMP_MASKED_TASKLOOP_SIMD:
13975 0 : return ST_OMP_MASKED_TASKLOOP_SIMD;
13976 1 : case EXEC_OMP_MASTER:
13977 1 : return ST_OMP_MASTER;
13978 0 : case EXEC_OMP_MASTER_TASKLOOP:
13979 0 : return ST_OMP_MASTER_TASKLOOP;
13980 0 : case EXEC_OMP_MASTER_TASKLOOP_SIMD:
13981 0 : return ST_OMP_MASTER_TASKLOOP_SIMD;
13982 1 : case EXEC_OMP_SINGLE:
13983 1 : return ST_OMP_SINGLE;
13984 1 : case EXEC_OMP_TASK:
13985 1 : return ST_OMP_TASK;
13986 1 : case EXEC_OMP_WORKSHARE:
13987 1 : return ST_OMP_WORKSHARE;
13988 1 : case EXEC_OMP_PARALLEL_WORKSHARE:
13989 1 : return ST_OMP_PARALLEL_WORKSHARE;
13990 3 : case EXEC_OMP_DO:
13991 3 : return ST_OMP_DO;
13992 0 : case EXEC_OMP_LOOP:
13993 0 : return ST_OMP_LOOP;
13994 0 : case EXEC_OMP_ALLOCATE:
13995 0 : return ST_OMP_ALLOCATE_EXEC;
13996 0 : case EXEC_OMP_ALLOCATORS:
13997 0 : return ST_OMP_ALLOCATORS;
13998 0 : case EXEC_OMP_ASSUME:
13999 0 : return ST_OMP_ASSUME;
14000 1 : case EXEC_OMP_ATOMIC:
14001 1 : return ST_OMP_ATOMIC;
14002 1 : case EXEC_OMP_BARRIER:
14003 1 : return ST_OMP_BARRIER;
14004 1 : case EXEC_OMP_CANCEL:
14005 1 : return ST_OMP_CANCEL;
14006 1 : case EXEC_OMP_CANCELLATION_POINT:
14007 1 : return ST_OMP_CANCELLATION_POINT;
14008 0 : case EXEC_OMP_ERROR:
14009 0 : return ST_OMP_ERROR;
14010 1 : case EXEC_OMP_FLUSH:
14011 1 : return ST_OMP_FLUSH;
14012 0 : case EXEC_OMP_INTEROP:
14013 0 : return ST_OMP_INTEROP;
14014 1 : case EXEC_OMP_DISTRIBUTE:
14015 1 : return ST_OMP_DISTRIBUTE;
14016 1 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
14017 1 : return ST_OMP_DISTRIBUTE_PARALLEL_DO;
14018 1 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
14019 1 : return ST_OMP_DISTRIBUTE_PARALLEL_DO_SIMD;
14020 1 : case EXEC_OMP_DISTRIBUTE_SIMD:
14021 1 : return ST_OMP_DISTRIBUTE_SIMD;
14022 1 : case EXEC_OMP_DO_SIMD:
14023 1 : return ST_OMP_DO_SIMD;
14024 0 : case EXEC_OMP_SCAN:
14025 0 : return ST_OMP_SCAN;
14026 0 : case EXEC_OMP_SCOPE:
14027 0 : return ST_OMP_SCOPE;
14028 1 : case EXEC_OMP_SIMD:
14029 1 : return ST_OMP_SIMD;
14030 1 : case EXEC_OMP_TARGET:
14031 1 : return ST_OMP_TARGET;
14032 1 : case EXEC_OMP_TARGET_DATA:
14033 1 : return ST_OMP_TARGET_DATA;
14034 1 : case EXEC_OMP_TARGET_ENTER_DATA:
14035 1 : return ST_OMP_TARGET_ENTER_DATA;
14036 1 : case EXEC_OMP_TARGET_EXIT_DATA:
14037 1 : return ST_OMP_TARGET_EXIT_DATA;
14038 1 : case EXEC_OMP_TARGET_PARALLEL:
14039 1 : return ST_OMP_TARGET_PARALLEL;
14040 1 : case EXEC_OMP_TARGET_PARALLEL_DO:
14041 1 : return ST_OMP_TARGET_PARALLEL_DO;
14042 1 : case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
14043 1 : return ST_OMP_TARGET_PARALLEL_DO_SIMD;
14044 0 : case EXEC_OMP_TARGET_PARALLEL_LOOP:
14045 0 : return ST_OMP_TARGET_PARALLEL_LOOP;
14046 1 : case EXEC_OMP_TARGET_SIMD:
14047 1 : return ST_OMP_TARGET_SIMD;
14048 1 : case EXEC_OMP_TARGET_TEAMS:
14049 1 : return ST_OMP_TARGET_TEAMS;
14050 1 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
14051 1 : return ST_OMP_TARGET_TEAMS_DISTRIBUTE;
14052 1 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
14053 1 : return ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO;
14054 1 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
14055 1 : return ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD;
14056 1 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
14057 1 : return ST_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD;
14058 0 : case EXEC_OMP_TARGET_TEAMS_LOOP:
14059 0 : return ST_OMP_TARGET_TEAMS_LOOP;
14060 1 : case EXEC_OMP_TARGET_UPDATE:
14061 1 : return ST_OMP_TARGET_UPDATE;
14062 1 : case EXEC_OMP_TASKGROUP:
14063 1 : return ST_OMP_TASKGROUP;
14064 1 : case EXEC_OMP_TASKLOOP:
14065 1 : return ST_OMP_TASKLOOP;
14066 1 : case EXEC_OMP_TASKLOOP_SIMD:
14067 1 : return ST_OMP_TASKLOOP_SIMD;
14068 1 : case EXEC_OMP_TASKWAIT:
14069 1 : return ST_OMP_TASKWAIT;
14070 1 : case EXEC_OMP_TASKYIELD:
14071 1 : return ST_OMP_TASKYIELD;
14072 1 : case EXEC_OMP_TEAMS:
14073 1 : return ST_OMP_TEAMS;
14074 1 : case EXEC_OMP_TEAMS_DISTRIBUTE:
14075 1 : return ST_OMP_TEAMS_DISTRIBUTE;
14076 1 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
14077 1 : return ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO;
14078 1 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
14079 1 : return ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD;
14080 1 : case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
14081 1 : return ST_OMP_TEAMS_DISTRIBUTE_SIMD;
14082 0 : case EXEC_OMP_TEAMS_LOOP:
14083 0 : return ST_OMP_TEAMS_LOOP;
14084 6 : case EXEC_OMP_PARALLEL_DO:
14085 6 : return ST_OMP_PARALLEL_DO;
14086 1 : case EXEC_OMP_PARALLEL_DO_SIMD:
14087 1 : return ST_OMP_PARALLEL_DO_SIMD;
14088 0 : case EXEC_OMP_PARALLEL_LOOP:
14089 0 : return ST_OMP_PARALLEL_LOOP;
14090 1 : case EXEC_OMP_DEPOBJ:
14091 1 : return ST_OMP_DEPOBJ;
14092 0 : case EXEC_OMP_TILE:
14093 0 : return ST_OMP_TILE;
14094 0 : case EXEC_OMP_UNROLL:
14095 0 : return ST_OMP_UNROLL;
14096 0 : case EXEC_OMP_DISPATCH:
14097 0 : return ST_OMP_DISPATCH;
14098 0 : default:
14099 0 : gcc_unreachable ();
14100 : }
14101 : }
14102 :
14103 : static gfc_statement
14104 63 : oacc_code_to_statement (gfc_code *code)
14105 : {
14106 63 : switch (code->op)
14107 : {
14108 : case EXEC_OACC_PARALLEL:
14109 : return ST_OACC_PARALLEL;
14110 : case EXEC_OACC_KERNELS:
14111 : return ST_OACC_KERNELS;
14112 : case EXEC_OACC_SERIAL:
14113 : return ST_OACC_SERIAL;
14114 : case EXEC_OACC_DATA:
14115 : return ST_OACC_DATA;
14116 : case EXEC_OACC_HOST_DATA:
14117 : return ST_OACC_HOST_DATA;
14118 : case EXEC_OACC_PARALLEL_LOOP:
14119 : return ST_OACC_PARALLEL_LOOP;
14120 : case EXEC_OACC_KERNELS_LOOP:
14121 : return ST_OACC_KERNELS_LOOP;
14122 : case EXEC_OACC_SERIAL_LOOP:
14123 : return ST_OACC_SERIAL_LOOP;
14124 : case EXEC_OACC_LOOP:
14125 : return ST_OACC_LOOP;
14126 : case EXEC_OACC_ATOMIC:
14127 : return ST_OACC_ATOMIC;
14128 : case EXEC_OACC_ROUTINE:
14129 : return ST_OACC_ROUTINE;
14130 : case EXEC_OACC_UPDATE:
14131 : return ST_OACC_UPDATE;
14132 : case EXEC_OACC_WAIT:
14133 : return ST_OACC_WAIT;
14134 : case EXEC_OACC_CACHE:
14135 : return ST_OACC_CACHE;
14136 : case EXEC_OACC_ENTER_DATA:
14137 : return ST_OACC_ENTER_DATA;
14138 : case EXEC_OACC_EXIT_DATA:
14139 : return ST_OACC_EXIT_DATA;
14140 : case EXEC_OACC_DECLARE:
14141 : return ST_OACC_DECLARE;
14142 : case EXEC_OACC_INIT:
14143 : return ST_OACC_INIT;
14144 : case EXEC_OACC_SHUTDOWN:
14145 : return ST_OACC_SHUTDOWN;
14146 : case EXEC_OACC_SET:
14147 : return ST_OACC_SET;
14148 0 : default:
14149 0 : gcc_unreachable ();
14150 : }
14151 : }
14152 :
14153 : static void
14154 13538 : resolve_oacc_directive_inside_omp_region (gfc_code *code)
14155 : {
14156 13538 : if (omp_current_ctx != NULL && omp_current_ctx->is_openmp)
14157 : {
14158 11 : gfc_statement st = omp_code_to_statement (omp_current_ctx->code);
14159 11 : gfc_statement oacc_st = oacc_code_to_statement (code);
14160 11 : gfc_error ("The %s directive cannot be specified within "
14161 : "a %s region at %L", gfc_ascii_statement (oacc_st),
14162 : gfc_ascii_statement (st), &code->loc);
14163 : }
14164 13538 : }
14165 :
14166 : static void
14167 21385 : resolve_omp_directive_inside_oacc_region (gfc_code *code)
14168 : {
14169 21385 : if (omp_current_ctx != NULL && !omp_current_ctx->is_openmp)
14170 : {
14171 52 : gfc_statement st = oacc_code_to_statement (omp_current_ctx->code);
14172 52 : gfc_statement omp_st = omp_code_to_statement (code);
14173 52 : gfc_error ("The %s directive cannot be specified within "
14174 : "a %s region at %L", gfc_ascii_statement (omp_st),
14175 : gfc_ascii_statement (st), &code->loc);
14176 : }
14177 21385 : }
14178 :
14179 :
14180 : static void
14181 5272 : resolve_oacc_nested_loops (gfc_code *code, gfc_code* do_code, int collapse,
14182 : const char *clause)
14183 : {
14184 5272 : gfc_symbol *dovar;
14185 5272 : gfc_code *c;
14186 5272 : int i;
14187 :
14188 5792 : for (i = 1; i <= collapse; i++)
14189 : {
14190 5792 : if (do_code->op == EXEC_DO_WHILE)
14191 : {
14192 10 : gfc_error ("!$ACC LOOP cannot be a DO WHILE or DO without loop control "
14193 : "at %L", &do_code->loc);
14194 10 : break;
14195 : }
14196 5782 : if (do_code->op == EXEC_DO_CONCURRENT)
14197 : {
14198 3 : gfc_error ("!$ACC LOOP cannot be a DO CONCURRENT loop at %L",
14199 : &do_code->loc);
14200 3 : break;
14201 : }
14202 5779 : gcc_assert (do_code->op == EXEC_DO);
14203 5779 : if (do_code->ext.iterator->var->ts.type != BT_INTEGER)
14204 6 : gfc_error ("!$ACC LOOP iteration variable must be of type integer at %L",
14205 : &do_code->loc);
14206 5779 : dovar = do_code->ext.iterator->var->symtree->n.sym;
14207 5779 : if (i > 1)
14208 : {
14209 518 : gfc_code *do_code2 = code->block->next;
14210 518 : int j;
14211 :
14212 1218 : for (j = 1; j < i; j++)
14213 : {
14214 710 : gfc_symbol *ivar = do_code2->ext.iterator->var->symtree->n.sym;
14215 710 : if (dovar == ivar
14216 710 : || gfc_find_sym_in_expr (ivar, do_code->ext.iterator->start)
14217 701 : || gfc_find_sym_in_expr (ivar, do_code->ext.iterator->end)
14218 1410 : || gfc_find_sym_in_expr (ivar, do_code->ext.iterator->step))
14219 : {
14220 10 : gfc_error ("!$ACC LOOP %s loops don't form rectangular "
14221 : "iteration space at %L", clause, &do_code->loc);
14222 10 : break;
14223 : }
14224 700 : do_code2 = do_code2->block->next;
14225 : }
14226 : }
14227 5779 : if (i == collapse)
14228 : break;
14229 577 : for (c = do_code->next; c; c = c->next)
14230 48 : if (c->op != EXEC_NOP && c->op != EXEC_CONTINUE)
14231 : {
14232 0 : gfc_error ("%s !$ACC LOOP loops not perfectly nested at %L",
14233 : clause, &c->loc);
14234 0 : break;
14235 : }
14236 529 : if (c)
14237 : break;
14238 529 : do_code = do_code->block;
14239 529 : if (do_code->op != EXEC_DO && do_code->op != EXEC_DO_WHILE
14240 0 : && do_code->op != EXEC_DO_CONCURRENT)
14241 : {
14242 0 : gfc_error ("not enough DO loops for %s !$ACC LOOP at %L",
14243 : clause, &code->loc);
14244 0 : break;
14245 : }
14246 529 : do_code = do_code->next;
14247 529 : if (do_code == NULL
14248 522 : || (do_code->op != EXEC_DO && do_code->op != EXEC_DO_WHILE
14249 2 : && do_code->op != EXEC_DO_CONCURRENT))
14250 : {
14251 9 : gfc_error ("not enough DO loops for %s !$ACC LOOP at %L",
14252 : clause, &code->loc);
14253 9 : break;
14254 : }
14255 : }
14256 5272 : }
14257 :
14258 :
14259 : static void
14260 10119 : resolve_oacc_loop_blocks (gfc_code *code)
14261 : {
14262 10119 : if (!oacc_is_loop (code))
14263 : return;
14264 :
14265 5272 : if (code->ext.omp_clauses->tile_list && code->ext.omp_clauses->gang
14266 24 : && code->ext.omp_clauses->worker && code->ext.omp_clauses->vector)
14267 0 : gfc_error ("Tiled loop cannot be parallelized across gangs, workers and "
14268 : "vectors at the same time at %L", &code->loc);
14269 :
14270 5272 : if (code->ext.omp_clauses->tile_list)
14271 : {
14272 : gfc_expr_list *el;
14273 501 : for (el = code->ext.omp_clauses->tile_list; el; el = el->next)
14274 : {
14275 304 : if (el->expr == NULL)
14276 : {
14277 : /* NULL expressions are used to represent '*' arguments.
14278 : Convert those to a 0 expressions. */
14279 113 : el->expr = gfc_get_constant_expr (BT_INTEGER,
14280 : gfc_default_integer_kind,
14281 : &code->loc);
14282 113 : mpz_set_si (el->expr->value.integer, 0);
14283 : }
14284 : else
14285 191 : resolve_positive_int_expr (el->expr, "TILE", false);
14286 : }
14287 : }
14288 : }
14289 :
14290 :
14291 : void
14292 10119 : gfc_resolve_oacc_blocks (gfc_code *code, gfc_namespace *ns)
14293 : {
14294 10119 : fortran_omp_context ctx;
14295 10119 : gfc_omp_clauses *omp_clauses = code->ext.omp_clauses;
14296 10119 : gfc_omp_namelist *n;
14297 :
14298 10119 : resolve_oacc_loop_blocks (code);
14299 :
14300 10119 : ctx.code = code;
14301 10119 : ctx.sharing_clauses = new hash_set<gfc_symbol *>;
14302 10119 : ctx.private_iterators = new hash_set<gfc_symbol *>;
14303 10119 : ctx.previous = omp_current_ctx;
14304 10119 : ctx.is_openmp = false;
14305 10119 : omp_current_ctx = &ctx;
14306 :
14307 404760 : for (enum gfc_omp_list_type list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
14308 394641 : list = gfc_omp_list_type (list + 1))
14309 394641 : switch (list)
14310 : {
14311 10119 : case OMP_LIST_PRIVATE:
14312 10710 : for (n = omp_clauses->lists[list]; n; n = n->next)
14313 591 : ctx.sharing_clauses->add (n->sym);
14314 : break;
14315 : default:
14316 : break;
14317 : }
14318 :
14319 10119 : gfc_resolve_blocks (code->block, ns);
14320 :
14321 10119 : omp_current_ctx = ctx.previous;
14322 20238 : delete ctx.sharing_clauses;
14323 20238 : delete ctx.private_iterators;
14324 10119 : }
14325 :
14326 :
14327 : static void
14328 5272 : resolve_oacc_loop (gfc_code *code)
14329 : {
14330 5272 : gfc_code *do_code;
14331 5272 : int collapse;
14332 :
14333 5272 : if (code->ext.omp_clauses)
14334 5272 : resolve_omp_clauses (code, code->ext.omp_clauses, NULL, true);
14335 :
14336 5272 : do_code = code->block->next;
14337 5272 : collapse = code->ext.omp_clauses->collapse;
14338 :
14339 : /* Both collapsed and tiled loops are lowered the same way, but are not
14340 : compatible. In gfc_trans_omp_do, the tile is prioritized. */
14341 5272 : if (code->ext.omp_clauses->tile_list)
14342 : {
14343 : int num = 0;
14344 : gfc_expr_list *el;
14345 501 : for (el = code->ext.omp_clauses->tile_list; el; el = el->next)
14346 304 : ++num;
14347 197 : resolve_oacc_nested_loops (code, code->block->next, num, "tiled");
14348 197 : return;
14349 : }
14350 :
14351 5075 : if (collapse <= 0)
14352 : collapse = 1;
14353 5075 : resolve_oacc_nested_loops (code, do_code, collapse, "collapsed");
14354 : }
14355 :
14356 : void
14357 351850 : gfc_resolve_oacc_declare (gfc_namespace *ns)
14358 : {
14359 351850 : enum gfc_omp_list_type list;
14360 351850 : gfc_omp_namelist *n;
14361 351850 : gfc_oacc_declare *oc;
14362 :
14363 351850 : if (ns->oacc_declare == NULL)
14364 : return;
14365 :
14366 290 : for (oc = ns->oacc_declare; oc; oc = oc->next)
14367 : {
14368 6480 : for (list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
14369 6318 : list = gfc_omp_list_type (list + 1))
14370 6574 : for (n = oc->clauses->lists[list]; n; n = n->next)
14371 : {
14372 256 : n->sym->mark = 0;
14373 256 : if (n->sym->attr.flavor != FL_VARIABLE
14374 16 : && (n->sym->attr.flavor != FL_PROCEDURE
14375 8 : || n->sym->result != n->sym))
14376 : {
14377 14 : if (n->sym->attr.flavor != FL_PARAMETER)
14378 : {
14379 8 : gfc_error ("Object %qs is not a variable at %L",
14380 : n->sym->name, &oc->loc);
14381 8 : continue;
14382 : }
14383 : /* Note that OpenACC 3.4 permits name constants, but the
14384 : implementation is permitted to ignore the clause;
14385 : as semantically, device_resident kind of makes sense
14386 : (and the wording with it is a bit odd), the warning
14387 : is suppressed. */
14388 6 : if (list != OMP_LIST_DEVICE_RESIDENT)
14389 5 : gfc_warning (OPT_Wsurprising, "Object %qs at %L is ignored as"
14390 : " parameters need not be copied", n->sym->name,
14391 : &oc->loc);
14392 : }
14393 :
14394 248 : if (n->expr && n->expr->ref->type == REF_ARRAY)
14395 : {
14396 1 : gfc_error ("Array sections: %qs not allowed in"
14397 1 : " !$ACC DECLARE at %L", n->sym->name, &oc->loc);
14398 1 : continue;
14399 : }
14400 : }
14401 :
14402 252 : for (n = oc->clauses->lists[OMP_LIST_DEVICE_RESIDENT]; n; n = n->next)
14403 90 : check_array_not_assumed (n->sym, oc->loc, "DEVICE_RESIDENT");
14404 : }
14405 :
14406 290 : for (oc = ns->oacc_declare; oc; oc = oc->next)
14407 : {
14408 6480 : for (list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
14409 6318 : list = gfc_omp_list_type (list + 1))
14410 6574 : for (n = oc->clauses->lists[list]; n; n = n->next)
14411 : {
14412 256 : if (n->sym->mark)
14413 : {
14414 9 : gfc_error ("Symbol %qs present on multiple clauses at %L",
14415 : n->sym->name, &oc->loc);
14416 9 : continue;
14417 : }
14418 : else
14419 247 : n->sym->mark = 1;
14420 : }
14421 : }
14422 :
14423 290 : for (oc = ns->oacc_declare; oc; oc = oc->next)
14424 : {
14425 6480 : for (list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
14426 6318 : list = gfc_omp_list_type (list + 1))
14427 6574 : for (n = oc->clauses->lists[list]; n; n = n->next)
14428 256 : n->sym->mark = 0;
14429 : }
14430 : }
14431 :
14432 :
14433 : void
14434 351850 : gfc_resolve_oacc_routines (gfc_namespace *ns)
14435 : {
14436 351850 : for (gfc_oacc_routine_name *orn = ns->oacc_routine_names;
14437 351950 : orn;
14438 100 : orn = orn->next)
14439 : {
14440 100 : gfc_symbol *sym = orn->sym;
14441 100 : if (!sym->attr.external
14442 29 : && !sym->attr.function
14443 27 : && !sym->attr.subroutine)
14444 : {
14445 7 : gfc_error ("NAME %qs does not refer to a subroutine or function"
14446 : " in !$ACC ROUTINE ( NAME ) at %L", sym->name, &orn->loc);
14447 7 : continue;
14448 : }
14449 93 : if (!gfc_add_omp_declare_target (&sym->attr, sym->name, &orn->loc))
14450 : {
14451 20 : gfc_error ("NAME %qs invalid"
14452 : " in !$ACC ROUTINE ( NAME ) at %L", sym->name, &orn->loc);
14453 20 : continue;
14454 : }
14455 : }
14456 351850 : }
14457 :
14458 :
14459 : void
14460 13538 : gfc_resolve_oacc_directive (gfc_code *code, gfc_namespace *ns ATTRIBUTE_UNUSED)
14461 : {
14462 13538 : resolve_oacc_directive_inside_omp_region (code);
14463 :
14464 13538 : switch (code->op)
14465 : {
14466 7723 : case EXEC_OACC_PARALLEL:
14467 7723 : case EXEC_OACC_KERNELS:
14468 7723 : case EXEC_OACC_SERIAL:
14469 7723 : case EXEC_OACC_DATA:
14470 7723 : case EXEC_OACC_HOST_DATA:
14471 7723 : case EXEC_OACC_UPDATE:
14472 7723 : case EXEC_OACC_ENTER_DATA:
14473 7723 : case EXEC_OACC_EXIT_DATA:
14474 7723 : case EXEC_OACC_WAIT:
14475 7723 : case EXEC_OACC_CACHE:
14476 7723 : case EXEC_OACC_INIT:
14477 7723 : case EXEC_OACC_SHUTDOWN:
14478 7723 : case EXEC_OACC_SET:
14479 7723 : resolve_omp_clauses (code, code->ext.omp_clauses, NULL, true);
14480 7723 : break;
14481 5272 : case EXEC_OACC_PARALLEL_LOOP:
14482 5272 : case EXEC_OACC_KERNELS_LOOP:
14483 5272 : case EXEC_OACC_SERIAL_LOOP:
14484 5272 : case EXEC_OACC_LOOP:
14485 5272 : resolve_oacc_loop (code);
14486 5272 : break;
14487 543 : case EXEC_OACC_ATOMIC:
14488 543 : resolve_omp_atomic (code);
14489 543 : break;
14490 : default:
14491 : break;
14492 : }
14493 13538 : }
14494 :
14495 :
14496 : static void
14497 2190 : resolve_omp_target (gfc_code *code)
14498 : {
14499 : #define GFC_IS_TEAMS_CONSTRUCT(op) \
14500 : (op == EXEC_OMP_TEAMS \
14501 : || op == EXEC_OMP_TEAMS_DISTRIBUTE \
14502 : || op == EXEC_OMP_TEAMS_DISTRIBUTE_SIMD \
14503 : || op == EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO \
14504 : || op == EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD \
14505 : || op == EXEC_OMP_TEAMS_LOOP)
14506 :
14507 2190 : if (!code->ext.omp_clauses->contains_teams_construct)
14508 : return;
14509 204 : gfc_code *c = code->block->next;
14510 204 : if (c->op == EXEC_BLOCK)
14511 30 : c = c->ext.block.ns->code;
14512 204 : if (code->ext.omp_clauses->target_first_st_is_teams_or_meta)
14513 : {
14514 193 : if (c->op == EXEC_OMP_METADIRECTIVE)
14515 : {
14516 16 : struct gfc_omp_variant *mc
14517 : = c->ext.omp_variants;
14518 : /* All mc->(next...->)code should be identical with regards
14519 : to the diagnostic below. */
14520 17 : do
14521 : {
14522 17 : if (mc->stmt != ST_NONE
14523 16 : && GFC_IS_TEAMS_CONSTRUCT (mc->code->op))
14524 : {
14525 15 : if (c->next == NULL && mc->code->next == NULL)
14526 : return;
14527 23 : c = mc->code;
14528 : break;
14529 : }
14530 2 : mc = mc->next;
14531 : }
14532 2 : while (mc);
14533 : }
14534 177 : else if (GFC_IS_TEAMS_CONSTRUCT (c->op) && c->next == NULL)
14535 : return;
14536 : }
14537 :
14538 31 : while (c && !GFC_IS_TEAMS_CONSTRUCT (c->op))
14539 8 : c = c->next;
14540 23 : if (c)
14541 19 : gfc_error ("!$OMP TARGET region at %L with a nested TEAMS at %L may not "
14542 : "contain any other statement, declaration or directive outside "
14543 : "of the single TEAMS construct", &c->loc, &code->loc);
14544 : else
14545 4 : gfc_error ("!$OMP TARGET region at %L with a nested TEAMS may not "
14546 : "contain any other statement, declaration or directive outside "
14547 : "of the single TEAMS construct", &code->loc);
14548 : #undef GFC_IS_TEAMS_CONSTRUCT
14549 : }
14550 :
14551 : static void
14552 154 : resolve_omp_dispatch (gfc_code *code)
14553 : {
14554 154 : gfc_code *next = code->block->next;
14555 154 : if (next == NULL)
14556 : return;
14557 :
14558 151 : gfc_exec_op op = next->op;
14559 151 : gcc_assert (op == EXEC_CALL || op == EXEC_ASSIGN);
14560 151 : if (op != EXEC_CALL
14561 74 : && (op != EXEC_ASSIGN || next->expr2->expr_type != EXPR_FUNCTION))
14562 3 : gfc_error (
14563 : "%<OMP DISPATCH%> directive at %L must be followed by a procedure "
14564 : "call with optional assignment",
14565 : &code->loc);
14566 :
14567 77 : if ((op == EXEC_CALL && next->resolved_sym != NULL
14568 76 : && next->resolved_sym->attr.proc_pointer)
14569 151 : || (op == EXEC_ASSIGN && gfc_expr_attr (next->expr2).proc_pointer))
14570 1 : gfc_error ("%<OMP DISPATCH%> directive at %L cannot be followed by a "
14571 : "procedure pointer",
14572 : &code->loc);
14573 : }
14574 :
14575 : /* Resolve OpenMP directive clauses and check various requirements
14576 : of each directive. */
14577 :
14578 : void
14579 21385 : gfc_resolve_omp_directive (gfc_code *code, gfc_namespace *ns)
14580 : {
14581 21385 : resolve_omp_directive_inside_oacc_region (code);
14582 :
14583 21385 : if (code->op != EXEC_OMP_ATOMIC)
14584 19218 : gfc_maybe_initialize_eh ();
14585 :
14586 21385 : switch (code->op)
14587 : {
14588 5463 : case EXEC_OMP_DISTRIBUTE:
14589 5463 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
14590 5463 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
14591 5463 : case EXEC_OMP_DISTRIBUTE_SIMD:
14592 5463 : case EXEC_OMP_DO:
14593 5463 : case EXEC_OMP_DO_SIMD:
14594 5463 : case EXEC_OMP_LOOP:
14595 5463 : case EXEC_OMP_PARALLEL_DO:
14596 5463 : case EXEC_OMP_PARALLEL_DO_SIMD:
14597 5463 : case EXEC_OMP_PARALLEL_LOOP:
14598 5463 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
14599 5463 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
14600 5463 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
14601 5463 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
14602 5463 : case EXEC_OMP_MASKED_TASKLOOP:
14603 5463 : case EXEC_OMP_MASKED_TASKLOOP_SIMD:
14604 5463 : case EXEC_OMP_MASTER_TASKLOOP:
14605 5463 : case EXEC_OMP_MASTER_TASKLOOP_SIMD:
14606 5463 : case EXEC_OMP_SIMD:
14607 5463 : case EXEC_OMP_TARGET_PARALLEL_DO:
14608 5463 : case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
14609 5463 : case EXEC_OMP_TARGET_PARALLEL_LOOP:
14610 5463 : case EXEC_OMP_TARGET_SIMD:
14611 5463 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
14612 5463 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
14613 5463 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
14614 5463 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
14615 5463 : case EXEC_OMP_TARGET_TEAMS_LOOP:
14616 5463 : case EXEC_OMP_TASKLOOP:
14617 5463 : case EXEC_OMP_TASKLOOP_SIMD:
14618 5463 : case EXEC_OMP_TEAMS_DISTRIBUTE:
14619 5463 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
14620 5463 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
14621 5463 : case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
14622 5463 : case EXEC_OMP_TEAMS_LOOP:
14623 5463 : case EXEC_OMP_TILE:
14624 5463 : case EXEC_OMP_UNROLL:
14625 5463 : resolve_omp_do (code);
14626 5463 : break;
14627 2190 : case EXEC_OMP_TARGET:
14628 2190 : resolve_omp_target (code);
14629 10336 : gcc_fallthrough ();
14630 10336 : case EXEC_OMP_ALLOCATE:
14631 10336 : case EXEC_OMP_ALLOCATORS:
14632 10336 : case EXEC_OMP_ASSUME:
14633 10336 : case EXEC_OMP_CANCEL:
14634 10336 : case EXEC_OMP_ERROR:
14635 10336 : case EXEC_OMP_INTEROP:
14636 10336 : case EXEC_OMP_MASKED:
14637 10336 : case EXEC_OMP_ORDERED:
14638 10336 : case EXEC_OMP_PARALLEL_WORKSHARE:
14639 10336 : case EXEC_OMP_PARALLEL:
14640 10336 : case EXEC_OMP_PARALLEL_MASKED:
14641 10336 : case EXEC_OMP_PARALLEL_MASTER:
14642 10336 : case EXEC_OMP_PARALLEL_SECTIONS:
14643 10336 : case EXEC_OMP_SCOPE:
14644 10336 : case EXEC_OMP_SECTIONS:
14645 10336 : case EXEC_OMP_SINGLE:
14646 10336 : case EXEC_OMP_TARGET_DATA:
14647 10336 : case EXEC_OMP_TARGET_ENTER_DATA:
14648 10336 : case EXEC_OMP_TARGET_EXIT_DATA:
14649 10336 : case EXEC_OMP_TARGET_PARALLEL:
14650 10336 : case EXEC_OMP_TARGET_TEAMS:
14651 10336 : case EXEC_OMP_TASK:
14652 10336 : case EXEC_OMP_TASKWAIT:
14653 10336 : case EXEC_OMP_TEAMS:
14654 10336 : case EXEC_OMP_WORKSHARE:
14655 10336 : case EXEC_OMP_DEPOBJ:
14656 10336 : if (code->ext.omp_clauses)
14657 10195 : resolve_omp_clauses (code, code->ext.omp_clauses, NULL);
14658 : break;
14659 1720 : case EXEC_OMP_TARGET_UPDATE:
14660 1720 : if (code->ext.omp_clauses)
14661 1720 : resolve_omp_clauses (code, code->ext.omp_clauses, NULL);
14662 1720 : if (code->ext.omp_clauses == NULL
14663 1720 : || (code->ext.omp_clauses->lists[OMP_LIST_TO] == NULL
14664 996 : && code->ext.omp_clauses->lists[OMP_LIST_FROM] == NULL))
14665 0 : gfc_error ("OMP TARGET UPDATE at %L requires at least one TO or "
14666 : "FROM clause", &code->loc);
14667 : break;
14668 2167 : case EXEC_OMP_ATOMIC:
14669 2167 : resolve_omp_clauses (code, code->block->ext.omp_clauses, NULL);
14670 2167 : resolve_omp_atomic (code);
14671 2167 : break;
14672 165 : case EXEC_OMP_CRITICAL:
14673 165 : resolve_omp_clauses (code, code->ext.omp_clauses, NULL);
14674 165 : if (!code->ext.omp_clauses->critical_name
14675 114 : && code->ext.omp_clauses->hint
14676 5 : && code->ext.omp_clauses->hint->ts.type == BT_INTEGER
14677 5 : && code->ext.omp_clauses->hint->expr_type == EXPR_CONSTANT
14678 5 : && mpz_sgn (code->ext.omp_clauses->hint->value.integer) != 0)
14679 1 : gfc_error ("OMP CRITICAL at %L with HINT clause requires a NAME, "
14680 : "except when omp_sync_hint_none is used", &code->loc);
14681 : break;
14682 49 : case EXEC_OMP_SCAN:
14683 : /* Flag is only used to checking, hence, it is unset afterwards. */
14684 49 : if (!code->ext.omp_clauses->if_present)
14685 10 : gfc_error ("Unexpected !$OMP SCAN at %L outside loop construct with "
14686 : "%<inscan%> REDUCTION clause", &code->loc);
14687 49 : code->ext.omp_clauses->if_present = false;
14688 49 : resolve_omp_clauses (code, code->ext.omp_clauses, ns);
14689 49 : break;
14690 154 : case EXEC_OMP_DISPATCH:
14691 154 : if (code->ext.omp_clauses)
14692 154 : resolve_omp_clauses (code, code->ext.omp_clauses, ns);
14693 154 : resolve_omp_dispatch (code);
14694 154 : break;
14695 146 : case EXEC_OMP_METADIRECTIVE:
14696 146 : resolve_omp_metadirective (code, ns);
14697 146 : break;
14698 : default:
14699 : break;
14700 : }
14701 21385 : }
14702 :
14703 : /* Resolve !$omp declare {variant|simd} constructs in NS.
14704 : Note that !$omp declare target is resolved in resolve_symbol. */
14705 :
14706 : void
14707 364147 : gfc_resolve_omp_declare (gfc_namespace *ns)
14708 : {
14709 364147 : gfc_omp_declare_simd *ods;
14710 364399 : for (ods = ns->omp_declare_simd; ods; ods = ods->next)
14711 : {
14712 252 : if (ods->proc_name != NULL
14713 197 : && ods->proc_name != ns->proc_name)
14714 6 : gfc_error ("!$OMP DECLARE SIMD should refer to containing procedure "
14715 : "%qs at %L", ns->proc_name->name, &ods->where);
14716 252 : if (ods->clauses)
14717 252 : resolve_omp_clauses (NULL, ods->clauses, ns);
14718 : }
14719 :
14720 364147 : gfc_omp_declare_variant *odv;
14721 364147 : gfc_omp_namelist *range_begin = NULL;
14722 :
14723 364624 : for (odv = ns->omp_declare_variant; odv; odv = odv->next)
14724 477 : gfc_resolve_omp_context_selector (odv->set_selectors, false, nullptr);
14725 364624 : for (odv = ns->omp_declare_variant; odv; odv = odv->next)
14726 680 : for (gfc_omp_namelist *n = odv->adjust_args_list; n != NULL; n = n->next)
14727 : {
14728 203 : if ((n->expr == NULL
14729 6 : && (range_begin
14730 4 : || n->u.adj_args.range_start
14731 1 : || n->u.adj_args.omp_num_args_plus
14732 1 : || n->u.adj_args.omp_num_args_minus))
14733 198 : || n->u.adj_args.error_p)
14734 : {
14735 : }
14736 197 : else if (range_begin
14737 191 : || n->u.adj_args.range_start
14738 186 : || n->u.adj_args.omp_num_args_plus
14739 186 : || n->u.adj_args.omp_num_args_minus)
14740 : {
14741 11 : if (!n->expr
14742 11 : || !gfc_resolve_expr (n->expr)
14743 11 : || n->expr->expr_type != EXPR_CONSTANT
14744 10 : || n->expr->ts.type != BT_INTEGER
14745 10 : || n->expr->rank != 0
14746 10 : || mpz_sgn (n->expr->value.integer) < 0
14747 20 : || ((n->u.adj_args.omp_num_args_plus
14748 8 : || n->u.adj_args.omp_num_args_minus)
14749 5 : && mpz_sgn (n->expr->value.integer) == 0))
14750 : {
14751 2 : if (n->u.adj_args.omp_num_args_plus
14752 2 : || n->u.adj_args.omp_num_args_minus)
14753 0 : gfc_error ("Expected constant non-negative scalar integer "
14754 : "offset expression at %L", &n->where);
14755 : else
14756 2 : gfc_error ("For range-based %<adjust_args%>, a constant "
14757 : "positive scalar integer expression is required "
14758 : "at %L", &n->where);
14759 : }
14760 : }
14761 186 : else if (n->expr
14762 186 : && n->expr->expr_type == EXPR_CONSTANT
14763 21 : && n->expr->ts.type == BT_INTEGER
14764 20 : && mpz_sgn (n->expr->value.integer) > 0)
14765 : {
14766 : }
14767 166 : else if (!n->expr
14768 166 : || !gfc_resolve_expr (n->expr)
14769 331 : || n->expr->expr_type != EXPR_VARIABLE)
14770 2 : gfc_error ("Expected dummy parameter name or a positive integer "
14771 : "at %L", &n->where);
14772 164 : else if (n->expr->expr_type == EXPR_VARIABLE)
14773 164 : n->sym = n->expr->symtree->n.sym;
14774 :
14775 203 : range_begin = n->u.adj_args.range_start ? n : NULL;
14776 : }
14777 364147 : }
14778 :
14779 : struct omp_udr_callback_data
14780 : {
14781 : gfc_omp_udr *omp_udr;
14782 : bool is_initializer;
14783 : };
14784 :
14785 : static int
14786 3746 : omp_udr_callback (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
14787 : void *data)
14788 : {
14789 3746 : struct omp_udr_callback_data *cd = (struct omp_udr_callback_data *) data;
14790 3746 : if ((*e)->expr_type == EXPR_VARIABLE)
14791 : {
14792 2303 : if (cd->is_initializer)
14793 : {
14794 545 : if ((*e)->symtree->n.sym != cd->omp_udr->omp_priv
14795 140 : && (*e)->symtree->n.sym != cd->omp_udr->omp_orig)
14796 4 : gfc_error ("Variable other than OMP_PRIV or OMP_ORIG used in "
14797 : "INITIALIZER clause of !$OMP DECLARE REDUCTION at %L",
14798 : &(*e)->where);
14799 : }
14800 : else
14801 : {
14802 1758 : if ((*e)->symtree->n.sym != cd->omp_udr->omp_out
14803 626 : && (*e)->symtree->n.sym != cd->omp_udr->omp_in)
14804 6 : gfc_error ("Variable other than OMP_OUT or OMP_IN used in "
14805 : "combiner of !$OMP DECLARE REDUCTION at %L",
14806 : &(*e)->where);
14807 : }
14808 : }
14809 3746 : return 0;
14810 : }
14811 :
14812 : /* Resolve !$omp declare reduction constructs. */
14813 :
14814 : static void
14815 633 : gfc_resolve_omp_udr (gfc_omp_udr *omp_udr)
14816 : {
14817 633 : gfc_actual_arglist *a;
14818 633 : const char *predef_name = NULL;
14819 :
14820 633 : switch (omp_udr->rop)
14821 : {
14822 632 : case OMP_REDUCTION_PLUS:
14823 632 : case OMP_REDUCTION_TIMES:
14824 632 : case OMP_REDUCTION_MINUS:
14825 632 : case OMP_REDUCTION_AND:
14826 632 : case OMP_REDUCTION_OR:
14827 632 : case OMP_REDUCTION_EQV:
14828 632 : case OMP_REDUCTION_NEQV:
14829 632 : case OMP_REDUCTION_MAX:
14830 632 : case OMP_REDUCTION_USER:
14831 632 : break;
14832 1 : default:
14833 1 : gfc_error ("Invalid operator for !$OMP DECLARE REDUCTION %s at %L",
14834 : omp_udr->name, &omp_udr->where);
14835 26 : return;
14836 : }
14837 :
14838 632 : if (gfc_omp_udr_predef (omp_udr->rop, omp_udr->name,
14839 : &omp_udr->ts, &predef_name))
14840 : {
14841 19 : if (predef_name)
14842 19 : gfc_error ("Redefinition of predefined %qs in "
14843 : "!$OMP DECLARE REDUCTION at %L",
14844 : predef_name, &omp_udr->where);
14845 : else
14846 0 : gfc_error ("Redefinition of predefined %qs in "
14847 : "!$OMP DECLARE REDUCTION at %L", omp_udr->name,
14848 : &omp_udr->where);
14849 : return;
14850 : }
14851 :
14852 613 : if (omp_udr->ts.type == BT_CHARACTER
14853 62 : && omp_udr->ts.u.cl->length
14854 32 : && omp_udr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
14855 : {
14856 1 : gfc_error ("CHARACTER length in !$OMP DECLARE REDUCTION %qs not "
14857 : "constant at %L", omp_udr->name, &omp_udr->where);
14858 1 : return;
14859 : }
14860 :
14861 612 : struct omp_udr_callback_data cd;
14862 612 : cd.omp_udr = omp_udr;
14863 612 : cd.is_initializer = false;
14864 612 : gfc_code_walker (&omp_udr->combiner_ns->code, gfc_dummy_code_callback,
14865 : omp_udr_callback, &cd);
14866 612 : if (omp_udr->combiner_ns->code->op == EXEC_CALL)
14867 : {
14868 346 : for (a = omp_udr->combiner_ns->code->ext.actual; a; a = a->next)
14869 237 : if (a->expr == NULL)
14870 : break;
14871 110 : if (a)
14872 1 : gfc_error ("Subroutine call with alternate returns in combiner "
14873 : "of !$OMP DECLARE REDUCTION at %L",
14874 : &omp_udr->combiner_ns->code->loc);
14875 : }
14876 612 : if (omp_udr->initializer_ns)
14877 : {
14878 383 : cd.is_initializer = true;
14879 383 : gfc_code_walker (&omp_udr->initializer_ns->code, gfc_dummy_code_callback,
14880 : omp_udr_callback, &cd);
14881 383 : if (omp_udr->initializer_ns->code->op == EXEC_CALL)
14882 : {
14883 377 : for (a = omp_udr->initializer_ns->code->ext.actual; a; a = a->next)
14884 243 : if (a->expr == NULL)
14885 : break;
14886 135 : if (a)
14887 1 : gfc_error ("Subroutine call with alternate returns in "
14888 : "INITIALIZER clause of !$OMP DECLARE REDUCTION "
14889 : "at %L", &omp_udr->initializer_ns->code->loc);
14890 136 : for (a = omp_udr->initializer_ns->code->ext.actual; a; a = a->next)
14891 135 : if (a->expr
14892 135 : && a->expr->expr_type == EXPR_VARIABLE
14893 135 : && a->expr->symtree->n.sym == omp_udr->omp_priv
14894 134 : && a->expr->ref == NULL)
14895 : break;
14896 135 : if (a == NULL)
14897 1 : gfc_error ("One of actual subroutine arguments in INITIALIZER "
14898 : "clause of !$OMP DECLARE REDUCTION must be OMP_PRIV "
14899 : "at %L", &omp_udr->initializer_ns->code->loc);
14900 : }
14901 : }
14902 229 : else if (omp_udr->ts.type == BT_DERIVED
14903 229 : && !gfc_has_default_initializer (omp_udr->ts.u.derived))
14904 : {
14905 4 : gfc_error ("Missing INITIALIZER clause for !$OMP DECLARE REDUCTION "
14906 : "of derived type without default initializer at %L",
14907 : &omp_udr->where);
14908 4 : return;
14909 : }
14910 : }
14911 :
14912 : void
14913 365215 : gfc_resolve_omp_udrs (gfc_symtree *st)
14914 : {
14915 365215 : gfc_omp_udr *omp_udr;
14916 :
14917 365215 : if (st == NULL)
14918 : return;
14919 534 : gfc_resolve_omp_udrs (st->left);
14920 534 : gfc_resolve_omp_udrs (st->right);
14921 1167 : for (omp_udr = st->n.omp_udr; omp_udr; omp_udr = omp_udr->next)
14922 633 : gfc_resolve_omp_udr (omp_udr);
14923 : }
14924 :
14925 : /* Resolve !$omp declare mapper constructs. */
14926 :
14927 : static void
14928 30 : gfc_resolve_omp_udm (gfc_omp_udm *omp_udm)
14929 : {
14930 30 : resolve_omp_clauses (NULL, omp_udm->clauses, omp_udm->mapper_ns);
14931 :
14932 30 : gfc_omp_namelist *n;
14933 32 : for (n = omp_udm->clauses->lists[OMP_LIST_MAP]; n; n = n->next)
14934 30 : if (n->sym == omp_udm->var_sym)
14935 : break;
14936 30 : if (!n)
14937 2 : gfc_error ("At least one %<map%> clause in !$OMP DECLARE MAPPER at %L must "
14938 : "map %qs or an element of it",
14939 2 : &omp_udm->where, omp_udm->var_sym->name);
14940 30 : }
14941 :
14942 : void
14943 364205 : gfc_resolve_omp_udms (gfc_symtree *st)
14944 : {
14945 364205 : gfc_omp_udm *omp_udm;
14946 :
14947 364205 : if (st == NULL)
14948 : return;
14949 29 : gfc_resolve_omp_udms (st->left);
14950 29 : gfc_resolve_omp_udms (st->right);
14951 59 : for (omp_udm = st->n.omp_udm; omp_udm; omp_udm = omp_udm->next)
14952 30 : gfc_resolve_omp_udm (omp_udm);
14953 : }
|