1 /* OpenMP directive matching and resolving.
2 Copyright (C) 2005-2020 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 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "gfortran.h"
25 #include "arith.h"
26 #include "match.h"
27 #include "parse.h"
28 #include "diagnostic.h"
29 #include "gomp-constants.h"
30
31 /* Match an end of OpenMP directive. End of OpenMP directive is optional
32 whitespace, followed by '\n' or comment '!'. */
33
34 static match
gfc_match_omp_eos(void)35 gfc_match_omp_eos (void)
36 {
37 locus old_loc;
38 char c;
39
40 old_loc = gfc_current_locus;
41 gfc_gobble_whitespace ();
42
43 c = gfc_next_ascii_char ();
44 switch (c)
45 {
46 case '!':
47 do
48 c = gfc_next_ascii_char ();
49 while (c != '\n');
50 /* Fall through */
51
52 case '\n':
53 return MATCH_YES;
54 }
55
56 gfc_current_locus = old_loc;
57 return MATCH_NO;
58 }
59
60 match
gfc_match_omp_eos_error(void)61 gfc_match_omp_eos_error (void)
62 {
63 if (gfc_match_omp_eos() == MATCH_YES)
64 return MATCH_YES;
65
66 gfc_error ("Unexpected junk at %C");
67 return MATCH_ERROR;
68 }
69
70
71 /* Free an omp_clauses structure. */
72
73 void
gfc_free_omp_clauses(gfc_omp_clauses * c)74 gfc_free_omp_clauses (gfc_omp_clauses *c)
75 {
76 int i;
77 if (c == NULL)
78 return;
79
80 gfc_free_expr (c->if_expr);
81 gfc_free_expr (c->final_expr);
82 gfc_free_expr (c->num_threads);
83 gfc_free_expr (c->chunk_size);
84 gfc_free_expr (c->safelen_expr);
85 gfc_free_expr (c->simdlen_expr);
86 gfc_free_expr (c->num_teams);
87 gfc_free_expr (c->device);
88 gfc_free_expr (c->thread_limit);
89 gfc_free_expr (c->dist_chunk_size);
90 gfc_free_expr (c->grainsize);
91 gfc_free_expr (c->hint);
92 gfc_free_expr (c->num_tasks);
93 gfc_free_expr (c->priority);
94 for (i = 0; i < OMP_IF_LAST; i++)
95 gfc_free_expr (c->if_exprs[i]);
96 gfc_free_expr (c->async_expr);
97 gfc_free_expr (c->gang_num_expr);
98 gfc_free_expr (c->gang_static_expr);
99 gfc_free_expr (c->worker_expr);
100 gfc_free_expr (c->vector_expr);
101 gfc_free_expr (c->num_gangs_expr);
102 gfc_free_expr (c->num_workers_expr);
103 gfc_free_expr (c->vector_length_expr);
104 for (i = 0; i < OMP_LIST_NUM; i++)
105 gfc_free_omp_namelist (c->lists[i]);
106 gfc_free_expr_list (c->wait_list);
107 gfc_free_expr_list (c->tile_list);
108 free (CONST_CAST (char *, c->critical_name));
109 free (c);
110 }
111
112 /* Free oacc_declare structures. */
113
114 void
gfc_free_oacc_declare_clauses(struct gfc_oacc_declare * oc)115 gfc_free_oacc_declare_clauses (struct gfc_oacc_declare *oc)
116 {
117 struct gfc_oacc_declare *decl = oc;
118
119 do
120 {
121 struct gfc_oacc_declare *next;
122
123 next = decl->next;
124 gfc_free_omp_clauses (decl->clauses);
125 free (decl);
126 decl = next;
127 }
128 while (decl);
129 }
130
131 /* Free expression list. */
132 void
gfc_free_expr_list(gfc_expr_list * list)133 gfc_free_expr_list (gfc_expr_list *list)
134 {
135 gfc_expr_list *n;
136
137 for (; list; list = n)
138 {
139 n = list->next;
140 free (list);
141 }
142 }
143
144 /* Free an !$omp declare simd construct list. */
145
146 void
gfc_free_omp_declare_simd(gfc_omp_declare_simd * ods)147 gfc_free_omp_declare_simd (gfc_omp_declare_simd *ods)
148 {
149 if (ods)
150 {
151 gfc_free_omp_clauses (ods->clauses);
152 free (ods);
153 }
154 }
155
156 void
gfc_free_omp_declare_simd_list(gfc_omp_declare_simd * list)157 gfc_free_omp_declare_simd_list (gfc_omp_declare_simd *list)
158 {
159 while (list)
160 {
161 gfc_omp_declare_simd *current = list;
162 list = list->next;
163 gfc_free_omp_declare_simd (current);
164 }
165 }
166
167 /* Free an !$omp declare reduction. */
168
169 void
gfc_free_omp_udr(gfc_omp_udr * omp_udr)170 gfc_free_omp_udr (gfc_omp_udr *omp_udr)
171 {
172 if (omp_udr)
173 {
174 gfc_free_omp_udr (omp_udr->next);
175 gfc_free_namespace (omp_udr->combiner_ns);
176 if (omp_udr->initializer_ns)
177 gfc_free_namespace (omp_udr->initializer_ns);
178 free (omp_udr);
179 }
180 }
181
182
183 static gfc_omp_udr *
gfc_find_omp_udr(gfc_namespace * ns,const char * name,gfc_typespec * ts)184 gfc_find_omp_udr (gfc_namespace *ns, const char *name, gfc_typespec *ts)
185 {
186 gfc_symtree *st;
187
188 if (ns == NULL)
189 ns = gfc_current_ns;
190 do
191 {
192 gfc_omp_udr *omp_udr;
193
194 st = gfc_find_symtree (ns->omp_udr_root, name);
195 if (st != NULL)
196 {
197 for (omp_udr = st->n.omp_udr; omp_udr; omp_udr = omp_udr->next)
198 if (ts == NULL)
199 return omp_udr;
200 else if (gfc_compare_types (&omp_udr->ts, ts))
201 {
202 if (ts->type == BT_CHARACTER)
203 {
204 if (omp_udr->ts.u.cl->length == NULL)
205 return omp_udr;
206 if (ts->u.cl->length == NULL)
207 continue;
208 if (gfc_compare_expr (omp_udr->ts.u.cl->length,
209 ts->u.cl->length,
210 INTRINSIC_EQ) != 0)
211 continue;
212 }
213 return omp_udr;
214 }
215 }
216
217 /* Don't escape an interface block. */
218 if (ns && !ns->has_import_set
219 && ns->proc_name && ns->proc_name->attr.if_source == IFSRC_IFBODY)
220 break;
221
222 ns = ns->parent;
223 }
224 while (ns != NULL);
225
226 return NULL;
227 }
228
229
230 /* Match a variable/common block list and construct a namelist from it. */
231
232 static match
233 gfc_match_omp_variable_list (const char *str, gfc_omp_namelist **list,
234 bool allow_common, bool *end_colon = NULL,
235 gfc_omp_namelist ***headp = NULL,
236 bool allow_sections = false,
237 bool allow_derived = false)
238 {
239 gfc_omp_namelist *head, *tail, *p;
240 locus old_loc, cur_loc;
241 char n[GFC_MAX_SYMBOL_LEN+1];
242 gfc_symbol *sym;
243 match m;
244 gfc_symtree *st;
245
246 head = tail = NULL;
247
248 old_loc = gfc_current_locus;
249
250 m = gfc_match (str);
251 if (m != MATCH_YES)
252 return m;
253
254 for (;;)
255 {
256 cur_loc = gfc_current_locus;
257 m = gfc_match_symbol (&sym, 1);
258 switch (m)
259 {
260 case MATCH_YES:
261 gfc_expr *expr;
262 expr = NULL;
263 if ((allow_sections && gfc_peek_ascii_char () == '(')
264 || (allow_derived && gfc_peek_ascii_char () == '%'))
265 {
266 gfc_current_locus = cur_loc;
267 m = gfc_match_variable (&expr, 0);
268 switch (m)
269 {
270 case MATCH_ERROR:
271 goto cleanup;
272 case MATCH_NO:
273 goto syntax;
274 default:
275 break;
276 }
277 if (gfc_is_coindexed (expr))
278 {
279 gfc_error ("List item shall not be coindexed at %C");
280 goto cleanup;
281 }
282 }
283 gfc_set_sym_referenced (sym);
284 p = gfc_get_omp_namelist ();
285 if (head == NULL)
286 head = tail = p;
287 else
288 {
289 tail->next = p;
290 tail = tail->next;
291 }
292 tail->sym = sym;
293 tail->expr = expr;
294 tail->where = cur_loc;
295 goto next_item;
296 case MATCH_NO:
297 break;
298 case MATCH_ERROR:
299 goto cleanup;
300 }
301
302 if (!allow_common)
303 goto syntax;
304
305 m = gfc_match (" / %n /", n);
306 if (m == MATCH_ERROR)
307 goto cleanup;
308 if (m == MATCH_NO)
309 goto syntax;
310
311 st = gfc_find_symtree (gfc_current_ns->common_root, n);
312 if (st == NULL)
313 {
314 gfc_error ("COMMON block /%s/ not found at %C", n);
315 goto cleanup;
316 }
317 for (sym = st->n.common->head; sym; sym = sym->common_next)
318 {
319 gfc_set_sym_referenced (sym);
320 p = gfc_get_omp_namelist ();
321 if (head == NULL)
322 head = tail = p;
323 else
324 {
325 tail->next = p;
326 tail = tail->next;
327 }
328 tail->sym = sym;
329 tail->where = cur_loc;
330 }
331
332 next_item:
333 if (end_colon && gfc_match_char (':') == MATCH_YES)
334 {
335 *end_colon = true;
336 break;
337 }
338 if (gfc_match_char (')') == MATCH_YES)
339 break;
340 if (gfc_match_char (',') != MATCH_YES)
341 goto syntax;
342 }
343
344 while (*list)
345 list = &(*list)->next;
346
347 *list = head;
348 if (headp)
349 *headp = list;
350 return MATCH_YES;
351
352 syntax:
353 gfc_error ("Syntax error in OpenMP variable list at %C");
354
355 cleanup:
356 gfc_free_omp_namelist (head);
357 gfc_current_locus = old_loc;
358 return MATCH_ERROR;
359 }
360
361 /* Match a variable/procedure/common block list and construct a namelist
362 from it. */
363
364 static match
gfc_match_omp_to_link(const char * str,gfc_omp_namelist ** list)365 gfc_match_omp_to_link (const char *str, gfc_omp_namelist **list)
366 {
367 gfc_omp_namelist *head, *tail, *p;
368 locus old_loc, cur_loc;
369 char n[GFC_MAX_SYMBOL_LEN+1];
370 gfc_symbol *sym;
371 match m;
372 gfc_symtree *st;
373
374 head = tail = NULL;
375
376 old_loc = gfc_current_locus;
377
378 m = gfc_match (str);
379 if (m != MATCH_YES)
380 return m;
381
382 for (;;)
383 {
384 cur_loc = gfc_current_locus;
385 m = gfc_match_symbol (&sym, 1);
386 switch (m)
387 {
388 case MATCH_YES:
389 p = gfc_get_omp_namelist ();
390 if (head == NULL)
391 head = tail = p;
392 else
393 {
394 tail->next = p;
395 tail = tail->next;
396 }
397 tail->sym = sym;
398 tail->where = cur_loc;
399 goto next_item;
400 case MATCH_NO:
401 break;
402 case MATCH_ERROR:
403 goto cleanup;
404 }
405
406 m = gfc_match (" / %n /", n);
407 if (m == MATCH_ERROR)
408 goto cleanup;
409 if (m == MATCH_NO)
410 goto syntax;
411
412 st = gfc_find_symtree (gfc_current_ns->common_root, n);
413 if (st == NULL)
414 {
415 gfc_error ("COMMON block /%s/ not found at %C", n);
416 goto cleanup;
417 }
418 p = gfc_get_omp_namelist ();
419 if (head == NULL)
420 head = tail = p;
421 else
422 {
423 tail->next = p;
424 tail = tail->next;
425 }
426 tail->u.common = st->n.common;
427 tail->where = cur_loc;
428
429 next_item:
430 if (gfc_match_char (')') == MATCH_YES)
431 break;
432 if (gfc_match_char (',') != MATCH_YES)
433 goto syntax;
434 }
435
436 while (*list)
437 list = &(*list)->next;
438
439 *list = head;
440 return MATCH_YES;
441
442 syntax:
443 gfc_error ("Syntax error in OpenMP variable list at %C");
444
445 cleanup:
446 gfc_free_omp_namelist (head);
447 gfc_current_locus = old_loc;
448 return MATCH_ERROR;
449 }
450
451 /* Match depend(sink : ...) construct a namelist from it. */
452
453 static match
gfc_match_omp_depend_sink(gfc_omp_namelist ** list)454 gfc_match_omp_depend_sink (gfc_omp_namelist **list)
455 {
456 gfc_omp_namelist *head, *tail, *p;
457 locus old_loc, cur_loc;
458 gfc_symbol *sym;
459
460 head = tail = NULL;
461
462 old_loc = gfc_current_locus;
463
464 for (;;)
465 {
466 cur_loc = gfc_current_locus;
467 switch (gfc_match_symbol (&sym, 1))
468 {
469 case MATCH_YES:
470 gfc_set_sym_referenced (sym);
471 p = gfc_get_omp_namelist ();
472 if (head == NULL)
473 {
474 head = tail = p;
475 head->u.depend_op = OMP_DEPEND_SINK_FIRST;
476 }
477 else
478 {
479 tail->next = p;
480 tail = tail->next;
481 tail->u.depend_op = OMP_DEPEND_SINK;
482 }
483 tail->sym = sym;
484 tail->expr = NULL;
485 tail->where = cur_loc;
486 if (gfc_match_char ('+') == MATCH_YES)
487 {
488 if (gfc_match_literal_constant (&tail->expr, 0) != MATCH_YES)
489 goto syntax;
490 }
491 else if (gfc_match_char ('-') == MATCH_YES)
492 {
493 if (gfc_match_literal_constant (&tail->expr, 0) != MATCH_YES)
494 goto syntax;
495 tail->expr = gfc_uminus (tail->expr);
496 }
497 break;
498 case MATCH_NO:
499 goto syntax;
500 case MATCH_ERROR:
501 goto cleanup;
502 }
503
504 if (gfc_match_char (')') == MATCH_YES)
505 break;
506 if (gfc_match_char (',') != MATCH_YES)
507 goto syntax;
508 }
509
510 while (*list)
511 list = &(*list)->next;
512
513 *list = head;
514 return MATCH_YES;
515
516 syntax:
517 gfc_error ("Syntax error in OpenMP DEPEND SINK list at %C");
518
519 cleanup:
520 gfc_free_omp_namelist (head);
521 gfc_current_locus = old_loc;
522 return MATCH_ERROR;
523 }
524
525 static match
match_oacc_expr_list(const char * str,gfc_expr_list ** list,bool allow_asterisk)526 match_oacc_expr_list (const char *str, gfc_expr_list **list,
527 bool allow_asterisk)
528 {
529 gfc_expr_list *head, *tail, *p;
530 locus old_loc;
531 gfc_expr *expr;
532 match m;
533
534 head = tail = NULL;
535
536 old_loc = gfc_current_locus;
537
538 m = gfc_match (str);
539 if (m != MATCH_YES)
540 return m;
541
542 for (;;)
543 {
544 m = gfc_match_expr (&expr);
545 if (m == MATCH_YES || allow_asterisk)
546 {
547 p = gfc_get_expr_list ();
548 if (head == NULL)
549 head = tail = p;
550 else
551 {
552 tail->next = p;
553 tail = tail->next;
554 }
555 if (m == MATCH_YES)
556 tail->expr = expr;
557 else if (gfc_match (" *") != MATCH_YES)
558 goto syntax;
559 goto next_item;
560 }
561 if (m == MATCH_ERROR)
562 goto cleanup;
563 goto syntax;
564
565 next_item:
566 if (gfc_match_char (')') == MATCH_YES)
567 break;
568 if (gfc_match_char (',') != MATCH_YES)
569 goto syntax;
570 }
571
572 while (*list)
573 list = &(*list)->next;
574
575 *list = head;
576 return MATCH_YES;
577
578 syntax:
579 gfc_error ("Syntax error in OpenACC expression list at %C");
580
581 cleanup:
582 gfc_free_expr_list (head);
583 gfc_current_locus = old_loc;
584 return MATCH_ERROR;
585 }
586
587 static match
match_oacc_clause_gwv(gfc_omp_clauses * cp,unsigned gwv)588 match_oacc_clause_gwv (gfc_omp_clauses *cp, unsigned gwv)
589 {
590 match ret = MATCH_YES;
591
592 if (gfc_match (" ( ") != MATCH_YES)
593 return MATCH_NO;
594
595 if (gwv == GOMP_DIM_GANG)
596 {
597 /* The gang clause accepts two optional arguments, num and static.
598 The num argument may either be explicit (num: <val>) or
599 implicit without (<val> without num:). */
600
601 while (ret == MATCH_YES)
602 {
603 if (gfc_match (" static :") == MATCH_YES)
604 {
605 if (cp->gang_static)
606 return MATCH_ERROR;
607 else
608 cp->gang_static = true;
609 if (gfc_match_char ('*') == MATCH_YES)
610 cp->gang_static_expr = NULL;
611 else if (gfc_match (" %e ", &cp->gang_static_expr) != MATCH_YES)
612 return MATCH_ERROR;
613 }
614 else
615 {
616 if (cp->gang_num_expr)
617 return MATCH_ERROR;
618
619 /* The 'num' argument is optional. */
620 gfc_match (" num :");
621
622 if (gfc_match (" %e ", &cp->gang_num_expr) != MATCH_YES)
623 return MATCH_ERROR;
624 }
625
626 ret = gfc_match (" , ");
627 }
628 }
629 else if (gwv == GOMP_DIM_WORKER)
630 {
631 /* The 'num' argument is optional. */
632 gfc_match (" num :");
633
634 if (gfc_match (" %e ", &cp->worker_expr) != MATCH_YES)
635 return MATCH_ERROR;
636 }
637 else if (gwv == GOMP_DIM_VECTOR)
638 {
639 /* The 'length' argument is optional. */
640 gfc_match (" length :");
641
642 if (gfc_match (" %e ", &cp->vector_expr) != MATCH_YES)
643 return MATCH_ERROR;
644 }
645 else
646 gfc_fatal_error ("Unexpected OpenACC parallelism.");
647
648 return gfc_match (" )");
649 }
650
651 static match
gfc_match_oacc_clause_link(const char * str,gfc_omp_namelist ** list)652 gfc_match_oacc_clause_link (const char *str, gfc_omp_namelist **list)
653 {
654 gfc_omp_namelist *head = NULL;
655 gfc_omp_namelist *tail, *p;
656 locus old_loc;
657 char n[GFC_MAX_SYMBOL_LEN+1];
658 gfc_symbol *sym;
659 match m;
660 gfc_symtree *st;
661
662 old_loc = gfc_current_locus;
663
664 m = gfc_match (str);
665 if (m != MATCH_YES)
666 return m;
667
668 m = gfc_match (" (");
669
670 for (;;)
671 {
672 m = gfc_match_symbol (&sym, 0);
673 switch (m)
674 {
675 case MATCH_YES:
676 if (sym->attr.in_common)
677 {
678 gfc_error_now ("Variable at %C is an element of a COMMON block");
679 goto cleanup;
680 }
681 gfc_set_sym_referenced (sym);
682 p = gfc_get_omp_namelist ();
683 if (head == NULL)
684 head = tail = p;
685 else
686 {
687 tail->next = p;
688 tail = tail->next;
689 }
690 tail->sym = sym;
691 tail->expr = NULL;
692 tail->where = gfc_current_locus;
693 goto next_item;
694 case MATCH_NO:
695 break;
696
697 case MATCH_ERROR:
698 goto cleanup;
699 }
700
701 m = gfc_match (" / %n /", n);
702 if (m == MATCH_ERROR)
703 goto cleanup;
704 if (m == MATCH_NO || n[0] == '\0')
705 goto syntax;
706
707 st = gfc_find_symtree (gfc_current_ns->common_root, n);
708 if (st == NULL)
709 {
710 gfc_error ("COMMON block /%s/ not found at %C", n);
711 goto cleanup;
712 }
713
714 for (sym = st->n.common->head; sym; sym = sym->common_next)
715 {
716 gfc_set_sym_referenced (sym);
717 p = gfc_get_omp_namelist ();
718 if (head == NULL)
719 head = tail = p;
720 else
721 {
722 tail->next = p;
723 tail = tail->next;
724 }
725 tail->sym = sym;
726 tail->where = gfc_current_locus;
727 }
728
729 next_item:
730 if (gfc_match_char (')') == MATCH_YES)
731 break;
732 if (gfc_match_char (',') != MATCH_YES)
733 goto syntax;
734 }
735
736 if (gfc_match_omp_eos () != MATCH_YES)
737 {
738 gfc_error ("Unexpected junk after !$ACC DECLARE at %C");
739 goto cleanup;
740 }
741
742 while (*list)
743 list = &(*list)->next;
744 *list = head;
745 return MATCH_YES;
746
747 syntax:
748 gfc_error ("Syntax error in !$ACC DECLARE list at %C");
749
750 cleanup:
751 gfc_current_locus = old_loc;
752 return MATCH_ERROR;
753 }
754
755 /* OpenMP 4.5 clauses. */
756 enum omp_mask1
757 {
758 OMP_CLAUSE_PRIVATE,
759 OMP_CLAUSE_FIRSTPRIVATE,
760 OMP_CLAUSE_LASTPRIVATE,
761 OMP_CLAUSE_COPYPRIVATE,
762 OMP_CLAUSE_SHARED,
763 OMP_CLAUSE_COPYIN,
764 OMP_CLAUSE_REDUCTION,
765 OMP_CLAUSE_IF,
766 OMP_CLAUSE_NUM_THREADS,
767 OMP_CLAUSE_SCHEDULE,
768 OMP_CLAUSE_DEFAULT,
769 OMP_CLAUSE_ORDERED,
770 OMP_CLAUSE_COLLAPSE,
771 OMP_CLAUSE_UNTIED,
772 OMP_CLAUSE_FINAL,
773 OMP_CLAUSE_MERGEABLE,
774 OMP_CLAUSE_ALIGNED,
775 OMP_CLAUSE_DEPEND,
776 OMP_CLAUSE_INBRANCH,
777 OMP_CLAUSE_LINEAR,
778 OMP_CLAUSE_NOTINBRANCH,
779 OMP_CLAUSE_PROC_BIND,
780 OMP_CLAUSE_SAFELEN,
781 OMP_CLAUSE_SIMDLEN,
782 OMP_CLAUSE_UNIFORM,
783 OMP_CLAUSE_DEVICE,
784 OMP_CLAUSE_MAP,
785 OMP_CLAUSE_TO,
786 OMP_CLAUSE_FROM,
787 OMP_CLAUSE_NUM_TEAMS,
788 OMP_CLAUSE_THREAD_LIMIT,
789 OMP_CLAUSE_DIST_SCHEDULE,
790 OMP_CLAUSE_DEFAULTMAP,
791 OMP_CLAUSE_GRAINSIZE,
792 OMP_CLAUSE_HINT,
793 OMP_CLAUSE_IS_DEVICE_PTR,
794 OMP_CLAUSE_LINK,
795 OMP_CLAUSE_NOGROUP,
796 OMP_CLAUSE_NUM_TASKS,
797 OMP_CLAUSE_PRIORITY,
798 OMP_CLAUSE_SIMD,
799 OMP_CLAUSE_THREADS,
800 OMP_CLAUSE_USE_DEVICE_PTR,
801 OMP_CLAUSE_USE_DEVICE_ADDR, /* Actually, OpenMP 5.0. */
802 OMP_CLAUSE_NOWAIT,
803 /* This must come last. */
804 OMP_MASK1_LAST
805 };
806
807 /* OpenACC 2.0+ specific clauses. */
808 enum omp_mask2
809 {
810 OMP_CLAUSE_ASYNC,
811 OMP_CLAUSE_NUM_GANGS,
812 OMP_CLAUSE_NUM_WORKERS,
813 OMP_CLAUSE_VECTOR_LENGTH,
814 OMP_CLAUSE_COPY,
815 OMP_CLAUSE_COPYOUT,
816 OMP_CLAUSE_CREATE,
817 OMP_CLAUSE_NO_CREATE,
818 OMP_CLAUSE_PRESENT,
819 OMP_CLAUSE_DEVICEPTR,
820 OMP_CLAUSE_GANG,
821 OMP_CLAUSE_WORKER,
822 OMP_CLAUSE_VECTOR,
823 OMP_CLAUSE_SEQ,
824 OMP_CLAUSE_INDEPENDENT,
825 OMP_CLAUSE_USE_DEVICE,
826 OMP_CLAUSE_DEVICE_RESIDENT,
827 OMP_CLAUSE_HOST_SELF,
828 OMP_CLAUSE_WAIT,
829 OMP_CLAUSE_DELETE,
830 OMP_CLAUSE_AUTO,
831 OMP_CLAUSE_TILE,
832 OMP_CLAUSE_IF_PRESENT,
833 OMP_CLAUSE_FINALIZE,
834 OMP_CLAUSE_ATTACH,
835 OMP_CLAUSE_DETACH,
836 /* This must come last. */
837 OMP_MASK2_LAST
838 };
839
840 struct omp_inv_mask;
841
842 /* Customized bitset for up to 128-bits.
843 The two enums above provide bit numbers to use, and which of the
844 two enums it is determines which of the two mask fields is used.
845 Supported operations are defining a mask, like:
846 #define XXX_CLAUSES \
847 (omp_mask (OMP_CLAUSE_XXX) | OMP_CLAUSE_YYY | OMP_CLAUSE_ZZZ)
848 oring such bitsets together or removing selected bits:
849 (XXX_CLAUSES | YYY_CLAUSES) & ~(omp_mask (OMP_CLAUSE_VVV))
850 and testing individual bits:
851 if (mask & OMP_CLAUSE_UUU) */
852
853 struct omp_mask {
854 const uint64_t mask1;
855 const uint64_t mask2;
856 inline omp_mask ();
857 inline omp_mask (omp_mask1);
858 inline omp_mask (omp_mask2);
859 inline omp_mask (uint64_t, uint64_t);
860 inline omp_mask operator| (omp_mask1) const;
861 inline omp_mask operator| (omp_mask2) const;
862 inline omp_mask operator| (omp_mask) const;
863 inline omp_mask operator& (const omp_inv_mask &) const;
864 inline bool operator& (omp_mask1) const;
865 inline bool operator& (omp_mask2) const;
866 inline omp_inv_mask operator~ () const;
867 };
868
869 struct omp_inv_mask : public omp_mask {
870 inline omp_inv_mask (const omp_mask &);
871 };
872
omp_mask()873 omp_mask::omp_mask () : mask1 (0), mask2 (0)
874 {
875 }
876
omp_mask(omp_mask1 m)877 omp_mask::omp_mask (omp_mask1 m) : mask1 (((uint64_t) 1) << m), mask2 (0)
878 {
879 }
880
omp_mask(omp_mask2 m)881 omp_mask::omp_mask (omp_mask2 m) : mask1 (0), mask2 (((uint64_t) 1) << m)
882 {
883 }
884
omp_mask(uint64_t m1,uint64_t m2)885 omp_mask::omp_mask (uint64_t m1, uint64_t m2) : mask1 (m1), mask2 (m2)
886 {
887 }
888
889 omp_mask
890 omp_mask::operator| (omp_mask1 m) const
891 {
892 return omp_mask (mask1 | (((uint64_t) 1) << m), mask2);
893 }
894
895 omp_mask
896 omp_mask::operator| (omp_mask2 m) const
897 {
898 return omp_mask (mask1, mask2 | (((uint64_t) 1) << m));
899 }
900
901 omp_mask
902 omp_mask::operator| (omp_mask m) const
903 {
904 return omp_mask (mask1 | m.mask1, mask2 | m.mask2);
905 }
906
907 omp_mask
908 omp_mask::operator& (const omp_inv_mask &m) const
909 {
910 return omp_mask (mask1 & ~m.mask1, mask2 & ~m.mask2);
911 }
912
913 bool
914 omp_mask::operator& (omp_mask1 m) const
915 {
916 return (mask1 & (((uint64_t) 1) << m)) != 0;
917 }
918
919 bool
920 omp_mask::operator& (omp_mask2 m) const
921 {
922 return (mask2 & (((uint64_t) 1) << m)) != 0;
923 }
924
925 omp_inv_mask
926 omp_mask::operator~ () const
927 {
928 return omp_inv_mask (*this);
929 }
930
omp_inv_mask(const omp_mask & m)931 omp_inv_mask::omp_inv_mask (const omp_mask &m) : omp_mask (m)
932 {
933 }
934
935 /* Helper function for OpenACC and OpenMP clauses involving memory
936 mapping. */
937
938 static bool
gfc_match_omp_map_clause(gfc_omp_namelist ** list,gfc_omp_map_op map_op,bool allow_common,bool allow_derived)939 gfc_match_omp_map_clause (gfc_omp_namelist **list, gfc_omp_map_op map_op,
940 bool allow_common, bool allow_derived)
941 {
942 gfc_omp_namelist **head = NULL;
943 if (gfc_match_omp_variable_list ("", list, allow_common, NULL, &head, true,
944 allow_derived)
945 == MATCH_YES)
946 {
947 gfc_omp_namelist *n;
948 for (n = *head; n; n = n->next)
949 n->u.map_op = map_op;
950 return true;
951 }
952
953 return false;
954 }
955
956 /* Match OpenMP and OpenACC directive clauses. MASK is a bitmask of
957 clauses that are allowed for a particular directive. */
958
959 static match
960 gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
961 bool first = true, bool needs_space = true,
962 bool openacc = false)
963 {
964 gfc_omp_clauses *c = gfc_get_omp_clauses ();
965 locus old_loc;
966 /* Determine whether we're dealing with an OpenACC directive that permits
967 derived type member accesses. This in particular disallows
968 "!$acc declare" from using such accesses, because it's not clear if/how
969 that should work. */
970 bool allow_derived = (openacc
971 && ((mask & OMP_CLAUSE_ATTACH)
972 || (mask & OMP_CLAUSE_DETACH)
973 || (mask & OMP_CLAUSE_HOST_SELF)));
974
975 gcc_checking_assert (OMP_MASK1_LAST <= 64 && OMP_MASK2_LAST <= 64);
976 *cp = NULL;
977 while (1)
978 {
979 if ((first || gfc_match_char (',') != MATCH_YES)
980 && (needs_space && gfc_match_space () != MATCH_YES))
981 break;
982 needs_space = false;
983 first = false;
984 gfc_gobble_whitespace ();
985 bool end_colon;
986 gfc_omp_namelist **head;
987 old_loc = gfc_current_locus;
988 char pc = gfc_peek_ascii_char ();
989 switch (pc)
990 {
991 case 'a':
992 end_colon = false;
993 head = NULL;
994 if ((mask & OMP_CLAUSE_ALIGNED)
995 && gfc_match_omp_variable_list ("aligned (",
996 &c->lists[OMP_LIST_ALIGNED],
997 false, &end_colon,
998 &head) == MATCH_YES)
999 {
1000 gfc_expr *alignment = NULL;
1001 gfc_omp_namelist *n;
1002
1003 if (end_colon && gfc_match (" %e )", &alignment) != MATCH_YES)
1004 {
1005 gfc_free_omp_namelist (*head);
1006 gfc_current_locus = old_loc;
1007 *head = NULL;
1008 break;
1009 }
1010 for (n = *head; n; n = n->next)
1011 if (n->next && alignment)
1012 n->expr = gfc_copy_expr (alignment);
1013 else
1014 n->expr = alignment;
1015 continue;
1016 }
1017 if ((mask & OMP_CLAUSE_ASYNC)
1018 && !c->async
1019 && gfc_match ("async") == MATCH_YES)
1020 {
1021 c->async = true;
1022 match m = gfc_match (" ( %e )", &c->async_expr);
1023 if (m == MATCH_ERROR)
1024 {
1025 gfc_current_locus = old_loc;
1026 break;
1027 }
1028 else if (m == MATCH_NO)
1029 {
1030 c->async_expr
1031 = gfc_get_constant_expr (BT_INTEGER,
1032 gfc_default_integer_kind,
1033 &gfc_current_locus);
1034 mpz_set_si (c->async_expr->value.integer, GOMP_ASYNC_NOVAL);
1035 needs_space = true;
1036 }
1037 continue;
1038 }
1039 if ((mask & OMP_CLAUSE_AUTO)
1040 && !c->par_auto
1041 && gfc_match ("auto") == MATCH_YES)
1042 {
1043 c->par_auto = true;
1044 needs_space = true;
1045 continue;
1046 }
1047 if ((mask & OMP_CLAUSE_ATTACH)
1048 && gfc_match ("attach ( ") == MATCH_YES
1049 && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1050 OMP_MAP_ATTACH, false,
1051 allow_derived))
1052 continue;
1053 break;
1054 case 'c':
1055 if ((mask & OMP_CLAUSE_COLLAPSE)
1056 && !c->collapse)
1057 {
1058 gfc_expr *cexpr = NULL;
1059 match m = gfc_match ("collapse ( %e )", &cexpr);
1060
1061 if (m == MATCH_YES)
1062 {
1063 int collapse;
1064 if (gfc_extract_int (cexpr, &collapse, -1))
1065 collapse = 1;
1066 else if (collapse <= 0)
1067 {
1068 gfc_error_now ("COLLAPSE clause argument not"
1069 " constant positive integer at %C");
1070 collapse = 1;
1071 }
1072 c->collapse = collapse;
1073 gfc_free_expr (cexpr);
1074 continue;
1075 }
1076 }
1077 if ((mask & OMP_CLAUSE_COPY)
1078 && gfc_match ("copy ( ") == MATCH_YES
1079 && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1080 OMP_MAP_TOFROM, true,
1081 allow_derived))
1082 continue;
1083 if (mask & OMP_CLAUSE_COPYIN)
1084 {
1085 if (openacc)
1086 {
1087 if (gfc_match ("copyin ( ") == MATCH_YES
1088 && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1089 OMP_MAP_TO, true,
1090 allow_derived))
1091 continue;
1092 }
1093 else if (gfc_match_omp_variable_list ("copyin (",
1094 &c->lists[OMP_LIST_COPYIN],
1095 true) == MATCH_YES)
1096 continue;
1097 }
1098 if ((mask & OMP_CLAUSE_COPYOUT)
1099 && gfc_match ("copyout ( ") == MATCH_YES
1100 && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1101 OMP_MAP_FROM, true, allow_derived))
1102 continue;
1103 if ((mask & OMP_CLAUSE_COPYPRIVATE)
1104 && gfc_match_omp_variable_list ("copyprivate (",
1105 &c->lists[OMP_LIST_COPYPRIVATE],
1106 true) == MATCH_YES)
1107 continue;
1108 if ((mask & OMP_CLAUSE_CREATE)
1109 && gfc_match ("create ( ") == MATCH_YES
1110 && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1111 OMP_MAP_ALLOC, true, allow_derived))
1112 continue;
1113 break;
1114 case 'd':
1115 if ((mask & OMP_CLAUSE_DEFAULT)
1116 && c->default_sharing == OMP_DEFAULT_UNKNOWN)
1117 {
1118 if (gfc_match ("default ( none )") == MATCH_YES)
1119 c->default_sharing = OMP_DEFAULT_NONE;
1120 else if (openacc)
1121 {
1122 if (gfc_match ("default ( present )") == MATCH_YES)
1123 c->default_sharing = OMP_DEFAULT_PRESENT;
1124 }
1125 else
1126 {
1127 if (gfc_match ("default ( firstprivate )") == MATCH_YES)
1128 c->default_sharing = OMP_DEFAULT_FIRSTPRIVATE;
1129 else if (gfc_match ("default ( private )") == MATCH_YES)
1130 c->default_sharing = OMP_DEFAULT_PRIVATE;
1131 else if (gfc_match ("default ( shared )") == MATCH_YES)
1132 c->default_sharing = OMP_DEFAULT_SHARED;
1133 }
1134 if (c->default_sharing != OMP_DEFAULT_UNKNOWN)
1135 continue;
1136 }
1137 if ((mask & OMP_CLAUSE_DEFAULTMAP)
1138 && !c->defaultmap
1139 && gfc_match ("defaultmap ( tofrom : scalar )") == MATCH_YES)
1140 {
1141 c->defaultmap = true;
1142 continue;
1143 }
1144 if ((mask & OMP_CLAUSE_DELETE)
1145 && gfc_match ("delete ( ") == MATCH_YES
1146 && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1147 OMP_MAP_RELEASE, true,
1148 allow_derived))
1149 continue;
1150 if ((mask & OMP_CLAUSE_DEPEND)
1151 && gfc_match ("depend ( ") == MATCH_YES)
1152 {
1153 match m = MATCH_YES;
1154 gfc_omp_depend_op depend_op = OMP_DEPEND_OUT;
1155 if (gfc_match ("inout") == MATCH_YES)
1156 depend_op = OMP_DEPEND_INOUT;
1157 else if (gfc_match ("in") == MATCH_YES)
1158 depend_op = OMP_DEPEND_IN;
1159 else if (gfc_match ("out") == MATCH_YES)
1160 depend_op = OMP_DEPEND_OUT;
1161 else if (!c->depend_source
1162 && gfc_match ("source )") == MATCH_YES)
1163 {
1164 c->depend_source = true;
1165 continue;
1166 }
1167 else if (gfc_match ("sink : ") == MATCH_YES)
1168 {
1169 if (gfc_match_omp_depend_sink (&c->lists[OMP_LIST_DEPEND])
1170 == MATCH_YES)
1171 continue;
1172 m = MATCH_NO;
1173 }
1174 else
1175 m = MATCH_NO;
1176 head = NULL;
1177 if (m == MATCH_YES
1178 && gfc_match_omp_variable_list (" : ",
1179 &c->lists[OMP_LIST_DEPEND],
1180 false, NULL, &head,
1181 true) == MATCH_YES)
1182 {
1183 gfc_omp_namelist *n;
1184 for (n = *head; n; n = n->next)
1185 n->u.depend_op = depend_op;
1186 continue;
1187 }
1188 else
1189 gfc_current_locus = old_loc;
1190 }
1191 if ((mask & OMP_CLAUSE_DETACH)
1192 && gfc_match ("detach ( ") == MATCH_YES
1193 && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1194 OMP_MAP_DETACH, false,
1195 allow_derived))
1196 continue;
1197 if ((mask & OMP_CLAUSE_DEVICE)
1198 && !openacc
1199 && c->device == NULL
1200 && gfc_match ("device ( %e )", &c->device) == MATCH_YES)
1201 continue;
1202 if ((mask & OMP_CLAUSE_DEVICE)
1203 && openacc
1204 && gfc_match ("device ( ") == MATCH_YES
1205 && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1206 OMP_MAP_FORCE_TO, true,
1207 allow_derived))
1208 continue;
1209 if ((mask & OMP_CLAUSE_DEVICEPTR)
1210 && gfc_match ("deviceptr ( ") == MATCH_YES
1211 && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1212 OMP_MAP_FORCE_DEVICEPTR, false,
1213 allow_derived))
1214 continue;
1215 if ((mask & OMP_CLAUSE_DEVICE_RESIDENT)
1216 && gfc_match_omp_variable_list
1217 ("device_resident (",
1218 &c->lists[OMP_LIST_DEVICE_RESIDENT], true) == MATCH_YES)
1219 continue;
1220 if ((mask & OMP_CLAUSE_DIST_SCHEDULE)
1221 && c->dist_sched_kind == OMP_SCHED_NONE
1222 && gfc_match ("dist_schedule ( static") == MATCH_YES)
1223 {
1224 match m = MATCH_NO;
1225 c->dist_sched_kind = OMP_SCHED_STATIC;
1226 m = gfc_match (" , %e )", &c->dist_chunk_size);
1227 if (m != MATCH_YES)
1228 m = gfc_match_char (')');
1229 if (m != MATCH_YES)
1230 {
1231 c->dist_sched_kind = OMP_SCHED_NONE;
1232 gfc_current_locus = old_loc;
1233 }
1234 else
1235 continue;
1236 }
1237 break;
1238 case 'f':
1239 if ((mask & OMP_CLAUSE_FINAL)
1240 && c->final_expr == NULL
1241 && gfc_match ("final ( %e )", &c->final_expr) == MATCH_YES)
1242 continue;
1243 if ((mask & OMP_CLAUSE_FINALIZE)
1244 && !c->finalize
1245 && gfc_match ("finalize") == MATCH_YES)
1246 {
1247 c->finalize = true;
1248 needs_space = true;
1249 continue;
1250 }
1251 if ((mask & OMP_CLAUSE_FIRSTPRIVATE)
1252 && gfc_match_omp_variable_list ("firstprivate (",
1253 &c->lists[OMP_LIST_FIRSTPRIVATE],
1254 true) == MATCH_YES)
1255 continue;
1256 if ((mask & OMP_CLAUSE_FROM)
1257 && gfc_match_omp_variable_list ("from (",
1258 &c->lists[OMP_LIST_FROM], false,
1259 NULL, &head, true) == MATCH_YES)
1260 continue;
1261 break;
1262 case 'g':
1263 if ((mask & OMP_CLAUSE_GANG)
1264 && !c->gang
1265 && gfc_match ("gang") == MATCH_YES)
1266 {
1267 c->gang = true;
1268 match m = match_oacc_clause_gwv (c, GOMP_DIM_GANG);
1269 if (m == MATCH_ERROR)
1270 {
1271 gfc_current_locus = old_loc;
1272 break;
1273 }
1274 else if (m == MATCH_NO)
1275 needs_space = true;
1276 continue;
1277 }
1278 if ((mask & OMP_CLAUSE_GRAINSIZE)
1279 && c->grainsize == NULL
1280 && gfc_match ("grainsize ( %e )", &c->grainsize) == MATCH_YES)
1281 continue;
1282 break;
1283 case 'h':
1284 if ((mask & OMP_CLAUSE_HINT)
1285 && c->hint == NULL
1286 && gfc_match ("hint ( %e )", &c->hint) == MATCH_YES)
1287 continue;
1288 if ((mask & OMP_CLAUSE_HOST_SELF)
1289 && gfc_match ("host ( ") == MATCH_YES
1290 && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1291 OMP_MAP_FORCE_FROM, true,
1292 allow_derived))
1293 continue;
1294 break;
1295 case 'i':
1296 if ((mask & OMP_CLAUSE_IF)
1297 && c->if_expr == NULL
1298 && gfc_match ("if ( ") == MATCH_YES)
1299 {
1300 if (gfc_match ("%e )", &c->if_expr) == MATCH_YES)
1301 continue;
1302 if (!openacc)
1303 {
1304 /* This should match the enum gfc_omp_if_kind order. */
1305 static const char *ifs[OMP_IF_LAST] = {
1306 " parallel : %e )",
1307 " task : %e )",
1308 " taskloop : %e )",
1309 " target : %e )",
1310 " target data : %e )",
1311 " target update : %e )",
1312 " target enter data : %e )",
1313 " target exit data : %e )" };
1314 int i;
1315 for (i = 0; i < OMP_IF_LAST; i++)
1316 if (c->if_exprs[i] == NULL
1317 && gfc_match (ifs[i], &c->if_exprs[i]) == MATCH_YES)
1318 break;
1319 if (i < OMP_IF_LAST)
1320 continue;
1321 }
1322 gfc_current_locus = old_loc;
1323 }
1324 if ((mask & OMP_CLAUSE_IF_PRESENT)
1325 && !c->if_present
1326 && gfc_match ("if_present") == MATCH_YES)
1327 {
1328 c->if_present = true;
1329 needs_space = true;
1330 continue;
1331 }
1332 if ((mask & OMP_CLAUSE_INBRANCH)
1333 && !c->inbranch
1334 && !c->notinbranch
1335 && gfc_match ("inbranch") == MATCH_YES)
1336 {
1337 c->inbranch = needs_space = true;
1338 continue;
1339 }
1340 if ((mask & OMP_CLAUSE_INDEPENDENT)
1341 && !c->independent
1342 && gfc_match ("independent") == MATCH_YES)
1343 {
1344 c->independent = true;
1345 needs_space = true;
1346 continue;
1347 }
1348 if ((mask & OMP_CLAUSE_IS_DEVICE_PTR)
1349 && gfc_match_omp_variable_list
1350 ("is_device_ptr (",
1351 &c->lists[OMP_LIST_IS_DEVICE_PTR], false) == MATCH_YES)
1352 continue;
1353 break;
1354 case 'l':
1355 if ((mask & OMP_CLAUSE_LASTPRIVATE)
1356 && gfc_match_omp_variable_list ("lastprivate (",
1357 &c->lists[OMP_LIST_LASTPRIVATE],
1358 true) == MATCH_YES)
1359 continue;
1360 end_colon = false;
1361 head = NULL;
1362 if ((mask & OMP_CLAUSE_LINEAR)
1363 && gfc_match ("linear (") == MATCH_YES)
1364 {
1365 gfc_omp_linear_op linear_op = OMP_LINEAR_DEFAULT;
1366 gfc_expr *step = NULL;
1367
1368 if (gfc_match_omp_variable_list (" ref (",
1369 &c->lists[OMP_LIST_LINEAR],
1370 false, NULL, &head)
1371 == MATCH_YES)
1372 linear_op = OMP_LINEAR_REF;
1373 else if (gfc_match_omp_variable_list (" val (",
1374 &c->lists[OMP_LIST_LINEAR],
1375 false, NULL, &head)
1376 == MATCH_YES)
1377 linear_op = OMP_LINEAR_VAL;
1378 else if (gfc_match_omp_variable_list (" uval (",
1379 &c->lists[OMP_LIST_LINEAR],
1380 false, NULL, &head)
1381 == MATCH_YES)
1382 linear_op = OMP_LINEAR_UVAL;
1383 else if (gfc_match_omp_variable_list ("",
1384 &c->lists[OMP_LIST_LINEAR],
1385 false, &end_colon, &head)
1386 == MATCH_YES)
1387 linear_op = OMP_LINEAR_DEFAULT;
1388 else
1389 {
1390 gfc_current_locus = old_loc;
1391 break;
1392 }
1393 if (linear_op != OMP_LINEAR_DEFAULT)
1394 {
1395 if (gfc_match (" :") == MATCH_YES)
1396 end_colon = true;
1397 else if (gfc_match (" )") != MATCH_YES)
1398 {
1399 gfc_free_omp_namelist (*head);
1400 gfc_current_locus = old_loc;
1401 *head = NULL;
1402 break;
1403 }
1404 }
1405 if (end_colon && gfc_match (" %e )", &step) != MATCH_YES)
1406 {
1407 gfc_free_omp_namelist (*head);
1408 gfc_current_locus = old_loc;
1409 *head = NULL;
1410 break;
1411 }
1412 else if (!end_colon)
1413 {
1414 step = gfc_get_constant_expr (BT_INTEGER,
1415 gfc_default_integer_kind,
1416 &old_loc);
1417 mpz_set_si (step->value.integer, 1);
1418 }
1419 (*head)->expr = step;
1420 if (linear_op != OMP_LINEAR_DEFAULT)
1421 for (gfc_omp_namelist *n = *head; n; n = n->next)
1422 n->u.linear_op = linear_op;
1423 continue;
1424 }
1425 if ((mask & OMP_CLAUSE_LINK)
1426 && openacc
1427 && (gfc_match_oacc_clause_link ("link (",
1428 &c->lists[OMP_LIST_LINK])
1429 == MATCH_YES))
1430 continue;
1431 else if ((mask & OMP_CLAUSE_LINK)
1432 && !openacc
1433 && (gfc_match_omp_to_link ("link (",
1434 &c->lists[OMP_LIST_LINK])
1435 == MATCH_YES))
1436 continue;
1437 break;
1438 case 'm':
1439 if ((mask & OMP_CLAUSE_MAP)
1440 && gfc_match ("map ( ") == MATCH_YES)
1441 {
1442 locus old_loc2 = gfc_current_locus;
1443 bool always = false;
1444 gfc_omp_map_op map_op = OMP_MAP_TOFROM;
1445 if (gfc_match ("always , ") == MATCH_YES)
1446 always = true;
1447 if (gfc_match ("alloc : ") == MATCH_YES)
1448 map_op = OMP_MAP_ALLOC;
1449 else if (gfc_match ("tofrom : ") == MATCH_YES)
1450 map_op = always ? OMP_MAP_ALWAYS_TOFROM : OMP_MAP_TOFROM;
1451 else if (gfc_match ("to : ") == MATCH_YES)
1452 map_op = always ? OMP_MAP_ALWAYS_TO : OMP_MAP_TO;
1453 else if (gfc_match ("from : ") == MATCH_YES)
1454 map_op = always ? OMP_MAP_ALWAYS_FROM : OMP_MAP_FROM;
1455 else if (gfc_match ("release : ") == MATCH_YES)
1456 map_op = OMP_MAP_RELEASE;
1457 else if (gfc_match ("delete : ") == MATCH_YES)
1458 map_op = OMP_MAP_DELETE;
1459 else if (always)
1460 {
1461 gfc_current_locus = old_loc2;
1462 always = false;
1463 }
1464 head = NULL;
1465 if (gfc_match_omp_variable_list ("", &c->lists[OMP_LIST_MAP],
1466 false, NULL, &head,
1467 true) == MATCH_YES)
1468 {
1469 gfc_omp_namelist *n;
1470 for (n = *head; n; n = n->next)
1471 n->u.map_op = map_op;
1472 continue;
1473 }
1474 else
1475 gfc_current_locus = old_loc;
1476 }
1477 if ((mask & OMP_CLAUSE_MERGEABLE) && !c->mergeable
1478 && gfc_match ("mergeable") == MATCH_YES)
1479 {
1480 c->mergeable = needs_space = true;
1481 continue;
1482 }
1483 break;
1484 case 'n':
1485 if ((mask & OMP_CLAUSE_NO_CREATE)
1486 && gfc_match ("no_create ( ") == MATCH_YES
1487 && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1488 OMP_MAP_IF_PRESENT, true,
1489 allow_derived))
1490 continue;
1491 if ((mask & OMP_CLAUSE_NOGROUP)
1492 && !c->nogroup
1493 && gfc_match ("nogroup") == MATCH_YES)
1494 {
1495 c->nogroup = needs_space = true;
1496 continue;
1497 }
1498 if ((mask & OMP_CLAUSE_NOTINBRANCH)
1499 && !c->notinbranch
1500 && !c->inbranch
1501 && gfc_match ("notinbranch") == MATCH_YES)
1502 {
1503 c->notinbranch = needs_space = true;
1504 continue;
1505 }
1506 if ((mask & OMP_CLAUSE_NOWAIT)
1507 && !c->nowait
1508 && gfc_match ("nowait") == MATCH_YES)
1509 {
1510 c->nowait = needs_space = true;
1511 continue;
1512 }
1513 if ((mask & OMP_CLAUSE_NUM_GANGS)
1514 && c->num_gangs_expr == NULL
1515 && gfc_match ("num_gangs ( %e )",
1516 &c->num_gangs_expr) == MATCH_YES)
1517 continue;
1518 if ((mask & OMP_CLAUSE_NUM_TASKS)
1519 && c->num_tasks == NULL
1520 && gfc_match ("num_tasks ( %e )", &c->num_tasks) == MATCH_YES)
1521 continue;
1522 if ((mask & OMP_CLAUSE_NUM_TEAMS)
1523 && c->num_teams == NULL
1524 && gfc_match ("num_teams ( %e )", &c->num_teams) == MATCH_YES)
1525 continue;
1526 if ((mask & OMP_CLAUSE_NUM_THREADS)
1527 && c->num_threads == NULL
1528 && (gfc_match ("num_threads ( %e )", &c->num_threads)
1529 == MATCH_YES))
1530 continue;
1531 if ((mask & OMP_CLAUSE_NUM_WORKERS)
1532 && c->num_workers_expr == NULL
1533 && gfc_match ("num_workers ( %e )",
1534 &c->num_workers_expr) == MATCH_YES)
1535 continue;
1536 break;
1537 case 'o':
1538 if ((mask & OMP_CLAUSE_ORDERED)
1539 && !c->ordered
1540 && gfc_match ("ordered") == MATCH_YES)
1541 {
1542 gfc_expr *cexpr = NULL;
1543 match m = gfc_match (" ( %e )", &cexpr);
1544
1545 c->ordered = true;
1546 if (m == MATCH_YES)
1547 {
1548 int ordered = 0;
1549 if (gfc_extract_int (cexpr, &ordered, -1))
1550 ordered = 0;
1551 else if (ordered <= 0)
1552 {
1553 gfc_error_now ("ORDERED clause argument not"
1554 " constant positive integer at %C");
1555 ordered = 0;
1556 }
1557 c->orderedc = ordered;
1558 gfc_free_expr (cexpr);
1559 continue;
1560 }
1561
1562 needs_space = true;
1563 continue;
1564 }
1565 break;
1566 case 'p':
1567 if ((mask & OMP_CLAUSE_COPY)
1568 && gfc_match ("pcopy ( ") == MATCH_YES
1569 && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1570 OMP_MAP_TOFROM, true, allow_derived))
1571 continue;
1572 if ((mask & OMP_CLAUSE_COPYIN)
1573 && gfc_match ("pcopyin ( ") == MATCH_YES
1574 && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1575 OMP_MAP_TO, true, allow_derived))
1576 continue;
1577 if ((mask & OMP_CLAUSE_COPYOUT)
1578 && gfc_match ("pcopyout ( ") == MATCH_YES
1579 && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1580 OMP_MAP_FROM, true, allow_derived))
1581 continue;
1582 if ((mask & OMP_CLAUSE_CREATE)
1583 && gfc_match ("pcreate ( ") == MATCH_YES
1584 && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1585 OMP_MAP_ALLOC, true, allow_derived))
1586 continue;
1587 if ((mask & OMP_CLAUSE_PRESENT)
1588 && gfc_match ("present ( ") == MATCH_YES
1589 && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1590 OMP_MAP_FORCE_PRESENT, false,
1591 allow_derived))
1592 continue;
1593 if ((mask & OMP_CLAUSE_COPY)
1594 && gfc_match ("present_or_copy ( ") == MATCH_YES
1595 && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1596 OMP_MAP_TOFROM, true,
1597 allow_derived))
1598 continue;
1599 if ((mask & OMP_CLAUSE_COPYIN)
1600 && gfc_match ("present_or_copyin ( ") == MATCH_YES
1601 && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1602 OMP_MAP_TO, true, allow_derived))
1603 continue;
1604 if ((mask & OMP_CLAUSE_COPYOUT)
1605 && gfc_match ("present_or_copyout ( ") == MATCH_YES
1606 && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1607 OMP_MAP_FROM, true, allow_derived))
1608 continue;
1609 if ((mask & OMP_CLAUSE_CREATE)
1610 && gfc_match ("present_or_create ( ") == MATCH_YES
1611 && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1612 OMP_MAP_ALLOC, true, allow_derived))
1613 continue;
1614 if ((mask & OMP_CLAUSE_PRIORITY)
1615 && c->priority == NULL
1616 && gfc_match ("priority ( %e )", &c->priority) == MATCH_YES)
1617 continue;
1618 if ((mask & OMP_CLAUSE_PRIVATE)
1619 && gfc_match_omp_variable_list ("private (",
1620 &c->lists[OMP_LIST_PRIVATE],
1621 true) == MATCH_YES)
1622 continue;
1623 if ((mask & OMP_CLAUSE_PROC_BIND)
1624 && c->proc_bind == OMP_PROC_BIND_UNKNOWN)
1625 {
1626 if (gfc_match ("proc_bind ( master )") == MATCH_YES)
1627 c->proc_bind = OMP_PROC_BIND_MASTER;
1628 else if (gfc_match ("proc_bind ( spread )") == MATCH_YES)
1629 c->proc_bind = OMP_PROC_BIND_SPREAD;
1630 else if (gfc_match ("proc_bind ( close )") == MATCH_YES)
1631 c->proc_bind = OMP_PROC_BIND_CLOSE;
1632 if (c->proc_bind != OMP_PROC_BIND_UNKNOWN)
1633 continue;
1634 }
1635 break;
1636 case 'r':
1637 if ((mask & OMP_CLAUSE_REDUCTION)
1638 && gfc_match ("reduction ( ") == MATCH_YES)
1639 {
1640 gfc_omp_reduction_op rop = OMP_REDUCTION_NONE;
1641 char buffer[GFC_MAX_SYMBOL_LEN + 3];
1642 if (gfc_match_char ('+') == MATCH_YES)
1643 rop = OMP_REDUCTION_PLUS;
1644 else if (gfc_match_char ('*') == MATCH_YES)
1645 rop = OMP_REDUCTION_TIMES;
1646 else if (gfc_match_char ('-') == MATCH_YES)
1647 rop = OMP_REDUCTION_MINUS;
1648 else if (gfc_match (".and.") == MATCH_YES)
1649 rop = OMP_REDUCTION_AND;
1650 else if (gfc_match (".or.") == MATCH_YES)
1651 rop = OMP_REDUCTION_OR;
1652 else if (gfc_match (".eqv.") == MATCH_YES)
1653 rop = OMP_REDUCTION_EQV;
1654 else if (gfc_match (".neqv.") == MATCH_YES)
1655 rop = OMP_REDUCTION_NEQV;
1656 if (rop != OMP_REDUCTION_NONE)
1657 snprintf (buffer, sizeof buffer, "operator %s",
1658 gfc_op2string ((gfc_intrinsic_op) rop));
1659 else if (gfc_match_defined_op_name (buffer + 1, 1) == MATCH_YES)
1660 {
1661 buffer[0] = '.';
1662 strcat (buffer, ".");
1663 }
1664 else if (gfc_match_name (buffer) == MATCH_YES)
1665 {
1666 gfc_symbol *sym;
1667 const char *n = buffer;
1668
1669 gfc_find_symbol (buffer, NULL, 1, &sym);
1670 if (sym != NULL)
1671 {
1672 if (sym->attr.intrinsic)
1673 n = sym->name;
1674 else if ((sym->attr.flavor != FL_UNKNOWN
1675 && sym->attr.flavor != FL_PROCEDURE)
1676 || sym->attr.external
1677 || sym->attr.generic
1678 || sym->attr.entry
1679 || sym->attr.result
1680 || sym->attr.dummy
1681 || sym->attr.subroutine
1682 || sym->attr.pointer
1683 || sym->attr.target
1684 || sym->attr.cray_pointer
1685 || sym->attr.cray_pointee
1686 || (sym->attr.proc != PROC_UNKNOWN
1687 && sym->attr.proc != PROC_INTRINSIC)
1688 || sym->attr.if_source != IFSRC_UNKNOWN
1689 || sym == sym->ns->proc_name)
1690 {
1691 sym = NULL;
1692 n = NULL;
1693 }
1694 else
1695 n = sym->name;
1696 }
1697 if (n == NULL)
1698 rop = OMP_REDUCTION_NONE;
1699 else if (strcmp (n, "max") == 0)
1700 rop = OMP_REDUCTION_MAX;
1701 else if (strcmp (n, "min") == 0)
1702 rop = OMP_REDUCTION_MIN;
1703 else if (strcmp (n, "iand") == 0)
1704 rop = OMP_REDUCTION_IAND;
1705 else if (strcmp (n, "ior") == 0)
1706 rop = OMP_REDUCTION_IOR;
1707 else if (strcmp (n, "ieor") == 0)
1708 rop = OMP_REDUCTION_IEOR;
1709 if (rop != OMP_REDUCTION_NONE
1710 && sym != NULL
1711 && ! sym->attr.intrinsic
1712 && ! sym->attr.use_assoc
1713 && ((sym->attr.flavor == FL_UNKNOWN
1714 && !gfc_add_flavor (&sym->attr, FL_PROCEDURE,
1715 sym->name, NULL))
1716 || !gfc_add_intrinsic (&sym->attr, NULL)))
1717 rop = OMP_REDUCTION_NONE;
1718 }
1719 else
1720 buffer[0] = '\0';
1721 gfc_omp_udr *udr
1722 = (buffer[0]
1723 ? gfc_find_omp_udr (gfc_current_ns, buffer, NULL) : NULL);
1724 gfc_omp_namelist **head = NULL;
1725 if (rop == OMP_REDUCTION_NONE && udr)
1726 rop = OMP_REDUCTION_USER;
1727
1728 if (gfc_match_omp_variable_list (" :",
1729 &c->lists[OMP_LIST_REDUCTION],
1730 false, NULL, &head, openacc,
1731 allow_derived) == MATCH_YES)
1732 {
1733 gfc_omp_namelist *n;
1734 if (rop == OMP_REDUCTION_NONE)
1735 {
1736 n = *head;
1737 *head = NULL;
1738 gfc_error_now ("!$OMP DECLARE REDUCTION %s not found "
1739 "at %L", buffer, &old_loc);
1740 gfc_free_omp_namelist (n);
1741 }
1742 else
1743 for (n = *head; n; n = n->next)
1744 {
1745 n->u.reduction_op = rop;
1746 if (udr)
1747 {
1748 n->udr = gfc_get_omp_namelist_udr ();
1749 n->udr->udr = udr;
1750 }
1751 }
1752 continue;
1753 }
1754 else
1755 gfc_current_locus = old_loc;
1756 }
1757 break;
1758 case 's':
1759 if ((mask & OMP_CLAUSE_SAFELEN)
1760 && c->safelen_expr == NULL
1761 && gfc_match ("safelen ( %e )", &c->safelen_expr) == MATCH_YES)
1762 continue;
1763 if ((mask & OMP_CLAUSE_SCHEDULE)
1764 && c->sched_kind == OMP_SCHED_NONE
1765 && gfc_match ("schedule ( ") == MATCH_YES)
1766 {
1767 int nmodifiers = 0;
1768 locus old_loc2 = gfc_current_locus;
1769 do
1770 {
1771 if (gfc_match ("simd") == MATCH_YES)
1772 {
1773 c->sched_simd = true;
1774 nmodifiers++;
1775 }
1776 else if (gfc_match ("monotonic") == MATCH_YES)
1777 {
1778 c->sched_monotonic = true;
1779 nmodifiers++;
1780 }
1781 else if (gfc_match ("nonmonotonic") == MATCH_YES)
1782 {
1783 c->sched_nonmonotonic = true;
1784 nmodifiers++;
1785 }
1786 else
1787 {
1788 if (nmodifiers)
1789 gfc_current_locus = old_loc2;
1790 break;
1791 }
1792 if (nmodifiers == 1
1793 && gfc_match (" , ") == MATCH_YES)
1794 continue;
1795 else if (gfc_match (" : ") == MATCH_YES)
1796 break;
1797 gfc_current_locus = old_loc2;
1798 break;
1799 }
1800 while (1);
1801 if (gfc_match ("static") == MATCH_YES)
1802 c->sched_kind = OMP_SCHED_STATIC;
1803 else if (gfc_match ("dynamic") == MATCH_YES)
1804 c->sched_kind = OMP_SCHED_DYNAMIC;
1805 else if (gfc_match ("guided") == MATCH_YES)
1806 c->sched_kind = OMP_SCHED_GUIDED;
1807 else if (gfc_match ("runtime") == MATCH_YES)
1808 c->sched_kind = OMP_SCHED_RUNTIME;
1809 else if (gfc_match ("auto") == MATCH_YES)
1810 c->sched_kind = OMP_SCHED_AUTO;
1811 if (c->sched_kind != OMP_SCHED_NONE)
1812 {
1813 match m = MATCH_NO;
1814 if (c->sched_kind != OMP_SCHED_RUNTIME
1815 && c->sched_kind != OMP_SCHED_AUTO)
1816 m = gfc_match (" , %e )", &c->chunk_size);
1817 if (m != MATCH_YES)
1818 m = gfc_match_char (')');
1819 if (m != MATCH_YES)
1820 c->sched_kind = OMP_SCHED_NONE;
1821 }
1822 if (c->sched_kind != OMP_SCHED_NONE)
1823 continue;
1824 else
1825 gfc_current_locus = old_loc;
1826 }
1827 if ((mask & OMP_CLAUSE_HOST_SELF)
1828 && gfc_match ("self ( ") == MATCH_YES
1829 && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1830 OMP_MAP_FORCE_FROM, true,
1831 allow_derived))
1832 continue;
1833 if ((mask & OMP_CLAUSE_SEQ)
1834 && !c->seq
1835 && gfc_match ("seq") == MATCH_YES)
1836 {
1837 c->seq = true;
1838 needs_space = true;
1839 continue;
1840 }
1841 if ((mask & OMP_CLAUSE_SHARED)
1842 && gfc_match_omp_variable_list ("shared (",
1843 &c->lists[OMP_LIST_SHARED],
1844 true) == MATCH_YES)
1845 continue;
1846 if ((mask & OMP_CLAUSE_SIMDLEN)
1847 && c->simdlen_expr == NULL
1848 && gfc_match ("simdlen ( %e )", &c->simdlen_expr) == MATCH_YES)
1849 continue;
1850 if ((mask & OMP_CLAUSE_SIMD)
1851 && !c->simd
1852 && gfc_match ("simd") == MATCH_YES)
1853 {
1854 c->simd = needs_space = true;
1855 continue;
1856 }
1857 break;
1858 case 't':
1859 if ((mask & OMP_CLAUSE_THREAD_LIMIT)
1860 && c->thread_limit == NULL
1861 && gfc_match ("thread_limit ( %e )",
1862 &c->thread_limit) == MATCH_YES)
1863 continue;
1864 if ((mask & OMP_CLAUSE_THREADS)
1865 && !c->threads
1866 && gfc_match ("threads") == MATCH_YES)
1867 {
1868 c->threads = needs_space = true;
1869 continue;
1870 }
1871 if ((mask & OMP_CLAUSE_TILE)
1872 && !c->tile_list
1873 && match_oacc_expr_list ("tile (", &c->tile_list,
1874 true) == MATCH_YES)
1875 continue;
1876 if ((mask & OMP_CLAUSE_TO) && (mask & OMP_CLAUSE_LINK))
1877 {
1878 if (gfc_match_omp_to_link ("to (", &c->lists[OMP_LIST_TO])
1879 == MATCH_YES)
1880 continue;
1881 }
1882 else if ((mask & OMP_CLAUSE_TO)
1883 && gfc_match_omp_variable_list ("to (",
1884 &c->lists[OMP_LIST_TO], false,
1885 NULL, &head, true) == MATCH_YES)
1886 continue;
1887 break;
1888 case 'u':
1889 if ((mask & OMP_CLAUSE_UNIFORM)
1890 && gfc_match_omp_variable_list ("uniform (",
1891 &c->lists[OMP_LIST_UNIFORM],
1892 false) == MATCH_YES)
1893 continue;
1894 if ((mask & OMP_CLAUSE_UNTIED)
1895 && !c->untied
1896 && gfc_match ("untied") == MATCH_YES)
1897 {
1898 c->untied = needs_space = true;
1899 continue;
1900 }
1901 if ((mask & OMP_CLAUSE_USE_DEVICE)
1902 && gfc_match_omp_variable_list ("use_device (",
1903 &c->lists[OMP_LIST_USE_DEVICE],
1904 true) == MATCH_YES)
1905 continue;
1906 if ((mask & OMP_CLAUSE_USE_DEVICE_PTR)
1907 && gfc_match_omp_variable_list
1908 ("use_device_ptr (",
1909 &c->lists[OMP_LIST_USE_DEVICE_PTR], false) == MATCH_YES)
1910 continue;
1911 if ((mask & OMP_CLAUSE_USE_DEVICE_ADDR)
1912 && gfc_match_omp_variable_list
1913 ("use_device_addr (",
1914 &c->lists[OMP_LIST_USE_DEVICE_ADDR], false) == MATCH_YES)
1915 continue;
1916 break;
1917 case 'v':
1918 /* VECTOR_LENGTH must be matched before VECTOR, because the latter
1919 doesn't unconditionally match '('. */
1920 if ((mask & OMP_CLAUSE_VECTOR_LENGTH)
1921 && c->vector_length_expr == NULL
1922 && (gfc_match ("vector_length ( %e )", &c->vector_length_expr)
1923 == MATCH_YES))
1924 continue;
1925 if ((mask & OMP_CLAUSE_VECTOR)
1926 && !c->vector
1927 && gfc_match ("vector") == MATCH_YES)
1928 {
1929 c->vector = true;
1930 match m = match_oacc_clause_gwv (c, GOMP_DIM_VECTOR);
1931 if (m == MATCH_ERROR)
1932 {
1933 gfc_current_locus = old_loc;
1934 break;
1935 }
1936 if (m == MATCH_NO)
1937 needs_space = true;
1938 continue;
1939 }
1940 break;
1941 case 'w':
1942 if ((mask & OMP_CLAUSE_WAIT)
1943 && gfc_match ("wait") == MATCH_YES)
1944 {
1945 match m = match_oacc_expr_list (" (", &c->wait_list, false);
1946 if (m == MATCH_ERROR)
1947 {
1948 gfc_current_locus = old_loc;
1949 break;
1950 }
1951 else if (m == MATCH_NO)
1952 {
1953 gfc_expr *expr
1954 = gfc_get_constant_expr (BT_INTEGER,
1955 gfc_default_integer_kind,
1956 &gfc_current_locus);
1957 mpz_set_si (expr->value.integer, GOMP_ASYNC_NOVAL);
1958 gfc_expr_list **expr_list = &c->wait_list;
1959 while (*expr_list)
1960 expr_list = &(*expr_list)->next;
1961 *expr_list = gfc_get_expr_list ();
1962 (*expr_list)->expr = expr;
1963 needs_space = true;
1964 }
1965 continue;
1966 }
1967 if ((mask & OMP_CLAUSE_WORKER)
1968 && !c->worker
1969 && gfc_match ("worker") == MATCH_YES)
1970 {
1971 c->worker = true;
1972 match m = match_oacc_clause_gwv (c, GOMP_DIM_WORKER);
1973 if (m == MATCH_ERROR)
1974 {
1975 gfc_current_locus = old_loc;
1976 break;
1977 }
1978 else if (m == MATCH_NO)
1979 needs_space = true;
1980 continue;
1981 }
1982 break;
1983 }
1984 break;
1985 }
1986
1987 if (gfc_match_omp_eos () != MATCH_YES)
1988 {
1989 if (!gfc_error_flag_test ())
1990 gfc_error ("Failed to match clause at %C");
1991 gfc_free_omp_clauses (c);
1992 return MATCH_ERROR;
1993 }
1994
1995 *cp = c;
1996 return MATCH_YES;
1997 }
1998
1999
2000 #define OACC_PARALLEL_CLAUSES \
2001 (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_NUM_GANGS \
2002 | OMP_CLAUSE_NUM_WORKERS | OMP_CLAUSE_VECTOR_LENGTH | OMP_CLAUSE_REDUCTION \
2003 | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT \
2004 | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT \
2005 | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE \
2006 | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH)
2007 #define OACC_KERNELS_CLAUSES \
2008 (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_NUM_GANGS \
2009 | OMP_CLAUSE_NUM_WORKERS | OMP_CLAUSE_VECTOR_LENGTH | OMP_CLAUSE_DEVICEPTR \
2010 | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT \
2011 | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT \
2012 | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH)
2013 #define OACC_SERIAL_CLAUSES \
2014 (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_REDUCTION \
2015 | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT \
2016 | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT \
2017 | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE \
2018 | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH)
2019 #define OACC_DATA_CLAUSES \
2020 (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_COPY \
2021 | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_CREATE \
2022 | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT | OMP_CLAUSE_ATTACH)
2023 #define OACC_LOOP_CLAUSES \
2024 (omp_mask (OMP_CLAUSE_COLLAPSE) | OMP_CLAUSE_GANG | OMP_CLAUSE_WORKER \
2025 | OMP_CLAUSE_VECTOR | OMP_CLAUSE_SEQ | OMP_CLAUSE_INDEPENDENT \
2026 | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_AUTO \
2027 | OMP_CLAUSE_TILE)
2028 #define OACC_PARALLEL_LOOP_CLAUSES \
2029 (OACC_LOOP_CLAUSES | OACC_PARALLEL_CLAUSES)
2030 #define OACC_KERNELS_LOOP_CLAUSES \
2031 (OACC_LOOP_CLAUSES | OACC_KERNELS_CLAUSES)
2032 #define OACC_SERIAL_LOOP_CLAUSES \
2033 (OACC_LOOP_CLAUSES | OACC_SERIAL_CLAUSES)
2034 #define OACC_HOST_DATA_CLAUSES \
2035 (omp_mask (OMP_CLAUSE_USE_DEVICE) \
2036 | OMP_CLAUSE_IF \
2037 | OMP_CLAUSE_IF_PRESENT)
2038 #define OACC_DECLARE_CLAUSES \
2039 (omp_mask (OMP_CLAUSE_COPY) | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT \
2040 | OMP_CLAUSE_CREATE | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_DEVICE_RESIDENT \
2041 | OMP_CLAUSE_PRESENT \
2042 | OMP_CLAUSE_LINK)
2043 #define OACC_UPDATE_CLAUSES \
2044 (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_HOST_SELF \
2045 | OMP_CLAUSE_DEVICE | OMP_CLAUSE_WAIT | OMP_CLAUSE_IF_PRESENT)
2046 #define OACC_ENTER_DATA_CLAUSES \
2047 (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_WAIT \
2048 | OMP_CLAUSE_COPYIN | OMP_CLAUSE_CREATE | OMP_CLAUSE_ATTACH)
2049 #define OACC_EXIT_DATA_CLAUSES \
2050 (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_WAIT \
2051 | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_DELETE | OMP_CLAUSE_FINALIZE \
2052 | OMP_CLAUSE_DETACH)
2053 #define OACC_WAIT_CLAUSES \
2054 omp_mask (OMP_CLAUSE_ASYNC)
2055 #define OACC_ROUTINE_CLAUSES \
2056 (omp_mask (OMP_CLAUSE_GANG) | OMP_CLAUSE_WORKER | OMP_CLAUSE_VECTOR \
2057 | OMP_CLAUSE_SEQ)
2058
2059
2060 static match
match_acc(gfc_exec_op op,const omp_mask mask)2061 match_acc (gfc_exec_op op, const omp_mask mask)
2062 {
2063 gfc_omp_clauses *c;
2064 if (gfc_match_omp_clauses (&c, mask, false, false, true) != MATCH_YES)
2065 return MATCH_ERROR;
2066 new_st.op = op;
2067 new_st.ext.omp_clauses = c;
2068 return MATCH_YES;
2069 }
2070
2071 match
gfc_match_oacc_parallel_loop(void)2072 gfc_match_oacc_parallel_loop (void)
2073 {
2074 return match_acc (EXEC_OACC_PARALLEL_LOOP, OACC_PARALLEL_LOOP_CLAUSES);
2075 }
2076
2077
2078 match
gfc_match_oacc_parallel(void)2079 gfc_match_oacc_parallel (void)
2080 {
2081 return match_acc (EXEC_OACC_PARALLEL, OACC_PARALLEL_CLAUSES);
2082 }
2083
2084
2085 match
gfc_match_oacc_kernels_loop(void)2086 gfc_match_oacc_kernels_loop (void)
2087 {
2088 return match_acc (EXEC_OACC_KERNELS_LOOP, OACC_KERNELS_LOOP_CLAUSES);
2089 }
2090
2091
2092 match
gfc_match_oacc_kernels(void)2093 gfc_match_oacc_kernels (void)
2094 {
2095 return match_acc (EXEC_OACC_KERNELS, OACC_KERNELS_CLAUSES);
2096 }
2097
2098
2099 match
gfc_match_oacc_serial_loop(void)2100 gfc_match_oacc_serial_loop (void)
2101 {
2102 return match_acc (EXEC_OACC_SERIAL_LOOP, OACC_SERIAL_LOOP_CLAUSES);
2103 }
2104
2105
2106 match
gfc_match_oacc_serial(void)2107 gfc_match_oacc_serial (void)
2108 {
2109 return match_acc (EXEC_OACC_SERIAL, OACC_SERIAL_CLAUSES);
2110 }
2111
2112
2113 match
gfc_match_oacc_data(void)2114 gfc_match_oacc_data (void)
2115 {
2116 return match_acc (EXEC_OACC_DATA, OACC_DATA_CLAUSES);
2117 }
2118
2119
2120 match
gfc_match_oacc_host_data(void)2121 gfc_match_oacc_host_data (void)
2122 {
2123 return match_acc (EXEC_OACC_HOST_DATA, OACC_HOST_DATA_CLAUSES);
2124 }
2125
2126
2127 match
gfc_match_oacc_loop(void)2128 gfc_match_oacc_loop (void)
2129 {
2130 return match_acc (EXEC_OACC_LOOP, OACC_LOOP_CLAUSES);
2131 }
2132
2133
2134 match
gfc_match_oacc_declare(void)2135 gfc_match_oacc_declare (void)
2136 {
2137 gfc_omp_clauses *c;
2138 gfc_omp_namelist *n;
2139 gfc_namespace *ns = gfc_current_ns;
2140 gfc_oacc_declare *new_oc;
2141 bool module_var = false;
2142 locus where = gfc_current_locus;
2143
2144 if (gfc_match_omp_clauses (&c, OACC_DECLARE_CLAUSES, false, false, true)
2145 != MATCH_YES)
2146 return MATCH_ERROR;
2147
2148 for (n = c->lists[OMP_LIST_DEVICE_RESIDENT]; n != NULL; n = n->next)
2149 n->sym->attr.oacc_declare_device_resident = 1;
2150
2151 for (n = c->lists[OMP_LIST_LINK]; n != NULL; n = n->next)
2152 n->sym->attr.oacc_declare_link = 1;
2153
2154 for (n = c->lists[OMP_LIST_MAP]; n != NULL; n = n->next)
2155 {
2156 gfc_symbol *s = n->sym;
2157
2158 if (gfc_current_ns->proc_name
2159 && gfc_current_ns->proc_name->attr.flavor == FL_MODULE)
2160 {
2161 if (n->u.map_op != OMP_MAP_ALLOC && n->u.map_op != OMP_MAP_TO)
2162 {
2163 gfc_error ("Invalid clause in module with !$ACC DECLARE at %L",
2164 &where);
2165 return MATCH_ERROR;
2166 }
2167
2168 module_var = true;
2169 }
2170
2171 if (s->attr.use_assoc)
2172 {
2173 gfc_error ("Variable is USE-associated with !$ACC DECLARE at %L",
2174 &where);
2175 return MATCH_ERROR;
2176 }
2177
2178 if ((s->result == s && s->ns->contained != gfc_current_ns)
2179 || ((s->attr.flavor == FL_UNKNOWN || s->attr.flavor == FL_VARIABLE)
2180 && s->ns != gfc_current_ns))
2181 {
2182 gfc_error ("Variable %qs shall be declared in the same scoping unit "
2183 "as !$ACC DECLARE at %L", s->name, &where);
2184 return MATCH_ERROR;
2185 }
2186
2187 if ((s->attr.dimension || s->attr.codimension)
2188 && s->attr.dummy && s->as->type != AS_EXPLICIT)
2189 {
2190 gfc_error ("Assumed-size dummy array with !$ACC DECLARE at %L",
2191 &where);
2192 return MATCH_ERROR;
2193 }
2194
2195 switch (n->u.map_op)
2196 {
2197 case OMP_MAP_FORCE_ALLOC:
2198 case OMP_MAP_ALLOC:
2199 s->attr.oacc_declare_create = 1;
2200 break;
2201
2202 case OMP_MAP_FORCE_TO:
2203 case OMP_MAP_TO:
2204 s->attr.oacc_declare_copyin = 1;
2205 break;
2206
2207 case OMP_MAP_FORCE_DEVICEPTR:
2208 s->attr.oacc_declare_deviceptr = 1;
2209 break;
2210
2211 default:
2212 break;
2213 }
2214 }
2215
2216 new_oc = gfc_get_oacc_declare ();
2217 new_oc->next = ns->oacc_declare;
2218 new_oc->module_var = module_var;
2219 new_oc->clauses = c;
2220 new_oc->loc = gfc_current_locus;
2221 ns->oacc_declare = new_oc;
2222
2223 return MATCH_YES;
2224 }
2225
2226
2227 match
gfc_match_oacc_update(void)2228 gfc_match_oacc_update (void)
2229 {
2230 gfc_omp_clauses *c;
2231 locus here = gfc_current_locus;
2232
2233 if (gfc_match_omp_clauses (&c, OACC_UPDATE_CLAUSES, false, false, true)
2234 != MATCH_YES)
2235 return MATCH_ERROR;
2236
2237 if (!c->lists[OMP_LIST_MAP])
2238 {
2239 gfc_error ("%<acc update%> must contain at least one "
2240 "%<device%> or %<host%> or %<self%> clause at %L", &here);
2241 return MATCH_ERROR;
2242 }
2243
2244 new_st.op = EXEC_OACC_UPDATE;
2245 new_st.ext.omp_clauses = c;
2246 return MATCH_YES;
2247 }
2248
2249
2250 match
gfc_match_oacc_enter_data(void)2251 gfc_match_oacc_enter_data (void)
2252 {
2253 return match_acc (EXEC_OACC_ENTER_DATA, OACC_ENTER_DATA_CLAUSES);
2254 }
2255
2256
2257 match
gfc_match_oacc_exit_data(void)2258 gfc_match_oacc_exit_data (void)
2259 {
2260 return match_acc (EXEC_OACC_EXIT_DATA, OACC_EXIT_DATA_CLAUSES);
2261 }
2262
2263
2264 match
gfc_match_oacc_wait(void)2265 gfc_match_oacc_wait (void)
2266 {
2267 gfc_omp_clauses *c = gfc_get_omp_clauses ();
2268 gfc_expr_list *wait_list = NULL, *el;
2269 bool space = true;
2270 match m;
2271
2272 m = match_oacc_expr_list (" (", &wait_list, true);
2273 if (m == MATCH_ERROR)
2274 return m;
2275 else if (m == MATCH_YES)
2276 space = false;
2277
2278 if (gfc_match_omp_clauses (&c, OACC_WAIT_CLAUSES, space, space, true)
2279 == MATCH_ERROR)
2280 return MATCH_ERROR;
2281
2282 if (wait_list)
2283 for (el = wait_list; el; el = el->next)
2284 {
2285 if (el->expr == NULL)
2286 {
2287 gfc_error ("Invalid argument to !$ACC WAIT at %C");
2288 return MATCH_ERROR;
2289 }
2290
2291 if (!gfc_resolve_expr (el->expr)
2292 || el->expr->ts.type != BT_INTEGER || el->expr->rank != 0)
2293 {
2294 gfc_error ("WAIT clause at %L requires a scalar INTEGER expression",
2295 &el->expr->where);
2296
2297 return MATCH_ERROR;
2298 }
2299 }
2300 c->wait_list = wait_list;
2301 new_st.op = EXEC_OACC_WAIT;
2302 new_st.ext.omp_clauses = c;
2303 return MATCH_YES;
2304 }
2305
2306
2307 match
gfc_match_oacc_cache(void)2308 gfc_match_oacc_cache (void)
2309 {
2310 gfc_omp_clauses *c = gfc_get_omp_clauses ();
2311 /* The OpenACC cache directive explicitly only allows "array elements or
2312 subarrays", which we're currently not checking here. Either check this
2313 after the call of gfc_match_omp_variable_list, or add something like a
2314 only_sections variant next to its allow_sections parameter. */
2315 match m = gfc_match_omp_variable_list (" (",
2316 &c->lists[OMP_LIST_CACHE], true,
2317 NULL, NULL, true);
2318 if (m != MATCH_YES)
2319 {
2320 gfc_free_omp_clauses(c);
2321 return m;
2322 }
2323
2324 if (gfc_current_state() != COMP_DO
2325 && gfc_current_state() != COMP_DO_CONCURRENT)
2326 {
2327 gfc_error ("ACC CACHE directive must be inside of loop %C");
2328 gfc_free_omp_clauses(c);
2329 return MATCH_ERROR;
2330 }
2331
2332 new_st.op = EXEC_OACC_CACHE;
2333 new_st.ext.omp_clauses = c;
2334 return MATCH_YES;
2335 }
2336
2337 /* Determine the OpenACC 'routine' directive's level of parallelism. */
2338
2339 static oacc_routine_lop
gfc_oacc_routine_lop(gfc_omp_clauses * clauses)2340 gfc_oacc_routine_lop (gfc_omp_clauses *clauses)
2341 {
2342 oacc_routine_lop ret = OACC_ROUTINE_LOP_SEQ;
2343
2344 if (clauses)
2345 {
2346 unsigned n_lop_clauses = 0;
2347
2348 if (clauses->gang)
2349 {
2350 ++n_lop_clauses;
2351 ret = OACC_ROUTINE_LOP_GANG;
2352 }
2353 if (clauses->worker)
2354 {
2355 ++n_lop_clauses;
2356 ret = OACC_ROUTINE_LOP_WORKER;
2357 }
2358 if (clauses->vector)
2359 {
2360 ++n_lop_clauses;
2361 ret = OACC_ROUTINE_LOP_VECTOR;
2362 }
2363 if (clauses->seq)
2364 {
2365 ++n_lop_clauses;
2366 ret = OACC_ROUTINE_LOP_SEQ;
2367 }
2368
2369 if (n_lop_clauses > 1)
2370 ret = OACC_ROUTINE_LOP_ERROR;
2371 }
2372
2373 return ret;
2374 }
2375
2376 match
gfc_match_oacc_routine(void)2377 gfc_match_oacc_routine (void)
2378 {
2379 locus old_loc;
2380 match m;
2381 gfc_intrinsic_sym *isym = NULL;
2382 gfc_symbol *sym = NULL;
2383 gfc_omp_clauses *c = NULL;
2384 gfc_oacc_routine_name *n = NULL;
2385 oacc_routine_lop lop = OACC_ROUTINE_LOP_NONE;
2386
2387 old_loc = gfc_current_locus;
2388
2389 m = gfc_match (" (");
2390
2391 if (gfc_current_ns->proc_name
2392 && gfc_current_ns->proc_name->attr.if_source == IFSRC_IFBODY
2393 && m == MATCH_YES)
2394 {
2395 gfc_error ("Only the !$ACC ROUTINE form without "
2396 "list is allowed in interface block at %C");
2397 goto cleanup;
2398 }
2399
2400 if (m == MATCH_YES)
2401 {
2402 char buffer[GFC_MAX_SYMBOL_LEN + 1];
2403
2404 m = gfc_match_name (buffer);
2405 if (m == MATCH_YES)
2406 {
2407 gfc_symtree *st = NULL;
2408
2409 /* First look for an intrinsic symbol. */
2410 isym = gfc_find_function (buffer);
2411 if (!isym)
2412 isym = gfc_find_subroutine (buffer);
2413 /* If no intrinsic symbol found, search the current namespace. */
2414 if (!isym)
2415 st = gfc_find_symtree (gfc_current_ns->sym_root, buffer);
2416 if (st)
2417 {
2418 sym = st->n.sym;
2419 /* If the name in a 'routine' directive refers to the containing
2420 subroutine or function, then make sure that we'll later handle
2421 this accordingly. */
2422 if (gfc_current_ns->proc_name != NULL
2423 && strcmp (sym->name, gfc_current_ns->proc_name->name) == 0)
2424 sym = NULL;
2425 }
2426
2427 if (isym == NULL && st == NULL)
2428 {
2429 gfc_error ("Invalid NAME %qs in !$ACC ROUTINE ( NAME ) at %C",
2430 buffer);
2431 gfc_current_locus = old_loc;
2432 return MATCH_ERROR;
2433 }
2434 }
2435 else
2436 {
2437 gfc_error ("Syntax error in !$ACC ROUTINE ( NAME ) at %C");
2438 gfc_current_locus = old_loc;
2439 return MATCH_ERROR;
2440 }
2441
2442 if (gfc_match_char (')') != MATCH_YES)
2443 {
2444 gfc_error ("Syntax error in !$ACC ROUTINE ( NAME ) at %C, expecting"
2445 " ')' after NAME");
2446 gfc_current_locus = old_loc;
2447 return MATCH_ERROR;
2448 }
2449 }
2450
2451 if (gfc_match_omp_eos () != MATCH_YES
2452 && (gfc_match_omp_clauses (&c, OACC_ROUTINE_CLAUSES, false, false, true)
2453 != MATCH_YES))
2454 return MATCH_ERROR;
2455
2456 lop = gfc_oacc_routine_lop (c);
2457 if (lop == OACC_ROUTINE_LOP_ERROR)
2458 {
2459 gfc_error ("Multiple loop axes specified for routine at %C");
2460 goto cleanup;
2461 }
2462
2463 if (isym != NULL)
2464 {
2465 /* Diagnose any OpenACC 'routine' directive that doesn't match the
2466 (implicit) one with a 'seq' clause. */
2467 if (c && (c->gang || c->worker || c->vector))
2468 {
2469 gfc_error ("Intrinsic symbol specified in !$ACC ROUTINE ( NAME )"
2470 " at %C marked with incompatible GANG, WORKER, or VECTOR"
2471 " clause");
2472 goto cleanup;
2473 }
2474 }
2475 else if (sym != NULL)
2476 {
2477 bool add = true;
2478
2479 /* For a repeated OpenACC 'routine' directive, diagnose if it doesn't
2480 match the first one. */
2481 for (gfc_oacc_routine_name *n_p = gfc_current_ns->oacc_routine_names;
2482 n_p;
2483 n_p = n_p->next)
2484 if (n_p->sym == sym)
2485 {
2486 add = false;
2487 if (lop != gfc_oacc_routine_lop (n_p->clauses))
2488 {
2489 gfc_error ("!$ACC ROUTINE already applied at %C");
2490 goto cleanup;
2491 }
2492 }
2493
2494 if (add)
2495 {
2496 sym->attr.oacc_routine_lop = lop;
2497
2498 n = gfc_get_oacc_routine_name ();
2499 n->sym = sym;
2500 n->clauses = c;
2501 n->next = gfc_current_ns->oacc_routine_names;
2502 n->loc = old_loc;
2503 gfc_current_ns->oacc_routine_names = n;
2504 }
2505 }
2506 else if (gfc_current_ns->proc_name)
2507 {
2508 /* For a repeated OpenACC 'routine' directive, diagnose if it doesn't
2509 match the first one. */
2510 oacc_routine_lop lop_p = gfc_current_ns->proc_name->attr.oacc_routine_lop;
2511 if (lop_p != OACC_ROUTINE_LOP_NONE
2512 && lop != lop_p)
2513 {
2514 gfc_error ("!$ACC ROUTINE already applied at %C");
2515 goto cleanup;
2516 }
2517
2518 if (!gfc_add_omp_declare_target (&gfc_current_ns->proc_name->attr,
2519 gfc_current_ns->proc_name->name,
2520 &old_loc))
2521 goto cleanup;
2522 gfc_current_ns->proc_name->attr.oacc_routine_lop = lop;
2523 }
2524 else
2525 /* Something has gone wrong, possibly a syntax error. */
2526 goto cleanup;
2527
2528 if (n)
2529 n->clauses = c;
2530 else if (gfc_current_ns->oacc_routine)
2531 gfc_current_ns->oacc_routine_clauses = c;
2532
2533 new_st.op = EXEC_OACC_ROUTINE;
2534 new_st.ext.omp_clauses = c;
2535 return MATCH_YES;
2536
2537 cleanup:
2538 gfc_current_locus = old_loc;
2539 return MATCH_ERROR;
2540 }
2541
2542
2543 #define OMP_PARALLEL_CLAUSES \
2544 (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
2545 | OMP_CLAUSE_SHARED | OMP_CLAUSE_COPYIN | OMP_CLAUSE_REDUCTION \
2546 | OMP_CLAUSE_IF | OMP_CLAUSE_NUM_THREADS | OMP_CLAUSE_DEFAULT \
2547 | OMP_CLAUSE_PROC_BIND)
2548 #define OMP_DECLARE_SIMD_CLAUSES \
2549 (omp_mask (OMP_CLAUSE_SIMDLEN) | OMP_CLAUSE_LINEAR \
2550 | OMP_CLAUSE_UNIFORM | OMP_CLAUSE_ALIGNED | OMP_CLAUSE_INBRANCH \
2551 | OMP_CLAUSE_NOTINBRANCH)
2552 #define OMP_DO_CLAUSES \
2553 (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
2554 | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION \
2555 | OMP_CLAUSE_SCHEDULE | OMP_CLAUSE_ORDERED | OMP_CLAUSE_COLLAPSE \
2556 | OMP_CLAUSE_LINEAR)
2557 #define OMP_SECTIONS_CLAUSES \
2558 (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
2559 | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION)
2560 #define OMP_SIMD_CLAUSES \
2561 (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_LASTPRIVATE \
2562 | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_SAFELEN \
2563 | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ALIGNED | OMP_CLAUSE_SIMDLEN)
2564 #define OMP_TASK_CLAUSES \
2565 (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
2566 | OMP_CLAUSE_SHARED | OMP_CLAUSE_IF | OMP_CLAUSE_DEFAULT \
2567 | OMP_CLAUSE_UNTIED | OMP_CLAUSE_FINAL | OMP_CLAUSE_MERGEABLE \
2568 | OMP_CLAUSE_DEPEND | OMP_CLAUSE_PRIORITY)
2569 #define OMP_TASKLOOP_CLAUSES \
2570 (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
2571 | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_IF \
2572 | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_UNTIED | OMP_CLAUSE_FINAL \
2573 | OMP_CLAUSE_MERGEABLE | OMP_CLAUSE_PRIORITY | OMP_CLAUSE_GRAINSIZE \
2574 | OMP_CLAUSE_NUM_TASKS | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_NOGROUP)
2575 #define OMP_TARGET_CLAUSES \
2576 (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF \
2577 | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_PRIVATE \
2578 | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_DEFAULTMAP \
2579 | OMP_CLAUSE_IS_DEVICE_PTR)
2580 #define OMP_TARGET_DATA_CLAUSES \
2581 (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF \
2582 | OMP_CLAUSE_USE_DEVICE_PTR | OMP_CLAUSE_USE_DEVICE_ADDR)
2583 #define OMP_TARGET_ENTER_DATA_CLAUSES \
2584 (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF \
2585 | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT)
2586 #define OMP_TARGET_EXIT_DATA_CLAUSES \
2587 (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF \
2588 | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT)
2589 #define OMP_TARGET_UPDATE_CLAUSES \
2590 (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_IF | OMP_CLAUSE_TO \
2591 | OMP_CLAUSE_FROM | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT)
2592 #define OMP_TEAMS_CLAUSES \
2593 (omp_mask (OMP_CLAUSE_NUM_TEAMS) | OMP_CLAUSE_THREAD_LIMIT \
2594 | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE \
2595 | OMP_CLAUSE_SHARED | OMP_CLAUSE_REDUCTION)
2596 #define OMP_DISTRIBUTE_CLAUSES \
2597 (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \
2598 | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_DIST_SCHEDULE)
2599 #define OMP_SINGLE_CLAUSES \
2600 (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE)
2601 #define OMP_ORDERED_CLAUSES \
2602 (omp_mask (OMP_CLAUSE_THREADS) | OMP_CLAUSE_SIMD)
2603 #define OMP_DECLARE_TARGET_CLAUSES \
2604 (omp_mask (OMP_CLAUSE_TO) | OMP_CLAUSE_LINK)
2605
2606
2607 static match
match_omp(gfc_exec_op op,const omp_mask mask)2608 match_omp (gfc_exec_op op, const omp_mask mask)
2609 {
2610 gfc_omp_clauses *c;
2611 if (gfc_match_omp_clauses (&c, mask) != MATCH_YES)
2612 return MATCH_ERROR;
2613 new_st.op = op;
2614 new_st.ext.omp_clauses = c;
2615 return MATCH_YES;
2616 }
2617
2618
2619 match
gfc_match_omp_critical(void)2620 gfc_match_omp_critical (void)
2621 {
2622 char n[GFC_MAX_SYMBOL_LEN+1];
2623 gfc_omp_clauses *c = NULL;
2624
2625 if (gfc_match (" ( %n )", n) != MATCH_YES)
2626 {
2627 n[0] = '\0';
2628 if (gfc_match_omp_eos () != MATCH_YES)
2629 {
2630 gfc_error ("Unexpected junk after $OMP CRITICAL statement at %C");
2631 return MATCH_ERROR;
2632 }
2633 }
2634 else if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_HINT)) != MATCH_YES)
2635 return MATCH_ERROR;
2636
2637 new_st.op = EXEC_OMP_CRITICAL;
2638 new_st.ext.omp_clauses = c;
2639 if (n[0])
2640 c->critical_name = xstrdup (n);
2641 return MATCH_YES;
2642 }
2643
2644
2645 match
gfc_match_omp_end_critical(void)2646 gfc_match_omp_end_critical (void)
2647 {
2648 char n[GFC_MAX_SYMBOL_LEN+1];
2649
2650 if (gfc_match (" ( %n )", n) != MATCH_YES)
2651 n[0] = '\0';
2652 if (gfc_match_omp_eos () != MATCH_YES)
2653 {
2654 gfc_error ("Unexpected junk after $OMP CRITICAL statement at %C");
2655 return MATCH_ERROR;
2656 }
2657
2658 new_st.op = EXEC_OMP_END_CRITICAL;
2659 new_st.ext.omp_name = n[0] ? xstrdup (n) : NULL;
2660 return MATCH_YES;
2661 }
2662
2663
2664 match
gfc_match_omp_distribute(void)2665 gfc_match_omp_distribute (void)
2666 {
2667 return match_omp (EXEC_OMP_DISTRIBUTE, OMP_DISTRIBUTE_CLAUSES);
2668 }
2669
2670
2671 match
gfc_match_omp_distribute_parallel_do(void)2672 gfc_match_omp_distribute_parallel_do (void)
2673 {
2674 return match_omp (EXEC_OMP_DISTRIBUTE_PARALLEL_DO,
2675 (OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
2676 | OMP_DO_CLAUSES)
2677 & ~(omp_mask (OMP_CLAUSE_ORDERED))
2678 & ~(omp_mask (OMP_CLAUSE_LINEAR)));
2679 }
2680
2681
2682 match
gfc_match_omp_distribute_parallel_do_simd(void)2683 gfc_match_omp_distribute_parallel_do_simd (void)
2684 {
2685 return match_omp (EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD,
2686 (OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
2687 | OMP_DO_CLAUSES | OMP_SIMD_CLAUSES)
2688 & ~(omp_mask (OMP_CLAUSE_ORDERED)));
2689 }
2690
2691
2692 match
gfc_match_omp_distribute_simd(void)2693 gfc_match_omp_distribute_simd (void)
2694 {
2695 return match_omp (EXEC_OMP_DISTRIBUTE_SIMD,
2696 OMP_DISTRIBUTE_CLAUSES | OMP_SIMD_CLAUSES);
2697 }
2698
2699
2700 match
gfc_match_omp_do(void)2701 gfc_match_omp_do (void)
2702 {
2703 return match_omp (EXEC_OMP_DO, OMP_DO_CLAUSES);
2704 }
2705
2706
2707 match
gfc_match_omp_do_simd(void)2708 gfc_match_omp_do_simd (void)
2709 {
2710 return match_omp (EXEC_OMP_DO_SIMD, OMP_DO_CLAUSES | OMP_SIMD_CLAUSES);
2711 }
2712
2713
2714 match
gfc_match_omp_flush(void)2715 gfc_match_omp_flush (void)
2716 {
2717 gfc_omp_namelist *list = NULL;
2718 gfc_match_omp_variable_list (" (", &list, true);
2719 if (gfc_match_omp_eos () != MATCH_YES)
2720 {
2721 gfc_error ("Unexpected junk after $OMP FLUSH statement at %C");
2722 gfc_free_omp_namelist (list);
2723 return MATCH_ERROR;
2724 }
2725 new_st.op = EXEC_OMP_FLUSH;
2726 new_st.ext.omp_namelist = list;
2727 return MATCH_YES;
2728 }
2729
2730
2731 match
gfc_match_omp_declare_simd(void)2732 gfc_match_omp_declare_simd (void)
2733 {
2734 locus where = gfc_current_locus;
2735 gfc_symbol *proc_name;
2736 gfc_omp_clauses *c;
2737 gfc_omp_declare_simd *ods;
2738 bool needs_space = false;
2739
2740 switch (gfc_match (" ( %s ) ", &proc_name))
2741 {
2742 case MATCH_YES: break;
2743 case MATCH_NO: proc_name = NULL; needs_space = true; break;
2744 case MATCH_ERROR: return MATCH_ERROR;
2745 }
2746
2747 if (gfc_match_omp_clauses (&c, OMP_DECLARE_SIMD_CLAUSES, true,
2748 needs_space) != MATCH_YES)
2749 return MATCH_ERROR;
2750
2751 if (gfc_current_ns->is_block_data)
2752 {
2753 gfc_free_omp_clauses (c);
2754 return MATCH_YES;
2755 }
2756
2757 ods = gfc_get_omp_declare_simd ();
2758 ods->where = where;
2759 ods->proc_name = proc_name;
2760 ods->clauses = c;
2761 ods->next = gfc_current_ns->omp_declare_simd;
2762 gfc_current_ns->omp_declare_simd = ods;
2763 return MATCH_YES;
2764 }
2765
2766
2767 static bool
match_udr_expr(gfc_symtree * omp_sym1,gfc_symtree * omp_sym2)2768 match_udr_expr (gfc_symtree *omp_sym1, gfc_symtree *omp_sym2)
2769 {
2770 match m;
2771 locus old_loc = gfc_current_locus;
2772 char sname[GFC_MAX_SYMBOL_LEN + 1];
2773 gfc_symbol *sym;
2774 gfc_namespace *ns = gfc_current_ns;
2775 gfc_expr *lvalue = NULL, *rvalue = NULL;
2776 gfc_symtree *st;
2777 gfc_actual_arglist *arglist;
2778
2779 m = gfc_match (" %v =", &lvalue);
2780 if (m != MATCH_YES)
2781 gfc_current_locus = old_loc;
2782 else
2783 {
2784 m = gfc_match (" %e )", &rvalue);
2785 if (m == MATCH_YES)
2786 {
2787 ns->code = gfc_get_code (EXEC_ASSIGN);
2788 ns->code->expr1 = lvalue;
2789 ns->code->expr2 = rvalue;
2790 ns->code->loc = old_loc;
2791 return true;
2792 }
2793
2794 gfc_current_locus = old_loc;
2795 gfc_free_expr (lvalue);
2796 }
2797
2798 m = gfc_match (" %n", sname);
2799 if (m != MATCH_YES)
2800 return false;
2801
2802 if (strcmp (sname, omp_sym1->name) == 0
2803 || strcmp (sname, omp_sym2->name) == 0)
2804 return false;
2805
2806 gfc_current_ns = ns->parent;
2807 if (gfc_get_ha_sym_tree (sname, &st))
2808 return false;
2809
2810 sym = st->n.sym;
2811 if (sym->attr.flavor != FL_PROCEDURE
2812 && sym->attr.flavor != FL_UNKNOWN)
2813 return false;
2814
2815 if (!sym->attr.generic
2816 && !sym->attr.subroutine
2817 && !sym->attr.function)
2818 {
2819 if (!(sym->attr.external && !sym->attr.referenced))
2820 {
2821 /* ...create a symbol in this scope... */
2822 if (sym->ns != gfc_current_ns
2823 && gfc_get_sym_tree (sname, NULL, &st, false) == 1)
2824 return false;
2825
2826 if (sym != st->n.sym)
2827 sym = st->n.sym;
2828 }
2829
2830 /* ...and then to try to make the symbol into a subroutine. */
2831 if (!gfc_add_subroutine (&sym->attr, sym->name, NULL))
2832 return false;
2833 }
2834
2835 gfc_set_sym_referenced (sym);
2836 gfc_gobble_whitespace ();
2837 if (gfc_peek_ascii_char () != '(')
2838 return false;
2839
2840 gfc_current_ns = ns;
2841 m = gfc_match_actual_arglist (1, &arglist);
2842 if (m != MATCH_YES)
2843 return false;
2844
2845 if (gfc_match_char (')') != MATCH_YES)
2846 return false;
2847
2848 ns->code = gfc_get_code (EXEC_CALL);
2849 ns->code->symtree = st;
2850 ns->code->ext.actual = arglist;
2851 ns->code->loc = old_loc;
2852 return true;
2853 }
2854
2855 static bool
gfc_omp_udr_predef(gfc_omp_reduction_op rop,const char * name,gfc_typespec * ts,const char ** n)2856 gfc_omp_udr_predef (gfc_omp_reduction_op rop, const char *name,
2857 gfc_typespec *ts, const char **n)
2858 {
2859 if (!gfc_numeric_ts (ts) && ts->type != BT_LOGICAL)
2860 return false;
2861
2862 switch (rop)
2863 {
2864 case OMP_REDUCTION_PLUS:
2865 case OMP_REDUCTION_MINUS:
2866 case OMP_REDUCTION_TIMES:
2867 return ts->type != BT_LOGICAL;
2868 case OMP_REDUCTION_AND:
2869 case OMP_REDUCTION_OR:
2870 case OMP_REDUCTION_EQV:
2871 case OMP_REDUCTION_NEQV:
2872 return ts->type == BT_LOGICAL;
2873 case OMP_REDUCTION_USER:
2874 if (name[0] != '.' && (ts->type == BT_INTEGER || ts->type == BT_REAL))
2875 {
2876 gfc_symbol *sym;
2877
2878 gfc_find_symbol (name, NULL, 1, &sym);
2879 if (sym != NULL)
2880 {
2881 if (sym->attr.intrinsic)
2882 *n = sym->name;
2883 else if ((sym->attr.flavor != FL_UNKNOWN
2884 && sym->attr.flavor != FL_PROCEDURE)
2885 || sym->attr.external
2886 || sym->attr.generic
2887 || sym->attr.entry
2888 || sym->attr.result
2889 || sym->attr.dummy
2890 || sym->attr.subroutine
2891 || sym->attr.pointer
2892 || sym->attr.target
2893 || sym->attr.cray_pointer
2894 || sym->attr.cray_pointee
2895 || (sym->attr.proc != PROC_UNKNOWN
2896 && sym->attr.proc != PROC_INTRINSIC)
2897 || sym->attr.if_source != IFSRC_UNKNOWN
2898 || sym == sym->ns->proc_name)
2899 *n = NULL;
2900 else
2901 *n = sym->name;
2902 }
2903 else
2904 *n = name;
2905 if (*n
2906 && (strcmp (*n, "max") == 0 || strcmp (*n, "min") == 0))
2907 return true;
2908 else if (*n
2909 && ts->type == BT_INTEGER
2910 && (strcmp (*n, "iand") == 0
2911 || strcmp (*n, "ior") == 0
2912 || strcmp (*n, "ieor") == 0))
2913 return true;
2914 }
2915 break;
2916 default:
2917 break;
2918 }
2919 return false;
2920 }
2921
2922 gfc_omp_udr *
gfc_omp_udr_find(gfc_symtree * st,gfc_typespec * ts)2923 gfc_omp_udr_find (gfc_symtree *st, gfc_typespec *ts)
2924 {
2925 gfc_omp_udr *omp_udr;
2926
2927 if (st == NULL)
2928 return NULL;
2929
2930 for (omp_udr = st->n.omp_udr; omp_udr; omp_udr = omp_udr->next)
2931 if (omp_udr->ts.type == ts->type
2932 || ((omp_udr->ts.type == BT_DERIVED || omp_udr->ts.type == BT_CLASS)
2933 && (ts->type == BT_DERIVED || ts->type == BT_CLASS)))
2934 {
2935 if (omp_udr->ts.type == BT_DERIVED || omp_udr->ts.type == BT_CLASS)
2936 {
2937 if (strcmp (omp_udr->ts.u.derived->name, ts->u.derived->name) == 0)
2938 return omp_udr;
2939 }
2940 else if (omp_udr->ts.kind == ts->kind)
2941 {
2942 if (omp_udr->ts.type == BT_CHARACTER)
2943 {
2944 if (omp_udr->ts.u.cl->length == NULL
2945 || ts->u.cl->length == NULL)
2946 return omp_udr;
2947 if (omp_udr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
2948 return omp_udr;
2949 if (ts->u.cl->length->expr_type != EXPR_CONSTANT)
2950 return omp_udr;
2951 if (omp_udr->ts.u.cl->length->ts.type != BT_INTEGER)
2952 return omp_udr;
2953 if (ts->u.cl->length->ts.type != BT_INTEGER)
2954 return omp_udr;
2955 if (gfc_compare_expr (omp_udr->ts.u.cl->length,
2956 ts->u.cl->length, INTRINSIC_EQ) != 0)
2957 continue;
2958 }
2959 return omp_udr;
2960 }
2961 }
2962 return NULL;
2963 }
2964
2965 match
gfc_match_omp_declare_reduction(void)2966 gfc_match_omp_declare_reduction (void)
2967 {
2968 match m;
2969 gfc_intrinsic_op op;
2970 char name[GFC_MAX_SYMBOL_LEN + 3];
2971 auto_vec<gfc_typespec, 5> tss;
2972 gfc_typespec ts;
2973 unsigned int i;
2974 gfc_symtree *st;
2975 locus where = gfc_current_locus;
2976 locus end_loc = gfc_current_locus;
2977 bool end_loc_set = false;
2978 gfc_omp_reduction_op rop = OMP_REDUCTION_NONE;
2979
2980 if (gfc_match_char ('(') != MATCH_YES)
2981 return MATCH_ERROR;
2982
2983 m = gfc_match (" %o : ", &op);
2984 if (m == MATCH_ERROR)
2985 return MATCH_ERROR;
2986 if (m == MATCH_YES)
2987 {
2988 snprintf (name, sizeof name, "operator %s", gfc_op2string (op));
2989 rop = (gfc_omp_reduction_op) op;
2990 }
2991 else
2992 {
2993 m = gfc_match_defined_op_name (name + 1, 1);
2994 if (m == MATCH_ERROR)
2995 return MATCH_ERROR;
2996 if (m == MATCH_YES)
2997 {
2998 name[0] = '.';
2999 strcat (name, ".");
3000 if (gfc_match (" : ") != MATCH_YES)
3001 return MATCH_ERROR;
3002 }
3003 else
3004 {
3005 if (gfc_match (" %n : ", name) != MATCH_YES)
3006 return MATCH_ERROR;
3007 }
3008 rop = OMP_REDUCTION_USER;
3009 }
3010
3011 m = gfc_match_type_spec (&ts);
3012 if (m != MATCH_YES)
3013 return MATCH_ERROR;
3014 /* Treat len=: the same as len=*. */
3015 if (ts.type == BT_CHARACTER)
3016 ts.deferred = false;
3017 tss.safe_push (ts);
3018
3019 while (gfc_match_char (',') == MATCH_YES)
3020 {
3021 m = gfc_match_type_spec (&ts);
3022 if (m != MATCH_YES)
3023 return MATCH_ERROR;
3024 tss.safe_push (ts);
3025 }
3026 if (gfc_match_char (':') != MATCH_YES)
3027 return MATCH_ERROR;
3028
3029 st = gfc_find_symtree (gfc_current_ns->omp_udr_root, name);
3030 for (i = 0; i < tss.length (); i++)
3031 {
3032 gfc_symtree *omp_out, *omp_in;
3033 gfc_symtree *omp_priv = NULL, *omp_orig = NULL;
3034 gfc_namespace *combiner_ns, *initializer_ns = NULL;
3035 gfc_omp_udr *prev_udr, *omp_udr;
3036 const char *predef_name = NULL;
3037
3038 omp_udr = gfc_get_omp_udr ();
3039 omp_udr->name = gfc_get_string ("%s", name);
3040 omp_udr->rop = rop;
3041 omp_udr->ts = tss[i];
3042 omp_udr->where = where;
3043
3044 gfc_current_ns = combiner_ns = gfc_get_namespace (gfc_current_ns, 1);
3045 combiner_ns->proc_name = combiner_ns->parent->proc_name;
3046
3047 gfc_get_sym_tree ("omp_out", combiner_ns, &omp_out, false);
3048 gfc_get_sym_tree ("omp_in", combiner_ns, &omp_in, false);
3049 combiner_ns->omp_udr_ns = 1;
3050 omp_out->n.sym->ts = tss[i];
3051 omp_in->n.sym->ts = tss[i];
3052 omp_out->n.sym->attr.omp_udr_artificial_var = 1;
3053 omp_in->n.sym->attr.omp_udr_artificial_var = 1;
3054 omp_out->n.sym->attr.flavor = FL_VARIABLE;
3055 omp_in->n.sym->attr.flavor = FL_VARIABLE;
3056 gfc_commit_symbols ();
3057 omp_udr->combiner_ns = combiner_ns;
3058 omp_udr->omp_out = omp_out->n.sym;
3059 omp_udr->omp_in = omp_in->n.sym;
3060
3061 locus old_loc = gfc_current_locus;
3062
3063 if (!match_udr_expr (omp_out, omp_in))
3064 {
3065 syntax:
3066 gfc_current_locus = old_loc;
3067 gfc_current_ns = combiner_ns->parent;
3068 gfc_undo_symbols ();
3069 gfc_free_omp_udr (omp_udr);
3070 return MATCH_ERROR;
3071 }
3072
3073 if (gfc_match (" initializer ( ") == MATCH_YES)
3074 {
3075 gfc_current_ns = combiner_ns->parent;
3076 initializer_ns = gfc_get_namespace (gfc_current_ns, 1);
3077 gfc_current_ns = initializer_ns;
3078 initializer_ns->proc_name = initializer_ns->parent->proc_name;
3079
3080 gfc_get_sym_tree ("omp_priv", initializer_ns, &omp_priv, false);
3081 gfc_get_sym_tree ("omp_orig", initializer_ns, &omp_orig, false);
3082 initializer_ns->omp_udr_ns = 1;
3083 omp_priv->n.sym->ts = tss[i];
3084 omp_orig->n.sym->ts = tss[i];
3085 omp_priv->n.sym->attr.omp_udr_artificial_var = 1;
3086 omp_orig->n.sym->attr.omp_udr_artificial_var = 1;
3087 omp_priv->n.sym->attr.flavor = FL_VARIABLE;
3088 omp_orig->n.sym->attr.flavor = FL_VARIABLE;
3089 gfc_commit_symbols ();
3090 omp_udr->initializer_ns = initializer_ns;
3091 omp_udr->omp_priv = omp_priv->n.sym;
3092 omp_udr->omp_orig = omp_orig->n.sym;
3093
3094 if (!match_udr_expr (omp_priv, omp_orig))
3095 goto syntax;
3096 }
3097
3098 gfc_current_ns = combiner_ns->parent;
3099 if (!end_loc_set)
3100 {
3101 end_loc_set = true;
3102 end_loc = gfc_current_locus;
3103 }
3104 gfc_current_locus = old_loc;
3105
3106 prev_udr = gfc_omp_udr_find (st, &tss[i]);
3107 if (gfc_omp_udr_predef (rop, name, &tss[i], &predef_name)
3108 /* Don't error on !$omp declare reduction (min : integer : ...)
3109 just yet, there could be integer :: min afterwards,
3110 making it valid. When the UDR is resolved, we'll get
3111 to it again. */
3112 && (rop != OMP_REDUCTION_USER || name[0] == '.'))
3113 {
3114 if (predef_name)
3115 gfc_error_now ("Redefinition of predefined %s "
3116 "!$OMP DECLARE REDUCTION at %L",
3117 predef_name, &where);
3118 else
3119 gfc_error_now ("Redefinition of predefined "
3120 "!$OMP DECLARE REDUCTION at %L", &where);
3121 }
3122 else if (prev_udr)
3123 {
3124 gfc_error_now ("Redefinition of !$OMP DECLARE REDUCTION at %L",
3125 &where);
3126 gfc_error_now ("Previous !$OMP DECLARE REDUCTION at %L",
3127 &prev_udr->where);
3128 }
3129 else if (st)
3130 {
3131 omp_udr->next = st->n.omp_udr;
3132 st->n.omp_udr = omp_udr;
3133 }
3134 else
3135 {
3136 st = gfc_new_symtree (&gfc_current_ns->omp_udr_root, name);
3137 st->n.omp_udr = omp_udr;
3138 }
3139 }
3140
3141 if (end_loc_set)
3142 {
3143 gfc_current_locus = end_loc;
3144 if (gfc_match_omp_eos () != MATCH_YES)
3145 {
3146 gfc_error ("Unexpected junk after !$OMP DECLARE REDUCTION at %C");
3147 gfc_current_locus = where;
3148 return MATCH_ERROR;
3149 }
3150
3151 return MATCH_YES;
3152 }
3153 gfc_clear_error ();
3154 return MATCH_ERROR;
3155 }
3156
3157
3158 match
gfc_match_omp_declare_target(void)3159 gfc_match_omp_declare_target (void)
3160 {
3161 locus old_loc;
3162 match m;
3163 gfc_omp_clauses *c = NULL;
3164 int list;
3165 gfc_omp_namelist *n;
3166 gfc_symbol *s;
3167
3168 old_loc = gfc_current_locus;
3169
3170 if (gfc_current_ns->proc_name
3171 && gfc_match_omp_eos () == MATCH_YES)
3172 {
3173 if (!gfc_add_omp_declare_target (&gfc_current_ns->proc_name->attr,
3174 gfc_current_ns->proc_name->name,
3175 &old_loc))
3176 goto cleanup;
3177 return MATCH_YES;
3178 }
3179
3180 if (gfc_current_ns->proc_name
3181 && gfc_current_ns->proc_name->attr.if_source == IFSRC_IFBODY)
3182 {
3183 gfc_error ("Only the !$OMP DECLARE TARGET form without "
3184 "clauses is allowed in interface block at %C");
3185 goto cleanup;
3186 }
3187
3188 m = gfc_match (" (");
3189 if (m == MATCH_YES)
3190 {
3191 c = gfc_get_omp_clauses ();
3192 gfc_current_locus = old_loc;
3193 m = gfc_match_omp_to_link (" (", &c->lists[OMP_LIST_TO]);
3194 if (m != MATCH_YES)
3195 goto syntax;
3196 if (gfc_match_omp_eos () != MATCH_YES)
3197 {
3198 gfc_error ("Unexpected junk after !$OMP DECLARE TARGET at %C");
3199 goto cleanup;
3200 }
3201 }
3202 else if (gfc_match_omp_clauses (&c, OMP_DECLARE_TARGET_CLAUSES) != MATCH_YES)
3203 return MATCH_ERROR;
3204
3205 gfc_buffer_error (false);
3206
3207 for (list = OMP_LIST_TO; list != OMP_LIST_NUM;
3208 list = (list == OMP_LIST_TO ? OMP_LIST_LINK : OMP_LIST_NUM))
3209 for (n = c->lists[list]; n; n = n->next)
3210 if (n->sym)
3211 n->sym->mark = 0;
3212 else if (n->u.common->head)
3213 n->u.common->head->mark = 0;
3214
3215 for (list = OMP_LIST_TO; list != OMP_LIST_NUM;
3216 list = (list == OMP_LIST_TO ? OMP_LIST_LINK : OMP_LIST_NUM))
3217 for (n = c->lists[list]; n; n = n->next)
3218 if (n->sym)
3219 {
3220 if (n->sym->attr.in_common)
3221 gfc_error_now ("OMP DECLARE TARGET variable at %L is an "
3222 "element of a COMMON block", &n->where);
3223 else if (n->sym->attr.omp_declare_target
3224 && n->sym->attr.omp_declare_target_link
3225 && list != OMP_LIST_LINK)
3226 gfc_error_now ("OMP DECLARE TARGET variable at %L previously "
3227 "mentioned in LINK clause and later in TO clause",
3228 &n->where);
3229 else if (n->sym->attr.omp_declare_target
3230 && !n->sym->attr.omp_declare_target_link
3231 && list == OMP_LIST_LINK)
3232 gfc_error_now ("OMP DECLARE TARGET variable at %L previously "
3233 "mentioned in TO clause and later in LINK clause",
3234 &n->where);
3235 else if (n->sym->mark)
3236 gfc_error_now ("Variable at %L mentioned multiple times in "
3237 "clauses of the same OMP DECLARE TARGET directive",
3238 &n->where);
3239 else if (gfc_add_omp_declare_target (&n->sym->attr, n->sym->name,
3240 &n->sym->declared_at))
3241 {
3242 if (list == OMP_LIST_LINK)
3243 gfc_add_omp_declare_target_link (&n->sym->attr, n->sym->name,
3244 &n->sym->declared_at);
3245 }
3246 n->sym->mark = 1;
3247 }
3248 else if (n->u.common->omp_declare_target
3249 && n->u.common->omp_declare_target_link
3250 && list != OMP_LIST_LINK)
3251 gfc_error_now ("OMP DECLARE TARGET COMMON at %L previously "
3252 "mentioned in LINK clause and later in TO clause",
3253 &n->where);
3254 else if (n->u.common->omp_declare_target
3255 && !n->u.common->omp_declare_target_link
3256 && list == OMP_LIST_LINK)
3257 gfc_error_now ("OMP DECLARE TARGET COMMON at %L previously "
3258 "mentioned in TO clause and later in LINK clause",
3259 &n->where);
3260 else if (n->u.common->head && n->u.common->head->mark)
3261 gfc_error_now ("COMMON at %L mentioned multiple times in "
3262 "clauses of the same OMP DECLARE TARGET directive",
3263 &n->where);
3264 else
3265 {
3266 n->u.common->omp_declare_target = 1;
3267 n->u.common->omp_declare_target_link = (list == OMP_LIST_LINK);
3268 for (s = n->u.common->head; s; s = s->common_next)
3269 {
3270 s->mark = 1;
3271 if (gfc_add_omp_declare_target (&s->attr, s->name,
3272 &s->declared_at))
3273 {
3274 if (list == OMP_LIST_LINK)
3275 gfc_add_omp_declare_target_link (&s->attr, s->name,
3276 &s->declared_at);
3277 }
3278 }
3279 }
3280
3281 gfc_buffer_error (true);
3282
3283 if (c)
3284 gfc_free_omp_clauses (c);
3285 return MATCH_YES;
3286
3287 syntax:
3288 gfc_error ("Syntax error in !$OMP DECLARE TARGET list at %C");
3289
3290 cleanup:
3291 gfc_current_locus = old_loc;
3292 if (c)
3293 gfc_free_omp_clauses (c);
3294 return MATCH_ERROR;
3295 }
3296
3297
3298 match
gfc_match_omp_threadprivate(void)3299 gfc_match_omp_threadprivate (void)
3300 {
3301 locus old_loc;
3302 char n[GFC_MAX_SYMBOL_LEN+1];
3303 gfc_symbol *sym;
3304 match m;
3305 gfc_symtree *st;
3306
3307 old_loc = gfc_current_locus;
3308
3309 m = gfc_match (" (");
3310 if (m != MATCH_YES)
3311 return m;
3312
3313 for (;;)
3314 {
3315 m = gfc_match_symbol (&sym, 0);
3316 switch (m)
3317 {
3318 case MATCH_YES:
3319 if (sym->attr.in_common)
3320 gfc_error_now ("Threadprivate variable at %C is an element of "
3321 "a COMMON block");
3322 else if (!gfc_add_threadprivate (&sym->attr, sym->name, &sym->declared_at))
3323 goto cleanup;
3324 goto next_item;
3325 case MATCH_NO:
3326 break;
3327 case MATCH_ERROR:
3328 goto cleanup;
3329 }
3330
3331 m = gfc_match (" / %n /", n);
3332 if (m == MATCH_ERROR)
3333 goto cleanup;
3334 if (m == MATCH_NO || n[0] == '\0')
3335 goto syntax;
3336
3337 st = gfc_find_symtree (gfc_current_ns->common_root, n);
3338 if (st == NULL)
3339 {
3340 gfc_error ("COMMON block /%s/ not found at %C", n);
3341 goto cleanup;
3342 }
3343 st->n.common->threadprivate = 1;
3344 for (sym = st->n.common->head; sym; sym = sym->common_next)
3345 if (!gfc_add_threadprivate (&sym->attr, sym->name, &sym->declared_at))
3346 goto cleanup;
3347
3348 next_item:
3349 if (gfc_match_char (')') == MATCH_YES)
3350 break;
3351 if (gfc_match_char (',') != MATCH_YES)
3352 goto syntax;
3353 }
3354
3355 if (gfc_match_omp_eos () != MATCH_YES)
3356 {
3357 gfc_error ("Unexpected junk after OMP THREADPRIVATE at %C");
3358 goto cleanup;
3359 }
3360
3361 return MATCH_YES;
3362
3363 syntax:
3364 gfc_error ("Syntax error in !$OMP THREADPRIVATE list at %C");
3365
3366 cleanup:
3367 gfc_current_locus = old_loc;
3368 return MATCH_ERROR;
3369 }
3370
3371
3372 match
gfc_match_omp_parallel(void)3373 gfc_match_omp_parallel (void)
3374 {
3375 return match_omp (EXEC_OMP_PARALLEL, OMP_PARALLEL_CLAUSES);
3376 }
3377
3378
3379 match
gfc_match_omp_parallel_do(void)3380 gfc_match_omp_parallel_do (void)
3381 {
3382 return match_omp (EXEC_OMP_PARALLEL_DO,
3383 OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES);
3384 }
3385
3386
3387 match
gfc_match_omp_parallel_do_simd(void)3388 gfc_match_omp_parallel_do_simd (void)
3389 {
3390 return match_omp (EXEC_OMP_PARALLEL_DO_SIMD,
3391 OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES | OMP_SIMD_CLAUSES);
3392 }
3393
3394
3395 match
gfc_match_omp_parallel_sections(void)3396 gfc_match_omp_parallel_sections (void)
3397 {
3398 return match_omp (EXEC_OMP_PARALLEL_SECTIONS,
3399 OMP_PARALLEL_CLAUSES | OMP_SECTIONS_CLAUSES);
3400 }
3401
3402
3403 match
gfc_match_omp_parallel_workshare(void)3404 gfc_match_omp_parallel_workshare (void)
3405 {
3406 return match_omp (EXEC_OMP_PARALLEL_WORKSHARE, OMP_PARALLEL_CLAUSES);
3407 }
3408
3409
3410 match
gfc_match_omp_sections(void)3411 gfc_match_omp_sections (void)
3412 {
3413 return match_omp (EXEC_OMP_SECTIONS, OMP_SECTIONS_CLAUSES);
3414 }
3415
3416
3417 match
gfc_match_omp_simd(void)3418 gfc_match_omp_simd (void)
3419 {
3420 return match_omp (EXEC_OMP_SIMD, OMP_SIMD_CLAUSES);
3421 }
3422
3423
3424 match
gfc_match_omp_single(void)3425 gfc_match_omp_single (void)
3426 {
3427 return match_omp (EXEC_OMP_SINGLE, OMP_SINGLE_CLAUSES);
3428 }
3429
3430
3431 match
gfc_match_omp_target(void)3432 gfc_match_omp_target (void)
3433 {
3434 return match_omp (EXEC_OMP_TARGET, OMP_TARGET_CLAUSES);
3435 }
3436
3437
3438 match
gfc_match_omp_target_data(void)3439 gfc_match_omp_target_data (void)
3440 {
3441 return match_omp (EXEC_OMP_TARGET_DATA, OMP_TARGET_DATA_CLAUSES);
3442 }
3443
3444
3445 match
gfc_match_omp_target_enter_data(void)3446 gfc_match_omp_target_enter_data (void)
3447 {
3448 return match_omp (EXEC_OMP_TARGET_ENTER_DATA, OMP_TARGET_ENTER_DATA_CLAUSES);
3449 }
3450
3451
3452 match
gfc_match_omp_target_exit_data(void)3453 gfc_match_omp_target_exit_data (void)
3454 {
3455 return match_omp (EXEC_OMP_TARGET_EXIT_DATA, OMP_TARGET_EXIT_DATA_CLAUSES);
3456 }
3457
3458
3459 match
gfc_match_omp_target_parallel(void)3460 gfc_match_omp_target_parallel (void)
3461 {
3462 return match_omp (EXEC_OMP_TARGET_PARALLEL,
3463 (OMP_TARGET_CLAUSES | OMP_PARALLEL_CLAUSES)
3464 & ~(omp_mask (OMP_CLAUSE_COPYIN)));
3465 }
3466
3467
3468 match
gfc_match_omp_target_parallel_do(void)3469 gfc_match_omp_target_parallel_do (void)
3470 {
3471 return match_omp (EXEC_OMP_TARGET_PARALLEL_DO,
3472 (OMP_TARGET_CLAUSES | OMP_PARALLEL_CLAUSES
3473 | OMP_DO_CLAUSES) & ~(omp_mask (OMP_CLAUSE_COPYIN)));
3474 }
3475
3476
3477 match
gfc_match_omp_target_parallel_do_simd(void)3478 gfc_match_omp_target_parallel_do_simd (void)
3479 {
3480 return match_omp (EXEC_OMP_TARGET_PARALLEL_DO_SIMD,
3481 (OMP_TARGET_CLAUSES | OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES
3482 | OMP_SIMD_CLAUSES) & ~(omp_mask (OMP_CLAUSE_COPYIN)));
3483 }
3484
3485
3486 match
gfc_match_omp_target_simd(void)3487 gfc_match_omp_target_simd (void)
3488 {
3489 return match_omp (EXEC_OMP_TARGET_SIMD,
3490 OMP_TARGET_CLAUSES | OMP_SIMD_CLAUSES);
3491 }
3492
3493
3494 match
gfc_match_omp_target_teams(void)3495 gfc_match_omp_target_teams (void)
3496 {
3497 return match_omp (EXEC_OMP_TARGET_TEAMS,
3498 OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES);
3499 }
3500
3501
3502 match
gfc_match_omp_target_teams_distribute(void)3503 gfc_match_omp_target_teams_distribute (void)
3504 {
3505 return match_omp (EXEC_OMP_TARGET_TEAMS_DISTRIBUTE,
3506 OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES
3507 | OMP_DISTRIBUTE_CLAUSES);
3508 }
3509
3510
3511 match
gfc_match_omp_target_teams_distribute_parallel_do(void)3512 gfc_match_omp_target_teams_distribute_parallel_do (void)
3513 {
3514 return match_omp (EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO,
3515 (OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES
3516 | OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
3517 | OMP_DO_CLAUSES)
3518 & ~(omp_mask (OMP_CLAUSE_ORDERED))
3519 & ~(omp_mask (OMP_CLAUSE_LINEAR)));
3520 }
3521
3522
3523 match
gfc_match_omp_target_teams_distribute_parallel_do_simd(void)3524 gfc_match_omp_target_teams_distribute_parallel_do_simd (void)
3525 {
3526 return match_omp (EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD,
3527 (OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES
3528 | OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
3529 | OMP_DO_CLAUSES | OMP_SIMD_CLAUSES)
3530 & ~(omp_mask (OMP_CLAUSE_ORDERED)));
3531 }
3532
3533
3534 match
gfc_match_omp_target_teams_distribute_simd(void)3535 gfc_match_omp_target_teams_distribute_simd (void)
3536 {
3537 return match_omp (EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD,
3538 OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES
3539 | OMP_DISTRIBUTE_CLAUSES | OMP_SIMD_CLAUSES);
3540 }
3541
3542
3543 match
gfc_match_omp_target_update(void)3544 gfc_match_omp_target_update (void)
3545 {
3546 return match_omp (EXEC_OMP_TARGET_UPDATE, OMP_TARGET_UPDATE_CLAUSES);
3547 }
3548
3549
3550 match
gfc_match_omp_task(void)3551 gfc_match_omp_task (void)
3552 {
3553 return match_omp (EXEC_OMP_TASK, OMP_TASK_CLAUSES);
3554 }
3555
3556
3557 match
gfc_match_omp_taskloop(void)3558 gfc_match_omp_taskloop (void)
3559 {
3560 return match_omp (EXEC_OMP_TASKLOOP, OMP_TASKLOOP_CLAUSES);
3561 }
3562
3563
3564 match
gfc_match_omp_taskloop_simd(void)3565 gfc_match_omp_taskloop_simd (void)
3566 {
3567 return match_omp (EXEC_OMP_TASKLOOP_SIMD,
3568 (OMP_TASKLOOP_CLAUSES | OMP_SIMD_CLAUSES)
3569 & ~(omp_mask (OMP_CLAUSE_REDUCTION)));
3570 }
3571
3572
3573 match
gfc_match_omp_taskwait(void)3574 gfc_match_omp_taskwait (void)
3575 {
3576 if (gfc_match_omp_eos () != MATCH_YES)
3577 {
3578 gfc_error ("Unexpected junk after TASKWAIT clause at %C");
3579 return MATCH_ERROR;
3580 }
3581 new_st.op = EXEC_OMP_TASKWAIT;
3582 new_st.ext.omp_clauses = NULL;
3583 return MATCH_YES;
3584 }
3585
3586
3587 match
gfc_match_omp_taskyield(void)3588 gfc_match_omp_taskyield (void)
3589 {
3590 if (gfc_match_omp_eos () != MATCH_YES)
3591 {
3592 gfc_error ("Unexpected junk after TASKYIELD clause at %C");
3593 return MATCH_ERROR;
3594 }
3595 new_st.op = EXEC_OMP_TASKYIELD;
3596 new_st.ext.omp_clauses = NULL;
3597 return MATCH_YES;
3598 }
3599
3600
3601 match
gfc_match_omp_teams(void)3602 gfc_match_omp_teams (void)
3603 {
3604 return match_omp (EXEC_OMP_TEAMS, OMP_TEAMS_CLAUSES);
3605 }
3606
3607
3608 match
gfc_match_omp_teams_distribute(void)3609 gfc_match_omp_teams_distribute (void)
3610 {
3611 return match_omp (EXEC_OMP_TEAMS_DISTRIBUTE,
3612 OMP_TEAMS_CLAUSES | OMP_DISTRIBUTE_CLAUSES);
3613 }
3614
3615
3616 match
gfc_match_omp_teams_distribute_parallel_do(void)3617 gfc_match_omp_teams_distribute_parallel_do (void)
3618 {
3619 return match_omp (EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO,
3620 (OMP_TEAMS_CLAUSES | OMP_DISTRIBUTE_CLAUSES
3621 | OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES)
3622 & ~(omp_mask (OMP_CLAUSE_ORDERED))
3623 & ~(omp_mask (OMP_CLAUSE_LINEAR)));
3624 }
3625
3626
3627 match
gfc_match_omp_teams_distribute_parallel_do_simd(void)3628 gfc_match_omp_teams_distribute_parallel_do_simd (void)
3629 {
3630 return match_omp (EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD,
3631 (OMP_TEAMS_CLAUSES | OMP_DISTRIBUTE_CLAUSES
3632 | OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES
3633 | OMP_SIMD_CLAUSES) & ~(omp_mask (OMP_CLAUSE_ORDERED)));
3634 }
3635
3636
3637 match
gfc_match_omp_teams_distribute_simd(void)3638 gfc_match_omp_teams_distribute_simd (void)
3639 {
3640 return match_omp (EXEC_OMP_TEAMS_DISTRIBUTE_SIMD,
3641 OMP_TEAMS_CLAUSES | OMP_DISTRIBUTE_CLAUSES
3642 | OMP_SIMD_CLAUSES);
3643 }
3644
3645
3646 match
gfc_match_omp_workshare(void)3647 gfc_match_omp_workshare (void)
3648 {
3649 if (gfc_match_omp_eos () != MATCH_YES)
3650 {
3651 gfc_error ("Unexpected junk after $OMP WORKSHARE statement at %C");
3652 return MATCH_ERROR;
3653 }
3654 new_st.op = EXEC_OMP_WORKSHARE;
3655 new_st.ext.omp_clauses = gfc_get_omp_clauses ();
3656 return MATCH_YES;
3657 }
3658
3659
3660 match
gfc_match_omp_master(void)3661 gfc_match_omp_master (void)
3662 {
3663 if (gfc_match_omp_eos () != MATCH_YES)
3664 {
3665 gfc_error ("Unexpected junk after $OMP MASTER statement at %C");
3666 return MATCH_ERROR;
3667 }
3668 new_st.op = EXEC_OMP_MASTER;
3669 new_st.ext.omp_clauses = NULL;
3670 return MATCH_YES;
3671 }
3672
3673
3674 match
gfc_match_omp_ordered(void)3675 gfc_match_omp_ordered (void)
3676 {
3677 return match_omp (EXEC_OMP_ORDERED, OMP_ORDERED_CLAUSES);
3678 }
3679
3680
3681 match
gfc_match_omp_ordered_depend(void)3682 gfc_match_omp_ordered_depend (void)
3683 {
3684 return match_omp (EXEC_OMP_ORDERED, omp_mask (OMP_CLAUSE_DEPEND));
3685 }
3686
3687
3688 static match
gfc_match_omp_oacc_atomic(bool omp_p)3689 gfc_match_omp_oacc_atomic (bool omp_p)
3690 {
3691 gfc_omp_atomic_op op = GFC_OMP_ATOMIC_UPDATE;
3692 int seq_cst = 0;
3693 if (gfc_match ("% seq_cst") == MATCH_YES)
3694 seq_cst = 1;
3695 locus old_loc = gfc_current_locus;
3696 if (seq_cst && gfc_match_char (',') == MATCH_YES)
3697 seq_cst = 2;
3698 if (seq_cst == 2
3699 || gfc_match_space () == MATCH_YES)
3700 {
3701 gfc_gobble_whitespace ();
3702 if (gfc_match ("update") == MATCH_YES)
3703 op = GFC_OMP_ATOMIC_UPDATE;
3704 else if (gfc_match ("read") == MATCH_YES)
3705 op = GFC_OMP_ATOMIC_READ;
3706 else if (gfc_match ("write") == MATCH_YES)
3707 op = GFC_OMP_ATOMIC_WRITE;
3708 else if (gfc_match ("capture") == MATCH_YES)
3709 op = GFC_OMP_ATOMIC_CAPTURE;
3710 else
3711 {
3712 if (seq_cst == 2)
3713 gfc_current_locus = old_loc;
3714 goto finish;
3715 }
3716 if (!seq_cst
3717 && (gfc_match (", seq_cst") == MATCH_YES
3718 || gfc_match ("% seq_cst") == MATCH_YES))
3719 seq_cst = 1;
3720 }
3721 finish:
3722 if (gfc_match_omp_eos () != MATCH_YES)
3723 {
3724 gfc_error ("Unexpected junk after $OMP ATOMIC statement at %C");
3725 return MATCH_ERROR;
3726 }
3727 new_st.op = (omp_p ? EXEC_OMP_ATOMIC : EXEC_OACC_ATOMIC);
3728 if (seq_cst)
3729 op = (gfc_omp_atomic_op) (op | GFC_OMP_ATOMIC_SEQ_CST);
3730 new_st.ext.omp_atomic = op;
3731 return MATCH_YES;
3732 }
3733
3734 match
gfc_match_oacc_atomic(void)3735 gfc_match_oacc_atomic (void)
3736 {
3737 return gfc_match_omp_oacc_atomic (false);
3738 }
3739
3740 match
gfc_match_omp_atomic(void)3741 gfc_match_omp_atomic (void)
3742 {
3743 return gfc_match_omp_oacc_atomic (true);
3744 }
3745
3746 match
gfc_match_omp_barrier(void)3747 gfc_match_omp_barrier (void)
3748 {
3749 if (gfc_match_omp_eos () != MATCH_YES)
3750 {
3751 gfc_error ("Unexpected junk after $OMP BARRIER statement at %C");
3752 return MATCH_ERROR;
3753 }
3754 new_st.op = EXEC_OMP_BARRIER;
3755 new_st.ext.omp_clauses = NULL;
3756 return MATCH_YES;
3757 }
3758
3759
3760 match
gfc_match_omp_taskgroup(void)3761 gfc_match_omp_taskgroup (void)
3762 {
3763 if (gfc_match_omp_eos () != MATCH_YES)
3764 {
3765 gfc_error ("Unexpected junk after $OMP TASKGROUP statement at %C");
3766 return MATCH_ERROR;
3767 }
3768 new_st.op = EXEC_OMP_TASKGROUP;
3769 return MATCH_YES;
3770 }
3771
3772
3773 static enum gfc_omp_cancel_kind
gfc_match_omp_cancel_kind(void)3774 gfc_match_omp_cancel_kind (void)
3775 {
3776 if (gfc_match_space () != MATCH_YES)
3777 return OMP_CANCEL_UNKNOWN;
3778 if (gfc_match ("parallel") == MATCH_YES)
3779 return OMP_CANCEL_PARALLEL;
3780 if (gfc_match ("sections") == MATCH_YES)
3781 return OMP_CANCEL_SECTIONS;
3782 if (gfc_match ("do") == MATCH_YES)
3783 return OMP_CANCEL_DO;
3784 if (gfc_match ("taskgroup") == MATCH_YES)
3785 return OMP_CANCEL_TASKGROUP;
3786 return OMP_CANCEL_UNKNOWN;
3787 }
3788
3789
3790 match
gfc_match_omp_cancel(void)3791 gfc_match_omp_cancel (void)
3792 {
3793 gfc_omp_clauses *c;
3794 enum gfc_omp_cancel_kind kind = gfc_match_omp_cancel_kind ();
3795 if (kind == OMP_CANCEL_UNKNOWN)
3796 return MATCH_ERROR;
3797 if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_IF), false) != MATCH_YES)
3798 return MATCH_ERROR;
3799 c->cancel = kind;
3800 new_st.op = EXEC_OMP_CANCEL;
3801 new_st.ext.omp_clauses = c;
3802 return MATCH_YES;
3803 }
3804
3805
3806 match
gfc_match_omp_cancellation_point(void)3807 gfc_match_omp_cancellation_point (void)
3808 {
3809 gfc_omp_clauses *c;
3810 enum gfc_omp_cancel_kind kind = gfc_match_omp_cancel_kind ();
3811 if (kind == OMP_CANCEL_UNKNOWN)
3812 return MATCH_ERROR;
3813 if (gfc_match_omp_eos () != MATCH_YES)
3814 {
3815 gfc_error ("Unexpected junk after $OMP CANCELLATION POINT statement "
3816 "at %C");
3817 return MATCH_ERROR;
3818 }
3819 c = gfc_get_omp_clauses ();
3820 c->cancel = kind;
3821 new_st.op = EXEC_OMP_CANCELLATION_POINT;
3822 new_st.ext.omp_clauses = c;
3823 return MATCH_YES;
3824 }
3825
3826
3827 match
gfc_match_omp_end_nowait(void)3828 gfc_match_omp_end_nowait (void)
3829 {
3830 bool nowait = false;
3831 if (gfc_match ("% nowait") == MATCH_YES)
3832 nowait = true;
3833 if (gfc_match_omp_eos () != MATCH_YES)
3834 {
3835 gfc_error ("Unexpected junk after NOWAIT clause at %C");
3836 return MATCH_ERROR;
3837 }
3838 new_st.op = EXEC_OMP_END_NOWAIT;
3839 new_st.ext.omp_bool = nowait;
3840 return MATCH_YES;
3841 }
3842
3843
3844 match
gfc_match_omp_end_single(void)3845 gfc_match_omp_end_single (void)
3846 {
3847 gfc_omp_clauses *c;
3848 if (gfc_match ("% nowait") == MATCH_YES)
3849 {
3850 new_st.op = EXEC_OMP_END_NOWAIT;
3851 new_st.ext.omp_bool = true;
3852 return MATCH_YES;
3853 }
3854 if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_COPYPRIVATE))
3855 != MATCH_YES)
3856 return MATCH_ERROR;
3857 new_st.op = EXEC_OMP_END_SINGLE;
3858 new_st.ext.omp_clauses = c;
3859 return MATCH_YES;
3860 }
3861
3862
3863 static bool
oacc_is_loop(gfc_code * code)3864 oacc_is_loop (gfc_code *code)
3865 {
3866 return code->op == EXEC_OACC_PARALLEL_LOOP
3867 || code->op == EXEC_OACC_KERNELS_LOOP
3868 || code->op == EXEC_OACC_SERIAL_LOOP
3869 || code->op == EXEC_OACC_LOOP;
3870 }
3871
3872 static void
resolve_scalar_int_expr(gfc_expr * expr,const char * clause)3873 resolve_scalar_int_expr (gfc_expr *expr, const char *clause)
3874 {
3875 if (!gfc_resolve_expr (expr)
3876 || expr->ts.type != BT_INTEGER
3877 || expr->rank != 0)
3878 gfc_error ("%s clause at %L requires a scalar INTEGER expression",
3879 clause, &expr->where);
3880 }
3881
3882 static void
resolve_positive_int_expr(gfc_expr * expr,const char * clause)3883 resolve_positive_int_expr (gfc_expr *expr, const char *clause)
3884 {
3885 resolve_scalar_int_expr (expr, clause);
3886 if (expr->expr_type == EXPR_CONSTANT
3887 && expr->ts.type == BT_INTEGER
3888 && mpz_sgn (expr->value.integer) <= 0)
3889 gfc_warning (0, "INTEGER expression of %s clause at %L must be positive",
3890 clause, &expr->where);
3891 }
3892
3893 static void
resolve_nonnegative_int_expr(gfc_expr * expr,const char * clause)3894 resolve_nonnegative_int_expr (gfc_expr *expr, const char *clause)
3895 {
3896 resolve_scalar_int_expr (expr, clause);
3897 if (expr->expr_type == EXPR_CONSTANT
3898 && expr->ts.type == BT_INTEGER
3899 && mpz_sgn (expr->value.integer) < 0)
3900 gfc_warning (0, "INTEGER expression of %s clause at %L must be "
3901 "non-negative", clause, &expr->where);
3902 }
3903
3904 /* Emits error when symbol is pointer, cray pointer or cray pointee
3905 of derived of polymorphic type. */
3906
3907 static void
check_symbol_not_pointer(gfc_symbol * sym,locus loc,const char * name)3908 check_symbol_not_pointer (gfc_symbol *sym, locus loc, const char *name)
3909 {
3910 if (sym->ts.type == BT_DERIVED && sym->attr.cray_pointer)
3911 gfc_error ("Cray pointer object %qs of derived type in %s clause at %L",
3912 sym->name, name, &loc);
3913 if (sym->ts.type == BT_DERIVED && sym->attr.cray_pointee)
3914 gfc_error ("Cray pointee object %qs of derived type in %s clause at %L",
3915 sym->name, name, &loc);
3916
3917 if ((sym->ts.type == BT_ASSUMED && sym->attr.pointer)
3918 || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
3919 && CLASS_DATA (sym)->attr.pointer))
3920 gfc_error ("POINTER object %qs of polymorphic type in %s clause at %L",
3921 sym->name, name, &loc);
3922 if ((sym->ts.type == BT_ASSUMED && sym->attr.cray_pointer)
3923 || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
3924 && CLASS_DATA (sym)->attr.cray_pointer))
3925 gfc_error ("Cray pointer object %qs of polymorphic type in %s clause at %L",
3926 sym->name, name, &loc);
3927 if ((sym->ts.type == BT_ASSUMED && sym->attr.cray_pointee)
3928 || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
3929 && CLASS_DATA (sym)->attr.cray_pointee))
3930 gfc_error ("Cray pointee object %qs of polymorphic type in %s clause at %L",
3931 sym->name, name, &loc);
3932 }
3933
3934 /* Emits error when symbol represents assumed size/rank array. */
3935
3936 static void
check_array_not_assumed(gfc_symbol * sym,locus loc,const char * name)3937 check_array_not_assumed (gfc_symbol *sym, locus loc, const char *name)
3938 {
3939 if (sym->as && sym->as->type == AS_ASSUMED_SIZE)
3940 gfc_error ("Assumed size array %qs in %s clause at %L",
3941 sym->name, name, &loc);
3942 if (sym->as && sym->as->type == AS_ASSUMED_RANK)
3943 gfc_error ("Assumed rank array %qs in %s clause at %L",
3944 sym->name, name, &loc);
3945 }
3946
3947 static void
resolve_oacc_data_clauses(gfc_symbol * sym,locus loc,const char * name)3948 resolve_oacc_data_clauses (gfc_symbol *sym, locus loc, const char *name)
3949 {
3950 check_array_not_assumed (sym, loc, name);
3951 }
3952
3953 static void
resolve_oacc_deviceptr_clause(gfc_symbol * sym,locus loc,const char * name)3954 resolve_oacc_deviceptr_clause (gfc_symbol *sym, locus loc, const char *name)
3955 {
3956 if (sym->attr.pointer
3957 || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
3958 && CLASS_DATA (sym)->attr.class_pointer))
3959 gfc_error ("POINTER object %qs in %s clause at %L",
3960 sym->name, name, &loc);
3961 if (sym->attr.cray_pointer
3962 || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
3963 && CLASS_DATA (sym)->attr.cray_pointer))
3964 gfc_error ("Cray pointer object %qs in %s clause at %L",
3965 sym->name, name, &loc);
3966 if (sym->attr.cray_pointee
3967 || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
3968 && CLASS_DATA (sym)->attr.cray_pointee))
3969 gfc_error ("Cray pointee object %qs in %s clause at %L",
3970 sym->name, name, &loc);
3971 if (sym->attr.allocatable
3972 || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
3973 && CLASS_DATA (sym)->attr.allocatable))
3974 gfc_error ("ALLOCATABLE object %qs in %s clause at %L",
3975 sym->name, name, &loc);
3976 if (sym->attr.value)
3977 gfc_error ("VALUE object %qs in %s clause at %L",
3978 sym->name, name, &loc);
3979 check_array_not_assumed (sym, loc, name);
3980 }
3981
3982
3983 struct resolve_omp_udr_callback_data
3984 {
3985 gfc_symbol *sym1, *sym2;
3986 };
3987
3988
3989 static int
resolve_omp_udr_callback(gfc_expr ** e,int *,void * data)3990 resolve_omp_udr_callback (gfc_expr **e, int *, void *data)
3991 {
3992 struct resolve_omp_udr_callback_data *rcd
3993 = (struct resolve_omp_udr_callback_data *) data;
3994 if ((*e)->expr_type == EXPR_VARIABLE
3995 && ((*e)->symtree->n.sym == rcd->sym1
3996 || (*e)->symtree->n.sym == rcd->sym2))
3997 {
3998 gfc_ref *ref = gfc_get_ref ();
3999 ref->type = REF_ARRAY;
4000 ref->u.ar.where = (*e)->where;
4001 ref->u.ar.as = (*e)->symtree->n.sym->as;
4002 ref->u.ar.type = AR_FULL;
4003 ref->u.ar.dimen = 0;
4004 ref->next = (*e)->ref;
4005 (*e)->ref = ref;
4006 }
4007 return 0;
4008 }
4009
4010
4011 static int
resolve_omp_udr_callback2(gfc_expr ** e,int *,void *)4012 resolve_omp_udr_callback2 (gfc_expr **e, int *, void *)
4013 {
4014 if ((*e)->expr_type == EXPR_FUNCTION
4015 && (*e)->value.function.isym == NULL)
4016 {
4017 gfc_symbol *sym = (*e)->symtree->n.sym;
4018 if (!sym->attr.intrinsic
4019 && sym->attr.if_source == IFSRC_UNKNOWN)
4020 gfc_error ("Implicitly declared function %s used in "
4021 "!$OMP DECLARE REDUCTION at %L", sym->name, &(*e)->where);
4022 }
4023 return 0;
4024 }
4025
4026
4027 static gfc_code *
resolve_omp_udr_clause(gfc_omp_namelist * n,gfc_namespace * ns,gfc_symbol * sym1,gfc_symbol * sym2)4028 resolve_omp_udr_clause (gfc_omp_namelist *n, gfc_namespace *ns,
4029 gfc_symbol *sym1, gfc_symbol *sym2)
4030 {
4031 gfc_code *copy;
4032 gfc_symbol sym1_copy, sym2_copy;
4033
4034 if (ns->code->op == EXEC_ASSIGN)
4035 {
4036 copy = gfc_get_code (EXEC_ASSIGN);
4037 copy->expr1 = gfc_copy_expr (ns->code->expr1);
4038 copy->expr2 = gfc_copy_expr (ns->code->expr2);
4039 }
4040 else
4041 {
4042 copy = gfc_get_code (EXEC_CALL);
4043 copy->symtree = ns->code->symtree;
4044 copy->ext.actual = gfc_copy_actual_arglist (ns->code->ext.actual);
4045 }
4046 copy->loc = ns->code->loc;
4047 sym1_copy = *sym1;
4048 sym2_copy = *sym2;
4049 *sym1 = *n->sym;
4050 *sym2 = *n->sym;
4051 sym1->name = sym1_copy.name;
4052 sym2->name = sym2_copy.name;
4053 ns->proc_name = ns->parent->proc_name;
4054 if (n->sym->attr.dimension)
4055 {
4056 struct resolve_omp_udr_callback_data rcd;
4057 rcd.sym1 = sym1;
4058 rcd.sym2 = sym2;
4059 gfc_code_walker (©, gfc_dummy_code_callback,
4060 resolve_omp_udr_callback, &rcd);
4061 }
4062 gfc_resolve_code (copy, gfc_current_ns);
4063 if (copy->op == EXEC_CALL && copy->resolved_isym == NULL)
4064 {
4065 gfc_symbol *sym = copy->resolved_sym;
4066 if (sym
4067 && !sym->attr.intrinsic
4068 && sym->attr.if_source == IFSRC_UNKNOWN)
4069 gfc_error ("Implicitly declared subroutine %s used in "
4070 "!$OMP DECLARE REDUCTION at %L", sym->name,
4071 ©->loc);
4072 }
4073 gfc_code_walker (©, gfc_dummy_code_callback,
4074 resolve_omp_udr_callback2, NULL);
4075 *sym1 = sym1_copy;
4076 *sym2 = sym2_copy;
4077 return copy;
4078 }
4079
4080 /* OpenMP directive resolving routines. */
4081
4082 static void
4083 resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
4084 gfc_namespace *ns, bool openacc = false)
4085 {
4086 gfc_omp_namelist *n;
4087 gfc_expr_list *el;
4088 int list;
4089 int ifc;
4090 bool if_without_mod = false;
4091 gfc_omp_linear_op linear_op = OMP_LINEAR_DEFAULT;
4092 static const char *clause_names[]
4093 = { "PRIVATE", "FIRSTPRIVATE", "LASTPRIVATE", "COPYPRIVATE", "SHARED",
4094 "COPYIN", "UNIFORM", "ALIGNED", "LINEAR", "DEPEND", "MAP",
4095 "TO", "FROM", "REDUCTION", "DEVICE_RESIDENT", "LINK", "USE_DEVICE",
4096 "CACHE", "IS_DEVICE_PTR", "USE_DEVICE_PTR", "USE_DEVICE_ADDR" };
4097
4098 if (omp_clauses == NULL)
4099 return;
4100
4101 if (omp_clauses->orderedc && omp_clauses->orderedc < omp_clauses->collapse)
4102 gfc_error ("ORDERED clause parameter is less than COLLAPSE at %L",
4103 &code->loc);
4104
4105 if (omp_clauses->if_expr)
4106 {
4107 gfc_expr *expr = omp_clauses->if_expr;
4108 if (!gfc_resolve_expr (expr)
4109 || expr->ts.type != BT_LOGICAL || expr->rank != 0)
4110 gfc_error ("IF clause at %L requires a scalar LOGICAL expression",
4111 &expr->where);
4112 if_without_mod = true;
4113 }
4114 for (ifc = 0; ifc < OMP_IF_LAST; ifc++)
4115 if (omp_clauses->if_exprs[ifc])
4116 {
4117 gfc_expr *expr = omp_clauses->if_exprs[ifc];
4118 bool ok = true;
4119 if (!gfc_resolve_expr (expr)
4120 || expr->ts.type != BT_LOGICAL || expr->rank != 0)
4121 gfc_error ("IF clause at %L requires a scalar LOGICAL expression",
4122 &expr->where);
4123 else if (if_without_mod)
4124 {
4125 gfc_error ("IF clause without modifier at %L used together with "
4126 "IF clauses with modifiers",
4127 &omp_clauses->if_expr->where);
4128 if_without_mod = false;
4129 }
4130 else
4131 switch (code->op)
4132 {
4133 case EXEC_OMP_PARALLEL:
4134 case EXEC_OMP_PARALLEL_DO:
4135 case EXEC_OMP_PARALLEL_SECTIONS:
4136 case EXEC_OMP_PARALLEL_WORKSHARE:
4137 case EXEC_OMP_PARALLEL_DO_SIMD:
4138 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
4139 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
4140 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
4141 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
4142 ok = ifc == OMP_IF_PARALLEL;
4143 break;
4144
4145 case EXEC_OMP_TASK:
4146 ok = ifc == OMP_IF_TASK;
4147 break;
4148
4149 case EXEC_OMP_TASKLOOP:
4150 case EXEC_OMP_TASKLOOP_SIMD:
4151 ok = ifc == OMP_IF_TASKLOOP;
4152 break;
4153
4154 case EXEC_OMP_TARGET:
4155 case EXEC_OMP_TARGET_TEAMS:
4156 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
4157 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
4158 case EXEC_OMP_TARGET_SIMD:
4159 ok = ifc == OMP_IF_TARGET;
4160 break;
4161
4162 case EXEC_OMP_TARGET_DATA:
4163 ok = ifc == OMP_IF_TARGET_DATA;
4164 break;
4165
4166 case EXEC_OMP_TARGET_UPDATE:
4167 ok = ifc == OMP_IF_TARGET_UPDATE;
4168 break;
4169
4170 case EXEC_OMP_TARGET_ENTER_DATA:
4171 ok = ifc == OMP_IF_TARGET_ENTER_DATA;
4172 break;
4173
4174 case EXEC_OMP_TARGET_EXIT_DATA:
4175 ok = ifc == OMP_IF_TARGET_EXIT_DATA;
4176 break;
4177
4178 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
4179 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
4180 case EXEC_OMP_TARGET_PARALLEL:
4181 case EXEC_OMP_TARGET_PARALLEL_DO:
4182 case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
4183 ok = ifc == OMP_IF_TARGET || ifc == OMP_IF_PARALLEL;
4184 break;
4185
4186 default:
4187 ok = false;
4188 break;
4189 }
4190 if (!ok)
4191 {
4192 static const char *ifs[] = {
4193 "PARALLEL",
4194 "TASK",
4195 "TASKLOOP",
4196 "TARGET",
4197 "TARGET DATA",
4198 "TARGET UPDATE",
4199 "TARGET ENTER DATA",
4200 "TARGET EXIT DATA"
4201 };
4202 gfc_error ("IF clause modifier %s at %L not appropriate for "
4203 "the current OpenMP construct", ifs[ifc], &expr->where);
4204 }
4205 }
4206
4207 if (omp_clauses->final_expr)
4208 {
4209 gfc_expr *expr = omp_clauses->final_expr;
4210 if (!gfc_resolve_expr (expr)
4211 || expr->ts.type != BT_LOGICAL || expr->rank != 0)
4212 gfc_error ("FINAL clause at %L requires a scalar LOGICAL expression",
4213 &expr->where);
4214 }
4215 if (omp_clauses->num_threads)
4216 resolve_positive_int_expr (omp_clauses->num_threads, "NUM_THREADS");
4217 if (omp_clauses->chunk_size)
4218 {
4219 gfc_expr *expr = omp_clauses->chunk_size;
4220 if (!gfc_resolve_expr (expr)
4221 || expr->ts.type != BT_INTEGER || expr->rank != 0)
4222 gfc_error ("SCHEDULE clause's chunk_size at %L requires "
4223 "a scalar INTEGER expression", &expr->where);
4224 else if (expr->expr_type == EXPR_CONSTANT
4225 && expr->ts.type == BT_INTEGER
4226 && mpz_sgn (expr->value.integer) <= 0)
4227 gfc_warning (0, "INTEGER expression of SCHEDULE clause's chunk_size "
4228 "at %L must be positive", &expr->where);
4229 }
4230 if (omp_clauses->sched_kind != OMP_SCHED_NONE
4231 && omp_clauses->sched_nonmonotonic)
4232 {
4233 if (omp_clauses->sched_kind != OMP_SCHED_DYNAMIC
4234 && omp_clauses->sched_kind != OMP_SCHED_GUIDED)
4235 {
4236 const char *p;
4237 switch (omp_clauses->sched_kind)
4238 {
4239 case OMP_SCHED_STATIC: p = "STATIC"; break;
4240 case OMP_SCHED_RUNTIME: p = "RUNTIME"; break;
4241 case OMP_SCHED_AUTO: p = "AUTO"; break;
4242 default: gcc_unreachable ();
4243 }
4244 gfc_error ("NONMONOTONIC modifier specified for %s schedule kind "
4245 "at %L", p, &code->loc);
4246 }
4247 else if (omp_clauses->sched_monotonic)
4248 gfc_error ("Both MONOTONIC and NONMONOTONIC schedule modifiers "
4249 "specified at %L", &code->loc);
4250 else if (omp_clauses->ordered)
4251 gfc_error ("NONMONOTONIC schedule modifier specified with ORDERED "
4252 "clause at %L", &code->loc);
4253 }
4254
4255 /* Check that no symbol appears on multiple clauses, except that
4256 a symbol can appear on both firstprivate and lastprivate. */
4257 for (list = 0; list < OMP_LIST_NUM; list++)
4258 for (n = omp_clauses->lists[list]; n; n = n->next)
4259 {
4260 n->sym->mark = 0;
4261 n->sym->comp_mark = 0;
4262 if (n->sym->attr.flavor == FL_VARIABLE
4263 || n->sym->attr.proc_pointer
4264 || (!code && (!n->sym->attr.dummy || n->sym->ns != ns)))
4265 {
4266 if (!code && (!n->sym->attr.dummy || n->sym->ns != ns))
4267 gfc_error ("Variable %qs is not a dummy argument at %L",
4268 n->sym->name, &n->where);
4269 continue;
4270 }
4271 if (n->sym->attr.flavor == FL_PROCEDURE
4272 && n->sym->result == n->sym
4273 && n->sym->attr.function)
4274 {
4275 if (gfc_current_ns->proc_name == n->sym
4276 || (gfc_current_ns->parent
4277 && gfc_current_ns->parent->proc_name == n->sym))
4278 continue;
4279 if (gfc_current_ns->proc_name->attr.entry_master)
4280 {
4281 gfc_entry_list *el = gfc_current_ns->entries;
4282 for (; el; el = el->next)
4283 if (el->sym == n->sym)
4284 break;
4285 if (el)
4286 continue;
4287 }
4288 if (gfc_current_ns->parent
4289 && gfc_current_ns->parent->proc_name->attr.entry_master)
4290 {
4291 gfc_entry_list *el = gfc_current_ns->parent->entries;
4292 for (; el; el = el->next)
4293 if (el->sym == n->sym)
4294 break;
4295 if (el)
4296 continue;
4297 }
4298 }
4299 if (list == OMP_LIST_MAP
4300 && n->sym->attr.flavor == FL_PARAMETER)
4301 {
4302 if (openacc)
4303 gfc_error ("Object %qs is not a variable at %L; parameters"
4304 " cannot be and need not be copied", n->sym->name,
4305 &n->where);
4306 else
4307 gfc_error ("Object %qs is not a variable at %L; parameters"
4308 " cannot be and need not be mapped", n->sym->name,
4309 &n->where);
4310 }
4311 else
4312 gfc_error ("Object %qs is not a variable at %L", n->sym->name,
4313 &n->where);
4314 }
4315
4316 for (list = 0; list < OMP_LIST_NUM; list++)
4317 if (list != OMP_LIST_FIRSTPRIVATE
4318 && list != OMP_LIST_LASTPRIVATE
4319 && list != OMP_LIST_ALIGNED
4320 && list != OMP_LIST_DEPEND
4321 && (list != OMP_LIST_MAP || openacc)
4322 && list != OMP_LIST_FROM
4323 && list != OMP_LIST_TO
4324 && (list != OMP_LIST_REDUCTION || !openacc))
4325 for (n = omp_clauses->lists[list]; n; n = n->next)
4326 {
4327 bool component_ref_p = false;
4328
4329 /* Allow multiple components of the same (e.g. derived-type)
4330 variable here. Duplicate components are detected elsewhere. */
4331 if (n->expr && n->expr->expr_type == EXPR_VARIABLE)
4332 for (gfc_ref *ref = n->expr->ref; ref; ref = ref->next)
4333 if (ref->type == REF_COMPONENT)
4334 component_ref_p = true;
4335 if ((!component_ref_p && n->sym->comp_mark)
4336 || (component_ref_p && n->sym->mark))
4337 gfc_error ("Symbol %qs has mixed component and non-component "
4338 "accesses at %L", n->sym->name, &n->where);
4339 else if (n->sym->mark)
4340 gfc_error ("Symbol %qs present on multiple clauses at %L",
4341 n->sym->name, &n->where);
4342 else
4343 {
4344 if (component_ref_p)
4345 n->sym->comp_mark = 1;
4346 else
4347 n->sym->mark = 1;
4348 }
4349 }
4350
4351 gcc_assert (OMP_LIST_LASTPRIVATE == OMP_LIST_FIRSTPRIVATE + 1);
4352 for (list = OMP_LIST_FIRSTPRIVATE; list <= OMP_LIST_LASTPRIVATE; list++)
4353 for (n = omp_clauses->lists[list]; n; n = n->next)
4354 if (n->sym->mark)
4355 {
4356 gfc_error ("Symbol %qs present on multiple clauses at %L",
4357 n->sym->name, &n->where);
4358 n->sym->mark = 0;
4359 }
4360
4361 for (n = omp_clauses->lists[OMP_LIST_FIRSTPRIVATE]; n; n = n->next)
4362 {
4363 if (n->sym->mark)
4364 gfc_error ("Symbol %qs present on multiple clauses at %L",
4365 n->sym->name, &n->where);
4366 else
4367 n->sym->mark = 1;
4368 }
4369 for (n = omp_clauses->lists[OMP_LIST_LASTPRIVATE]; n; n = n->next)
4370 n->sym->mark = 0;
4371
4372 for (n = omp_clauses->lists[OMP_LIST_LASTPRIVATE]; n; n = n->next)
4373 {
4374 if (n->sym->mark)
4375 gfc_error ("Symbol %qs present on multiple clauses at %L",
4376 n->sym->name, &n->where);
4377 else
4378 n->sym->mark = 1;
4379 }
4380
4381 for (n = omp_clauses->lists[OMP_LIST_ALIGNED]; n; n = n->next)
4382 n->sym->mark = 0;
4383
4384 for (n = omp_clauses->lists[OMP_LIST_ALIGNED]; n; n = n->next)
4385 {
4386 if (n->sym->mark)
4387 gfc_error ("Symbol %qs present on multiple clauses at %L",
4388 n->sym->name, &n->where);
4389 else
4390 n->sym->mark = 1;
4391 }
4392
4393 /* OpenACC reductions. */
4394 if (openacc)
4395 {
4396 for (n = omp_clauses->lists[OMP_LIST_REDUCTION]; n; n = n->next)
4397 n->sym->mark = 0;
4398
4399 for (n = omp_clauses->lists[OMP_LIST_REDUCTION]; n; n = n->next)
4400 {
4401 if (n->sym->mark)
4402 gfc_error ("Symbol %qs present on multiple clauses at %L",
4403 n->sym->name, &n->where);
4404 else
4405 n->sym->mark = 1;
4406
4407 /* OpenACC does not support reductions on arrays. */
4408 if (n->sym->as)
4409 gfc_error ("Array %qs is not permitted in reduction at %L",
4410 n->sym->name, &n->where);
4411 }
4412 }
4413
4414 for (n = omp_clauses->lists[OMP_LIST_TO]; n; n = n->next)
4415 n->sym->mark = 0;
4416 for (n = omp_clauses->lists[OMP_LIST_FROM]; n; n = n->next)
4417 if (n->expr == NULL)
4418 n->sym->mark = 1;
4419 for (n = omp_clauses->lists[OMP_LIST_TO]; n; n = n->next)
4420 {
4421 if (n->expr == NULL && n->sym->mark)
4422 gfc_error ("Symbol %qs present on both FROM and TO clauses at %L",
4423 n->sym->name, &n->where);
4424 else
4425 n->sym->mark = 1;
4426 }
4427
4428 for (list = 0; list < OMP_LIST_NUM; list++)
4429 if ((n = omp_clauses->lists[list]) != NULL)
4430 {
4431 const char *name;
4432
4433 if (list < OMP_LIST_NUM)
4434 name = clause_names[list];
4435 else
4436 gcc_unreachable ();
4437
4438 switch (list)
4439 {
4440 case OMP_LIST_COPYIN:
4441 for (; n != NULL; n = n->next)
4442 {
4443 if (!n->sym->attr.threadprivate)
4444 gfc_error ("Non-THREADPRIVATE object %qs in COPYIN clause"
4445 " at %L", n->sym->name, &n->where);
4446 }
4447 break;
4448 case OMP_LIST_COPYPRIVATE:
4449 for (; n != NULL; n = n->next)
4450 {
4451 if (n->sym->as && n->sym->as->type == AS_ASSUMED_SIZE)
4452 gfc_error ("Assumed size array %qs in COPYPRIVATE clause "
4453 "at %L", n->sym->name, &n->where);
4454 if (n->sym->attr.pointer && n->sym->attr.intent == INTENT_IN)
4455 gfc_error ("INTENT(IN) POINTER %qs in COPYPRIVATE clause "
4456 "at %L", n->sym->name, &n->where);
4457 }
4458 break;
4459 case OMP_LIST_SHARED:
4460 for (; n != NULL; n = n->next)
4461 {
4462 if (n->sym->attr.threadprivate)
4463 gfc_error ("THREADPRIVATE object %qs in SHARED clause at "
4464 "%L", n->sym->name, &n->where);
4465 if (n->sym->attr.cray_pointee)
4466 gfc_error ("Cray pointee %qs in SHARED clause at %L",
4467 n->sym->name, &n->where);
4468 if (n->sym->attr.associate_var)
4469 gfc_error ("ASSOCIATE name %qs in SHARED clause at %L",
4470 n->sym->name, &n->where);
4471 }
4472 break;
4473 case OMP_LIST_ALIGNED:
4474 for (; n != NULL; n = n->next)
4475 {
4476 if (!n->sym->attr.pointer
4477 && !n->sym->attr.allocatable
4478 && !n->sym->attr.cray_pointer
4479 && (n->sym->ts.type != BT_DERIVED
4480 || (n->sym->ts.u.derived->from_intmod
4481 != INTMOD_ISO_C_BINDING)
4482 || (n->sym->ts.u.derived->intmod_sym_id
4483 != ISOCBINDING_PTR)))
4484 gfc_error ("%qs in ALIGNED clause must be POINTER, "
4485 "ALLOCATABLE, Cray pointer or C_PTR at %L",
4486 n->sym->name, &n->where);
4487 else if (n->expr)
4488 {
4489 gfc_expr *expr = n->expr;
4490 int alignment = 0;
4491 if (!gfc_resolve_expr (expr)
4492 || expr->ts.type != BT_INTEGER
4493 || expr->rank != 0
4494 || gfc_extract_int (expr, &alignment)
4495 || alignment <= 0)
4496 gfc_error ("%qs in ALIGNED clause at %L requires a scalar "
4497 "positive constant integer alignment "
4498 "expression", n->sym->name, &n->where);
4499 }
4500 }
4501 break;
4502 case OMP_LIST_DEPEND:
4503 case OMP_LIST_MAP:
4504 case OMP_LIST_TO:
4505 case OMP_LIST_FROM:
4506 case OMP_LIST_CACHE:
4507 for (; n != NULL; n = n->next)
4508 {
4509 if (list == OMP_LIST_DEPEND)
4510 {
4511 if (n->u.depend_op == OMP_DEPEND_SINK_FIRST
4512 || n->u.depend_op == OMP_DEPEND_SINK)
4513 {
4514 if (code->op != EXEC_OMP_ORDERED)
4515 gfc_error ("SINK dependence type only allowed "
4516 "on ORDERED directive at %L", &n->where);
4517 else if (omp_clauses->depend_source)
4518 {
4519 gfc_error ("DEPEND SINK used together with "
4520 "DEPEND SOURCE on the same construct "
4521 "at %L", &n->where);
4522 omp_clauses->depend_source = false;
4523 }
4524 else if (n->expr)
4525 {
4526 if (!gfc_resolve_expr (n->expr)
4527 || n->expr->ts.type != BT_INTEGER
4528 || n->expr->rank != 0)
4529 gfc_error ("SINK addend not a constant integer "
4530 "at %L", &n->where);
4531 }
4532 continue;
4533 }
4534 else if (code->op == EXEC_OMP_ORDERED)
4535 gfc_error ("Only SOURCE or SINK dependence types "
4536 "are allowed on ORDERED directive at %L",
4537 &n->where);
4538 }
4539 gfc_ref *array_ref = NULL;
4540 bool resolved = false;
4541 if (n->expr)
4542 {
4543 array_ref = n->expr->ref;
4544 resolved = gfc_resolve_expr (n->expr);
4545
4546 /* Look through component refs to find last array
4547 reference. */
4548 if (openacc && resolved)
4549 {
4550 /* The "!$acc cache" directive allows rectangular
4551 subarrays to be specified, with some restrictions
4552 on the form of bounds (not implemented).
4553 Only raise an error here if we're really sure the
4554 array isn't contiguous. An expression such as
4555 arr(-n:n,-n:n) could be contiguous even if it looks
4556 like it may not be. */
4557 if (list != OMP_LIST_CACHE
4558 && !gfc_is_simply_contiguous (n->expr, false, true)
4559 && gfc_is_not_contiguous (n->expr))
4560 gfc_error ("Array is not contiguous at %L",
4561 &n->where);
4562
4563 while (array_ref
4564 && (array_ref->type == REF_COMPONENT
4565 || (array_ref->type == REF_ARRAY
4566 && array_ref->next
4567 && (array_ref->next->type
4568 == REF_COMPONENT))))
4569 array_ref = array_ref->next;
4570 }
4571 }
4572 if (array_ref
4573 || (n->expr
4574 && (!resolved || n->expr->expr_type != EXPR_VARIABLE)))
4575 {
4576 if (!resolved
4577 || n->expr->expr_type != EXPR_VARIABLE
4578 || array_ref->next
4579 || array_ref->type != REF_ARRAY)
4580 gfc_error ("%qs in %s clause at %L is not a proper "
4581 "array section", n->sym->name, name,
4582 &n->where);
4583 else
4584 {
4585 int i;
4586 gfc_array_ref *ar = &array_ref->u.ar;
4587 for (i = 0; i < ar->dimen; i++)
4588 if (ar->stride[i])
4589 {
4590 gfc_error ("Stride should not be specified for "
4591 "array section in %s clause at %L",
4592 name, &n->where);
4593 break;
4594 }
4595 else if (ar->dimen_type[i] != DIMEN_ELEMENT
4596 && ar->dimen_type[i] != DIMEN_RANGE)
4597 {
4598 gfc_error ("%qs in %s clause at %L is not a "
4599 "proper array section",
4600 n->sym->name, name, &n->where);
4601 break;
4602 }
4603 else if (list == OMP_LIST_DEPEND
4604 && ar->start[i]
4605 && ar->start[i]->expr_type == EXPR_CONSTANT
4606 && ar->end[i]
4607 && ar->end[i]->expr_type == EXPR_CONSTANT
4608 && mpz_cmp (ar->start[i]->value.integer,
4609 ar->end[i]->value.integer) > 0)
4610 {
4611 gfc_error ("%qs in DEPEND clause at %L is a "
4612 "zero size array section",
4613 n->sym->name, &n->where);
4614 break;
4615 }
4616 }
4617 }
4618 else if (openacc)
4619 {
4620 if (list == OMP_LIST_MAP
4621 && n->u.map_op == OMP_MAP_FORCE_DEVICEPTR)
4622 resolve_oacc_deviceptr_clause (n->sym, n->where, name);
4623 else
4624 resolve_oacc_data_clauses (n->sym, n->where, name);
4625 }
4626 else if (list != OMP_LIST_DEPEND
4627 && n->sym->as
4628 && n->sym->as->type == AS_ASSUMED_SIZE)
4629 gfc_error ("Assumed size array %qs in %s clause at %L",
4630 n->sym->name, name, &n->where);
4631 if (list == OMP_LIST_MAP && !openacc)
4632 switch (code->op)
4633 {
4634 case EXEC_OMP_TARGET:
4635 case EXEC_OMP_TARGET_DATA:
4636 switch (n->u.map_op)
4637 {
4638 case OMP_MAP_TO:
4639 case OMP_MAP_ALWAYS_TO:
4640 case OMP_MAP_FROM:
4641 case OMP_MAP_ALWAYS_FROM:
4642 case OMP_MAP_TOFROM:
4643 case OMP_MAP_ALWAYS_TOFROM:
4644 case OMP_MAP_ALLOC:
4645 break;
4646 default:
4647 gfc_error ("TARGET%s with map-type other than TO, "
4648 "FROM, TOFROM, or ALLOC on MAP clause "
4649 "at %L",
4650 code->op == EXEC_OMP_TARGET
4651 ? "" : " DATA", &n->where);
4652 break;
4653 }
4654 break;
4655 case EXEC_OMP_TARGET_ENTER_DATA:
4656 switch (n->u.map_op)
4657 {
4658 case OMP_MAP_TO:
4659 case OMP_MAP_ALWAYS_TO:
4660 case OMP_MAP_ALLOC:
4661 break;
4662 default:
4663 gfc_error ("TARGET ENTER DATA with map-type other "
4664 "than TO, or ALLOC on MAP clause at %L",
4665 &n->where);
4666 break;
4667 }
4668 break;
4669 case EXEC_OMP_TARGET_EXIT_DATA:
4670 switch (n->u.map_op)
4671 {
4672 case OMP_MAP_FROM:
4673 case OMP_MAP_ALWAYS_FROM:
4674 case OMP_MAP_RELEASE:
4675 case OMP_MAP_DELETE:
4676 break;
4677 default:
4678 gfc_error ("TARGET EXIT DATA with map-type other "
4679 "than FROM, RELEASE, or DELETE on MAP "
4680 "clause at %L", &n->where);
4681 break;
4682 }
4683 break;
4684 default:
4685 break;
4686 }
4687 }
4688
4689 if (list != OMP_LIST_DEPEND)
4690 for (n = omp_clauses->lists[list]; n != NULL; n = n->next)
4691 {
4692 n->sym->attr.referenced = 1;
4693 if (n->sym->attr.threadprivate)
4694 gfc_error ("THREADPRIVATE object %qs in %s clause at %L",
4695 n->sym->name, name, &n->where);
4696 if (n->sym->attr.cray_pointee)
4697 gfc_error ("Cray pointee %qs in %s clause at %L",
4698 n->sym->name, name, &n->where);
4699 }
4700 break;
4701 case OMP_LIST_IS_DEVICE_PTR:
4702 if (!n->sym->attr.dummy)
4703 gfc_error ("Non-dummy object %qs in %s clause at %L",
4704 n->sym->name, name, &n->where);
4705 if (n->sym->attr.allocatable
4706 || (n->sym->ts.type == BT_CLASS
4707 && CLASS_DATA (n->sym)->attr.allocatable))
4708 gfc_error ("ALLOCATABLE object %qs in %s clause at %L",
4709 n->sym->name, name, &n->where);
4710 if (n->sym->attr.pointer
4711 || (n->sym->ts.type == BT_CLASS
4712 && CLASS_DATA (n->sym)->attr.pointer))
4713 gfc_error ("POINTER object %qs in %s clause at %L",
4714 n->sym->name, name, &n->where);
4715 if (n->sym->attr.value)
4716 gfc_error ("VALUE object %qs in %s clause at %L",
4717 n->sym->name, name, &n->where);
4718 break;
4719 case OMP_LIST_USE_DEVICE_PTR:
4720 case OMP_LIST_USE_DEVICE_ADDR:
4721 /* FIXME: Handle OMP_LIST_USE_DEVICE_PTR. */
4722 break;
4723 default:
4724 for (; n != NULL; n = n->next)
4725 {
4726 bool bad = false;
4727 if (n->sym->attr.threadprivate)
4728 gfc_error ("THREADPRIVATE object %qs in %s clause at %L",
4729 n->sym->name, name, &n->where);
4730 if (n->sym->attr.cray_pointee)
4731 gfc_error ("Cray pointee %qs in %s clause at %L",
4732 n->sym->name, name, &n->where);
4733 if (n->sym->attr.associate_var)
4734 gfc_error ("ASSOCIATE name %qs in %s clause at %L",
4735 n->sym->name, name, &n->where);
4736 if (list != OMP_LIST_PRIVATE)
4737 {
4738 if (n->sym->attr.proc_pointer && list == OMP_LIST_REDUCTION)
4739 gfc_error ("Procedure pointer %qs in %s clause at %L",
4740 n->sym->name, name, &n->where);
4741 if (n->sym->attr.pointer && list == OMP_LIST_REDUCTION)
4742 gfc_error ("POINTER object %qs in %s clause at %L",
4743 n->sym->name, name, &n->where);
4744 if (n->sym->attr.cray_pointer && list == OMP_LIST_REDUCTION)
4745 gfc_error ("Cray pointer %qs in %s clause at %L",
4746 n->sym->name, name, &n->where);
4747 }
4748 if (code
4749 && (oacc_is_loop (code)
4750 || code->op == EXEC_OACC_PARALLEL
4751 || code->op == EXEC_OACC_SERIAL))
4752 check_array_not_assumed (n->sym, n->where, name);
4753 else if (n->sym->as && n->sym->as->type == AS_ASSUMED_SIZE)
4754 gfc_error ("Assumed size array %qs in %s clause at %L",
4755 n->sym->name, name, &n->where);
4756 if (n->sym->attr.in_namelist && list != OMP_LIST_REDUCTION)
4757 gfc_error ("Variable %qs in %s clause is used in "
4758 "NAMELIST statement at %L",
4759 n->sym->name, name, &n->where);
4760 if (n->sym->attr.pointer && n->sym->attr.intent == INTENT_IN)
4761 switch (list)
4762 {
4763 case OMP_LIST_PRIVATE:
4764 case OMP_LIST_LASTPRIVATE:
4765 case OMP_LIST_LINEAR:
4766 /* case OMP_LIST_REDUCTION: */
4767 gfc_error ("INTENT(IN) POINTER %qs in %s clause at %L",
4768 n->sym->name, name, &n->where);
4769 break;
4770 default:
4771 break;
4772 }
4773
4774 switch (list)
4775 {
4776 case OMP_LIST_REDUCTION:
4777 switch (n->u.reduction_op)
4778 {
4779 case OMP_REDUCTION_PLUS:
4780 case OMP_REDUCTION_TIMES:
4781 case OMP_REDUCTION_MINUS:
4782 if (!gfc_numeric_ts (&n->sym->ts))
4783 bad = true;
4784 break;
4785 case OMP_REDUCTION_AND:
4786 case OMP_REDUCTION_OR:
4787 case OMP_REDUCTION_EQV:
4788 case OMP_REDUCTION_NEQV:
4789 if (n->sym->ts.type != BT_LOGICAL)
4790 bad = true;
4791 break;
4792 case OMP_REDUCTION_MAX:
4793 case OMP_REDUCTION_MIN:
4794 if (n->sym->ts.type != BT_INTEGER
4795 && n->sym->ts.type != BT_REAL)
4796 bad = true;
4797 break;
4798 case OMP_REDUCTION_IAND:
4799 case OMP_REDUCTION_IOR:
4800 case OMP_REDUCTION_IEOR:
4801 if (n->sym->ts.type != BT_INTEGER)
4802 bad = true;
4803 break;
4804 case OMP_REDUCTION_USER:
4805 bad = true;
4806 break;
4807 default:
4808 break;
4809 }
4810 if (!bad)
4811 n->udr = NULL;
4812 else
4813 {
4814 const char *udr_name = NULL;
4815 if (n->udr)
4816 {
4817 udr_name = n->udr->udr->name;
4818 n->udr->udr
4819 = gfc_find_omp_udr (NULL, udr_name,
4820 &n->sym->ts);
4821 if (n->udr->udr == NULL)
4822 {
4823 free (n->udr);
4824 n->udr = NULL;
4825 }
4826 }
4827 if (n->udr == NULL)
4828 {
4829 if (udr_name == NULL)
4830 switch (n->u.reduction_op)
4831 {
4832 case OMP_REDUCTION_PLUS:
4833 case OMP_REDUCTION_TIMES:
4834 case OMP_REDUCTION_MINUS:
4835 case OMP_REDUCTION_AND:
4836 case OMP_REDUCTION_OR:
4837 case OMP_REDUCTION_EQV:
4838 case OMP_REDUCTION_NEQV:
4839 udr_name = gfc_op2string ((gfc_intrinsic_op)
4840 n->u.reduction_op);
4841 break;
4842 case OMP_REDUCTION_MAX:
4843 udr_name = "max";
4844 break;
4845 case OMP_REDUCTION_MIN:
4846 udr_name = "min";
4847 break;
4848 case OMP_REDUCTION_IAND:
4849 udr_name = "iand";
4850 break;
4851 case OMP_REDUCTION_IOR:
4852 udr_name = "ior";
4853 break;
4854 case OMP_REDUCTION_IEOR:
4855 udr_name = "ieor";
4856 break;
4857 default:
4858 gcc_unreachable ();
4859 }
4860 gfc_error ("!$OMP DECLARE REDUCTION %s not found "
4861 "for type %s at %L", udr_name,
4862 gfc_typename (&n->sym->ts), &n->where);
4863 }
4864 else
4865 {
4866 gfc_omp_udr *udr = n->udr->udr;
4867 n->u.reduction_op = OMP_REDUCTION_USER;
4868 n->udr->combiner
4869 = resolve_omp_udr_clause (n, udr->combiner_ns,
4870 udr->omp_out,
4871 udr->omp_in);
4872 if (udr->initializer_ns)
4873 n->udr->initializer
4874 = resolve_omp_udr_clause (n,
4875 udr->initializer_ns,
4876 udr->omp_priv,
4877 udr->omp_orig);
4878 }
4879 }
4880 break;
4881 case OMP_LIST_LINEAR:
4882 if (code
4883 && n->u.linear_op != OMP_LINEAR_DEFAULT
4884 && n->u.linear_op != linear_op)
4885 {
4886 gfc_error ("LINEAR clause modifier used on DO or SIMD"
4887 " construct at %L", &n->where);
4888 linear_op = n->u.linear_op;
4889 }
4890 else if (omp_clauses->orderedc)
4891 gfc_error ("LINEAR clause specified together with "
4892 "ORDERED clause with argument at %L",
4893 &n->where);
4894 else if (n->u.linear_op != OMP_LINEAR_REF
4895 && n->sym->ts.type != BT_INTEGER)
4896 gfc_error ("LINEAR variable %qs must be INTEGER "
4897 "at %L", n->sym->name, &n->where);
4898 else if ((n->u.linear_op == OMP_LINEAR_REF
4899 || n->u.linear_op == OMP_LINEAR_UVAL)
4900 && n->sym->attr.value)
4901 gfc_error ("LINEAR dummy argument %qs with VALUE "
4902 "attribute with %s modifier at %L",
4903 n->sym->name,
4904 n->u.linear_op == OMP_LINEAR_REF
4905 ? "REF" : "UVAL", &n->where);
4906 else if (n->expr)
4907 {
4908 gfc_expr *expr = n->expr;
4909 if (!gfc_resolve_expr (expr)
4910 || expr->ts.type != BT_INTEGER
4911 || expr->rank != 0)
4912 gfc_error ("%qs in LINEAR clause at %L requires "
4913 "a scalar integer linear-step expression",
4914 n->sym->name, &n->where);
4915 else if (!code && expr->expr_type != EXPR_CONSTANT)
4916 {
4917 if (expr->expr_type == EXPR_VARIABLE
4918 && expr->symtree->n.sym->attr.dummy
4919 && expr->symtree->n.sym->ns == ns)
4920 {
4921 gfc_omp_namelist *n2;
4922 for (n2 = omp_clauses->lists[OMP_LIST_UNIFORM];
4923 n2; n2 = n2->next)
4924 if (n2->sym == expr->symtree->n.sym)
4925 break;
4926 if (n2)
4927 break;
4928 }
4929 gfc_error ("%qs in LINEAR clause at %L requires "
4930 "a constant integer linear-step "
4931 "expression or dummy argument "
4932 "specified in UNIFORM clause",
4933 n->sym->name, &n->where);
4934 }
4935 }
4936 break;
4937 /* Workaround for PR middle-end/26316, nothing really needs
4938 to be done here for OMP_LIST_PRIVATE. */
4939 case OMP_LIST_PRIVATE:
4940 gcc_assert (code && code->op != EXEC_NOP);
4941 break;
4942 case OMP_LIST_USE_DEVICE:
4943 if (n->sym->attr.allocatable
4944 || (n->sym->ts.type == BT_CLASS && CLASS_DATA (n->sym)
4945 && CLASS_DATA (n->sym)->attr.allocatable))
4946 gfc_error ("ALLOCATABLE object %qs in %s clause at %L",
4947 n->sym->name, name, &n->where);
4948 if (n->sym->ts.type == BT_CLASS
4949 && CLASS_DATA (n->sym)
4950 && CLASS_DATA (n->sym)->attr.class_pointer)
4951 gfc_error ("POINTER object %qs of polymorphic type in "
4952 "%s clause at %L", n->sym->name, name,
4953 &n->where);
4954 if (n->sym->attr.cray_pointer)
4955 gfc_error ("Cray pointer object %qs in %s clause at %L",
4956 n->sym->name, name, &n->where);
4957 else if (n->sym->attr.cray_pointee)
4958 gfc_error ("Cray pointee object %qs in %s clause at %L",
4959 n->sym->name, name, &n->where);
4960 else if (n->sym->attr.flavor == FL_VARIABLE
4961 && !n->sym->as
4962 && !n->sym->attr.pointer)
4963 gfc_error ("%s clause variable %qs at %L is neither "
4964 "a POINTER nor an array", name,
4965 n->sym->name, &n->where);
4966 /* FALLTHRU */
4967 case OMP_LIST_DEVICE_RESIDENT:
4968 check_symbol_not_pointer (n->sym, n->where, name);
4969 check_array_not_assumed (n->sym, n->where, name);
4970 break;
4971 default:
4972 break;
4973 }
4974 }
4975 break;
4976 }
4977 }
4978 if (omp_clauses->safelen_expr)
4979 resolve_positive_int_expr (omp_clauses->safelen_expr, "SAFELEN");
4980 if (omp_clauses->simdlen_expr)
4981 resolve_positive_int_expr (omp_clauses->simdlen_expr, "SIMDLEN");
4982 if (omp_clauses->num_teams)
4983 resolve_positive_int_expr (omp_clauses->num_teams, "NUM_TEAMS");
4984 if (omp_clauses->device)
4985 resolve_nonnegative_int_expr (omp_clauses->device, "DEVICE");
4986 if (omp_clauses->hint)
4987 resolve_scalar_int_expr (omp_clauses->hint, "HINT");
4988 if (omp_clauses->priority)
4989 resolve_nonnegative_int_expr (omp_clauses->priority, "PRIORITY");
4990 if (omp_clauses->dist_chunk_size)
4991 {
4992 gfc_expr *expr = omp_clauses->dist_chunk_size;
4993 if (!gfc_resolve_expr (expr)
4994 || expr->ts.type != BT_INTEGER || expr->rank != 0)
4995 gfc_error ("DIST_SCHEDULE clause's chunk_size at %L requires "
4996 "a scalar INTEGER expression", &expr->where);
4997 }
4998 if (omp_clauses->thread_limit)
4999 resolve_positive_int_expr (omp_clauses->thread_limit, "THREAD_LIMIT");
5000 if (omp_clauses->grainsize)
5001 resolve_positive_int_expr (omp_clauses->grainsize, "GRAINSIZE");
5002 if (omp_clauses->num_tasks)
5003 resolve_positive_int_expr (omp_clauses->num_tasks, "NUM_TASKS");
5004 if (omp_clauses->async)
5005 if (omp_clauses->async_expr)
5006 resolve_scalar_int_expr (omp_clauses->async_expr, "ASYNC");
5007 if (omp_clauses->num_gangs_expr)
5008 resolve_positive_int_expr (omp_clauses->num_gangs_expr, "NUM_GANGS");
5009 if (omp_clauses->num_workers_expr)
5010 resolve_positive_int_expr (omp_clauses->num_workers_expr, "NUM_WORKERS");
5011 if (omp_clauses->vector_length_expr)
5012 resolve_positive_int_expr (omp_clauses->vector_length_expr,
5013 "VECTOR_LENGTH");
5014 if (omp_clauses->gang_num_expr)
5015 resolve_positive_int_expr (omp_clauses->gang_num_expr, "GANG");
5016 if (omp_clauses->gang_static_expr)
5017 resolve_positive_int_expr (omp_clauses->gang_static_expr, "GANG");
5018 if (omp_clauses->worker_expr)
5019 resolve_positive_int_expr (omp_clauses->worker_expr, "WORKER");
5020 if (omp_clauses->vector_expr)
5021 resolve_positive_int_expr (omp_clauses->vector_expr, "VECTOR");
5022 for (el = omp_clauses->wait_list; el; el = el->next)
5023 resolve_scalar_int_expr (el->expr, "WAIT");
5024 if (omp_clauses->collapse && omp_clauses->tile_list)
5025 gfc_error ("Incompatible use of TILE and COLLAPSE at %L", &code->loc);
5026 if (omp_clauses->depend_source && code->op != EXEC_OMP_ORDERED)
5027 gfc_error ("SOURCE dependence type only allowed "
5028 "on ORDERED directive at %L", &code->loc);
5029 if (!openacc && code && omp_clauses->lists[OMP_LIST_MAP] == NULL)
5030 {
5031 const char *p = NULL;
5032 switch (code->op)
5033 {
5034 case EXEC_OMP_TARGET_DATA: p = "TARGET DATA"; break;
5035 case EXEC_OMP_TARGET_ENTER_DATA: p = "TARGET ENTER DATA"; break;
5036 case EXEC_OMP_TARGET_EXIT_DATA: p = "TARGET EXIT DATA"; break;
5037 default: break;
5038 }
5039 if (p)
5040 gfc_error ("%s must contain at least one MAP clause at %L",
5041 p, &code->loc);
5042 }
5043 }
5044
5045
5046 /* Return true if SYM is ever referenced in EXPR except in the SE node. */
5047
5048 static bool
expr_references_sym(gfc_expr * e,gfc_symbol * s,gfc_expr * se)5049 expr_references_sym (gfc_expr *e, gfc_symbol *s, gfc_expr *se)
5050 {
5051 gfc_actual_arglist *arg;
5052 if (e == NULL || e == se)
5053 return false;
5054 switch (e->expr_type)
5055 {
5056 case EXPR_CONSTANT:
5057 case EXPR_NULL:
5058 case EXPR_VARIABLE:
5059 case EXPR_STRUCTURE:
5060 case EXPR_ARRAY:
5061 if (e->symtree != NULL
5062 && e->symtree->n.sym == s)
5063 return true;
5064 return false;
5065 case EXPR_SUBSTRING:
5066 if (e->ref != NULL
5067 && (expr_references_sym (e->ref->u.ss.start, s, se)
5068 || expr_references_sym (e->ref->u.ss.end, s, se)))
5069 return true;
5070 return false;
5071 case EXPR_OP:
5072 if (expr_references_sym (e->value.op.op2, s, se))
5073 return true;
5074 return expr_references_sym (e->value.op.op1, s, se);
5075 case EXPR_FUNCTION:
5076 for (arg = e->value.function.actual; arg; arg = arg->next)
5077 if (expr_references_sym (arg->expr, s, se))
5078 return true;
5079 return false;
5080 default:
5081 gcc_unreachable ();
5082 }
5083 }
5084
5085
5086 /* If EXPR is a conversion function that widens the type
5087 if WIDENING is true or narrows the type if WIDENING is false,
5088 return the inner expression, otherwise return NULL. */
5089
5090 static gfc_expr *
is_conversion(gfc_expr * expr,bool widening)5091 is_conversion (gfc_expr *expr, bool widening)
5092 {
5093 gfc_typespec *ts1, *ts2;
5094
5095 if (expr->expr_type != EXPR_FUNCTION
5096 || expr->value.function.isym == NULL
5097 || expr->value.function.esym != NULL
5098 || expr->value.function.isym->id != GFC_ISYM_CONVERSION)
5099 return NULL;
5100
5101 if (widening)
5102 {
5103 ts1 = &expr->ts;
5104 ts2 = &expr->value.function.actual->expr->ts;
5105 }
5106 else
5107 {
5108 ts1 = &expr->value.function.actual->expr->ts;
5109 ts2 = &expr->ts;
5110 }
5111
5112 if (ts1->type > ts2->type
5113 || (ts1->type == ts2->type && ts1->kind > ts2->kind))
5114 return expr->value.function.actual->expr;
5115
5116 return NULL;
5117 }
5118
5119
5120 static void
resolve_omp_atomic(gfc_code * code)5121 resolve_omp_atomic (gfc_code *code)
5122 {
5123 gfc_code *atomic_code = code;
5124 gfc_symbol *var;
5125 gfc_expr *expr2, *expr2_tmp;
5126 gfc_omp_atomic_op aop
5127 = (gfc_omp_atomic_op) (atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_MASK);
5128
5129 code = code->block->next;
5130 /* resolve_blocks asserts this is initially EXEC_ASSIGN.
5131 If it changed to EXEC_NOP, assume an error has been emitted already. */
5132 if (code->op == EXEC_NOP)
5133 return;
5134 if (code->op != EXEC_ASSIGN)
5135 {
5136 unexpected:
5137 gfc_error ("unexpected !$OMP ATOMIC expression at %L", &code->loc);
5138 return;
5139 }
5140 if (aop != GFC_OMP_ATOMIC_CAPTURE)
5141 {
5142 if (code->next != NULL)
5143 goto unexpected;
5144 }
5145 else
5146 {
5147 if (code->next == NULL)
5148 goto unexpected;
5149 if (code->next->op == EXEC_NOP)
5150 return;
5151 if (code->next->op != EXEC_ASSIGN || code->next->next)
5152 {
5153 code = code->next;
5154 goto unexpected;
5155 }
5156 }
5157
5158 if (code->expr1->expr_type != EXPR_VARIABLE
5159 || code->expr1->symtree == NULL
5160 || code->expr1->rank != 0
5161 || (code->expr1->ts.type != BT_INTEGER
5162 && code->expr1->ts.type != BT_REAL
5163 && code->expr1->ts.type != BT_COMPLEX
5164 && code->expr1->ts.type != BT_LOGICAL))
5165 {
5166 gfc_error ("!$OMP ATOMIC statement must set a scalar variable of "
5167 "intrinsic type at %L", &code->loc);
5168 return;
5169 }
5170
5171 var = code->expr1->symtree->n.sym;
5172 expr2 = is_conversion (code->expr2, false);
5173 if (expr2 == NULL)
5174 {
5175 if (aop == GFC_OMP_ATOMIC_READ || aop == GFC_OMP_ATOMIC_WRITE)
5176 expr2 = is_conversion (code->expr2, true);
5177 if (expr2 == NULL)
5178 expr2 = code->expr2;
5179 }
5180
5181 switch (aop)
5182 {
5183 case GFC_OMP_ATOMIC_READ:
5184 if (expr2->expr_type != EXPR_VARIABLE
5185 || expr2->symtree == NULL
5186 || expr2->rank != 0
5187 || (expr2->ts.type != BT_INTEGER
5188 && expr2->ts.type != BT_REAL
5189 && expr2->ts.type != BT_COMPLEX
5190 && expr2->ts.type != BT_LOGICAL))
5191 gfc_error ("!$OMP ATOMIC READ statement must read from a scalar "
5192 "variable of intrinsic type at %L", &expr2->where);
5193 return;
5194 case GFC_OMP_ATOMIC_WRITE:
5195 if (expr2->rank != 0 || expr_references_sym (code->expr2, var, NULL))
5196 gfc_error ("expr in !$OMP ATOMIC WRITE assignment var = expr "
5197 "must be scalar and cannot reference var at %L",
5198 &expr2->where);
5199 return;
5200 case GFC_OMP_ATOMIC_CAPTURE:
5201 expr2_tmp = expr2;
5202 if (expr2 == code->expr2)
5203 {
5204 expr2_tmp = is_conversion (code->expr2, true);
5205 if (expr2_tmp == NULL)
5206 expr2_tmp = expr2;
5207 }
5208 if (expr2_tmp->expr_type == EXPR_VARIABLE)
5209 {
5210 if (expr2_tmp->symtree == NULL
5211 || expr2_tmp->rank != 0
5212 || (expr2_tmp->ts.type != BT_INTEGER
5213 && expr2_tmp->ts.type != BT_REAL
5214 && expr2_tmp->ts.type != BT_COMPLEX
5215 && expr2_tmp->ts.type != BT_LOGICAL)
5216 || expr2_tmp->symtree->n.sym == var)
5217 {
5218 gfc_error ("!$OMP ATOMIC CAPTURE capture statement must read from "
5219 "a scalar variable of intrinsic type at %L",
5220 &expr2_tmp->where);
5221 return;
5222 }
5223 var = expr2_tmp->symtree->n.sym;
5224 code = code->next;
5225 if (code->expr1->expr_type != EXPR_VARIABLE
5226 || code->expr1->symtree == NULL
5227 || code->expr1->rank != 0
5228 || (code->expr1->ts.type != BT_INTEGER
5229 && code->expr1->ts.type != BT_REAL
5230 && code->expr1->ts.type != BT_COMPLEX
5231 && code->expr1->ts.type != BT_LOGICAL))
5232 {
5233 gfc_error ("!$OMP ATOMIC CAPTURE update statement must set "
5234 "a scalar variable of intrinsic type at %L",
5235 &code->expr1->where);
5236 return;
5237 }
5238 if (code->expr1->symtree->n.sym != var)
5239 {
5240 gfc_error ("!$OMP ATOMIC CAPTURE capture statement reads from "
5241 "different variable than update statement writes "
5242 "into at %L", &code->expr1->where);
5243 return;
5244 }
5245 expr2 = is_conversion (code->expr2, false);
5246 if (expr2 == NULL)
5247 expr2 = code->expr2;
5248 }
5249 break;
5250 default:
5251 break;
5252 }
5253
5254 if (gfc_expr_attr (code->expr1).allocatable)
5255 {
5256 gfc_error ("!$OMP ATOMIC with ALLOCATABLE variable at %L",
5257 &code->loc);
5258 return;
5259 }
5260
5261 if (aop == GFC_OMP_ATOMIC_CAPTURE
5262 && code->next == NULL
5263 && code->expr2->rank == 0
5264 && !expr_references_sym (code->expr2, var, NULL))
5265 atomic_code->ext.omp_atomic
5266 = (gfc_omp_atomic_op) (atomic_code->ext.omp_atomic
5267 | GFC_OMP_ATOMIC_SWAP);
5268 else if (expr2->expr_type == EXPR_OP)
5269 {
5270 gfc_expr *v = NULL, *e, *c;
5271 gfc_intrinsic_op op = expr2->value.op.op;
5272 gfc_intrinsic_op alt_op = INTRINSIC_NONE;
5273
5274 switch (op)
5275 {
5276 case INTRINSIC_PLUS:
5277 alt_op = INTRINSIC_MINUS;
5278 break;
5279 case INTRINSIC_TIMES:
5280 alt_op = INTRINSIC_DIVIDE;
5281 break;
5282 case INTRINSIC_MINUS:
5283 alt_op = INTRINSIC_PLUS;
5284 break;
5285 case INTRINSIC_DIVIDE:
5286 alt_op = INTRINSIC_TIMES;
5287 break;
5288 case INTRINSIC_AND:
5289 case INTRINSIC_OR:
5290 break;
5291 case INTRINSIC_EQV:
5292 alt_op = INTRINSIC_NEQV;
5293 break;
5294 case INTRINSIC_NEQV:
5295 alt_op = INTRINSIC_EQV;
5296 break;
5297 default:
5298 gfc_error ("!$OMP ATOMIC assignment operator must be binary "
5299 "+, *, -, /, .AND., .OR., .EQV. or .NEQV. at %L",
5300 &expr2->where);
5301 return;
5302 }
5303
5304 /* Check for var = var op expr resp. var = expr op var where
5305 expr doesn't reference var and var op expr is mathematically
5306 equivalent to var op (expr) resp. expr op var equivalent to
5307 (expr) op var. We rely here on the fact that the matcher
5308 for x op1 y op2 z where op1 and op2 have equal precedence
5309 returns (x op1 y) op2 z. */
5310 e = expr2->value.op.op2;
5311 if (e->expr_type == EXPR_VARIABLE
5312 && e->symtree != NULL
5313 && e->symtree->n.sym == var)
5314 v = e;
5315 else if ((c = is_conversion (e, true)) != NULL
5316 && c->expr_type == EXPR_VARIABLE
5317 && c->symtree != NULL
5318 && c->symtree->n.sym == var)
5319 v = c;
5320 else
5321 {
5322 gfc_expr **p = NULL, **q;
5323 for (q = &expr2->value.op.op1; (e = *q) != NULL; )
5324 if (e->expr_type == EXPR_VARIABLE
5325 && e->symtree != NULL
5326 && e->symtree->n.sym == var)
5327 {
5328 v = e;
5329 break;
5330 }
5331 else if ((c = is_conversion (e, true)) != NULL)
5332 q = &e->value.function.actual->expr;
5333 else if (e->expr_type != EXPR_OP
5334 || (e->value.op.op != op
5335 && e->value.op.op != alt_op)
5336 || e->rank != 0)
5337 break;
5338 else
5339 {
5340 p = q;
5341 q = &e->value.op.op1;
5342 }
5343
5344 if (v == NULL)
5345 {
5346 gfc_error ("!$OMP ATOMIC assignment must be var = var op expr "
5347 "or var = expr op var at %L", &expr2->where);
5348 return;
5349 }
5350
5351 if (p != NULL)
5352 {
5353 e = *p;
5354 switch (e->value.op.op)
5355 {
5356 case INTRINSIC_MINUS:
5357 case INTRINSIC_DIVIDE:
5358 case INTRINSIC_EQV:
5359 case INTRINSIC_NEQV:
5360 gfc_error ("!$OMP ATOMIC var = var op expr not "
5361 "mathematically equivalent to var = var op "
5362 "(expr) at %L", &expr2->where);
5363 break;
5364 default:
5365 break;
5366 }
5367
5368 /* Canonicalize into var = var op (expr). */
5369 *p = e->value.op.op2;
5370 e->value.op.op2 = expr2;
5371 e->ts = expr2->ts;
5372 if (code->expr2 == expr2)
5373 code->expr2 = expr2 = e;
5374 else
5375 code->expr2->value.function.actual->expr = expr2 = e;
5376
5377 if (!gfc_compare_types (&expr2->value.op.op1->ts, &expr2->ts))
5378 {
5379 for (p = &expr2->value.op.op1; *p != v;
5380 p = &(*p)->value.function.actual->expr)
5381 ;
5382 *p = NULL;
5383 gfc_free_expr (expr2->value.op.op1);
5384 expr2->value.op.op1 = v;
5385 gfc_convert_type (v, &expr2->ts, 2);
5386 }
5387 }
5388 }
5389
5390 if (e->rank != 0 || expr_references_sym (code->expr2, var, v))
5391 {
5392 gfc_error ("expr in !$OMP ATOMIC assignment var = var op expr "
5393 "must be scalar and cannot reference var at %L",
5394 &expr2->where);
5395 return;
5396 }
5397 }
5398 else if (expr2->expr_type == EXPR_FUNCTION
5399 && expr2->value.function.isym != NULL
5400 && expr2->value.function.esym == NULL
5401 && expr2->value.function.actual != NULL
5402 && expr2->value.function.actual->next != NULL)
5403 {
5404 gfc_actual_arglist *arg, *var_arg;
5405
5406 switch (expr2->value.function.isym->id)
5407 {
5408 case GFC_ISYM_MIN:
5409 case GFC_ISYM_MAX:
5410 break;
5411 case GFC_ISYM_IAND:
5412 case GFC_ISYM_IOR:
5413 case GFC_ISYM_IEOR:
5414 if (expr2->value.function.actual->next->next != NULL)
5415 {
5416 gfc_error ("!$OMP ATOMIC assignment intrinsic IAND, IOR "
5417 "or IEOR must have two arguments at %L",
5418 &expr2->where);
5419 return;
5420 }
5421 break;
5422 default:
5423 gfc_error ("!$OMP ATOMIC assignment intrinsic must be "
5424 "MIN, MAX, IAND, IOR or IEOR at %L",
5425 &expr2->where);
5426 return;
5427 }
5428
5429 var_arg = NULL;
5430 for (arg = expr2->value.function.actual; arg; arg = arg->next)
5431 {
5432 if ((arg == expr2->value.function.actual
5433 || (var_arg == NULL && arg->next == NULL))
5434 && arg->expr->expr_type == EXPR_VARIABLE
5435 && arg->expr->symtree != NULL
5436 && arg->expr->symtree->n.sym == var)
5437 var_arg = arg;
5438 else if (expr_references_sym (arg->expr, var, NULL))
5439 {
5440 gfc_error ("!$OMP ATOMIC intrinsic arguments except one must "
5441 "not reference %qs at %L",
5442 var->name, &arg->expr->where);
5443 return;
5444 }
5445 if (arg->expr->rank != 0)
5446 {
5447 gfc_error ("!$OMP ATOMIC intrinsic arguments must be scalar "
5448 "at %L", &arg->expr->where);
5449 return;
5450 }
5451 }
5452
5453 if (var_arg == NULL)
5454 {
5455 gfc_error ("First or last !$OMP ATOMIC intrinsic argument must "
5456 "be %qs at %L", var->name, &expr2->where);
5457 return;
5458 }
5459
5460 if (var_arg != expr2->value.function.actual)
5461 {
5462 /* Canonicalize, so that var comes first. */
5463 gcc_assert (var_arg->next == NULL);
5464 for (arg = expr2->value.function.actual;
5465 arg->next != var_arg; arg = arg->next)
5466 ;
5467 var_arg->next = expr2->value.function.actual;
5468 expr2->value.function.actual = var_arg;
5469 arg->next = NULL;
5470 }
5471 }
5472 else
5473 gfc_error ("!$OMP ATOMIC assignment must have an operator or "
5474 "intrinsic on right hand side at %L", &expr2->where);
5475
5476 if (aop == GFC_OMP_ATOMIC_CAPTURE && code->next)
5477 {
5478 code = code->next;
5479 if (code->expr1->expr_type != EXPR_VARIABLE
5480 || code->expr1->symtree == NULL
5481 || code->expr1->rank != 0
5482 || (code->expr1->ts.type != BT_INTEGER
5483 && code->expr1->ts.type != BT_REAL
5484 && code->expr1->ts.type != BT_COMPLEX
5485 && code->expr1->ts.type != BT_LOGICAL))
5486 {
5487 gfc_error ("!$OMP ATOMIC CAPTURE capture statement must set "
5488 "a scalar variable of intrinsic type at %L",
5489 &code->expr1->where);
5490 return;
5491 }
5492
5493 expr2 = is_conversion (code->expr2, false);
5494 if (expr2 == NULL)
5495 {
5496 expr2 = is_conversion (code->expr2, true);
5497 if (expr2 == NULL)
5498 expr2 = code->expr2;
5499 }
5500
5501 if (expr2->expr_type != EXPR_VARIABLE
5502 || expr2->symtree == NULL
5503 || expr2->rank != 0
5504 || (expr2->ts.type != BT_INTEGER
5505 && expr2->ts.type != BT_REAL
5506 && expr2->ts.type != BT_COMPLEX
5507 && expr2->ts.type != BT_LOGICAL))
5508 {
5509 gfc_error ("!$OMP ATOMIC CAPTURE capture statement must read "
5510 "from a scalar variable of intrinsic type at %L",
5511 &expr2->where);
5512 return;
5513 }
5514 if (expr2->symtree->n.sym != var)
5515 {
5516 gfc_error ("!$OMP ATOMIC CAPTURE capture statement reads from "
5517 "different variable than update statement writes "
5518 "into at %L", &expr2->where);
5519 return;
5520 }
5521 }
5522 }
5523
5524
5525 static struct fortran_omp_context
5526 {
5527 gfc_code *code;
5528 hash_set<gfc_symbol *> *sharing_clauses;
5529 hash_set<gfc_symbol *> *private_iterators;
5530 struct fortran_omp_context *previous;
5531 bool is_openmp;
5532 } *omp_current_ctx;
5533 static gfc_code *omp_current_do_code;
5534 static int omp_current_do_collapse;
5535
5536 void
gfc_resolve_omp_do_blocks(gfc_code * code,gfc_namespace * ns)5537 gfc_resolve_omp_do_blocks (gfc_code *code, gfc_namespace *ns)
5538 {
5539 if (code->block->next && code->block->next->op == EXEC_DO)
5540 {
5541 int i;
5542 gfc_code *c;
5543
5544 omp_current_do_code = code->block->next;
5545 if (code->ext.omp_clauses->orderedc)
5546 omp_current_do_collapse = code->ext.omp_clauses->orderedc;
5547 else
5548 omp_current_do_collapse = code->ext.omp_clauses->collapse;
5549 for (i = 1, c = omp_current_do_code; i < omp_current_do_collapse; i++)
5550 {
5551 c = c->block;
5552 if (c->op != EXEC_DO || c->next == NULL)
5553 break;
5554 c = c->next;
5555 if (c->op != EXEC_DO)
5556 break;
5557 }
5558 if (i < omp_current_do_collapse || omp_current_do_collapse <= 0)
5559 omp_current_do_collapse = 1;
5560 }
5561 gfc_resolve_blocks (code->block, ns);
5562 omp_current_do_collapse = 0;
5563 omp_current_do_code = NULL;
5564 }
5565
5566
5567 void
gfc_resolve_omp_parallel_blocks(gfc_code * code,gfc_namespace * ns)5568 gfc_resolve_omp_parallel_blocks (gfc_code *code, gfc_namespace *ns)
5569 {
5570 struct fortran_omp_context ctx;
5571 gfc_omp_clauses *omp_clauses = code->ext.omp_clauses;
5572 gfc_omp_namelist *n;
5573 int list;
5574
5575 ctx.code = code;
5576 ctx.sharing_clauses = new hash_set<gfc_symbol *>;
5577 ctx.private_iterators = new hash_set<gfc_symbol *>;
5578 ctx.previous = omp_current_ctx;
5579 ctx.is_openmp = true;
5580 omp_current_ctx = &ctx;
5581
5582 for (list = 0; list < OMP_LIST_NUM; list++)
5583 switch (list)
5584 {
5585 case OMP_LIST_SHARED:
5586 case OMP_LIST_PRIVATE:
5587 case OMP_LIST_FIRSTPRIVATE:
5588 case OMP_LIST_LASTPRIVATE:
5589 case OMP_LIST_REDUCTION:
5590 case OMP_LIST_LINEAR:
5591 for (n = omp_clauses->lists[list]; n; n = n->next)
5592 ctx.sharing_clauses->add (n->sym);
5593 break;
5594 default:
5595 break;
5596 }
5597
5598 switch (code->op)
5599 {
5600 case EXEC_OMP_PARALLEL_DO:
5601 case EXEC_OMP_PARALLEL_DO_SIMD:
5602 case EXEC_OMP_TARGET_PARALLEL_DO:
5603 case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
5604 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
5605 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
5606 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
5607 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
5608 case EXEC_OMP_TASKLOOP:
5609 case EXEC_OMP_TASKLOOP_SIMD:
5610 case EXEC_OMP_TEAMS_DISTRIBUTE:
5611 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
5612 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
5613 case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
5614 gfc_resolve_omp_do_blocks (code, ns);
5615 break;
5616 default:
5617 gfc_resolve_blocks (code->block, ns);
5618 }
5619
5620 omp_current_ctx = ctx.previous;
5621 delete ctx.sharing_clauses;
5622 delete ctx.private_iterators;
5623 }
5624
5625
5626 /* Save and clear openmp.c private state. */
5627
5628 void
gfc_omp_save_and_clear_state(struct gfc_omp_saved_state * state)5629 gfc_omp_save_and_clear_state (struct gfc_omp_saved_state *state)
5630 {
5631 state->ptrs[0] = omp_current_ctx;
5632 state->ptrs[1] = omp_current_do_code;
5633 state->ints[0] = omp_current_do_collapse;
5634 omp_current_ctx = NULL;
5635 omp_current_do_code = NULL;
5636 omp_current_do_collapse = 0;
5637 }
5638
5639
5640 /* Restore openmp.c private state from the saved state. */
5641
5642 void
gfc_omp_restore_state(struct gfc_omp_saved_state * state)5643 gfc_omp_restore_state (struct gfc_omp_saved_state *state)
5644 {
5645 omp_current_ctx = (struct fortran_omp_context *) state->ptrs[0];
5646 omp_current_do_code = (gfc_code *) state->ptrs[1];
5647 omp_current_do_collapse = state->ints[0];
5648 }
5649
5650
5651 /* Note a DO iterator variable. This is special in !$omp parallel
5652 construct, where they are predetermined private. */
5653
5654 void
gfc_resolve_do_iterator(gfc_code * code,gfc_symbol * sym,bool add_clause)5655 gfc_resolve_do_iterator (gfc_code *code, gfc_symbol *sym, bool add_clause)
5656 {
5657 if (omp_current_ctx == NULL)
5658 return;
5659
5660 int i = omp_current_do_collapse;
5661 gfc_code *c = omp_current_do_code;
5662
5663 if (sym->attr.threadprivate)
5664 return;
5665
5666 /* !$omp do and !$omp parallel do iteration variable is predetermined
5667 private just in the !$omp do resp. !$omp parallel do construct,
5668 with no implications for the outer parallel constructs. */
5669
5670 while (i-- >= 1)
5671 {
5672 if (code == c)
5673 return;
5674
5675 c = c->block->next;
5676 }
5677
5678 /* An openacc context may represent a data clause. Abort if so. */
5679 if (!omp_current_ctx->is_openmp && !oacc_is_loop (omp_current_ctx->code))
5680 return;
5681
5682 if (omp_current_ctx->sharing_clauses->contains (sym))
5683 return;
5684
5685 if (! omp_current_ctx->private_iterators->add (sym) && add_clause)
5686 {
5687 gfc_omp_clauses *omp_clauses = omp_current_ctx->code->ext.omp_clauses;
5688 gfc_omp_namelist *p;
5689
5690 p = gfc_get_omp_namelist ();
5691 p->sym = sym;
5692 p->next = omp_clauses->lists[OMP_LIST_PRIVATE];
5693 omp_clauses->lists[OMP_LIST_PRIVATE] = p;
5694 }
5695 }
5696
5697 static void
handle_local_var(gfc_symbol * sym)5698 handle_local_var (gfc_symbol *sym)
5699 {
5700 if (sym->attr.flavor != FL_VARIABLE
5701 || sym->as != NULL
5702 || (sym->ts.type != BT_INTEGER && sym->ts.type != BT_REAL))
5703 return;
5704 gfc_resolve_do_iterator (sym->ns->code, sym, false);
5705 }
5706
5707 void
gfc_resolve_omp_local_vars(gfc_namespace * ns)5708 gfc_resolve_omp_local_vars (gfc_namespace *ns)
5709 {
5710 if (omp_current_ctx)
5711 gfc_traverse_ns (ns, handle_local_var);
5712 }
5713
5714 static void
resolve_omp_do(gfc_code * code)5715 resolve_omp_do (gfc_code *code)
5716 {
5717 gfc_code *do_code, *c;
5718 int list, i, collapse;
5719 gfc_omp_namelist *n;
5720 gfc_symbol *dovar;
5721 const char *name;
5722 bool is_simd = false;
5723
5724 switch (code->op)
5725 {
5726 case EXEC_OMP_DISTRIBUTE: name = "!$OMP DISTRIBUTE"; break;
5727 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
5728 name = "!$OMP DISTRIBUTE PARALLEL DO";
5729 break;
5730 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
5731 name = "!$OMP DISTRIBUTE PARALLEL DO SIMD";
5732 is_simd = true;
5733 break;
5734 case EXEC_OMP_DISTRIBUTE_SIMD:
5735 name = "!$OMP DISTRIBUTE SIMD";
5736 is_simd = true;
5737 break;
5738 case EXEC_OMP_DO: name = "!$OMP DO"; break;
5739 case EXEC_OMP_DO_SIMD: name = "!$OMP DO SIMD"; is_simd = true; break;
5740 case EXEC_OMP_PARALLEL_DO: name = "!$OMP PARALLEL DO"; break;
5741 case EXEC_OMP_PARALLEL_DO_SIMD:
5742 name = "!$OMP PARALLEL DO SIMD";
5743 is_simd = true;
5744 break;
5745 case EXEC_OMP_SIMD: name = "!$OMP SIMD"; is_simd = true; break;
5746 case EXEC_OMP_TARGET_PARALLEL_DO: name = "!$OMP TARGET PARALLEL DO"; break;
5747 case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
5748 name = "!$OMP TARGET PARALLEL DO SIMD";
5749 is_simd = true;
5750 break;
5751 case EXEC_OMP_TARGET_SIMD:
5752 name = "!$OMP TARGET SIMD";
5753 is_simd = true;
5754 break;
5755 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
5756 name = "!$OMP TARGET TEAMS DISTRIBUTE";
5757 break;
5758 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
5759 name = "!$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO";
5760 break;
5761 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
5762 name = "!$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD";
5763 is_simd = true;
5764 break;
5765 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
5766 name = "!$OMP TARGET TEAMS DISTRIBUTE SIMD";
5767 is_simd = true;
5768 break;
5769 case EXEC_OMP_TASKLOOP: name = "!$OMP TASKLOOP"; break;
5770 case EXEC_OMP_TASKLOOP_SIMD:
5771 name = "!$OMP TASKLOOP SIMD";
5772 is_simd = true;
5773 break;
5774 case EXEC_OMP_TEAMS_DISTRIBUTE: name = "!$OMP TEAMS DISTRIBUTE"; break;
5775 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
5776 name = "!$OMP TEAMS DISTRIBUTE PARALLEL DO";
5777 break;
5778 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
5779 name = "!$OMP TEAMS DISTRIBUTE PARALLEL DO SIMD";
5780 is_simd = true;
5781 break;
5782 case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
5783 name = "!$OMP TEAMS DISTRIBUTE SIMD";
5784 is_simd = true;
5785 break;
5786 default: gcc_unreachable ();
5787 }
5788
5789 if (code->ext.omp_clauses)
5790 resolve_omp_clauses (code, code->ext.omp_clauses, NULL);
5791
5792 do_code = code->block->next;
5793 if (code->ext.omp_clauses->orderedc)
5794 collapse = code->ext.omp_clauses->orderedc;
5795 else
5796 {
5797 collapse = code->ext.omp_clauses->collapse;
5798 if (collapse <= 0)
5799 collapse = 1;
5800 }
5801 for (i = 1; i <= collapse; i++)
5802 {
5803 if (do_code->op == EXEC_DO_WHILE)
5804 {
5805 gfc_error ("%s cannot be a DO WHILE or DO without loop control "
5806 "at %L", name, &do_code->loc);
5807 break;
5808 }
5809 if (do_code->op == EXEC_DO_CONCURRENT)
5810 {
5811 gfc_error ("%s cannot be a DO CONCURRENT loop at %L", name,
5812 &do_code->loc);
5813 break;
5814 }
5815 gcc_assert (do_code->op == EXEC_DO);
5816 if (do_code->ext.iterator->var->ts.type != BT_INTEGER)
5817 gfc_error ("%s iteration variable must be of type integer at %L",
5818 name, &do_code->loc);
5819 dovar = do_code->ext.iterator->var->symtree->n.sym;
5820 if (dovar->attr.threadprivate)
5821 gfc_error ("%s iteration variable must not be THREADPRIVATE "
5822 "at %L", name, &do_code->loc);
5823 if (code->ext.omp_clauses)
5824 for (list = 0; list < OMP_LIST_NUM; list++)
5825 if (!is_simd
5826 ? (list != OMP_LIST_PRIVATE && list != OMP_LIST_LASTPRIVATE)
5827 : code->ext.omp_clauses->collapse > 1
5828 ? (list != OMP_LIST_LASTPRIVATE)
5829 : (list != OMP_LIST_LINEAR))
5830 for (n = code->ext.omp_clauses->lists[list]; n; n = n->next)
5831 if (dovar == n->sym)
5832 {
5833 if (!is_simd)
5834 gfc_error ("%s iteration variable present on clause "
5835 "other than PRIVATE or LASTPRIVATE at %L",
5836 name, &do_code->loc);
5837 else if (code->ext.omp_clauses->collapse > 1)
5838 gfc_error ("%s iteration variable present on clause "
5839 "other than LASTPRIVATE at %L",
5840 name, &do_code->loc);
5841 else
5842 gfc_error ("%s iteration variable present on clause "
5843 "other than LINEAR at %L",
5844 name, &do_code->loc);
5845 break;
5846 }
5847 if (i > 1)
5848 {
5849 gfc_code *do_code2 = code->block->next;
5850 int j;
5851
5852 for (j = 1; j < i; j++)
5853 {
5854 gfc_symbol *ivar = do_code2->ext.iterator->var->symtree->n.sym;
5855 if (dovar == ivar
5856 || gfc_find_sym_in_expr (ivar, do_code->ext.iterator->start)
5857 || gfc_find_sym_in_expr (ivar, do_code->ext.iterator->end)
5858 || gfc_find_sym_in_expr (ivar, do_code->ext.iterator->step))
5859 {
5860 gfc_error ("%s collapsed loops don't form rectangular "
5861 "iteration space at %L", name, &do_code->loc);
5862 break;
5863 }
5864 do_code2 = do_code2->block->next;
5865 }
5866 }
5867 if (i == collapse)
5868 break;
5869 for (c = do_code->next; c; c = c->next)
5870 if (c->op != EXEC_NOP && c->op != EXEC_CONTINUE)
5871 {
5872 gfc_error ("collapsed %s loops not perfectly nested at %L",
5873 name, &c->loc);
5874 break;
5875 }
5876 if (c)
5877 break;
5878 do_code = do_code->block;
5879 if (do_code->op != EXEC_DO && do_code->op != EXEC_DO_WHILE)
5880 {
5881 gfc_error ("not enough DO loops for collapsed %s at %L",
5882 name, &code->loc);
5883 break;
5884 }
5885 do_code = do_code->next;
5886 if (do_code == NULL
5887 || (do_code->op != EXEC_DO && do_code->op != EXEC_DO_WHILE))
5888 {
5889 gfc_error ("not enough DO loops for collapsed %s at %L",
5890 name, &code->loc);
5891 break;
5892 }
5893 }
5894 }
5895
5896 static bool
oacc_is_parallel(gfc_code * code)5897 oacc_is_parallel (gfc_code *code)
5898 {
5899 return code->op == EXEC_OACC_PARALLEL || code->op == EXEC_OACC_PARALLEL_LOOP;
5900 }
5901
5902 static gfc_statement
omp_code_to_statement(gfc_code * code)5903 omp_code_to_statement (gfc_code *code)
5904 {
5905 switch (code->op)
5906 {
5907 case EXEC_OMP_PARALLEL:
5908 return ST_OMP_PARALLEL;
5909 case EXEC_OMP_PARALLEL_SECTIONS:
5910 return ST_OMP_PARALLEL_SECTIONS;
5911 case EXEC_OMP_SECTIONS:
5912 return ST_OMP_SECTIONS;
5913 case EXEC_OMP_ORDERED:
5914 return ST_OMP_ORDERED;
5915 case EXEC_OMP_CRITICAL:
5916 return ST_OMP_CRITICAL;
5917 case EXEC_OMP_MASTER:
5918 return ST_OMP_MASTER;
5919 case EXEC_OMP_SINGLE:
5920 return ST_OMP_SINGLE;
5921 case EXEC_OMP_TASK:
5922 return ST_OMP_TASK;
5923 case EXEC_OMP_WORKSHARE:
5924 return ST_OMP_WORKSHARE;
5925 case EXEC_OMP_PARALLEL_WORKSHARE:
5926 return ST_OMP_PARALLEL_WORKSHARE;
5927 case EXEC_OMP_DO:
5928 return ST_OMP_DO;
5929 case EXEC_OMP_ATOMIC:
5930 return ST_OMP_ATOMIC;
5931 case EXEC_OMP_BARRIER:
5932 return ST_OMP_BARRIER;
5933 case EXEC_OMP_CANCEL:
5934 return ST_OMP_CANCEL;
5935 case EXEC_OMP_CANCELLATION_POINT:
5936 return ST_OMP_CANCELLATION_POINT;
5937 case EXEC_OMP_FLUSH:
5938 return ST_OMP_FLUSH;
5939 case EXEC_OMP_DISTRIBUTE:
5940 return ST_OMP_DISTRIBUTE;
5941 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
5942 return ST_OMP_DISTRIBUTE_PARALLEL_DO;
5943 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
5944 return ST_OMP_DISTRIBUTE_PARALLEL_DO_SIMD;
5945 case EXEC_OMP_DISTRIBUTE_SIMD:
5946 return ST_OMP_DISTRIBUTE_SIMD;
5947 case EXEC_OMP_DO_SIMD:
5948 return ST_OMP_DO_SIMD;
5949 case EXEC_OMP_SIMD:
5950 return ST_OMP_SIMD;
5951 case EXEC_OMP_TARGET:
5952 return ST_OMP_TARGET;
5953 case EXEC_OMP_TARGET_DATA:
5954 return ST_OMP_TARGET_DATA;
5955 case EXEC_OMP_TARGET_ENTER_DATA:
5956 return ST_OMP_TARGET_ENTER_DATA;
5957 case EXEC_OMP_TARGET_EXIT_DATA:
5958 return ST_OMP_TARGET_EXIT_DATA;
5959 case EXEC_OMP_TARGET_PARALLEL:
5960 return ST_OMP_TARGET_PARALLEL;
5961 case EXEC_OMP_TARGET_PARALLEL_DO:
5962 return ST_OMP_TARGET_PARALLEL_DO;
5963 case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
5964 return ST_OMP_TARGET_PARALLEL_DO_SIMD;
5965 case EXEC_OMP_TARGET_SIMD:
5966 return ST_OMP_TARGET_SIMD;
5967 case EXEC_OMP_TARGET_TEAMS:
5968 return ST_OMP_TARGET_TEAMS;
5969 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
5970 return ST_OMP_TARGET_TEAMS_DISTRIBUTE;
5971 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
5972 return ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO;
5973 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
5974 return ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD;
5975 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
5976 return ST_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD;
5977 case EXEC_OMP_TARGET_UPDATE:
5978 return ST_OMP_TARGET_UPDATE;
5979 case EXEC_OMP_TASKGROUP:
5980 return ST_OMP_TASKGROUP;
5981 case EXEC_OMP_TASKLOOP:
5982 return ST_OMP_TASKLOOP;
5983 case EXEC_OMP_TASKLOOP_SIMD:
5984 return ST_OMP_TASKLOOP_SIMD;
5985 case EXEC_OMP_TASKWAIT:
5986 return ST_OMP_TASKWAIT;
5987 case EXEC_OMP_TASKYIELD:
5988 return ST_OMP_TASKYIELD;
5989 case EXEC_OMP_TEAMS:
5990 return ST_OMP_TEAMS;
5991 case EXEC_OMP_TEAMS_DISTRIBUTE:
5992 return ST_OMP_TEAMS_DISTRIBUTE;
5993 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
5994 return ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO;
5995 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
5996 return ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD;
5997 case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
5998 return ST_OMP_TEAMS_DISTRIBUTE_SIMD;
5999 case EXEC_OMP_PARALLEL_DO:
6000 return ST_OMP_PARALLEL_DO;
6001 case EXEC_OMP_PARALLEL_DO_SIMD:
6002 return ST_OMP_PARALLEL_DO_SIMD;
6003
6004 default:
6005 gcc_unreachable ();
6006 }
6007 }
6008
6009 static gfc_statement
oacc_code_to_statement(gfc_code * code)6010 oacc_code_to_statement (gfc_code *code)
6011 {
6012 switch (code->op)
6013 {
6014 case EXEC_OACC_PARALLEL:
6015 return ST_OACC_PARALLEL;
6016 case EXEC_OACC_KERNELS:
6017 return ST_OACC_KERNELS;
6018 case EXEC_OACC_SERIAL:
6019 return ST_OACC_SERIAL;
6020 case EXEC_OACC_DATA:
6021 return ST_OACC_DATA;
6022 case EXEC_OACC_HOST_DATA:
6023 return ST_OACC_HOST_DATA;
6024 case EXEC_OACC_PARALLEL_LOOP:
6025 return ST_OACC_PARALLEL_LOOP;
6026 case EXEC_OACC_KERNELS_LOOP:
6027 return ST_OACC_KERNELS_LOOP;
6028 case EXEC_OACC_SERIAL_LOOP:
6029 return ST_OACC_SERIAL_LOOP;
6030 case EXEC_OACC_LOOP:
6031 return ST_OACC_LOOP;
6032 case EXEC_OACC_ATOMIC:
6033 return ST_OACC_ATOMIC;
6034 case EXEC_OACC_ROUTINE:
6035 return ST_OACC_ROUTINE;
6036 case EXEC_OACC_UPDATE:
6037 return ST_OACC_UPDATE;
6038 case EXEC_OACC_WAIT:
6039 return ST_OACC_WAIT;
6040 case EXEC_OACC_CACHE:
6041 return ST_OACC_CACHE;
6042 case EXEC_OACC_ENTER_DATA:
6043 return ST_OACC_ENTER_DATA;
6044 case EXEC_OACC_EXIT_DATA:
6045 return ST_OACC_EXIT_DATA;
6046 case EXEC_OACC_DECLARE:
6047 return ST_OACC_DECLARE;
6048 default:
6049 gcc_unreachable ();
6050 }
6051 }
6052
6053 static void
resolve_oacc_directive_inside_omp_region(gfc_code * code)6054 resolve_oacc_directive_inside_omp_region (gfc_code *code)
6055 {
6056 if (omp_current_ctx != NULL && omp_current_ctx->is_openmp)
6057 {
6058 gfc_statement st = omp_code_to_statement (omp_current_ctx->code);
6059 gfc_statement oacc_st = oacc_code_to_statement (code);
6060 gfc_error ("The %s directive cannot be specified within "
6061 "a %s region at %L", gfc_ascii_statement (oacc_st),
6062 gfc_ascii_statement (st), &code->loc);
6063 }
6064 }
6065
6066 static void
resolve_omp_directive_inside_oacc_region(gfc_code * code)6067 resolve_omp_directive_inside_oacc_region (gfc_code *code)
6068 {
6069 if (omp_current_ctx != NULL && !omp_current_ctx->is_openmp)
6070 {
6071 gfc_statement st = oacc_code_to_statement (omp_current_ctx->code);
6072 gfc_statement omp_st = omp_code_to_statement (code);
6073 gfc_error ("The %s directive cannot be specified within "
6074 "a %s region at %L", gfc_ascii_statement (omp_st),
6075 gfc_ascii_statement (st), &code->loc);
6076 }
6077 }
6078
6079
6080 static void
resolve_oacc_nested_loops(gfc_code * code,gfc_code * do_code,int collapse,const char * clause)6081 resolve_oacc_nested_loops (gfc_code *code, gfc_code* do_code, int collapse,
6082 const char *clause)
6083 {
6084 gfc_symbol *dovar;
6085 gfc_code *c;
6086 int i;
6087
6088 for (i = 1; i <= collapse; i++)
6089 {
6090 if (do_code->op == EXEC_DO_WHILE)
6091 {
6092 gfc_error ("!$ACC LOOP cannot be a DO WHILE or DO without loop control "
6093 "at %L", &do_code->loc);
6094 break;
6095 }
6096 if (do_code->op == EXEC_DO_CONCURRENT)
6097 {
6098 gfc_error ("!$ACC LOOP cannot be a DO CONCURRENT loop at %L",
6099 &do_code->loc);
6100 break;
6101 }
6102 gcc_assert (do_code->op == EXEC_DO);
6103 if (do_code->ext.iterator->var->ts.type != BT_INTEGER)
6104 gfc_error ("!$ACC LOOP iteration variable must be of type integer at %L",
6105 &do_code->loc);
6106 dovar = do_code->ext.iterator->var->symtree->n.sym;
6107 if (i > 1)
6108 {
6109 gfc_code *do_code2 = code->block->next;
6110 int j;
6111
6112 for (j = 1; j < i; j++)
6113 {
6114 gfc_symbol *ivar = do_code2->ext.iterator->var->symtree->n.sym;
6115 if (dovar == ivar
6116 || gfc_find_sym_in_expr (ivar, do_code->ext.iterator->start)
6117 || gfc_find_sym_in_expr (ivar, do_code->ext.iterator->end)
6118 || gfc_find_sym_in_expr (ivar, do_code->ext.iterator->step))
6119 {
6120 gfc_error ("!$ACC LOOP %s loops don't form rectangular "
6121 "iteration space at %L", clause, &do_code->loc);
6122 break;
6123 }
6124 do_code2 = do_code2->block->next;
6125 }
6126 }
6127 if (i == collapse)
6128 break;
6129 for (c = do_code->next; c; c = c->next)
6130 if (c->op != EXEC_NOP && c->op != EXEC_CONTINUE)
6131 {
6132 gfc_error ("%s !$ACC LOOP loops not perfectly nested at %L",
6133 clause, &c->loc);
6134 break;
6135 }
6136 if (c)
6137 break;
6138 do_code = do_code->block;
6139 if (do_code->op != EXEC_DO && do_code->op != EXEC_DO_WHILE
6140 && do_code->op != EXEC_DO_CONCURRENT)
6141 {
6142 gfc_error ("not enough DO loops for %s !$ACC LOOP at %L",
6143 clause, &code->loc);
6144 break;
6145 }
6146 do_code = do_code->next;
6147 if (do_code == NULL
6148 || (do_code->op != EXEC_DO && do_code->op != EXEC_DO_WHILE
6149 && do_code->op != EXEC_DO_CONCURRENT))
6150 {
6151 gfc_error ("not enough DO loops for %s !$ACC LOOP at %L",
6152 clause, &code->loc);
6153 break;
6154 }
6155 }
6156 }
6157
6158
6159 static void
resolve_oacc_params_in_parallel(gfc_code * code,const char * clause,const char * arg)6160 resolve_oacc_params_in_parallel (gfc_code *code, const char *clause,
6161 const char *arg)
6162 {
6163 fortran_omp_context *c;
6164
6165 if (oacc_is_parallel (code))
6166 gfc_error ("!$ACC LOOP %s in PARALLEL region doesn't allow "
6167 "%s arguments at %L", clause, arg, &code->loc);
6168 for (c = omp_current_ctx; c; c = c->previous)
6169 {
6170 if (oacc_is_loop (c->code))
6171 break;
6172 if (oacc_is_parallel (c->code))
6173 gfc_error ("!$ACC LOOP %s in PARALLEL region doesn't allow "
6174 "%s arguments at %L", clause, arg, &code->loc);
6175 }
6176 }
6177
6178
6179 static void
resolve_oacc_loop_blocks(gfc_code * code)6180 resolve_oacc_loop_blocks (gfc_code *code)
6181 {
6182 if (!oacc_is_loop (code))
6183 return;
6184
6185 if (code->ext.omp_clauses->tile_list && code->ext.omp_clauses->gang
6186 && code->ext.omp_clauses->worker && code->ext.omp_clauses->vector)
6187 gfc_error ("Tiled loop cannot be parallelized across gangs, workers and "
6188 "vectors at the same time at %L", &code->loc);
6189
6190 if (code->ext.omp_clauses->gang
6191 && code->ext.omp_clauses->gang_num_expr)
6192 resolve_oacc_params_in_parallel (code, "GANG", "num");
6193
6194 if (code->ext.omp_clauses->worker
6195 && code->ext.omp_clauses->worker_expr)
6196 resolve_oacc_params_in_parallel (code, "WORKER", "num");
6197
6198 if (code->ext.omp_clauses->vector
6199 && code->ext.omp_clauses->vector_expr)
6200 resolve_oacc_params_in_parallel (code, "VECTOR", "length");
6201
6202 if (code->ext.omp_clauses->tile_list)
6203 {
6204 gfc_expr_list *el;
6205 for (el = code->ext.omp_clauses->tile_list; el; el = el->next)
6206 {
6207 if (el->expr == NULL)
6208 {
6209 /* NULL expressions are used to represent '*' arguments.
6210 Convert those to a 0 expressions. */
6211 el->expr = gfc_get_constant_expr (BT_INTEGER,
6212 gfc_default_integer_kind,
6213 &code->loc);
6214 mpz_set_si (el->expr->value.integer, 0);
6215 }
6216 else
6217 {
6218 resolve_positive_int_expr (el->expr, "TILE");
6219 if (el->expr->expr_type != EXPR_CONSTANT)
6220 gfc_error ("TILE requires constant expression at %L",
6221 &code->loc);
6222 }
6223 }
6224 }
6225 }
6226
6227
6228 void
gfc_resolve_oacc_blocks(gfc_code * code,gfc_namespace * ns)6229 gfc_resolve_oacc_blocks (gfc_code *code, gfc_namespace *ns)
6230 {
6231 fortran_omp_context ctx;
6232 gfc_omp_clauses *omp_clauses = code->ext.omp_clauses;
6233 gfc_omp_namelist *n;
6234 int list;
6235
6236 resolve_oacc_loop_blocks (code);
6237
6238 ctx.code = code;
6239 ctx.sharing_clauses = new hash_set<gfc_symbol *>;
6240 ctx.private_iterators = new hash_set<gfc_symbol *>;
6241 ctx.previous = omp_current_ctx;
6242 ctx.is_openmp = false;
6243 omp_current_ctx = &ctx;
6244
6245 for (list = 0; list < OMP_LIST_NUM; list++)
6246 switch (list)
6247 {
6248 case OMP_LIST_PRIVATE:
6249 for (n = omp_clauses->lists[list]; n; n = n->next)
6250 ctx.sharing_clauses->add (n->sym);
6251 break;
6252 default:
6253 break;
6254 }
6255
6256 gfc_resolve_blocks (code->block, ns);
6257
6258 omp_current_ctx = ctx.previous;
6259 delete ctx.sharing_clauses;
6260 delete ctx.private_iterators;
6261 }
6262
6263
6264 static void
resolve_oacc_loop(gfc_code * code)6265 resolve_oacc_loop (gfc_code *code)
6266 {
6267 gfc_code *do_code;
6268 int collapse;
6269
6270 if (code->ext.omp_clauses)
6271 resolve_omp_clauses (code, code->ext.omp_clauses, NULL, true);
6272
6273 do_code = code->block->next;
6274 collapse = code->ext.omp_clauses->collapse;
6275
6276 /* Both collapsed and tiled loops are lowered the same way, but are not
6277 compatible. In gfc_trans_omp_do, the tile is prioritized. */
6278 if (code->ext.omp_clauses->tile_list)
6279 {
6280 int num = 0;
6281 gfc_expr_list *el;
6282 for (el = code->ext.omp_clauses->tile_list; el; el = el->next)
6283 ++num;
6284 resolve_oacc_nested_loops (code, code->block->next, num, "tiled");
6285 return;
6286 }
6287
6288 if (collapse <= 0)
6289 collapse = 1;
6290 resolve_oacc_nested_loops (code, do_code, collapse, "collapsed");
6291 }
6292
6293 void
gfc_resolve_oacc_declare(gfc_namespace * ns)6294 gfc_resolve_oacc_declare (gfc_namespace *ns)
6295 {
6296 int list;
6297 gfc_omp_namelist *n;
6298 gfc_oacc_declare *oc;
6299
6300 if (ns->oacc_declare == NULL)
6301 return;
6302
6303 for (oc = ns->oacc_declare; oc; oc = oc->next)
6304 {
6305 for (list = 0; list < OMP_LIST_NUM; list++)
6306 for (n = oc->clauses->lists[list]; n; n = n->next)
6307 {
6308 n->sym->mark = 0;
6309 if (n->sym->attr.flavor != FL_VARIABLE
6310 && (n->sym->attr.flavor != FL_PROCEDURE
6311 || n->sym->result != n->sym))
6312 {
6313 gfc_error ("Object %qs is not a variable at %L",
6314 n->sym->name, &oc->loc);
6315 continue;
6316 }
6317
6318 if (n->expr && n->expr->ref->type == REF_ARRAY)
6319 {
6320 gfc_error ("Array sections: %qs not allowed in"
6321 " !$ACC DECLARE at %L", n->sym->name, &oc->loc);
6322 continue;
6323 }
6324 }
6325
6326 for (n = oc->clauses->lists[OMP_LIST_DEVICE_RESIDENT]; n; n = n->next)
6327 check_array_not_assumed (n->sym, oc->loc, "DEVICE_RESIDENT");
6328 }
6329
6330 for (oc = ns->oacc_declare; oc; oc = oc->next)
6331 {
6332 for (list = 0; list < OMP_LIST_NUM; list++)
6333 for (n = oc->clauses->lists[list]; n; n = n->next)
6334 {
6335 if (n->sym->mark)
6336 {
6337 gfc_error ("Symbol %qs present on multiple clauses at %L",
6338 n->sym->name, &oc->loc);
6339 continue;
6340 }
6341 else
6342 n->sym->mark = 1;
6343 }
6344 }
6345
6346 for (oc = ns->oacc_declare; oc; oc = oc->next)
6347 {
6348 for (list = 0; list < OMP_LIST_NUM; list++)
6349 for (n = oc->clauses->lists[list]; n; n = n->next)
6350 n->sym->mark = 0;
6351 }
6352 }
6353
6354
6355 void
gfc_resolve_oacc_routines(gfc_namespace * ns)6356 gfc_resolve_oacc_routines (gfc_namespace *ns)
6357 {
6358 for (gfc_oacc_routine_name *orn = ns->oacc_routine_names;
6359 orn;
6360 orn = orn->next)
6361 {
6362 gfc_symbol *sym = orn->sym;
6363 if (!sym->attr.external
6364 && !sym->attr.function
6365 && !sym->attr.subroutine)
6366 {
6367 gfc_error ("NAME %qs does not refer to a subroutine or function"
6368 " in !$ACC ROUTINE ( NAME ) at %L", sym->name, &orn->loc);
6369 continue;
6370 }
6371 if (!gfc_add_omp_declare_target (&sym->attr, sym->name, &orn->loc))
6372 {
6373 gfc_error ("NAME %qs invalid"
6374 " in !$ACC ROUTINE ( NAME ) at %L", sym->name, &orn->loc);
6375 continue;
6376 }
6377 }
6378 }
6379
6380
6381 void
gfc_resolve_oacc_directive(gfc_code * code,gfc_namespace * ns ATTRIBUTE_UNUSED)6382 gfc_resolve_oacc_directive (gfc_code *code, gfc_namespace *ns ATTRIBUTE_UNUSED)
6383 {
6384 resolve_oacc_directive_inside_omp_region (code);
6385
6386 switch (code->op)
6387 {
6388 case EXEC_OACC_PARALLEL:
6389 case EXEC_OACC_KERNELS:
6390 case EXEC_OACC_SERIAL:
6391 case EXEC_OACC_DATA:
6392 case EXEC_OACC_HOST_DATA:
6393 case EXEC_OACC_UPDATE:
6394 case EXEC_OACC_ENTER_DATA:
6395 case EXEC_OACC_EXIT_DATA:
6396 case EXEC_OACC_WAIT:
6397 case EXEC_OACC_CACHE:
6398 resolve_omp_clauses (code, code->ext.omp_clauses, NULL, true);
6399 break;
6400 case EXEC_OACC_PARALLEL_LOOP:
6401 case EXEC_OACC_KERNELS_LOOP:
6402 case EXEC_OACC_SERIAL_LOOP:
6403 case EXEC_OACC_LOOP:
6404 resolve_oacc_loop (code);
6405 break;
6406 case EXEC_OACC_ATOMIC:
6407 resolve_omp_atomic (code);
6408 break;
6409 default:
6410 break;
6411 }
6412 }
6413
6414
6415 /* Resolve OpenMP directive clauses and check various requirements
6416 of each directive. */
6417
6418 void
gfc_resolve_omp_directive(gfc_code * code,gfc_namespace * ns ATTRIBUTE_UNUSED)6419 gfc_resolve_omp_directive (gfc_code *code, gfc_namespace *ns ATTRIBUTE_UNUSED)
6420 {
6421 resolve_omp_directive_inside_oacc_region (code);
6422
6423 if (code->op != EXEC_OMP_ATOMIC)
6424 gfc_maybe_initialize_eh ();
6425
6426 switch (code->op)
6427 {
6428 case EXEC_OMP_DISTRIBUTE:
6429 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
6430 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
6431 case EXEC_OMP_DISTRIBUTE_SIMD:
6432 case EXEC_OMP_DO:
6433 case EXEC_OMP_DO_SIMD:
6434 case EXEC_OMP_PARALLEL_DO:
6435 case EXEC_OMP_PARALLEL_DO_SIMD:
6436 case EXEC_OMP_SIMD:
6437 case EXEC_OMP_TARGET_PARALLEL_DO:
6438 case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
6439 case EXEC_OMP_TARGET_SIMD:
6440 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
6441 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
6442 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
6443 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
6444 case EXEC_OMP_TASKLOOP:
6445 case EXEC_OMP_TASKLOOP_SIMD:
6446 case EXEC_OMP_TEAMS_DISTRIBUTE:
6447 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
6448 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
6449 case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
6450 resolve_omp_do (code);
6451 break;
6452 case EXEC_OMP_CANCEL:
6453 case EXEC_OMP_PARALLEL_WORKSHARE:
6454 case EXEC_OMP_PARALLEL:
6455 case EXEC_OMP_PARALLEL_SECTIONS:
6456 case EXEC_OMP_SECTIONS:
6457 case EXEC_OMP_SINGLE:
6458 case EXEC_OMP_TARGET:
6459 case EXEC_OMP_TARGET_DATA:
6460 case EXEC_OMP_TARGET_ENTER_DATA:
6461 case EXEC_OMP_TARGET_EXIT_DATA:
6462 case EXEC_OMP_TARGET_PARALLEL:
6463 case EXEC_OMP_TARGET_TEAMS:
6464 case EXEC_OMP_TASK:
6465 case EXEC_OMP_TEAMS:
6466 case EXEC_OMP_WORKSHARE:
6467 if (code->ext.omp_clauses)
6468 resolve_omp_clauses (code, code->ext.omp_clauses, NULL);
6469 break;
6470 case EXEC_OMP_TARGET_UPDATE:
6471 if (code->ext.omp_clauses)
6472 resolve_omp_clauses (code, code->ext.omp_clauses, NULL);
6473 if (code->ext.omp_clauses == NULL
6474 || (code->ext.omp_clauses->lists[OMP_LIST_TO] == NULL
6475 && code->ext.omp_clauses->lists[OMP_LIST_FROM] == NULL))
6476 gfc_error ("OMP TARGET UPDATE at %L requires at least one TO or "
6477 "FROM clause", &code->loc);
6478 break;
6479 case EXEC_OMP_ATOMIC:
6480 resolve_omp_atomic (code);
6481 break;
6482 default:
6483 break;
6484 }
6485 }
6486
6487 /* Resolve !$omp declare simd constructs in NS. */
6488
6489 void
gfc_resolve_omp_declare_simd(gfc_namespace * ns)6490 gfc_resolve_omp_declare_simd (gfc_namespace *ns)
6491 {
6492 gfc_omp_declare_simd *ods;
6493
6494 for (ods = ns->omp_declare_simd; ods; ods = ods->next)
6495 {
6496 if (ods->proc_name != NULL
6497 && ods->proc_name != ns->proc_name)
6498 gfc_error ("!$OMP DECLARE SIMD should refer to containing procedure "
6499 "%qs at %L", ns->proc_name->name, &ods->where);
6500 if (ods->clauses)
6501 resolve_omp_clauses (NULL, ods->clauses, ns);
6502 }
6503 }
6504
6505 struct omp_udr_callback_data
6506 {
6507 gfc_omp_udr *omp_udr;
6508 bool is_initializer;
6509 };
6510
6511 static int
omp_udr_callback(gfc_expr ** e,int * walk_subtrees ATTRIBUTE_UNUSED,void * data)6512 omp_udr_callback (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
6513 void *data)
6514 {
6515 struct omp_udr_callback_data *cd = (struct omp_udr_callback_data *) data;
6516 if ((*e)->expr_type == EXPR_VARIABLE)
6517 {
6518 if (cd->is_initializer)
6519 {
6520 if ((*e)->symtree->n.sym != cd->omp_udr->omp_priv
6521 && (*e)->symtree->n.sym != cd->omp_udr->omp_orig)
6522 gfc_error ("Variable other than OMP_PRIV or OMP_ORIG used in "
6523 "INITIALIZER clause of !$OMP DECLARE REDUCTION at %L",
6524 &(*e)->where);
6525 }
6526 else
6527 {
6528 if ((*e)->symtree->n.sym != cd->omp_udr->omp_out
6529 && (*e)->symtree->n.sym != cd->omp_udr->omp_in)
6530 gfc_error ("Variable other than OMP_OUT or OMP_IN used in "
6531 "combiner of !$OMP DECLARE REDUCTION at %L",
6532 &(*e)->where);
6533 }
6534 }
6535 return 0;
6536 }
6537
6538 /* Resolve !$omp declare reduction constructs. */
6539
6540 static void
gfc_resolve_omp_udr(gfc_omp_udr * omp_udr)6541 gfc_resolve_omp_udr (gfc_omp_udr *omp_udr)
6542 {
6543 gfc_actual_arglist *a;
6544 const char *predef_name = NULL;
6545
6546 switch (omp_udr->rop)
6547 {
6548 case OMP_REDUCTION_PLUS:
6549 case OMP_REDUCTION_TIMES:
6550 case OMP_REDUCTION_MINUS:
6551 case OMP_REDUCTION_AND:
6552 case OMP_REDUCTION_OR:
6553 case OMP_REDUCTION_EQV:
6554 case OMP_REDUCTION_NEQV:
6555 case OMP_REDUCTION_MAX:
6556 case OMP_REDUCTION_USER:
6557 break;
6558 default:
6559 gfc_error ("Invalid operator for !$OMP DECLARE REDUCTION %s at %L",
6560 omp_udr->name, &omp_udr->where);
6561 return;
6562 }
6563
6564 if (gfc_omp_udr_predef (omp_udr->rop, omp_udr->name,
6565 &omp_udr->ts, &predef_name))
6566 {
6567 if (predef_name)
6568 gfc_error_now ("Redefinition of predefined %s "
6569 "!$OMP DECLARE REDUCTION at %L",
6570 predef_name, &omp_udr->where);
6571 else
6572 gfc_error_now ("Redefinition of predefined "
6573 "!$OMP DECLARE REDUCTION at %L", &omp_udr->where);
6574 return;
6575 }
6576
6577 if (omp_udr->ts.type == BT_CHARACTER
6578 && omp_udr->ts.u.cl->length
6579 && omp_udr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
6580 {
6581 gfc_error ("CHARACTER length in !$OMP DECLARE REDUCTION %s not "
6582 "constant at %L", omp_udr->name, &omp_udr->where);
6583 return;
6584 }
6585
6586 struct omp_udr_callback_data cd;
6587 cd.omp_udr = omp_udr;
6588 cd.is_initializer = false;
6589 gfc_code_walker (&omp_udr->combiner_ns->code, gfc_dummy_code_callback,
6590 omp_udr_callback, &cd);
6591 if (omp_udr->combiner_ns->code->op == EXEC_CALL)
6592 {
6593 for (a = omp_udr->combiner_ns->code->ext.actual; a; a = a->next)
6594 if (a->expr == NULL)
6595 break;
6596 if (a)
6597 gfc_error ("Subroutine call with alternate returns in combiner "
6598 "of !$OMP DECLARE REDUCTION at %L",
6599 &omp_udr->combiner_ns->code->loc);
6600 }
6601 if (omp_udr->initializer_ns)
6602 {
6603 cd.is_initializer = true;
6604 gfc_code_walker (&omp_udr->initializer_ns->code, gfc_dummy_code_callback,
6605 omp_udr_callback, &cd);
6606 if (omp_udr->initializer_ns->code->op == EXEC_CALL)
6607 {
6608 for (a = omp_udr->initializer_ns->code->ext.actual; a; a = a->next)
6609 if (a->expr == NULL)
6610 break;
6611 if (a)
6612 gfc_error ("Subroutine call with alternate returns in "
6613 "INITIALIZER clause of !$OMP DECLARE REDUCTION "
6614 "at %L", &omp_udr->initializer_ns->code->loc);
6615 for (a = omp_udr->initializer_ns->code->ext.actual; a; a = a->next)
6616 if (a->expr
6617 && a->expr->expr_type == EXPR_VARIABLE
6618 && a->expr->symtree->n.sym == omp_udr->omp_priv
6619 && a->expr->ref == NULL)
6620 break;
6621 if (a == NULL)
6622 gfc_error ("One of actual subroutine arguments in INITIALIZER "
6623 "clause of !$OMP DECLARE REDUCTION must be OMP_PRIV "
6624 "at %L", &omp_udr->initializer_ns->code->loc);
6625 }
6626 }
6627 else if (omp_udr->ts.type == BT_DERIVED
6628 && !gfc_has_default_initializer (omp_udr->ts.u.derived))
6629 {
6630 gfc_error ("Missing INITIALIZER clause for !$OMP DECLARE REDUCTION "
6631 "of derived type without default initializer at %L",
6632 &omp_udr->where);
6633 return;
6634 }
6635 }
6636
6637 void
gfc_resolve_omp_udrs(gfc_symtree * st)6638 gfc_resolve_omp_udrs (gfc_symtree *st)
6639 {
6640 gfc_omp_udr *omp_udr;
6641
6642 if (st == NULL)
6643 return;
6644 gfc_resolve_omp_udrs (st->left);
6645 gfc_resolve_omp_udrs (st->right);
6646 for (omp_udr = st->n.omp_udr; omp_udr; omp_udr = omp_udr->next)
6647 gfc_resolve_omp_udr (omp_udr);
6648 }
6649