xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/fortran/openmp.c (revision 4c3eb207d36f67d31994830c0a694161fc1ca39b)
1627f7eb2Smrg /* OpenMP directive matching and resolving.
2*4c3eb207Smrg    Copyright (C) 2005-2020 Free Software Foundation, Inc.
3627f7eb2Smrg    Contributed by Jakub Jelinek
4627f7eb2Smrg 
5627f7eb2Smrg This file is part of GCC.
6627f7eb2Smrg 
7627f7eb2Smrg GCC is free software; you can redistribute it and/or modify it under
8627f7eb2Smrg the terms of the GNU General Public License as published by the Free
9627f7eb2Smrg Software Foundation; either version 3, or (at your option) any later
10627f7eb2Smrg version.
11627f7eb2Smrg 
12627f7eb2Smrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13627f7eb2Smrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
14627f7eb2Smrg FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15627f7eb2Smrg for more details.
16627f7eb2Smrg 
17627f7eb2Smrg You should have received a copy of the GNU General Public License
18627f7eb2Smrg along with GCC; see the file COPYING3.  If not see
19627f7eb2Smrg <http://www.gnu.org/licenses/>.  */
20627f7eb2Smrg 
21627f7eb2Smrg #include "config.h"
22627f7eb2Smrg #include "system.h"
23627f7eb2Smrg #include "coretypes.h"
24627f7eb2Smrg #include "gfortran.h"
25627f7eb2Smrg #include "arith.h"
26627f7eb2Smrg #include "match.h"
27627f7eb2Smrg #include "parse.h"
28627f7eb2Smrg #include "diagnostic.h"
29627f7eb2Smrg #include "gomp-constants.h"
30627f7eb2Smrg 
31627f7eb2Smrg /* Match an end of OpenMP directive.  End of OpenMP directive is optional
32627f7eb2Smrg    whitespace, followed by '\n' or comment '!'.  */
33627f7eb2Smrg 
34*4c3eb207Smrg static match
gfc_match_omp_eos(void)35627f7eb2Smrg gfc_match_omp_eos (void)
36627f7eb2Smrg {
37627f7eb2Smrg   locus old_loc;
38627f7eb2Smrg   char c;
39627f7eb2Smrg 
40627f7eb2Smrg   old_loc = gfc_current_locus;
41627f7eb2Smrg   gfc_gobble_whitespace ();
42627f7eb2Smrg 
43627f7eb2Smrg   c = gfc_next_ascii_char ();
44627f7eb2Smrg   switch (c)
45627f7eb2Smrg     {
46627f7eb2Smrg     case '!':
47627f7eb2Smrg       do
48627f7eb2Smrg 	c = gfc_next_ascii_char ();
49627f7eb2Smrg       while (c != '\n');
50627f7eb2Smrg       /* Fall through */
51627f7eb2Smrg 
52627f7eb2Smrg     case '\n':
53627f7eb2Smrg       return MATCH_YES;
54627f7eb2Smrg     }
55627f7eb2Smrg 
56627f7eb2Smrg   gfc_current_locus = old_loc;
57627f7eb2Smrg   return MATCH_NO;
58627f7eb2Smrg }
59627f7eb2Smrg 
60*4c3eb207Smrg match
gfc_match_omp_eos_error(void)61*4c3eb207Smrg gfc_match_omp_eos_error (void)
62*4c3eb207Smrg {
63*4c3eb207Smrg   if (gfc_match_omp_eos() == MATCH_YES)
64*4c3eb207Smrg     return MATCH_YES;
65*4c3eb207Smrg 
66*4c3eb207Smrg   gfc_error ("Unexpected junk at %C");
67*4c3eb207Smrg   return MATCH_ERROR;
68*4c3eb207Smrg }
69*4c3eb207Smrg 
70*4c3eb207Smrg 
71627f7eb2Smrg /* Free an omp_clauses structure.  */
72627f7eb2Smrg 
73627f7eb2Smrg void
gfc_free_omp_clauses(gfc_omp_clauses * c)74627f7eb2Smrg gfc_free_omp_clauses (gfc_omp_clauses *c)
75627f7eb2Smrg {
76627f7eb2Smrg   int i;
77627f7eb2Smrg   if (c == NULL)
78627f7eb2Smrg     return;
79627f7eb2Smrg 
80627f7eb2Smrg   gfc_free_expr (c->if_expr);
81627f7eb2Smrg   gfc_free_expr (c->final_expr);
82627f7eb2Smrg   gfc_free_expr (c->num_threads);
83627f7eb2Smrg   gfc_free_expr (c->chunk_size);
84627f7eb2Smrg   gfc_free_expr (c->safelen_expr);
85627f7eb2Smrg   gfc_free_expr (c->simdlen_expr);
86627f7eb2Smrg   gfc_free_expr (c->num_teams);
87627f7eb2Smrg   gfc_free_expr (c->device);
88627f7eb2Smrg   gfc_free_expr (c->thread_limit);
89627f7eb2Smrg   gfc_free_expr (c->dist_chunk_size);
90627f7eb2Smrg   gfc_free_expr (c->grainsize);
91627f7eb2Smrg   gfc_free_expr (c->hint);
92627f7eb2Smrg   gfc_free_expr (c->num_tasks);
93627f7eb2Smrg   gfc_free_expr (c->priority);
94627f7eb2Smrg   for (i = 0; i < OMP_IF_LAST; i++)
95627f7eb2Smrg     gfc_free_expr (c->if_exprs[i]);
96627f7eb2Smrg   gfc_free_expr (c->async_expr);
97627f7eb2Smrg   gfc_free_expr (c->gang_num_expr);
98627f7eb2Smrg   gfc_free_expr (c->gang_static_expr);
99627f7eb2Smrg   gfc_free_expr (c->worker_expr);
100627f7eb2Smrg   gfc_free_expr (c->vector_expr);
101627f7eb2Smrg   gfc_free_expr (c->num_gangs_expr);
102627f7eb2Smrg   gfc_free_expr (c->num_workers_expr);
103627f7eb2Smrg   gfc_free_expr (c->vector_length_expr);
104627f7eb2Smrg   for (i = 0; i < OMP_LIST_NUM; i++)
105627f7eb2Smrg     gfc_free_omp_namelist (c->lists[i]);
106627f7eb2Smrg   gfc_free_expr_list (c->wait_list);
107627f7eb2Smrg   gfc_free_expr_list (c->tile_list);
108627f7eb2Smrg   free (CONST_CAST (char *, c->critical_name));
109627f7eb2Smrg   free (c);
110627f7eb2Smrg }
111627f7eb2Smrg 
112627f7eb2Smrg /* Free oacc_declare structures.  */
113627f7eb2Smrg 
114627f7eb2Smrg void
gfc_free_oacc_declare_clauses(struct gfc_oacc_declare * oc)115627f7eb2Smrg gfc_free_oacc_declare_clauses (struct gfc_oacc_declare *oc)
116627f7eb2Smrg {
117627f7eb2Smrg   struct gfc_oacc_declare *decl = oc;
118627f7eb2Smrg 
119627f7eb2Smrg   do
120627f7eb2Smrg     {
121627f7eb2Smrg       struct gfc_oacc_declare *next;
122627f7eb2Smrg 
123627f7eb2Smrg       next = decl->next;
124627f7eb2Smrg       gfc_free_omp_clauses (decl->clauses);
125627f7eb2Smrg       free (decl);
126627f7eb2Smrg       decl = next;
127627f7eb2Smrg     }
128627f7eb2Smrg   while (decl);
129627f7eb2Smrg }
130627f7eb2Smrg 
131627f7eb2Smrg /* Free expression list. */
132627f7eb2Smrg void
gfc_free_expr_list(gfc_expr_list * list)133627f7eb2Smrg gfc_free_expr_list (gfc_expr_list *list)
134627f7eb2Smrg {
135627f7eb2Smrg   gfc_expr_list *n;
136627f7eb2Smrg 
137627f7eb2Smrg   for (; list; list = n)
138627f7eb2Smrg     {
139627f7eb2Smrg       n = list->next;
140627f7eb2Smrg       free (list);
141627f7eb2Smrg     }
142627f7eb2Smrg }
143627f7eb2Smrg 
144627f7eb2Smrg /* Free an !$omp declare simd construct list.  */
145627f7eb2Smrg 
146627f7eb2Smrg void
gfc_free_omp_declare_simd(gfc_omp_declare_simd * ods)147627f7eb2Smrg gfc_free_omp_declare_simd (gfc_omp_declare_simd *ods)
148627f7eb2Smrg {
149627f7eb2Smrg   if (ods)
150627f7eb2Smrg     {
151627f7eb2Smrg       gfc_free_omp_clauses (ods->clauses);
152627f7eb2Smrg       free (ods);
153627f7eb2Smrg     }
154627f7eb2Smrg }
155627f7eb2Smrg 
156627f7eb2Smrg void
gfc_free_omp_declare_simd_list(gfc_omp_declare_simd * list)157627f7eb2Smrg gfc_free_omp_declare_simd_list (gfc_omp_declare_simd *list)
158627f7eb2Smrg {
159627f7eb2Smrg   while (list)
160627f7eb2Smrg     {
161627f7eb2Smrg       gfc_omp_declare_simd *current = list;
162627f7eb2Smrg       list = list->next;
163627f7eb2Smrg       gfc_free_omp_declare_simd (current);
164627f7eb2Smrg     }
165627f7eb2Smrg }
166627f7eb2Smrg 
167627f7eb2Smrg /* Free an !$omp declare reduction.  */
168627f7eb2Smrg 
169627f7eb2Smrg void
gfc_free_omp_udr(gfc_omp_udr * omp_udr)170627f7eb2Smrg gfc_free_omp_udr (gfc_omp_udr *omp_udr)
171627f7eb2Smrg {
172627f7eb2Smrg   if (omp_udr)
173627f7eb2Smrg     {
174627f7eb2Smrg       gfc_free_omp_udr (omp_udr->next);
175627f7eb2Smrg       gfc_free_namespace (omp_udr->combiner_ns);
176627f7eb2Smrg       if (omp_udr->initializer_ns)
177627f7eb2Smrg 	gfc_free_namespace (omp_udr->initializer_ns);
178627f7eb2Smrg       free (omp_udr);
179627f7eb2Smrg     }
180627f7eb2Smrg }
181627f7eb2Smrg 
182627f7eb2Smrg 
183627f7eb2Smrg static gfc_omp_udr *
gfc_find_omp_udr(gfc_namespace * ns,const char * name,gfc_typespec * ts)184627f7eb2Smrg gfc_find_omp_udr (gfc_namespace *ns, const char *name, gfc_typespec *ts)
185627f7eb2Smrg {
186627f7eb2Smrg   gfc_symtree *st;
187627f7eb2Smrg 
188627f7eb2Smrg   if (ns == NULL)
189627f7eb2Smrg     ns = gfc_current_ns;
190627f7eb2Smrg   do
191627f7eb2Smrg     {
192627f7eb2Smrg       gfc_omp_udr *omp_udr;
193627f7eb2Smrg 
194627f7eb2Smrg       st = gfc_find_symtree (ns->omp_udr_root, name);
195627f7eb2Smrg       if (st != NULL)
196627f7eb2Smrg 	{
197627f7eb2Smrg 	  for (omp_udr = st->n.omp_udr; omp_udr; omp_udr = omp_udr->next)
198627f7eb2Smrg 	    if (ts == NULL)
199627f7eb2Smrg 	      return omp_udr;
200627f7eb2Smrg 	    else if (gfc_compare_types (&omp_udr->ts, ts))
201627f7eb2Smrg 	      {
202627f7eb2Smrg 		if (ts->type == BT_CHARACTER)
203627f7eb2Smrg 		  {
204627f7eb2Smrg 		    if (omp_udr->ts.u.cl->length == NULL)
205627f7eb2Smrg 		      return omp_udr;
206627f7eb2Smrg 		    if (ts->u.cl->length == NULL)
207627f7eb2Smrg 		      continue;
208627f7eb2Smrg 		    if (gfc_compare_expr (omp_udr->ts.u.cl->length,
209627f7eb2Smrg 					  ts->u.cl->length,
210627f7eb2Smrg 					  INTRINSIC_EQ) != 0)
211627f7eb2Smrg 		      continue;
212627f7eb2Smrg 		  }
213627f7eb2Smrg 		return omp_udr;
214627f7eb2Smrg 	      }
215627f7eb2Smrg 	}
216627f7eb2Smrg 
217627f7eb2Smrg       /* Don't escape an interface block.  */
218627f7eb2Smrg       if (ns && !ns->has_import_set
219627f7eb2Smrg 	  && ns->proc_name && ns->proc_name->attr.if_source == IFSRC_IFBODY)
220627f7eb2Smrg 	break;
221627f7eb2Smrg 
222627f7eb2Smrg       ns = ns->parent;
223627f7eb2Smrg     }
224627f7eb2Smrg   while (ns != NULL);
225627f7eb2Smrg 
226627f7eb2Smrg   return NULL;
227627f7eb2Smrg }
228627f7eb2Smrg 
229627f7eb2Smrg 
230627f7eb2Smrg /* Match a variable/common block list and construct a namelist from it.  */
231627f7eb2Smrg 
232627f7eb2Smrg static match
233627f7eb2Smrg gfc_match_omp_variable_list (const char *str, gfc_omp_namelist **list,
234627f7eb2Smrg 			     bool allow_common, bool *end_colon = NULL,
235627f7eb2Smrg 			     gfc_omp_namelist ***headp = NULL,
236*4c3eb207Smrg 			     bool allow_sections = false,
237*4c3eb207Smrg 			     bool allow_derived = false)
238627f7eb2Smrg {
239627f7eb2Smrg   gfc_omp_namelist *head, *tail, *p;
240627f7eb2Smrg   locus old_loc, cur_loc;
241627f7eb2Smrg   char n[GFC_MAX_SYMBOL_LEN+1];
242627f7eb2Smrg   gfc_symbol *sym;
243627f7eb2Smrg   match m;
244627f7eb2Smrg   gfc_symtree *st;
245627f7eb2Smrg 
246627f7eb2Smrg   head = tail = NULL;
247627f7eb2Smrg 
248627f7eb2Smrg   old_loc = gfc_current_locus;
249627f7eb2Smrg 
250627f7eb2Smrg   m = gfc_match (str);
251627f7eb2Smrg   if (m != MATCH_YES)
252627f7eb2Smrg     return m;
253627f7eb2Smrg 
254627f7eb2Smrg   for (;;)
255627f7eb2Smrg     {
256627f7eb2Smrg       cur_loc = gfc_current_locus;
257627f7eb2Smrg       m = gfc_match_symbol (&sym, 1);
258627f7eb2Smrg       switch (m)
259627f7eb2Smrg 	{
260627f7eb2Smrg 	case MATCH_YES:
261627f7eb2Smrg 	  gfc_expr *expr;
262627f7eb2Smrg 	  expr = NULL;
263*4c3eb207Smrg 	  gfc_gobble_whitespace ();
264*4c3eb207Smrg 	  if ((allow_sections && gfc_peek_ascii_char () == '(')
265*4c3eb207Smrg 	      || (allow_derived && gfc_peek_ascii_char () == '%'))
266627f7eb2Smrg 	    {
267627f7eb2Smrg 	      gfc_current_locus = cur_loc;
268627f7eb2Smrg 	      m = gfc_match_variable (&expr, 0);
269627f7eb2Smrg 	      switch (m)
270627f7eb2Smrg 		{
271627f7eb2Smrg 		case MATCH_ERROR:
272627f7eb2Smrg 		  goto cleanup;
273627f7eb2Smrg 		case MATCH_NO:
274627f7eb2Smrg 		  goto syntax;
275627f7eb2Smrg 		default:
276627f7eb2Smrg 		  break;
277627f7eb2Smrg 		}
278*4c3eb207Smrg 	      if (gfc_is_coindexed (expr))
279*4c3eb207Smrg 		{
280*4c3eb207Smrg 		  gfc_error ("List item shall not be coindexed at %C");
281*4c3eb207Smrg 		  goto cleanup;
282*4c3eb207Smrg 		}
283627f7eb2Smrg 	    }
284627f7eb2Smrg 	  gfc_set_sym_referenced (sym);
285627f7eb2Smrg 	  p = gfc_get_omp_namelist ();
286627f7eb2Smrg 	  if (head == NULL)
287627f7eb2Smrg 	    head = tail = p;
288627f7eb2Smrg 	  else
289627f7eb2Smrg 	    {
290627f7eb2Smrg 	      tail->next = p;
291627f7eb2Smrg 	      tail = tail->next;
292627f7eb2Smrg 	    }
293627f7eb2Smrg 	  tail->sym = sym;
294627f7eb2Smrg 	  tail->expr = expr;
295627f7eb2Smrg 	  tail->where = cur_loc;
296627f7eb2Smrg 	  goto next_item;
297627f7eb2Smrg 	case MATCH_NO:
298627f7eb2Smrg 	  break;
299627f7eb2Smrg 	case MATCH_ERROR:
300627f7eb2Smrg 	  goto cleanup;
301627f7eb2Smrg 	}
302627f7eb2Smrg 
303627f7eb2Smrg       if (!allow_common)
304627f7eb2Smrg 	goto syntax;
305627f7eb2Smrg 
306627f7eb2Smrg       m = gfc_match (" / %n /", n);
307627f7eb2Smrg       if (m == MATCH_ERROR)
308627f7eb2Smrg 	goto cleanup;
309627f7eb2Smrg       if (m == MATCH_NO)
310627f7eb2Smrg 	goto syntax;
311627f7eb2Smrg 
312627f7eb2Smrg       st = gfc_find_symtree (gfc_current_ns->common_root, n);
313627f7eb2Smrg       if (st == NULL)
314627f7eb2Smrg 	{
315627f7eb2Smrg 	  gfc_error ("COMMON block /%s/ not found at %C", n);
316627f7eb2Smrg 	  goto cleanup;
317627f7eb2Smrg 	}
318627f7eb2Smrg       for (sym = st->n.common->head; sym; sym = sym->common_next)
319627f7eb2Smrg 	{
320627f7eb2Smrg 	  gfc_set_sym_referenced (sym);
321627f7eb2Smrg 	  p = gfc_get_omp_namelist ();
322627f7eb2Smrg 	  if (head == NULL)
323627f7eb2Smrg 	    head = tail = p;
324627f7eb2Smrg 	  else
325627f7eb2Smrg 	    {
326627f7eb2Smrg 	      tail->next = p;
327627f7eb2Smrg 	      tail = tail->next;
328627f7eb2Smrg 	    }
329627f7eb2Smrg 	  tail->sym = sym;
330627f7eb2Smrg 	  tail->where = cur_loc;
331627f7eb2Smrg 	}
332627f7eb2Smrg 
333627f7eb2Smrg     next_item:
334627f7eb2Smrg       if (end_colon && gfc_match_char (':') == MATCH_YES)
335627f7eb2Smrg 	{
336627f7eb2Smrg 	  *end_colon = true;
337627f7eb2Smrg 	  break;
338627f7eb2Smrg 	}
339627f7eb2Smrg       if (gfc_match_char (')') == MATCH_YES)
340627f7eb2Smrg 	break;
341627f7eb2Smrg       if (gfc_match_char (',') != MATCH_YES)
342627f7eb2Smrg 	goto syntax;
343627f7eb2Smrg     }
344627f7eb2Smrg 
345627f7eb2Smrg   while (*list)
346627f7eb2Smrg     list = &(*list)->next;
347627f7eb2Smrg 
348627f7eb2Smrg   *list = head;
349627f7eb2Smrg   if (headp)
350627f7eb2Smrg     *headp = list;
351627f7eb2Smrg   return MATCH_YES;
352627f7eb2Smrg 
353627f7eb2Smrg syntax:
354627f7eb2Smrg   gfc_error ("Syntax error in OpenMP variable list at %C");
355627f7eb2Smrg 
356627f7eb2Smrg cleanup:
357627f7eb2Smrg   gfc_free_omp_namelist (head);
358627f7eb2Smrg   gfc_current_locus = old_loc;
359627f7eb2Smrg   return MATCH_ERROR;
360627f7eb2Smrg }
361627f7eb2Smrg 
362627f7eb2Smrg /* Match a variable/procedure/common block list and construct a namelist
363627f7eb2Smrg    from it.  */
364627f7eb2Smrg 
365627f7eb2Smrg static match
gfc_match_omp_to_link(const char * str,gfc_omp_namelist ** list)366627f7eb2Smrg gfc_match_omp_to_link (const char *str, gfc_omp_namelist **list)
367627f7eb2Smrg {
368627f7eb2Smrg   gfc_omp_namelist *head, *tail, *p;
369627f7eb2Smrg   locus old_loc, cur_loc;
370627f7eb2Smrg   char n[GFC_MAX_SYMBOL_LEN+1];
371627f7eb2Smrg   gfc_symbol *sym;
372627f7eb2Smrg   match m;
373627f7eb2Smrg   gfc_symtree *st;
374627f7eb2Smrg 
375627f7eb2Smrg   head = tail = NULL;
376627f7eb2Smrg 
377627f7eb2Smrg   old_loc = gfc_current_locus;
378627f7eb2Smrg 
379627f7eb2Smrg   m = gfc_match (str);
380627f7eb2Smrg   if (m != MATCH_YES)
381627f7eb2Smrg     return m;
382627f7eb2Smrg 
383627f7eb2Smrg   for (;;)
384627f7eb2Smrg     {
385627f7eb2Smrg       cur_loc = gfc_current_locus;
386627f7eb2Smrg       m = gfc_match_symbol (&sym, 1);
387627f7eb2Smrg       switch (m)
388627f7eb2Smrg 	{
389627f7eb2Smrg 	case MATCH_YES:
390627f7eb2Smrg 	  p = gfc_get_omp_namelist ();
391627f7eb2Smrg 	  if (head == NULL)
392627f7eb2Smrg 	    head = tail = p;
393627f7eb2Smrg 	  else
394627f7eb2Smrg 	    {
395627f7eb2Smrg 	      tail->next = p;
396627f7eb2Smrg 	      tail = tail->next;
397627f7eb2Smrg 	    }
398627f7eb2Smrg 	  tail->sym = sym;
399627f7eb2Smrg 	  tail->where = cur_loc;
400627f7eb2Smrg 	  goto next_item;
401627f7eb2Smrg 	case MATCH_NO:
402627f7eb2Smrg 	  break;
403627f7eb2Smrg 	case MATCH_ERROR:
404627f7eb2Smrg 	  goto cleanup;
405627f7eb2Smrg 	}
406627f7eb2Smrg 
407627f7eb2Smrg       m = gfc_match (" / %n /", n);
408627f7eb2Smrg       if (m == MATCH_ERROR)
409627f7eb2Smrg 	goto cleanup;
410627f7eb2Smrg       if (m == MATCH_NO)
411627f7eb2Smrg 	goto syntax;
412627f7eb2Smrg 
413627f7eb2Smrg       st = gfc_find_symtree (gfc_current_ns->common_root, n);
414627f7eb2Smrg       if (st == NULL)
415627f7eb2Smrg 	{
416627f7eb2Smrg 	  gfc_error ("COMMON block /%s/ not found at %C", n);
417627f7eb2Smrg 	  goto cleanup;
418627f7eb2Smrg 	}
419627f7eb2Smrg       p = gfc_get_omp_namelist ();
420627f7eb2Smrg       if (head == NULL)
421627f7eb2Smrg 	head = tail = p;
422627f7eb2Smrg       else
423627f7eb2Smrg 	{
424627f7eb2Smrg 	  tail->next = p;
425627f7eb2Smrg 	  tail = tail->next;
426627f7eb2Smrg 	}
427627f7eb2Smrg       tail->u.common = st->n.common;
428627f7eb2Smrg       tail->where = cur_loc;
429627f7eb2Smrg 
430627f7eb2Smrg     next_item:
431627f7eb2Smrg       if (gfc_match_char (')') == MATCH_YES)
432627f7eb2Smrg 	break;
433627f7eb2Smrg       if (gfc_match_char (',') != MATCH_YES)
434627f7eb2Smrg 	goto syntax;
435627f7eb2Smrg     }
436627f7eb2Smrg 
437627f7eb2Smrg   while (*list)
438627f7eb2Smrg     list = &(*list)->next;
439627f7eb2Smrg 
440627f7eb2Smrg   *list = head;
441627f7eb2Smrg   return MATCH_YES;
442627f7eb2Smrg 
443627f7eb2Smrg syntax:
444627f7eb2Smrg   gfc_error ("Syntax error in OpenMP variable list at %C");
445627f7eb2Smrg 
446627f7eb2Smrg cleanup:
447627f7eb2Smrg   gfc_free_omp_namelist (head);
448627f7eb2Smrg   gfc_current_locus = old_loc;
449627f7eb2Smrg   return MATCH_ERROR;
450627f7eb2Smrg }
451627f7eb2Smrg 
452627f7eb2Smrg /* Match depend(sink : ...) construct a namelist from it.  */
453627f7eb2Smrg 
454627f7eb2Smrg static match
gfc_match_omp_depend_sink(gfc_omp_namelist ** list)455627f7eb2Smrg gfc_match_omp_depend_sink (gfc_omp_namelist **list)
456627f7eb2Smrg {
457627f7eb2Smrg   gfc_omp_namelist *head, *tail, *p;
458627f7eb2Smrg   locus old_loc, cur_loc;
459627f7eb2Smrg   gfc_symbol *sym;
460627f7eb2Smrg 
461627f7eb2Smrg   head = tail = NULL;
462627f7eb2Smrg 
463627f7eb2Smrg   old_loc = gfc_current_locus;
464627f7eb2Smrg 
465627f7eb2Smrg   for (;;)
466627f7eb2Smrg     {
467627f7eb2Smrg       cur_loc = gfc_current_locus;
468627f7eb2Smrg       switch (gfc_match_symbol (&sym, 1))
469627f7eb2Smrg 	{
470627f7eb2Smrg 	case MATCH_YES:
471627f7eb2Smrg 	  gfc_set_sym_referenced (sym);
472627f7eb2Smrg 	  p = gfc_get_omp_namelist ();
473627f7eb2Smrg 	  if (head == NULL)
474627f7eb2Smrg 	    {
475627f7eb2Smrg 	      head = tail = p;
476627f7eb2Smrg 	      head->u.depend_op = OMP_DEPEND_SINK_FIRST;
477627f7eb2Smrg 	    }
478627f7eb2Smrg 	  else
479627f7eb2Smrg 	    {
480627f7eb2Smrg 	      tail->next = p;
481627f7eb2Smrg 	      tail = tail->next;
482627f7eb2Smrg 	      tail->u.depend_op = OMP_DEPEND_SINK;
483627f7eb2Smrg 	    }
484627f7eb2Smrg 	  tail->sym = sym;
485627f7eb2Smrg 	  tail->expr = NULL;
486627f7eb2Smrg 	  tail->where = cur_loc;
487627f7eb2Smrg 	  if (gfc_match_char ('+') == MATCH_YES)
488627f7eb2Smrg 	    {
489627f7eb2Smrg 	      if (gfc_match_literal_constant (&tail->expr, 0) != MATCH_YES)
490627f7eb2Smrg 		goto syntax;
491627f7eb2Smrg 	    }
492627f7eb2Smrg 	  else if (gfc_match_char ('-') == MATCH_YES)
493627f7eb2Smrg 	    {
494627f7eb2Smrg 	      if (gfc_match_literal_constant (&tail->expr, 0) != MATCH_YES)
495627f7eb2Smrg 		goto syntax;
496627f7eb2Smrg 	      tail->expr = gfc_uminus (tail->expr);
497627f7eb2Smrg 	    }
498627f7eb2Smrg 	  break;
499627f7eb2Smrg 	case MATCH_NO:
500627f7eb2Smrg 	  goto syntax;
501627f7eb2Smrg 	case MATCH_ERROR:
502627f7eb2Smrg 	  goto cleanup;
503627f7eb2Smrg 	}
504627f7eb2Smrg 
505627f7eb2Smrg       if (gfc_match_char (')') == MATCH_YES)
506627f7eb2Smrg 	break;
507627f7eb2Smrg       if (gfc_match_char (',') != MATCH_YES)
508627f7eb2Smrg 	goto syntax;
509627f7eb2Smrg     }
510627f7eb2Smrg 
511627f7eb2Smrg   while (*list)
512627f7eb2Smrg     list = &(*list)->next;
513627f7eb2Smrg 
514627f7eb2Smrg   *list = head;
515627f7eb2Smrg   return MATCH_YES;
516627f7eb2Smrg 
517627f7eb2Smrg syntax:
518627f7eb2Smrg   gfc_error ("Syntax error in OpenMP DEPEND SINK list at %C");
519627f7eb2Smrg 
520627f7eb2Smrg cleanup:
521627f7eb2Smrg   gfc_free_omp_namelist (head);
522627f7eb2Smrg   gfc_current_locus = old_loc;
523627f7eb2Smrg   return MATCH_ERROR;
524627f7eb2Smrg }
525627f7eb2Smrg 
526627f7eb2Smrg static match
match_oacc_expr_list(const char * str,gfc_expr_list ** list,bool allow_asterisk)527627f7eb2Smrg match_oacc_expr_list (const char *str, gfc_expr_list **list,
528627f7eb2Smrg 		      bool allow_asterisk)
529627f7eb2Smrg {
530627f7eb2Smrg   gfc_expr_list *head, *tail, *p;
531627f7eb2Smrg   locus old_loc;
532627f7eb2Smrg   gfc_expr *expr;
533627f7eb2Smrg   match m;
534627f7eb2Smrg 
535627f7eb2Smrg   head = tail = NULL;
536627f7eb2Smrg 
537627f7eb2Smrg   old_loc = gfc_current_locus;
538627f7eb2Smrg 
539627f7eb2Smrg   m = gfc_match (str);
540627f7eb2Smrg   if (m != MATCH_YES)
541627f7eb2Smrg     return m;
542627f7eb2Smrg 
543627f7eb2Smrg   for (;;)
544627f7eb2Smrg     {
545627f7eb2Smrg       m = gfc_match_expr (&expr);
546627f7eb2Smrg       if (m == MATCH_YES || allow_asterisk)
547627f7eb2Smrg 	{
548627f7eb2Smrg 	  p = gfc_get_expr_list ();
549627f7eb2Smrg 	  if (head == NULL)
550627f7eb2Smrg 	    head = tail = p;
551627f7eb2Smrg 	  else
552627f7eb2Smrg 	    {
553627f7eb2Smrg 	      tail->next = p;
554627f7eb2Smrg 	      tail = tail->next;
555627f7eb2Smrg 	    }
556627f7eb2Smrg 	  if (m == MATCH_YES)
557627f7eb2Smrg 	    tail->expr = expr;
558627f7eb2Smrg 	  else if (gfc_match (" *") != MATCH_YES)
559627f7eb2Smrg 	    goto syntax;
560627f7eb2Smrg 	  goto next_item;
561627f7eb2Smrg 	}
562627f7eb2Smrg       if (m == MATCH_ERROR)
563627f7eb2Smrg 	goto cleanup;
564627f7eb2Smrg       goto syntax;
565627f7eb2Smrg 
566627f7eb2Smrg     next_item:
567627f7eb2Smrg       if (gfc_match_char (')') == MATCH_YES)
568627f7eb2Smrg 	break;
569627f7eb2Smrg       if (gfc_match_char (',') != MATCH_YES)
570627f7eb2Smrg 	goto syntax;
571627f7eb2Smrg     }
572627f7eb2Smrg 
573627f7eb2Smrg   while (*list)
574627f7eb2Smrg     list = &(*list)->next;
575627f7eb2Smrg 
576627f7eb2Smrg   *list = head;
577627f7eb2Smrg   return MATCH_YES;
578627f7eb2Smrg 
579627f7eb2Smrg syntax:
580627f7eb2Smrg   gfc_error ("Syntax error in OpenACC expression list at %C");
581627f7eb2Smrg 
582627f7eb2Smrg cleanup:
583627f7eb2Smrg   gfc_free_expr_list (head);
584627f7eb2Smrg   gfc_current_locus = old_loc;
585627f7eb2Smrg   return MATCH_ERROR;
586627f7eb2Smrg }
587627f7eb2Smrg 
588627f7eb2Smrg static match
match_oacc_clause_gwv(gfc_omp_clauses * cp,unsigned gwv)589627f7eb2Smrg match_oacc_clause_gwv (gfc_omp_clauses *cp, unsigned gwv)
590627f7eb2Smrg {
591627f7eb2Smrg   match ret = MATCH_YES;
592627f7eb2Smrg 
593627f7eb2Smrg   if (gfc_match (" ( ") != MATCH_YES)
594627f7eb2Smrg     return MATCH_NO;
595627f7eb2Smrg 
596627f7eb2Smrg   if (gwv == GOMP_DIM_GANG)
597627f7eb2Smrg     {
598627f7eb2Smrg         /* The gang clause accepts two optional arguments, num and static.
599627f7eb2Smrg 	 The num argument may either be explicit (num: <val>) or
600627f7eb2Smrg 	 implicit without (<val> without num:).  */
601627f7eb2Smrg 
602627f7eb2Smrg       while (ret == MATCH_YES)
603627f7eb2Smrg 	{
604627f7eb2Smrg 	  if (gfc_match (" static :") == MATCH_YES)
605627f7eb2Smrg 	    {
606627f7eb2Smrg 	      if (cp->gang_static)
607627f7eb2Smrg 		return MATCH_ERROR;
608627f7eb2Smrg 	      else
609627f7eb2Smrg 		cp->gang_static = true;
610627f7eb2Smrg 	      if (gfc_match_char ('*') == MATCH_YES)
611627f7eb2Smrg 		cp->gang_static_expr = NULL;
612627f7eb2Smrg 	      else if (gfc_match (" %e ", &cp->gang_static_expr) != MATCH_YES)
613627f7eb2Smrg 		return MATCH_ERROR;
614627f7eb2Smrg 	    }
615627f7eb2Smrg 	  else
616627f7eb2Smrg 	    {
617627f7eb2Smrg 	      if (cp->gang_num_expr)
618627f7eb2Smrg 		return MATCH_ERROR;
619627f7eb2Smrg 
620627f7eb2Smrg 	      /* The 'num' argument is optional.  */
621627f7eb2Smrg 	      gfc_match (" num :");
622627f7eb2Smrg 
623627f7eb2Smrg 	      if (gfc_match (" %e ", &cp->gang_num_expr) != MATCH_YES)
624627f7eb2Smrg 		return MATCH_ERROR;
625627f7eb2Smrg 	    }
626627f7eb2Smrg 
627627f7eb2Smrg 	  ret = gfc_match (" , ");
628627f7eb2Smrg 	}
629627f7eb2Smrg     }
630627f7eb2Smrg   else if (gwv == GOMP_DIM_WORKER)
631627f7eb2Smrg     {
632627f7eb2Smrg       /* The 'num' argument is optional.  */
633627f7eb2Smrg       gfc_match (" num :");
634627f7eb2Smrg 
635627f7eb2Smrg       if (gfc_match (" %e ", &cp->worker_expr) != MATCH_YES)
636627f7eb2Smrg 	return MATCH_ERROR;
637627f7eb2Smrg     }
638627f7eb2Smrg   else if (gwv == GOMP_DIM_VECTOR)
639627f7eb2Smrg     {
640627f7eb2Smrg       /* The 'length' argument is optional.  */
641627f7eb2Smrg       gfc_match (" length :");
642627f7eb2Smrg 
643627f7eb2Smrg       if (gfc_match (" %e ", &cp->vector_expr) != MATCH_YES)
644627f7eb2Smrg 	return MATCH_ERROR;
645627f7eb2Smrg     }
646627f7eb2Smrg   else
647627f7eb2Smrg     gfc_fatal_error ("Unexpected OpenACC parallelism.");
648627f7eb2Smrg 
649627f7eb2Smrg   return gfc_match (" )");
650627f7eb2Smrg }
651627f7eb2Smrg 
652627f7eb2Smrg static match
gfc_match_oacc_clause_link(const char * str,gfc_omp_namelist ** list)653627f7eb2Smrg gfc_match_oacc_clause_link (const char *str, gfc_omp_namelist **list)
654627f7eb2Smrg {
655627f7eb2Smrg   gfc_omp_namelist *head = NULL;
656627f7eb2Smrg   gfc_omp_namelist *tail, *p;
657627f7eb2Smrg   locus old_loc;
658627f7eb2Smrg   char n[GFC_MAX_SYMBOL_LEN+1];
659627f7eb2Smrg   gfc_symbol *sym;
660627f7eb2Smrg   match m;
661627f7eb2Smrg   gfc_symtree *st;
662627f7eb2Smrg 
663627f7eb2Smrg   old_loc = gfc_current_locus;
664627f7eb2Smrg 
665627f7eb2Smrg   m = gfc_match (str);
666627f7eb2Smrg   if (m != MATCH_YES)
667627f7eb2Smrg     return m;
668627f7eb2Smrg 
669627f7eb2Smrg   m = gfc_match (" (");
670627f7eb2Smrg 
671627f7eb2Smrg   for (;;)
672627f7eb2Smrg     {
673627f7eb2Smrg       m = gfc_match_symbol (&sym, 0);
674627f7eb2Smrg       switch (m)
675627f7eb2Smrg 	{
676627f7eb2Smrg 	case MATCH_YES:
677627f7eb2Smrg 	  if (sym->attr.in_common)
678627f7eb2Smrg 	    {
679627f7eb2Smrg 	      gfc_error_now ("Variable at %C is an element of a COMMON block");
680627f7eb2Smrg 	      goto cleanup;
681627f7eb2Smrg 	    }
682627f7eb2Smrg 	  gfc_set_sym_referenced (sym);
683627f7eb2Smrg 	  p = gfc_get_omp_namelist ();
684627f7eb2Smrg 	  if (head == NULL)
685627f7eb2Smrg 	    head = tail = p;
686627f7eb2Smrg 	  else
687627f7eb2Smrg 	    {
688627f7eb2Smrg 	      tail->next = p;
689627f7eb2Smrg 	      tail = tail->next;
690627f7eb2Smrg 	    }
691627f7eb2Smrg 	  tail->sym = sym;
692627f7eb2Smrg 	  tail->expr = NULL;
693627f7eb2Smrg 	  tail->where = gfc_current_locus;
694627f7eb2Smrg 	  goto next_item;
695627f7eb2Smrg 	case MATCH_NO:
696627f7eb2Smrg 	  break;
697627f7eb2Smrg 
698627f7eb2Smrg 	case MATCH_ERROR:
699627f7eb2Smrg 	  goto cleanup;
700627f7eb2Smrg 	}
701627f7eb2Smrg 
702627f7eb2Smrg       m = gfc_match (" / %n /", n);
703627f7eb2Smrg       if (m == MATCH_ERROR)
704627f7eb2Smrg 	goto cleanup;
705627f7eb2Smrg       if (m == MATCH_NO || n[0] == '\0')
706627f7eb2Smrg 	goto syntax;
707627f7eb2Smrg 
708627f7eb2Smrg       st = gfc_find_symtree (gfc_current_ns->common_root, n);
709627f7eb2Smrg       if (st == NULL)
710627f7eb2Smrg 	{
711627f7eb2Smrg 	  gfc_error ("COMMON block /%s/ not found at %C", n);
712627f7eb2Smrg 	  goto cleanup;
713627f7eb2Smrg 	}
714627f7eb2Smrg 
715627f7eb2Smrg       for (sym = st->n.common->head; sym; sym = sym->common_next)
716627f7eb2Smrg 	{
717627f7eb2Smrg 	  gfc_set_sym_referenced (sym);
718627f7eb2Smrg 	  p = gfc_get_omp_namelist ();
719627f7eb2Smrg 	  if (head == NULL)
720627f7eb2Smrg 	    head = tail = p;
721627f7eb2Smrg 	  else
722627f7eb2Smrg 	    {
723627f7eb2Smrg 	      tail->next = p;
724627f7eb2Smrg 	      tail = tail->next;
725627f7eb2Smrg 	    }
726627f7eb2Smrg 	  tail->sym = sym;
727627f7eb2Smrg 	  tail->where = gfc_current_locus;
728627f7eb2Smrg 	}
729627f7eb2Smrg 
730627f7eb2Smrg     next_item:
731627f7eb2Smrg       if (gfc_match_char (')') == MATCH_YES)
732627f7eb2Smrg 	break;
733627f7eb2Smrg       if (gfc_match_char (',') != MATCH_YES)
734627f7eb2Smrg 	goto syntax;
735627f7eb2Smrg     }
736627f7eb2Smrg 
737627f7eb2Smrg   if (gfc_match_omp_eos () != MATCH_YES)
738627f7eb2Smrg     {
739627f7eb2Smrg       gfc_error ("Unexpected junk after !$ACC DECLARE at %C");
740627f7eb2Smrg       goto cleanup;
741627f7eb2Smrg     }
742627f7eb2Smrg 
743627f7eb2Smrg   while (*list)
744627f7eb2Smrg     list = &(*list)->next;
745627f7eb2Smrg   *list = head;
746627f7eb2Smrg   return MATCH_YES;
747627f7eb2Smrg 
748627f7eb2Smrg syntax:
749627f7eb2Smrg   gfc_error ("Syntax error in !$ACC DECLARE list at %C");
750627f7eb2Smrg 
751627f7eb2Smrg cleanup:
752627f7eb2Smrg   gfc_current_locus = old_loc;
753627f7eb2Smrg   return MATCH_ERROR;
754627f7eb2Smrg }
755627f7eb2Smrg 
756627f7eb2Smrg /* OpenMP 4.5 clauses.  */
757627f7eb2Smrg enum omp_mask1
758627f7eb2Smrg {
759627f7eb2Smrg   OMP_CLAUSE_PRIVATE,
760627f7eb2Smrg   OMP_CLAUSE_FIRSTPRIVATE,
761627f7eb2Smrg   OMP_CLAUSE_LASTPRIVATE,
762627f7eb2Smrg   OMP_CLAUSE_COPYPRIVATE,
763627f7eb2Smrg   OMP_CLAUSE_SHARED,
764627f7eb2Smrg   OMP_CLAUSE_COPYIN,
765627f7eb2Smrg   OMP_CLAUSE_REDUCTION,
766627f7eb2Smrg   OMP_CLAUSE_IF,
767627f7eb2Smrg   OMP_CLAUSE_NUM_THREADS,
768627f7eb2Smrg   OMP_CLAUSE_SCHEDULE,
769627f7eb2Smrg   OMP_CLAUSE_DEFAULT,
770627f7eb2Smrg   OMP_CLAUSE_ORDERED,
771627f7eb2Smrg   OMP_CLAUSE_COLLAPSE,
772627f7eb2Smrg   OMP_CLAUSE_UNTIED,
773627f7eb2Smrg   OMP_CLAUSE_FINAL,
774627f7eb2Smrg   OMP_CLAUSE_MERGEABLE,
775627f7eb2Smrg   OMP_CLAUSE_ALIGNED,
776627f7eb2Smrg   OMP_CLAUSE_DEPEND,
777627f7eb2Smrg   OMP_CLAUSE_INBRANCH,
778627f7eb2Smrg   OMP_CLAUSE_LINEAR,
779627f7eb2Smrg   OMP_CLAUSE_NOTINBRANCH,
780627f7eb2Smrg   OMP_CLAUSE_PROC_BIND,
781627f7eb2Smrg   OMP_CLAUSE_SAFELEN,
782627f7eb2Smrg   OMP_CLAUSE_SIMDLEN,
783627f7eb2Smrg   OMP_CLAUSE_UNIFORM,
784627f7eb2Smrg   OMP_CLAUSE_DEVICE,
785627f7eb2Smrg   OMP_CLAUSE_MAP,
786627f7eb2Smrg   OMP_CLAUSE_TO,
787627f7eb2Smrg   OMP_CLAUSE_FROM,
788627f7eb2Smrg   OMP_CLAUSE_NUM_TEAMS,
789627f7eb2Smrg   OMP_CLAUSE_THREAD_LIMIT,
790627f7eb2Smrg   OMP_CLAUSE_DIST_SCHEDULE,
791627f7eb2Smrg   OMP_CLAUSE_DEFAULTMAP,
792627f7eb2Smrg   OMP_CLAUSE_GRAINSIZE,
793627f7eb2Smrg   OMP_CLAUSE_HINT,
794627f7eb2Smrg   OMP_CLAUSE_IS_DEVICE_PTR,
795627f7eb2Smrg   OMP_CLAUSE_LINK,
796627f7eb2Smrg   OMP_CLAUSE_NOGROUP,
797627f7eb2Smrg   OMP_CLAUSE_NUM_TASKS,
798627f7eb2Smrg   OMP_CLAUSE_PRIORITY,
799627f7eb2Smrg   OMP_CLAUSE_SIMD,
800627f7eb2Smrg   OMP_CLAUSE_THREADS,
801627f7eb2Smrg   OMP_CLAUSE_USE_DEVICE_PTR,
802*4c3eb207Smrg   OMP_CLAUSE_USE_DEVICE_ADDR,  /* Actually, OpenMP 5.0.  */
803627f7eb2Smrg   OMP_CLAUSE_NOWAIT,
804627f7eb2Smrg   /* This must come last.  */
805627f7eb2Smrg   OMP_MASK1_LAST
806627f7eb2Smrg };
807627f7eb2Smrg 
808*4c3eb207Smrg /* OpenACC 2.0+ specific clauses. */
809627f7eb2Smrg enum omp_mask2
810627f7eb2Smrg {
811627f7eb2Smrg   OMP_CLAUSE_ASYNC,
812627f7eb2Smrg   OMP_CLAUSE_NUM_GANGS,
813627f7eb2Smrg   OMP_CLAUSE_NUM_WORKERS,
814627f7eb2Smrg   OMP_CLAUSE_VECTOR_LENGTH,
815627f7eb2Smrg   OMP_CLAUSE_COPY,
816627f7eb2Smrg   OMP_CLAUSE_COPYOUT,
817627f7eb2Smrg   OMP_CLAUSE_CREATE,
818*4c3eb207Smrg   OMP_CLAUSE_NO_CREATE,
819627f7eb2Smrg   OMP_CLAUSE_PRESENT,
820627f7eb2Smrg   OMP_CLAUSE_DEVICEPTR,
821627f7eb2Smrg   OMP_CLAUSE_GANG,
822627f7eb2Smrg   OMP_CLAUSE_WORKER,
823627f7eb2Smrg   OMP_CLAUSE_VECTOR,
824627f7eb2Smrg   OMP_CLAUSE_SEQ,
825627f7eb2Smrg   OMP_CLAUSE_INDEPENDENT,
826627f7eb2Smrg   OMP_CLAUSE_USE_DEVICE,
827627f7eb2Smrg   OMP_CLAUSE_DEVICE_RESIDENT,
828627f7eb2Smrg   OMP_CLAUSE_HOST_SELF,
829627f7eb2Smrg   OMP_CLAUSE_WAIT,
830627f7eb2Smrg   OMP_CLAUSE_DELETE,
831627f7eb2Smrg   OMP_CLAUSE_AUTO,
832627f7eb2Smrg   OMP_CLAUSE_TILE,
833627f7eb2Smrg   OMP_CLAUSE_IF_PRESENT,
834627f7eb2Smrg   OMP_CLAUSE_FINALIZE,
835*4c3eb207Smrg   OMP_CLAUSE_ATTACH,
836*4c3eb207Smrg   OMP_CLAUSE_DETACH,
837627f7eb2Smrg   /* This must come last.  */
838627f7eb2Smrg   OMP_MASK2_LAST
839627f7eb2Smrg };
840627f7eb2Smrg 
841627f7eb2Smrg struct omp_inv_mask;
842627f7eb2Smrg 
843627f7eb2Smrg /* Customized bitset for up to 128-bits.
844627f7eb2Smrg    The two enums above provide bit numbers to use, and which of the
845627f7eb2Smrg    two enums it is determines which of the two mask fields is used.
846627f7eb2Smrg    Supported operations are defining a mask, like:
847627f7eb2Smrg    #define XXX_CLAUSES \
848627f7eb2Smrg      (omp_mask (OMP_CLAUSE_XXX) | OMP_CLAUSE_YYY | OMP_CLAUSE_ZZZ)
849627f7eb2Smrg    oring such bitsets together or removing selected bits:
850627f7eb2Smrg    (XXX_CLAUSES | YYY_CLAUSES) & ~(omp_mask (OMP_CLAUSE_VVV))
851627f7eb2Smrg    and testing individual bits:
852627f7eb2Smrg    if (mask & OMP_CLAUSE_UUU)  */
853627f7eb2Smrg 
854627f7eb2Smrg struct omp_mask {
855627f7eb2Smrg   const uint64_t mask1;
856627f7eb2Smrg   const uint64_t mask2;
857627f7eb2Smrg   inline omp_mask ();
858627f7eb2Smrg   inline omp_mask (omp_mask1);
859627f7eb2Smrg   inline omp_mask (omp_mask2);
860627f7eb2Smrg   inline omp_mask (uint64_t, uint64_t);
861627f7eb2Smrg   inline omp_mask operator| (omp_mask1) const;
862627f7eb2Smrg   inline omp_mask operator| (omp_mask2) const;
863627f7eb2Smrg   inline omp_mask operator| (omp_mask) const;
864627f7eb2Smrg   inline omp_mask operator& (const omp_inv_mask &) const;
865627f7eb2Smrg   inline bool operator& (omp_mask1) const;
866627f7eb2Smrg   inline bool operator& (omp_mask2) const;
867627f7eb2Smrg   inline omp_inv_mask operator~ () const;
868627f7eb2Smrg };
869627f7eb2Smrg 
870627f7eb2Smrg struct omp_inv_mask : public omp_mask {
871627f7eb2Smrg   inline omp_inv_mask (const omp_mask &);
872627f7eb2Smrg };
873627f7eb2Smrg 
omp_mask()874627f7eb2Smrg omp_mask::omp_mask () : mask1 (0), mask2 (0)
875627f7eb2Smrg {
876627f7eb2Smrg }
877627f7eb2Smrg 
omp_mask(omp_mask1 m)878627f7eb2Smrg omp_mask::omp_mask (omp_mask1 m) : mask1 (((uint64_t) 1) << m), mask2 (0)
879627f7eb2Smrg {
880627f7eb2Smrg }
881627f7eb2Smrg 
omp_mask(omp_mask2 m)882627f7eb2Smrg omp_mask::omp_mask (omp_mask2 m) : mask1 (0), mask2 (((uint64_t) 1) << m)
883627f7eb2Smrg {
884627f7eb2Smrg }
885627f7eb2Smrg 
omp_mask(uint64_t m1,uint64_t m2)886627f7eb2Smrg omp_mask::omp_mask (uint64_t m1, uint64_t m2) : mask1 (m1), mask2 (m2)
887627f7eb2Smrg {
888627f7eb2Smrg }
889627f7eb2Smrg 
890627f7eb2Smrg omp_mask
891627f7eb2Smrg omp_mask::operator| (omp_mask1 m) const
892627f7eb2Smrg {
893627f7eb2Smrg   return omp_mask (mask1 | (((uint64_t) 1) << m), mask2);
894627f7eb2Smrg }
895627f7eb2Smrg 
896627f7eb2Smrg omp_mask
897627f7eb2Smrg omp_mask::operator| (omp_mask2 m) const
898627f7eb2Smrg {
899627f7eb2Smrg   return omp_mask (mask1, mask2 | (((uint64_t) 1) << m));
900627f7eb2Smrg }
901627f7eb2Smrg 
902627f7eb2Smrg omp_mask
903627f7eb2Smrg omp_mask::operator| (omp_mask m) const
904627f7eb2Smrg {
905627f7eb2Smrg   return omp_mask (mask1 | m.mask1, mask2 | m.mask2);
906627f7eb2Smrg }
907627f7eb2Smrg 
908627f7eb2Smrg omp_mask
909627f7eb2Smrg omp_mask::operator& (const omp_inv_mask &m) const
910627f7eb2Smrg {
911627f7eb2Smrg   return omp_mask (mask1 & ~m.mask1, mask2 & ~m.mask2);
912627f7eb2Smrg }
913627f7eb2Smrg 
914627f7eb2Smrg bool
915627f7eb2Smrg omp_mask::operator& (omp_mask1 m) const
916627f7eb2Smrg {
917627f7eb2Smrg   return (mask1 & (((uint64_t) 1) << m)) != 0;
918627f7eb2Smrg }
919627f7eb2Smrg 
920627f7eb2Smrg bool
921627f7eb2Smrg omp_mask::operator& (omp_mask2 m) const
922627f7eb2Smrg {
923627f7eb2Smrg   return (mask2 & (((uint64_t) 1) << m)) != 0;
924627f7eb2Smrg }
925627f7eb2Smrg 
926627f7eb2Smrg omp_inv_mask
927627f7eb2Smrg omp_mask::operator~ () const
928627f7eb2Smrg {
929627f7eb2Smrg   return omp_inv_mask (*this);
930627f7eb2Smrg }
931627f7eb2Smrg 
omp_inv_mask(const omp_mask & m)932627f7eb2Smrg omp_inv_mask::omp_inv_mask (const omp_mask &m) : omp_mask (m)
933627f7eb2Smrg {
934627f7eb2Smrg }
935627f7eb2Smrg 
936627f7eb2Smrg /* Helper function for OpenACC and OpenMP clauses involving memory
937627f7eb2Smrg    mapping.  */
938627f7eb2Smrg 
939627f7eb2Smrg static bool
gfc_match_omp_map_clause(gfc_omp_namelist ** list,gfc_omp_map_op map_op,bool allow_common,bool allow_derived)940*4c3eb207Smrg gfc_match_omp_map_clause (gfc_omp_namelist **list, gfc_omp_map_op map_op,
941*4c3eb207Smrg 			  bool allow_common, bool allow_derived)
942627f7eb2Smrg {
943627f7eb2Smrg   gfc_omp_namelist **head = NULL;
944*4c3eb207Smrg   if (gfc_match_omp_variable_list ("", list, allow_common, NULL, &head, true,
945*4c3eb207Smrg 				   allow_derived)
946627f7eb2Smrg       == MATCH_YES)
947627f7eb2Smrg     {
948627f7eb2Smrg       gfc_omp_namelist *n;
949627f7eb2Smrg       for (n = *head; n; n = n->next)
950627f7eb2Smrg 	n->u.map_op = map_op;
951627f7eb2Smrg       return true;
952627f7eb2Smrg     }
953627f7eb2Smrg 
954627f7eb2Smrg   return false;
955627f7eb2Smrg }
956627f7eb2Smrg 
957627f7eb2Smrg /* Match OpenMP and OpenACC directive clauses. MASK is a bitmask of
958627f7eb2Smrg    clauses that are allowed for a particular directive.  */
959627f7eb2Smrg 
960627f7eb2Smrg static match
961627f7eb2Smrg gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
962627f7eb2Smrg 		       bool first = true, bool needs_space = true,
963627f7eb2Smrg 		       bool openacc = false)
964627f7eb2Smrg {
965627f7eb2Smrg   gfc_omp_clauses *c = gfc_get_omp_clauses ();
966627f7eb2Smrg   locus old_loc;
967*4c3eb207Smrg   /* Determine whether we're dealing with an OpenACC directive that permits
968*4c3eb207Smrg      derived type member accesses.  This in particular disallows
969*4c3eb207Smrg      "!$acc declare" from using such accesses, because it's not clear if/how
970*4c3eb207Smrg      that should work.  */
971*4c3eb207Smrg   bool allow_derived = (openacc
972*4c3eb207Smrg 			&& ((mask & OMP_CLAUSE_ATTACH)
973*4c3eb207Smrg 			    || (mask & OMP_CLAUSE_DETACH)
974*4c3eb207Smrg 			    || (mask & OMP_CLAUSE_HOST_SELF)));
975627f7eb2Smrg 
976627f7eb2Smrg   gcc_checking_assert (OMP_MASK1_LAST <= 64 && OMP_MASK2_LAST <= 64);
977627f7eb2Smrg   *cp = NULL;
978627f7eb2Smrg   while (1)
979627f7eb2Smrg     {
980627f7eb2Smrg       if ((first || gfc_match_char (',') != MATCH_YES)
981627f7eb2Smrg 	  && (needs_space && gfc_match_space () != MATCH_YES))
982627f7eb2Smrg 	break;
983627f7eb2Smrg       needs_space = false;
984627f7eb2Smrg       first = false;
985627f7eb2Smrg       gfc_gobble_whitespace ();
986627f7eb2Smrg       bool end_colon;
987627f7eb2Smrg       gfc_omp_namelist **head;
988627f7eb2Smrg       old_loc = gfc_current_locus;
989627f7eb2Smrg       char pc = gfc_peek_ascii_char ();
990627f7eb2Smrg       switch (pc)
991627f7eb2Smrg 	{
992627f7eb2Smrg 	case 'a':
993627f7eb2Smrg 	  end_colon = false;
994627f7eb2Smrg 	  head = NULL;
995627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_ALIGNED)
996627f7eb2Smrg 	      && gfc_match_omp_variable_list ("aligned (",
997627f7eb2Smrg 					      &c->lists[OMP_LIST_ALIGNED],
998627f7eb2Smrg 					      false, &end_colon,
999627f7eb2Smrg 					      &head) == MATCH_YES)
1000627f7eb2Smrg 	    {
1001627f7eb2Smrg 	      gfc_expr *alignment = NULL;
1002627f7eb2Smrg 	      gfc_omp_namelist *n;
1003627f7eb2Smrg 
1004627f7eb2Smrg 	      if (end_colon && gfc_match (" %e )", &alignment) != MATCH_YES)
1005627f7eb2Smrg 		{
1006627f7eb2Smrg 		  gfc_free_omp_namelist (*head);
1007627f7eb2Smrg 		  gfc_current_locus = old_loc;
1008627f7eb2Smrg 		  *head = NULL;
1009627f7eb2Smrg 		  break;
1010627f7eb2Smrg 		}
1011627f7eb2Smrg 	      for (n = *head; n; n = n->next)
1012627f7eb2Smrg 		if (n->next && alignment)
1013627f7eb2Smrg 		  n->expr = gfc_copy_expr (alignment);
1014627f7eb2Smrg 		else
1015627f7eb2Smrg 		  n->expr = alignment;
1016627f7eb2Smrg 	      continue;
1017627f7eb2Smrg 	    }
1018627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_ASYNC)
1019627f7eb2Smrg 	      && !c->async
1020627f7eb2Smrg 	      && gfc_match ("async") == MATCH_YES)
1021627f7eb2Smrg 	    {
1022627f7eb2Smrg 	      c->async = true;
1023627f7eb2Smrg 	      match m = gfc_match (" ( %e )", &c->async_expr);
1024627f7eb2Smrg 	      if (m == MATCH_ERROR)
1025627f7eb2Smrg 		{
1026627f7eb2Smrg 		  gfc_current_locus = old_loc;
1027627f7eb2Smrg 		  break;
1028627f7eb2Smrg 		}
1029627f7eb2Smrg 	      else if (m == MATCH_NO)
1030627f7eb2Smrg 		{
1031627f7eb2Smrg 		  c->async_expr
1032627f7eb2Smrg 		    = gfc_get_constant_expr (BT_INTEGER,
1033627f7eb2Smrg 					     gfc_default_integer_kind,
1034627f7eb2Smrg 					     &gfc_current_locus);
1035627f7eb2Smrg 		  mpz_set_si (c->async_expr->value.integer, GOMP_ASYNC_NOVAL);
1036627f7eb2Smrg 		  needs_space = true;
1037627f7eb2Smrg 		}
1038627f7eb2Smrg 	      continue;
1039627f7eb2Smrg 	    }
1040627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_AUTO)
1041627f7eb2Smrg 	      && !c->par_auto
1042627f7eb2Smrg 	      && gfc_match ("auto") == MATCH_YES)
1043627f7eb2Smrg 	    {
1044627f7eb2Smrg 	      c->par_auto = true;
1045627f7eb2Smrg 	      needs_space = true;
1046627f7eb2Smrg 	      continue;
1047627f7eb2Smrg 	    }
1048*4c3eb207Smrg 	  if ((mask & OMP_CLAUSE_ATTACH)
1049*4c3eb207Smrg 	      && gfc_match ("attach ( ") == MATCH_YES
1050*4c3eb207Smrg 	      && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1051*4c3eb207Smrg 					   OMP_MAP_ATTACH, false,
1052*4c3eb207Smrg 					   allow_derived))
1053*4c3eb207Smrg 	    continue;
1054627f7eb2Smrg 	  break;
1055627f7eb2Smrg 	case 'c':
1056627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_COLLAPSE)
1057627f7eb2Smrg 	      && !c->collapse)
1058627f7eb2Smrg 	    {
1059627f7eb2Smrg 	      gfc_expr *cexpr = NULL;
1060627f7eb2Smrg 	      match m = gfc_match ("collapse ( %e )", &cexpr);
1061627f7eb2Smrg 
1062627f7eb2Smrg 	      if (m == MATCH_YES)
1063627f7eb2Smrg 		{
1064627f7eb2Smrg 		  int collapse;
1065627f7eb2Smrg 		  if (gfc_extract_int (cexpr, &collapse, -1))
1066627f7eb2Smrg 		    collapse = 1;
1067627f7eb2Smrg 		  else if (collapse <= 0)
1068627f7eb2Smrg 		    {
1069627f7eb2Smrg 		      gfc_error_now ("COLLAPSE clause argument not"
1070627f7eb2Smrg 				     " constant positive integer at %C");
1071627f7eb2Smrg 		      collapse = 1;
1072627f7eb2Smrg 		    }
1073627f7eb2Smrg 		  c->collapse = collapse;
1074627f7eb2Smrg 		  gfc_free_expr (cexpr);
1075627f7eb2Smrg 		  continue;
1076627f7eb2Smrg 		}
1077627f7eb2Smrg 	    }
1078627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_COPY)
1079627f7eb2Smrg 	      && gfc_match ("copy ( ") == MATCH_YES
1080627f7eb2Smrg 	      && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1081*4c3eb207Smrg 					   OMP_MAP_TOFROM, true,
1082*4c3eb207Smrg 					   allow_derived))
1083627f7eb2Smrg 	    continue;
1084627f7eb2Smrg 	  if (mask & OMP_CLAUSE_COPYIN)
1085627f7eb2Smrg 	    {
1086627f7eb2Smrg 	      if (openacc)
1087627f7eb2Smrg 		{
1088627f7eb2Smrg 		  if (gfc_match ("copyin ( ") == MATCH_YES
1089627f7eb2Smrg 		      && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1090*4c3eb207Smrg 						   OMP_MAP_TO, true,
1091*4c3eb207Smrg 						   allow_derived))
1092627f7eb2Smrg 		    continue;
1093627f7eb2Smrg 		}
1094627f7eb2Smrg 	      else if (gfc_match_omp_variable_list ("copyin (",
1095627f7eb2Smrg 						    &c->lists[OMP_LIST_COPYIN],
1096627f7eb2Smrg 						    true) == MATCH_YES)
1097627f7eb2Smrg 		continue;
1098627f7eb2Smrg 	    }
1099627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_COPYOUT)
1100627f7eb2Smrg 	      && gfc_match ("copyout ( ") == MATCH_YES
1101627f7eb2Smrg 	      && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1102*4c3eb207Smrg 					   OMP_MAP_FROM, true, allow_derived))
1103627f7eb2Smrg 	    continue;
1104627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_COPYPRIVATE)
1105627f7eb2Smrg 	      && gfc_match_omp_variable_list ("copyprivate (",
1106627f7eb2Smrg 					      &c->lists[OMP_LIST_COPYPRIVATE],
1107627f7eb2Smrg 					      true) == MATCH_YES)
1108627f7eb2Smrg 	    continue;
1109627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_CREATE)
1110627f7eb2Smrg 	      && gfc_match ("create ( ") == MATCH_YES
1111627f7eb2Smrg 	      && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1112*4c3eb207Smrg 					   OMP_MAP_ALLOC, true, allow_derived))
1113627f7eb2Smrg 	    continue;
1114627f7eb2Smrg 	  break;
1115627f7eb2Smrg 	case 'd':
1116627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_DEFAULT)
1117627f7eb2Smrg 	      && c->default_sharing == OMP_DEFAULT_UNKNOWN)
1118627f7eb2Smrg 	    {
1119627f7eb2Smrg 	      if (gfc_match ("default ( none )") == MATCH_YES)
1120627f7eb2Smrg 		c->default_sharing = OMP_DEFAULT_NONE;
1121627f7eb2Smrg 	      else if (openacc)
1122627f7eb2Smrg 		{
1123627f7eb2Smrg 		  if (gfc_match ("default ( present )") == MATCH_YES)
1124627f7eb2Smrg 		    c->default_sharing = OMP_DEFAULT_PRESENT;
1125627f7eb2Smrg 		}
1126627f7eb2Smrg 	      else
1127627f7eb2Smrg 		{
1128627f7eb2Smrg 		  if (gfc_match ("default ( firstprivate )") == MATCH_YES)
1129627f7eb2Smrg 		    c->default_sharing = OMP_DEFAULT_FIRSTPRIVATE;
1130627f7eb2Smrg 		  else if (gfc_match ("default ( private )") == MATCH_YES)
1131627f7eb2Smrg 		    c->default_sharing = OMP_DEFAULT_PRIVATE;
1132627f7eb2Smrg 		  else if (gfc_match ("default ( shared )") == MATCH_YES)
1133627f7eb2Smrg 		    c->default_sharing = OMP_DEFAULT_SHARED;
1134627f7eb2Smrg 		}
1135627f7eb2Smrg 	      if (c->default_sharing != OMP_DEFAULT_UNKNOWN)
1136627f7eb2Smrg 		continue;
1137627f7eb2Smrg 	    }
1138627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_DEFAULTMAP)
1139627f7eb2Smrg 	      && !c->defaultmap
1140627f7eb2Smrg 	      && gfc_match ("defaultmap ( tofrom : scalar )") == MATCH_YES)
1141627f7eb2Smrg 	    {
1142627f7eb2Smrg 	      c->defaultmap = true;
1143627f7eb2Smrg 	      continue;
1144627f7eb2Smrg 	    }
1145627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_DELETE)
1146627f7eb2Smrg 	      && gfc_match ("delete ( ") == MATCH_YES
1147627f7eb2Smrg 	      && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1148*4c3eb207Smrg 					   OMP_MAP_RELEASE, true,
1149*4c3eb207Smrg 					   allow_derived))
1150627f7eb2Smrg 	    continue;
1151627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_DEPEND)
1152627f7eb2Smrg 	      && gfc_match ("depend ( ") == MATCH_YES)
1153627f7eb2Smrg 	    {
1154627f7eb2Smrg 	      match m = MATCH_YES;
1155627f7eb2Smrg 	      gfc_omp_depend_op depend_op = OMP_DEPEND_OUT;
1156627f7eb2Smrg 	      if (gfc_match ("inout") == MATCH_YES)
1157627f7eb2Smrg 		depend_op = OMP_DEPEND_INOUT;
1158627f7eb2Smrg 	      else if (gfc_match ("in") == MATCH_YES)
1159627f7eb2Smrg 		depend_op = OMP_DEPEND_IN;
1160627f7eb2Smrg 	      else if (gfc_match ("out") == MATCH_YES)
1161627f7eb2Smrg 		depend_op = OMP_DEPEND_OUT;
1162627f7eb2Smrg 	      else if (!c->depend_source
1163627f7eb2Smrg 		       && gfc_match ("source )") == MATCH_YES)
1164627f7eb2Smrg 		{
1165627f7eb2Smrg 		  c->depend_source = true;
1166627f7eb2Smrg 		  continue;
1167627f7eb2Smrg 		}
1168627f7eb2Smrg 	      else if (gfc_match ("sink : ") == MATCH_YES)
1169627f7eb2Smrg 		{
1170627f7eb2Smrg 		  if (gfc_match_omp_depend_sink (&c->lists[OMP_LIST_DEPEND])
1171627f7eb2Smrg 		      == MATCH_YES)
1172627f7eb2Smrg 		    continue;
1173627f7eb2Smrg 		  m = MATCH_NO;
1174627f7eb2Smrg 		}
1175627f7eb2Smrg 	      else
1176627f7eb2Smrg 		m = MATCH_NO;
1177627f7eb2Smrg 	      head = NULL;
1178627f7eb2Smrg 	      if (m == MATCH_YES
1179627f7eb2Smrg 		  && gfc_match_omp_variable_list (" : ",
1180627f7eb2Smrg 						  &c->lists[OMP_LIST_DEPEND],
1181627f7eb2Smrg 						  false, NULL, &head,
1182627f7eb2Smrg 						  true) == MATCH_YES)
1183627f7eb2Smrg 		{
1184627f7eb2Smrg 		  gfc_omp_namelist *n;
1185627f7eb2Smrg 		  for (n = *head; n; n = n->next)
1186627f7eb2Smrg 		    n->u.depend_op = depend_op;
1187627f7eb2Smrg 		  continue;
1188627f7eb2Smrg 		}
1189627f7eb2Smrg 	      else
1190627f7eb2Smrg 		gfc_current_locus = old_loc;
1191627f7eb2Smrg 	    }
1192*4c3eb207Smrg 	  if ((mask & OMP_CLAUSE_DETACH)
1193*4c3eb207Smrg 	      && gfc_match ("detach ( ") == MATCH_YES
1194*4c3eb207Smrg 	      && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1195*4c3eb207Smrg 					   OMP_MAP_DETACH, false,
1196*4c3eb207Smrg 					   allow_derived))
1197*4c3eb207Smrg 	    continue;
1198627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_DEVICE)
1199627f7eb2Smrg 	      && !openacc
1200627f7eb2Smrg 	      && c->device == NULL
1201627f7eb2Smrg 	      && gfc_match ("device ( %e )", &c->device) == MATCH_YES)
1202627f7eb2Smrg 	    continue;
1203627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_DEVICE)
1204627f7eb2Smrg 	      && openacc
1205627f7eb2Smrg 	      && gfc_match ("device ( ") == MATCH_YES
1206627f7eb2Smrg 	      && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1207*4c3eb207Smrg 					   OMP_MAP_FORCE_TO, true,
1208*4c3eb207Smrg 					   allow_derived))
1209627f7eb2Smrg 	    continue;
1210627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_DEVICEPTR)
1211627f7eb2Smrg 	      && gfc_match ("deviceptr ( ") == MATCH_YES
1212627f7eb2Smrg 	      && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1213*4c3eb207Smrg 					   OMP_MAP_FORCE_DEVICEPTR, false,
1214*4c3eb207Smrg 					   allow_derived))
1215627f7eb2Smrg 	    continue;
1216627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_DEVICE_RESIDENT)
1217627f7eb2Smrg 	      && gfc_match_omp_variable_list
1218627f7eb2Smrg 		   ("device_resident (",
1219627f7eb2Smrg 		    &c->lists[OMP_LIST_DEVICE_RESIDENT], true) == MATCH_YES)
1220627f7eb2Smrg 	    continue;
1221627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_DIST_SCHEDULE)
1222627f7eb2Smrg 	      && c->dist_sched_kind == OMP_SCHED_NONE
1223627f7eb2Smrg 	      && gfc_match ("dist_schedule ( static") == MATCH_YES)
1224627f7eb2Smrg 	    {
1225627f7eb2Smrg 	      match m = MATCH_NO;
1226627f7eb2Smrg 	      c->dist_sched_kind = OMP_SCHED_STATIC;
1227627f7eb2Smrg 	      m = gfc_match (" , %e )", &c->dist_chunk_size);
1228627f7eb2Smrg 	      if (m != MATCH_YES)
1229627f7eb2Smrg 		m = gfc_match_char (')');
1230627f7eb2Smrg 	      if (m != MATCH_YES)
1231627f7eb2Smrg 		{
1232627f7eb2Smrg 		  c->dist_sched_kind = OMP_SCHED_NONE;
1233627f7eb2Smrg 		  gfc_current_locus = old_loc;
1234627f7eb2Smrg 		}
1235627f7eb2Smrg 	      else
1236627f7eb2Smrg 		continue;
1237627f7eb2Smrg 	    }
1238627f7eb2Smrg 	  break;
1239627f7eb2Smrg 	case 'f':
1240627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_FINAL)
1241627f7eb2Smrg 	      && c->final_expr == NULL
1242627f7eb2Smrg 	      && gfc_match ("final ( %e )", &c->final_expr) == MATCH_YES)
1243627f7eb2Smrg 	    continue;
1244627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_FINALIZE)
1245627f7eb2Smrg 	      && !c->finalize
1246627f7eb2Smrg 	      && gfc_match ("finalize") == MATCH_YES)
1247627f7eb2Smrg 	    {
1248627f7eb2Smrg 	      c->finalize = true;
1249627f7eb2Smrg 	      needs_space = true;
1250627f7eb2Smrg 	      continue;
1251627f7eb2Smrg 	    }
1252627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_FIRSTPRIVATE)
1253627f7eb2Smrg 	      && gfc_match_omp_variable_list ("firstprivate (",
1254627f7eb2Smrg 					      &c->lists[OMP_LIST_FIRSTPRIVATE],
1255627f7eb2Smrg 					      true) == MATCH_YES)
1256627f7eb2Smrg 	    continue;
1257627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_FROM)
1258627f7eb2Smrg 	      && gfc_match_omp_variable_list ("from (",
1259627f7eb2Smrg 					      &c->lists[OMP_LIST_FROM], false,
1260627f7eb2Smrg 					      NULL, &head, true) == MATCH_YES)
1261627f7eb2Smrg 	    continue;
1262627f7eb2Smrg 	  break;
1263627f7eb2Smrg 	case 'g':
1264627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_GANG)
1265627f7eb2Smrg 	      && !c->gang
1266627f7eb2Smrg 	      && gfc_match ("gang") == MATCH_YES)
1267627f7eb2Smrg 	    {
1268627f7eb2Smrg 	      c->gang = true;
1269627f7eb2Smrg 	      match m = match_oacc_clause_gwv (c, GOMP_DIM_GANG);
1270627f7eb2Smrg 	      if (m == MATCH_ERROR)
1271627f7eb2Smrg 		{
1272627f7eb2Smrg 		  gfc_current_locus = old_loc;
1273627f7eb2Smrg 		  break;
1274627f7eb2Smrg 		}
1275627f7eb2Smrg 	      else if (m == MATCH_NO)
1276627f7eb2Smrg 		needs_space = true;
1277627f7eb2Smrg 	      continue;
1278627f7eb2Smrg 	    }
1279627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_GRAINSIZE)
1280627f7eb2Smrg 	      && c->grainsize == NULL
1281627f7eb2Smrg 	      && gfc_match ("grainsize ( %e )", &c->grainsize) == MATCH_YES)
1282627f7eb2Smrg 	    continue;
1283627f7eb2Smrg 	  break;
1284627f7eb2Smrg 	case 'h':
1285627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_HINT)
1286627f7eb2Smrg 	      && c->hint == NULL
1287627f7eb2Smrg 	      && gfc_match ("hint ( %e )", &c->hint) == MATCH_YES)
1288627f7eb2Smrg 	    continue;
1289627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_HOST_SELF)
1290627f7eb2Smrg 	      && gfc_match ("host ( ") == MATCH_YES
1291627f7eb2Smrg 	      && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1292*4c3eb207Smrg 					   OMP_MAP_FORCE_FROM, true,
1293*4c3eb207Smrg 					   allow_derived))
1294627f7eb2Smrg 	    continue;
1295627f7eb2Smrg 	  break;
1296627f7eb2Smrg 	case 'i':
1297627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_IF)
1298627f7eb2Smrg 	      && c->if_expr == NULL
1299627f7eb2Smrg 	      && gfc_match ("if ( ") == MATCH_YES)
1300627f7eb2Smrg 	    {
1301627f7eb2Smrg 	      if (gfc_match ("%e )", &c->if_expr) == MATCH_YES)
1302627f7eb2Smrg 		continue;
1303627f7eb2Smrg 	      if (!openacc)
1304627f7eb2Smrg 		{
1305627f7eb2Smrg 		  /* This should match the enum gfc_omp_if_kind order.  */
1306627f7eb2Smrg 		  static const char *ifs[OMP_IF_LAST] = {
1307627f7eb2Smrg 		    " parallel : %e )",
1308627f7eb2Smrg 		    " task : %e )",
1309627f7eb2Smrg 		    " taskloop : %e )",
1310627f7eb2Smrg 		    " target : %e )",
1311627f7eb2Smrg 		    " target data : %e )",
1312627f7eb2Smrg 		    " target update : %e )",
1313627f7eb2Smrg 		    " target enter data : %e )",
1314627f7eb2Smrg 		    " target exit data : %e )" };
1315627f7eb2Smrg 		  int i;
1316627f7eb2Smrg 		  for (i = 0; i < OMP_IF_LAST; i++)
1317627f7eb2Smrg 		    if (c->if_exprs[i] == NULL
1318627f7eb2Smrg 			&& gfc_match (ifs[i], &c->if_exprs[i]) == MATCH_YES)
1319627f7eb2Smrg 		      break;
1320627f7eb2Smrg 		  if (i < OMP_IF_LAST)
1321627f7eb2Smrg 		    continue;
1322627f7eb2Smrg 		}
1323627f7eb2Smrg 	      gfc_current_locus = old_loc;
1324627f7eb2Smrg 	    }
1325627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_IF_PRESENT)
1326627f7eb2Smrg 	      && !c->if_present
1327627f7eb2Smrg 	      && gfc_match ("if_present") == MATCH_YES)
1328627f7eb2Smrg 	    {
1329627f7eb2Smrg 	      c->if_present = true;
1330627f7eb2Smrg 	      needs_space = true;
1331627f7eb2Smrg 	      continue;
1332627f7eb2Smrg 	    }
1333627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_INBRANCH)
1334627f7eb2Smrg 	      && !c->inbranch
1335627f7eb2Smrg 	      && !c->notinbranch
1336627f7eb2Smrg 	      && gfc_match ("inbranch") == MATCH_YES)
1337627f7eb2Smrg 	    {
1338627f7eb2Smrg 	      c->inbranch = needs_space = true;
1339627f7eb2Smrg 	      continue;
1340627f7eb2Smrg 	    }
1341627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_INDEPENDENT)
1342627f7eb2Smrg 	      && !c->independent
1343627f7eb2Smrg 	      && gfc_match ("independent") == MATCH_YES)
1344627f7eb2Smrg 	    {
1345627f7eb2Smrg 	      c->independent = true;
1346627f7eb2Smrg 	      needs_space = true;
1347627f7eb2Smrg 	      continue;
1348627f7eb2Smrg 	    }
1349627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_IS_DEVICE_PTR)
1350627f7eb2Smrg 	      && gfc_match_omp_variable_list
1351627f7eb2Smrg 		   ("is_device_ptr (",
1352627f7eb2Smrg 		    &c->lists[OMP_LIST_IS_DEVICE_PTR], false) == MATCH_YES)
1353627f7eb2Smrg 	    continue;
1354627f7eb2Smrg 	  break;
1355627f7eb2Smrg 	case 'l':
1356627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_LASTPRIVATE)
1357627f7eb2Smrg 	      && gfc_match_omp_variable_list ("lastprivate (",
1358627f7eb2Smrg 					      &c->lists[OMP_LIST_LASTPRIVATE],
1359627f7eb2Smrg 					      true) == MATCH_YES)
1360627f7eb2Smrg 	    continue;
1361627f7eb2Smrg 	  end_colon = false;
1362627f7eb2Smrg 	  head = NULL;
1363627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_LINEAR)
1364627f7eb2Smrg 	      && gfc_match ("linear (") == MATCH_YES)
1365627f7eb2Smrg 	    {
1366627f7eb2Smrg 	      gfc_omp_linear_op linear_op = OMP_LINEAR_DEFAULT;
1367627f7eb2Smrg 	      gfc_expr *step = NULL;
1368627f7eb2Smrg 
1369627f7eb2Smrg 	      if (gfc_match_omp_variable_list (" ref (",
1370627f7eb2Smrg 					       &c->lists[OMP_LIST_LINEAR],
1371627f7eb2Smrg 					       false, NULL, &head)
1372627f7eb2Smrg 		  == MATCH_YES)
1373627f7eb2Smrg 		linear_op = OMP_LINEAR_REF;
1374627f7eb2Smrg 	      else if (gfc_match_omp_variable_list (" val (",
1375627f7eb2Smrg 						    &c->lists[OMP_LIST_LINEAR],
1376627f7eb2Smrg 						    false, NULL, &head)
1377627f7eb2Smrg 		       == MATCH_YES)
1378627f7eb2Smrg 		linear_op = OMP_LINEAR_VAL;
1379627f7eb2Smrg 	      else if (gfc_match_omp_variable_list (" uval (",
1380627f7eb2Smrg 						    &c->lists[OMP_LIST_LINEAR],
1381627f7eb2Smrg 						    false, NULL, &head)
1382627f7eb2Smrg 		       == MATCH_YES)
1383627f7eb2Smrg 		linear_op = OMP_LINEAR_UVAL;
1384627f7eb2Smrg 	      else if (gfc_match_omp_variable_list ("",
1385627f7eb2Smrg 						    &c->lists[OMP_LIST_LINEAR],
1386627f7eb2Smrg 						    false, &end_colon, &head)
1387627f7eb2Smrg 		       == MATCH_YES)
1388627f7eb2Smrg 		linear_op = OMP_LINEAR_DEFAULT;
1389627f7eb2Smrg 	      else
1390627f7eb2Smrg 		{
1391627f7eb2Smrg 		  gfc_current_locus = old_loc;
1392627f7eb2Smrg 		  break;
1393627f7eb2Smrg 		}
1394627f7eb2Smrg 	      if (linear_op != OMP_LINEAR_DEFAULT)
1395627f7eb2Smrg 		{
1396627f7eb2Smrg 		  if (gfc_match (" :") == MATCH_YES)
1397627f7eb2Smrg 		    end_colon = true;
1398627f7eb2Smrg 		  else if (gfc_match (" )") != MATCH_YES)
1399627f7eb2Smrg 		    {
1400627f7eb2Smrg 		      gfc_free_omp_namelist (*head);
1401627f7eb2Smrg 		      gfc_current_locus = old_loc;
1402627f7eb2Smrg 		      *head = NULL;
1403627f7eb2Smrg 		      break;
1404627f7eb2Smrg 		    }
1405627f7eb2Smrg 		}
1406627f7eb2Smrg 	      if (end_colon && gfc_match (" %e )", &step) != MATCH_YES)
1407627f7eb2Smrg 		{
1408627f7eb2Smrg 		  gfc_free_omp_namelist (*head);
1409627f7eb2Smrg 		  gfc_current_locus = old_loc;
1410627f7eb2Smrg 		  *head = NULL;
1411627f7eb2Smrg 		  break;
1412627f7eb2Smrg 		}
1413627f7eb2Smrg 	      else if (!end_colon)
1414627f7eb2Smrg 		{
1415627f7eb2Smrg 		  step = gfc_get_constant_expr (BT_INTEGER,
1416627f7eb2Smrg 						gfc_default_integer_kind,
1417627f7eb2Smrg 						&old_loc);
1418627f7eb2Smrg 		  mpz_set_si (step->value.integer, 1);
1419627f7eb2Smrg 		}
1420627f7eb2Smrg 	      (*head)->expr = step;
1421627f7eb2Smrg 	      if (linear_op != OMP_LINEAR_DEFAULT)
1422627f7eb2Smrg 		for (gfc_omp_namelist *n = *head; n; n = n->next)
1423627f7eb2Smrg 		  n->u.linear_op = linear_op;
1424627f7eb2Smrg 	      continue;
1425627f7eb2Smrg 	    }
1426627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_LINK)
1427627f7eb2Smrg 	      && openacc
1428627f7eb2Smrg 	      && (gfc_match_oacc_clause_link ("link (",
1429627f7eb2Smrg 					      &c->lists[OMP_LIST_LINK])
1430627f7eb2Smrg 		  == MATCH_YES))
1431627f7eb2Smrg 	    continue;
1432627f7eb2Smrg 	  else if ((mask & OMP_CLAUSE_LINK)
1433627f7eb2Smrg 		   && !openacc
1434627f7eb2Smrg 		   && (gfc_match_omp_to_link ("link (",
1435627f7eb2Smrg 					      &c->lists[OMP_LIST_LINK])
1436627f7eb2Smrg 		       == MATCH_YES))
1437627f7eb2Smrg 	    continue;
1438627f7eb2Smrg 	  break;
1439627f7eb2Smrg 	case 'm':
1440627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_MAP)
1441627f7eb2Smrg 	      && gfc_match ("map ( ") == MATCH_YES)
1442627f7eb2Smrg 	    {
1443627f7eb2Smrg 	      locus old_loc2 = gfc_current_locus;
1444627f7eb2Smrg 	      bool always = false;
1445627f7eb2Smrg 	      gfc_omp_map_op map_op = OMP_MAP_TOFROM;
1446627f7eb2Smrg 	      if (gfc_match ("always , ") == MATCH_YES)
1447627f7eb2Smrg 		always = true;
1448627f7eb2Smrg 	      if (gfc_match ("alloc : ") == MATCH_YES)
1449627f7eb2Smrg 		map_op = OMP_MAP_ALLOC;
1450627f7eb2Smrg 	      else if (gfc_match ("tofrom : ") == MATCH_YES)
1451627f7eb2Smrg 		map_op = always ? OMP_MAP_ALWAYS_TOFROM : OMP_MAP_TOFROM;
1452627f7eb2Smrg 	      else if (gfc_match ("to : ") == MATCH_YES)
1453627f7eb2Smrg 		map_op = always ? OMP_MAP_ALWAYS_TO : OMP_MAP_TO;
1454627f7eb2Smrg 	      else if (gfc_match ("from : ") == MATCH_YES)
1455627f7eb2Smrg 		map_op = always ? OMP_MAP_ALWAYS_FROM : OMP_MAP_FROM;
1456627f7eb2Smrg 	      else if (gfc_match ("release : ") == MATCH_YES)
1457627f7eb2Smrg 		map_op = OMP_MAP_RELEASE;
1458627f7eb2Smrg 	      else if (gfc_match ("delete : ") == MATCH_YES)
1459627f7eb2Smrg 		map_op = OMP_MAP_DELETE;
1460627f7eb2Smrg 	      else if (always)
1461627f7eb2Smrg 		{
1462627f7eb2Smrg 		  gfc_current_locus = old_loc2;
1463627f7eb2Smrg 		  always = false;
1464627f7eb2Smrg 		}
1465627f7eb2Smrg 	      head = NULL;
1466627f7eb2Smrg 	      if (gfc_match_omp_variable_list ("", &c->lists[OMP_LIST_MAP],
1467627f7eb2Smrg 					       false, NULL, &head,
1468627f7eb2Smrg 					       true) == MATCH_YES)
1469627f7eb2Smrg 		{
1470627f7eb2Smrg 		  gfc_omp_namelist *n;
1471627f7eb2Smrg 		  for (n = *head; n; n = n->next)
1472627f7eb2Smrg 		    n->u.map_op = map_op;
1473627f7eb2Smrg 		  continue;
1474627f7eb2Smrg 		}
1475627f7eb2Smrg 	      else
1476627f7eb2Smrg 		gfc_current_locus = old_loc;
1477627f7eb2Smrg 	    }
1478627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_MERGEABLE) && !c->mergeable
1479627f7eb2Smrg 	      && gfc_match ("mergeable") == MATCH_YES)
1480627f7eb2Smrg 	    {
1481627f7eb2Smrg 	      c->mergeable = needs_space = true;
1482627f7eb2Smrg 	      continue;
1483627f7eb2Smrg 	    }
1484627f7eb2Smrg 	  break;
1485627f7eb2Smrg 	case 'n':
1486*4c3eb207Smrg 	  if ((mask & OMP_CLAUSE_NO_CREATE)
1487*4c3eb207Smrg 	      && gfc_match ("no_create ( ") == MATCH_YES
1488*4c3eb207Smrg 	      && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1489*4c3eb207Smrg 					   OMP_MAP_IF_PRESENT, true,
1490*4c3eb207Smrg 					   allow_derived))
1491*4c3eb207Smrg 	    continue;
1492627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_NOGROUP)
1493627f7eb2Smrg 	      && !c->nogroup
1494627f7eb2Smrg 	      && gfc_match ("nogroup") == MATCH_YES)
1495627f7eb2Smrg 	    {
1496627f7eb2Smrg 	      c->nogroup = needs_space = true;
1497627f7eb2Smrg 	      continue;
1498627f7eb2Smrg 	    }
1499627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_NOTINBRANCH)
1500627f7eb2Smrg 	      && !c->notinbranch
1501627f7eb2Smrg 	      && !c->inbranch
1502627f7eb2Smrg 	      && gfc_match ("notinbranch") == MATCH_YES)
1503627f7eb2Smrg 	    {
1504627f7eb2Smrg 	      c->notinbranch = needs_space = true;
1505627f7eb2Smrg 	      continue;
1506627f7eb2Smrg 	    }
1507627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_NOWAIT)
1508627f7eb2Smrg 	      && !c->nowait
1509627f7eb2Smrg 	      && gfc_match ("nowait") == MATCH_YES)
1510627f7eb2Smrg 	    {
1511627f7eb2Smrg 	      c->nowait = needs_space = true;
1512627f7eb2Smrg 	      continue;
1513627f7eb2Smrg 	    }
1514627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_NUM_GANGS)
1515627f7eb2Smrg 	      && c->num_gangs_expr == NULL
1516627f7eb2Smrg 	      && gfc_match ("num_gangs ( %e )",
1517627f7eb2Smrg 			    &c->num_gangs_expr) == MATCH_YES)
1518627f7eb2Smrg 	    continue;
1519627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_NUM_TASKS)
1520627f7eb2Smrg 	      && c->num_tasks == NULL
1521627f7eb2Smrg 	      && gfc_match ("num_tasks ( %e )", &c->num_tasks) == MATCH_YES)
1522627f7eb2Smrg 	    continue;
1523627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_NUM_TEAMS)
1524627f7eb2Smrg 	      && c->num_teams == NULL
1525627f7eb2Smrg 	      && gfc_match ("num_teams ( %e )", &c->num_teams) == MATCH_YES)
1526627f7eb2Smrg 	    continue;
1527627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_NUM_THREADS)
1528627f7eb2Smrg 	      && c->num_threads == NULL
1529627f7eb2Smrg 	      && (gfc_match ("num_threads ( %e )", &c->num_threads)
1530627f7eb2Smrg 		  == MATCH_YES))
1531627f7eb2Smrg 	    continue;
1532627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_NUM_WORKERS)
1533627f7eb2Smrg 	      && c->num_workers_expr == NULL
1534627f7eb2Smrg 	      && gfc_match ("num_workers ( %e )",
1535627f7eb2Smrg 			    &c->num_workers_expr) == MATCH_YES)
1536627f7eb2Smrg 	    continue;
1537627f7eb2Smrg 	  break;
1538627f7eb2Smrg 	case 'o':
1539627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_ORDERED)
1540627f7eb2Smrg 	      && !c->ordered
1541627f7eb2Smrg 	      && gfc_match ("ordered") == MATCH_YES)
1542627f7eb2Smrg 	    {
1543627f7eb2Smrg 	      gfc_expr *cexpr = NULL;
1544627f7eb2Smrg 	      match m = gfc_match (" ( %e )", &cexpr);
1545627f7eb2Smrg 
1546627f7eb2Smrg 	      c->ordered = true;
1547627f7eb2Smrg 	      if (m == MATCH_YES)
1548627f7eb2Smrg 		{
1549627f7eb2Smrg 		  int ordered = 0;
1550627f7eb2Smrg 		  if (gfc_extract_int (cexpr, &ordered, -1))
1551627f7eb2Smrg 		    ordered = 0;
1552627f7eb2Smrg 		  else if (ordered <= 0)
1553627f7eb2Smrg 		    {
1554627f7eb2Smrg 		      gfc_error_now ("ORDERED clause argument not"
1555627f7eb2Smrg 				     " constant positive integer at %C");
1556627f7eb2Smrg 		      ordered = 0;
1557627f7eb2Smrg 		    }
1558627f7eb2Smrg 		  c->orderedc = ordered;
1559627f7eb2Smrg 		  gfc_free_expr (cexpr);
1560627f7eb2Smrg 		  continue;
1561627f7eb2Smrg 		}
1562627f7eb2Smrg 
1563627f7eb2Smrg 	      needs_space = true;
1564627f7eb2Smrg 	      continue;
1565627f7eb2Smrg 	    }
1566627f7eb2Smrg 	  break;
1567627f7eb2Smrg 	case 'p':
1568627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_COPY)
1569627f7eb2Smrg 	      && gfc_match ("pcopy ( ") == MATCH_YES
1570627f7eb2Smrg 	      && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1571*4c3eb207Smrg 					   OMP_MAP_TOFROM, true, allow_derived))
1572627f7eb2Smrg 	    continue;
1573627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_COPYIN)
1574627f7eb2Smrg 	      && gfc_match ("pcopyin ( ") == MATCH_YES
1575627f7eb2Smrg 	      && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1576*4c3eb207Smrg 					   OMP_MAP_TO, true, allow_derived))
1577627f7eb2Smrg 	    continue;
1578627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_COPYOUT)
1579627f7eb2Smrg 	      && gfc_match ("pcopyout ( ") == MATCH_YES
1580627f7eb2Smrg 	      && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1581*4c3eb207Smrg 					   OMP_MAP_FROM, true, allow_derived))
1582627f7eb2Smrg 	    continue;
1583627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_CREATE)
1584627f7eb2Smrg 	      && gfc_match ("pcreate ( ") == MATCH_YES
1585627f7eb2Smrg 	      && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1586*4c3eb207Smrg 					   OMP_MAP_ALLOC, true, allow_derived))
1587627f7eb2Smrg 	    continue;
1588627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_PRESENT)
1589627f7eb2Smrg 	      && gfc_match ("present ( ") == MATCH_YES
1590627f7eb2Smrg 	      && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1591*4c3eb207Smrg 					   OMP_MAP_FORCE_PRESENT, false,
1592*4c3eb207Smrg 					   allow_derived))
1593627f7eb2Smrg 	    continue;
1594627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_COPY)
1595627f7eb2Smrg 	      && gfc_match ("present_or_copy ( ") == MATCH_YES
1596627f7eb2Smrg 	      && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1597*4c3eb207Smrg 					   OMP_MAP_TOFROM, true,
1598*4c3eb207Smrg 					   allow_derived))
1599627f7eb2Smrg 	    continue;
1600627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_COPYIN)
1601627f7eb2Smrg 	      && gfc_match ("present_or_copyin ( ") == MATCH_YES
1602627f7eb2Smrg 	      && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1603*4c3eb207Smrg 					   OMP_MAP_TO, true, allow_derived))
1604627f7eb2Smrg 	    continue;
1605627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_COPYOUT)
1606627f7eb2Smrg 	      && gfc_match ("present_or_copyout ( ") == MATCH_YES
1607627f7eb2Smrg 	      && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1608*4c3eb207Smrg 					   OMP_MAP_FROM, true, allow_derived))
1609627f7eb2Smrg 	    continue;
1610627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_CREATE)
1611627f7eb2Smrg 	      && gfc_match ("present_or_create ( ") == MATCH_YES
1612627f7eb2Smrg 	      && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1613*4c3eb207Smrg 					   OMP_MAP_ALLOC, true, allow_derived))
1614627f7eb2Smrg 	    continue;
1615627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_PRIORITY)
1616627f7eb2Smrg 	      && c->priority == NULL
1617627f7eb2Smrg 	      && gfc_match ("priority ( %e )", &c->priority) == MATCH_YES)
1618627f7eb2Smrg 	    continue;
1619627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_PRIVATE)
1620627f7eb2Smrg 	      && gfc_match_omp_variable_list ("private (",
1621627f7eb2Smrg 					      &c->lists[OMP_LIST_PRIVATE],
1622627f7eb2Smrg 					      true) == MATCH_YES)
1623627f7eb2Smrg 	    continue;
1624627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_PROC_BIND)
1625627f7eb2Smrg 	      && c->proc_bind == OMP_PROC_BIND_UNKNOWN)
1626627f7eb2Smrg 	    {
1627627f7eb2Smrg 	      if (gfc_match ("proc_bind ( master )") == MATCH_YES)
1628627f7eb2Smrg 		c->proc_bind = OMP_PROC_BIND_MASTER;
1629627f7eb2Smrg 	      else if (gfc_match ("proc_bind ( spread )") == MATCH_YES)
1630627f7eb2Smrg 		c->proc_bind = OMP_PROC_BIND_SPREAD;
1631627f7eb2Smrg 	      else if (gfc_match ("proc_bind ( close )") == MATCH_YES)
1632627f7eb2Smrg 		c->proc_bind = OMP_PROC_BIND_CLOSE;
1633627f7eb2Smrg 	      if (c->proc_bind != OMP_PROC_BIND_UNKNOWN)
1634627f7eb2Smrg 		continue;
1635627f7eb2Smrg 	    }
1636627f7eb2Smrg 	  break;
1637627f7eb2Smrg 	case 'r':
1638627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_REDUCTION)
1639627f7eb2Smrg 	      && gfc_match ("reduction ( ") == MATCH_YES)
1640627f7eb2Smrg 	    {
1641627f7eb2Smrg 	      gfc_omp_reduction_op rop = OMP_REDUCTION_NONE;
1642627f7eb2Smrg 	      char buffer[GFC_MAX_SYMBOL_LEN + 3];
1643627f7eb2Smrg 	      if (gfc_match_char ('+') == MATCH_YES)
1644627f7eb2Smrg 		rop = OMP_REDUCTION_PLUS;
1645627f7eb2Smrg 	      else if (gfc_match_char ('*') == MATCH_YES)
1646627f7eb2Smrg 		rop = OMP_REDUCTION_TIMES;
1647627f7eb2Smrg 	      else if (gfc_match_char ('-') == MATCH_YES)
1648627f7eb2Smrg 		rop = OMP_REDUCTION_MINUS;
1649627f7eb2Smrg 	      else if (gfc_match (".and.") == MATCH_YES)
1650627f7eb2Smrg 		rop = OMP_REDUCTION_AND;
1651627f7eb2Smrg 	      else if (gfc_match (".or.") == MATCH_YES)
1652627f7eb2Smrg 		rop = OMP_REDUCTION_OR;
1653627f7eb2Smrg 	      else if (gfc_match (".eqv.") == MATCH_YES)
1654627f7eb2Smrg 		rop = OMP_REDUCTION_EQV;
1655627f7eb2Smrg 	      else if (gfc_match (".neqv.") == MATCH_YES)
1656627f7eb2Smrg 		rop = OMP_REDUCTION_NEQV;
1657627f7eb2Smrg 	      if (rop != OMP_REDUCTION_NONE)
1658627f7eb2Smrg 		snprintf (buffer, sizeof buffer, "operator %s",
1659627f7eb2Smrg 			  gfc_op2string ((gfc_intrinsic_op) rop));
1660627f7eb2Smrg 	      else if (gfc_match_defined_op_name (buffer + 1, 1) == MATCH_YES)
1661627f7eb2Smrg 		{
1662627f7eb2Smrg 		  buffer[0] = '.';
1663627f7eb2Smrg 		  strcat (buffer, ".");
1664627f7eb2Smrg 		}
1665627f7eb2Smrg 	      else if (gfc_match_name (buffer) == MATCH_YES)
1666627f7eb2Smrg 		{
1667627f7eb2Smrg 		  gfc_symbol *sym;
1668627f7eb2Smrg 		  const char *n = buffer;
1669627f7eb2Smrg 
1670627f7eb2Smrg 		  gfc_find_symbol (buffer, NULL, 1, &sym);
1671627f7eb2Smrg 		  if (sym != NULL)
1672627f7eb2Smrg 		    {
1673627f7eb2Smrg 		      if (sym->attr.intrinsic)
1674627f7eb2Smrg 			n = sym->name;
1675627f7eb2Smrg 		      else if ((sym->attr.flavor != FL_UNKNOWN
1676627f7eb2Smrg 				&& sym->attr.flavor != FL_PROCEDURE)
1677627f7eb2Smrg 			       || sym->attr.external
1678627f7eb2Smrg 			       || sym->attr.generic
1679627f7eb2Smrg 			       || sym->attr.entry
1680627f7eb2Smrg 			       || sym->attr.result
1681627f7eb2Smrg 			       || sym->attr.dummy
1682627f7eb2Smrg 			       || sym->attr.subroutine
1683627f7eb2Smrg 			       || sym->attr.pointer
1684627f7eb2Smrg 			       || sym->attr.target
1685627f7eb2Smrg 			       || sym->attr.cray_pointer
1686627f7eb2Smrg 			       || sym->attr.cray_pointee
1687627f7eb2Smrg 			       || (sym->attr.proc != PROC_UNKNOWN
1688627f7eb2Smrg 				   && sym->attr.proc != PROC_INTRINSIC)
1689627f7eb2Smrg 			       || sym->attr.if_source != IFSRC_UNKNOWN
1690627f7eb2Smrg 			       || sym == sym->ns->proc_name)
1691627f7eb2Smrg 			{
1692627f7eb2Smrg 			  sym = NULL;
1693627f7eb2Smrg 			  n = NULL;
1694627f7eb2Smrg 			}
1695627f7eb2Smrg 		      else
1696627f7eb2Smrg 			n = sym->name;
1697627f7eb2Smrg 		    }
1698627f7eb2Smrg 		  if (n == NULL)
1699627f7eb2Smrg 		    rop = OMP_REDUCTION_NONE;
1700627f7eb2Smrg 		  else if (strcmp (n, "max") == 0)
1701627f7eb2Smrg 		    rop = OMP_REDUCTION_MAX;
1702627f7eb2Smrg 		  else if (strcmp (n, "min") == 0)
1703627f7eb2Smrg 		    rop = OMP_REDUCTION_MIN;
1704627f7eb2Smrg 		  else if (strcmp (n, "iand") == 0)
1705627f7eb2Smrg 		    rop = OMP_REDUCTION_IAND;
1706627f7eb2Smrg 		  else if (strcmp (n, "ior") == 0)
1707627f7eb2Smrg 		    rop = OMP_REDUCTION_IOR;
1708627f7eb2Smrg 		  else if (strcmp (n, "ieor") == 0)
1709627f7eb2Smrg 		    rop = OMP_REDUCTION_IEOR;
1710627f7eb2Smrg 		  if (rop != OMP_REDUCTION_NONE
1711627f7eb2Smrg 		      && sym != NULL
1712627f7eb2Smrg 		      && ! sym->attr.intrinsic
1713627f7eb2Smrg 		      && ! sym->attr.use_assoc
1714627f7eb2Smrg 		      && ((sym->attr.flavor == FL_UNKNOWN
1715627f7eb2Smrg 			  && !gfc_add_flavor (&sym->attr, FL_PROCEDURE,
1716627f7eb2Smrg 					      sym->name, NULL))
1717627f7eb2Smrg 			  || !gfc_add_intrinsic (&sym->attr, NULL)))
1718627f7eb2Smrg 		    rop = OMP_REDUCTION_NONE;
1719627f7eb2Smrg 		}
1720627f7eb2Smrg 	      else
1721627f7eb2Smrg 		buffer[0] = '\0';
1722627f7eb2Smrg 	      gfc_omp_udr *udr
1723627f7eb2Smrg 		= (buffer[0]
1724627f7eb2Smrg 		   ? gfc_find_omp_udr (gfc_current_ns, buffer, NULL) : NULL);
1725627f7eb2Smrg 	      gfc_omp_namelist **head = NULL;
1726627f7eb2Smrg 	      if (rop == OMP_REDUCTION_NONE && udr)
1727627f7eb2Smrg 		rop = OMP_REDUCTION_USER;
1728627f7eb2Smrg 
1729627f7eb2Smrg 	      if (gfc_match_omp_variable_list (" :",
1730627f7eb2Smrg 					       &c->lists[OMP_LIST_REDUCTION],
1731*4c3eb207Smrg 					       false, NULL, &head, openacc,
1732*4c3eb207Smrg 					       allow_derived) == MATCH_YES)
1733627f7eb2Smrg 		{
1734627f7eb2Smrg 		  gfc_omp_namelist *n;
1735627f7eb2Smrg 		  if (rop == OMP_REDUCTION_NONE)
1736627f7eb2Smrg 		    {
1737627f7eb2Smrg 		      n = *head;
1738627f7eb2Smrg 		      *head = NULL;
1739627f7eb2Smrg 		      gfc_error_now ("!$OMP DECLARE REDUCTION %s not found "
1740627f7eb2Smrg 				     "at %L", buffer, &old_loc);
1741627f7eb2Smrg 		      gfc_free_omp_namelist (n);
1742627f7eb2Smrg 		    }
1743627f7eb2Smrg 		  else
1744627f7eb2Smrg 		    for (n = *head; n; n = n->next)
1745627f7eb2Smrg 		      {
1746627f7eb2Smrg 			n->u.reduction_op = rop;
1747627f7eb2Smrg 			if (udr)
1748627f7eb2Smrg 			  {
1749627f7eb2Smrg 			    n->udr = gfc_get_omp_namelist_udr ();
1750627f7eb2Smrg 			    n->udr->udr = udr;
1751627f7eb2Smrg 			  }
1752627f7eb2Smrg 		      }
1753627f7eb2Smrg 		  continue;
1754627f7eb2Smrg 		}
1755627f7eb2Smrg 	      else
1756627f7eb2Smrg 		gfc_current_locus = old_loc;
1757627f7eb2Smrg 	    }
1758627f7eb2Smrg 	  break;
1759627f7eb2Smrg 	case 's':
1760627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_SAFELEN)
1761627f7eb2Smrg 	      && c->safelen_expr == NULL
1762627f7eb2Smrg 	      && gfc_match ("safelen ( %e )", &c->safelen_expr) == MATCH_YES)
1763627f7eb2Smrg 	    continue;
1764627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_SCHEDULE)
1765627f7eb2Smrg 	      && c->sched_kind == OMP_SCHED_NONE
1766627f7eb2Smrg 	      && gfc_match ("schedule ( ") == MATCH_YES)
1767627f7eb2Smrg 	    {
1768627f7eb2Smrg 	      int nmodifiers = 0;
1769627f7eb2Smrg 	      locus old_loc2 = gfc_current_locus;
1770627f7eb2Smrg 	      do
1771627f7eb2Smrg 		{
1772627f7eb2Smrg 		  if (gfc_match ("simd") == MATCH_YES)
1773627f7eb2Smrg 		    {
1774627f7eb2Smrg 		      c->sched_simd = true;
1775627f7eb2Smrg 		      nmodifiers++;
1776627f7eb2Smrg 		    }
1777627f7eb2Smrg 		  else if (gfc_match ("monotonic") == MATCH_YES)
1778627f7eb2Smrg 		    {
1779627f7eb2Smrg 		      c->sched_monotonic = true;
1780627f7eb2Smrg 		      nmodifiers++;
1781627f7eb2Smrg 		    }
1782627f7eb2Smrg 		  else if (gfc_match ("nonmonotonic") == MATCH_YES)
1783627f7eb2Smrg 		    {
1784627f7eb2Smrg 		      c->sched_nonmonotonic = true;
1785627f7eb2Smrg 		      nmodifiers++;
1786627f7eb2Smrg 		    }
1787627f7eb2Smrg 		  else
1788627f7eb2Smrg 		    {
1789627f7eb2Smrg 		      if (nmodifiers)
1790627f7eb2Smrg 			gfc_current_locus = old_loc2;
1791627f7eb2Smrg 		      break;
1792627f7eb2Smrg 		    }
1793627f7eb2Smrg 		  if (nmodifiers == 1
1794627f7eb2Smrg 		      && gfc_match (" , ") == MATCH_YES)
1795627f7eb2Smrg 		    continue;
1796627f7eb2Smrg 		  else if (gfc_match (" : ") == MATCH_YES)
1797627f7eb2Smrg 		    break;
1798627f7eb2Smrg 		  gfc_current_locus = old_loc2;
1799627f7eb2Smrg 		  break;
1800627f7eb2Smrg 		}
1801627f7eb2Smrg 	      while (1);
1802627f7eb2Smrg 	      if (gfc_match ("static") == MATCH_YES)
1803627f7eb2Smrg 		c->sched_kind = OMP_SCHED_STATIC;
1804627f7eb2Smrg 	      else if (gfc_match ("dynamic") == MATCH_YES)
1805627f7eb2Smrg 		c->sched_kind = OMP_SCHED_DYNAMIC;
1806627f7eb2Smrg 	      else if (gfc_match ("guided") == MATCH_YES)
1807627f7eb2Smrg 		c->sched_kind = OMP_SCHED_GUIDED;
1808627f7eb2Smrg 	      else if (gfc_match ("runtime") == MATCH_YES)
1809627f7eb2Smrg 		c->sched_kind = OMP_SCHED_RUNTIME;
1810627f7eb2Smrg 	      else if (gfc_match ("auto") == MATCH_YES)
1811627f7eb2Smrg 		c->sched_kind = OMP_SCHED_AUTO;
1812627f7eb2Smrg 	      if (c->sched_kind != OMP_SCHED_NONE)
1813627f7eb2Smrg 		{
1814627f7eb2Smrg 		  match m = MATCH_NO;
1815627f7eb2Smrg 		  if (c->sched_kind != OMP_SCHED_RUNTIME
1816627f7eb2Smrg 		      && c->sched_kind != OMP_SCHED_AUTO)
1817627f7eb2Smrg 		    m = gfc_match (" , %e )", &c->chunk_size);
1818627f7eb2Smrg 		  if (m != MATCH_YES)
1819627f7eb2Smrg 		    m = gfc_match_char (')');
1820627f7eb2Smrg 		  if (m != MATCH_YES)
1821627f7eb2Smrg 		    c->sched_kind = OMP_SCHED_NONE;
1822627f7eb2Smrg 		}
1823627f7eb2Smrg 	      if (c->sched_kind != OMP_SCHED_NONE)
1824627f7eb2Smrg 		continue;
1825627f7eb2Smrg 	      else
1826627f7eb2Smrg 		gfc_current_locus = old_loc;
1827627f7eb2Smrg 	    }
1828627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_HOST_SELF)
1829627f7eb2Smrg 	      && gfc_match ("self ( ") == MATCH_YES
1830627f7eb2Smrg 	      && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
1831*4c3eb207Smrg 					   OMP_MAP_FORCE_FROM, true,
1832*4c3eb207Smrg 					   allow_derived))
1833627f7eb2Smrg 	    continue;
1834627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_SEQ)
1835627f7eb2Smrg 	      && !c->seq
1836627f7eb2Smrg 	      && gfc_match ("seq") == MATCH_YES)
1837627f7eb2Smrg 	    {
1838627f7eb2Smrg 	      c->seq = true;
1839627f7eb2Smrg 	      needs_space = true;
1840627f7eb2Smrg 	      continue;
1841627f7eb2Smrg 	    }
1842627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_SHARED)
1843627f7eb2Smrg 	      && gfc_match_omp_variable_list ("shared (",
1844627f7eb2Smrg 					      &c->lists[OMP_LIST_SHARED],
1845627f7eb2Smrg 					      true) == MATCH_YES)
1846627f7eb2Smrg 	    continue;
1847627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_SIMDLEN)
1848627f7eb2Smrg 	      && c->simdlen_expr == NULL
1849627f7eb2Smrg 	      && gfc_match ("simdlen ( %e )", &c->simdlen_expr) == MATCH_YES)
1850627f7eb2Smrg 	    continue;
1851627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_SIMD)
1852627f7eb2Smrg 	      && !c->simd
1853627f7eb2Smrg 	      && gfc_match ("simd") == MATCH_YES)
1854627f7eb2Smrg 	    {
1855627f7eb2Smrg 	      c->simd = needs_space = true;
1856627f7eb2Smrg 	      continue;
1857627f7eb2Smrg 	    }
1858627f7eb2Smrg 	  break;
1859627f7eb2Smrg 	case 't':
1860627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_THREAD_LIMIT)
1861627f7eb2Smrg 	      && c->thread_limit == NULL
1862627f7eb2Smrg 	      && gfc_match ("thread_limit ( %e )",
1863627f7eb2Smrg 			    &c->thread_limit) == MATCH_YES)
1864627f7eb2Smrg 	    continue;
1865627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_THREADS)
1866627f7eb2Smrg 	      && !c->threads
1867627f7eb2Smrg 	      && gfc_match ("threads") == MATCH_YES)
1868627f7eb2Smrg 	    {
1869627f7eb2Smrg 	      c->threads = needs_space = true;
1870627f7eb2Smrg 	      continue;
1871627f7eb2Smrg 	    }
1872627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_TILE)
1873627f7eb2Smrg 	      && !c->tile_list
1874627f7eb2Smrg 	      && match_oacc_expr_list ("tile (", &c->tile_list,
1875627f7eb2Smrg 				       true) == MATCH_YES)
1876627f7eb2Smrg 	    continue;
1877627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_TO) && (mask & OMP_CLAUSE_LINK))
1878627f7eb2Smrg 	    {
1879627f7eb2Smrg 	      if (gfc_match_omp_to_link ("to (", &c->lists[OMP_LIST_TO])
1880627f7eb2Smrg 		  == MATCH_YES)
1881627f7eb2Smrg 		continue;
1882627f7eb2Smrg 	    }
1883627f7eb2Smrg 	  else if ((mask & OMP_CLAUSE_TO)
1884627f7eb2Smrg 	      && gfc_match_omp_variable_list ("to (",
1885627f7eb2Smrg 					      &c->lists[OMP_LIST_TO], false,
1886627f7eb2Smrg 					      NULL, &head, true) == MATCH_YES)
1887627f7eb2Smrg 	    continue;
1888627f7eb2Smrg 	  break;
1889627f7eb2Smrg 	case 'u':
1890627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_UNIFORM)
1891627f7eb2Smrg 	      && gfc_match_omp_variable_list ("uniform (",
1892627f7eb2Smrg 					      &c->lists[OMP_LIST_UNIFORM],
1893627f7eb2Smrg 					      false) == MATCH_YES)
1894627f7eb2Smrg 	    continue;
1895627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_UNTIED)
1896627f7eb2Smrg 	      && !c->untied
1897627f7eb2Smrg 	      && gfc_match ("untied") == MATCH_YES)
1898627f7eb2Smrg 	    {
1899627f7eb2Smrg 	      c->untied = needs_space = true;
1900627f7eb2Smrg 	      continue;
1901627f7eb2Smrg 	    }
1902627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_USE_DEVICE)
1903627f7eb2Smrg 	      && gfc_match_omp_variable_list ("use_device (",
1904627f7eb2Smrg 					      &c->lists[OMP_LIST_USE_DEVICE],
1905627f7eb2Smrg 					      true) == MATCH_YES)
1906627f7eb2Smrg 	    continue;
1907627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_USE_DEVICE_PTR)
1908627f7eb2Smrg 	      && gfc_match_omp_variable_list
1909627f7eb2Smrg 		   ("use_device_ptr (",
1910627f7eb2Smrg 		    &c->lists[OMP_LIST_USE_DEVICE_PTR], false) == MATCH_YES)
1911627f7eb2Smrg 	    continue;
1912*4c3eb207Smrg 	  if ((mask & OMP_CLAUSE_USE_DEVICE_ADDR)
1913*4c3eb207Smrg 	      && gfc_match_omp_variable_list
1914*4c3eb207Smrg 		   ("use_device_addr (",
1915*4c3eb207Smrg 		    &c->lists[OMP_LIST_USE_DEVICE_ADDR], false) == MATCH_YES)
1916*4c3eb207Smrg 	    continue;
1917627f7eb2Smrg 	  break;
1918627f7eb2Smrg 	case 'v':
1919627f7eb2Smrg 	  /* VECTOR_LENGTH must be matched before VECTOR, because the latter
1920627f7eb2Smrg 	     doesn't unconditionally match '('.  */
1921627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_VECTOR_LENGTH)
1922627f7eb2Smrg 	      && c->vector_length_expr == NULL
1923627f7eb2Smrg 	      && (gfc_match ("vector_length ( %e )", &c->vector_length_expr)
1924627f7eb2Smrg 		  == MATCH_YES))
1925627f7eb2Smrg 	    continue;
1926627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_VECTOR)
1927627f7eb2Smrg 	      && !c->vector
1928627f7eb2Smrg 	      && gfc_match ("vector") == MATCH_YES)
1929627f7eb2Smrg 	    {
1930627f7eb2Smrg 	      c->vector = true;
1931627f7eb2Smrg 	      match m = match_oacc_clause_gwv (c, GOMP_DIM_VECTOR);
1932627f7eb2Smrg 	      if (m == MATCH_ERROR)
1933627f7eb2Smrg 		{
1934627f7eb2Smrg 		  gfc_current_locus = old_loc;
1935627f7eb2Smrg 		  break;
1936627f7eb2Smrg 		}
1937627f7eb2Smrg 	      if (m == MATCH_NO)
1938627f7eb2Smrg 		needs_space = true;
1939627f7eb2Smrg 	      continue;
1940627f7eb2Smrg 	    }
1941627f7eb2Smrg 	  break;
1942627f7eb2Smrg 	case 'w':
1943627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_WAIT)
1944627f7eb2Smrg 	      && gfc_match ("wait") == MATCH_YES)
1945627f7eb2Smrg 	    {
1946627f7eb2Smrg 	      match m = match_oacc_expr_list (" (", &c->wait_list, false);
1947627f7eb2Smrg 	      if (m == MATCH_ERROR)
1948627f7eb2Smrg 		{
1949627f7eb2Smrg 		  gfc_current_locus = old_loc;
1950627f7eb2Smrg 		  break;
1951627f7eb2Smrg 		}
1952627f7eb2Smrg 	      else if (m == MATCH_NO)
1953627f7eb2Smrg 		{
1954627f7eb2Smrg 		  gfc_expr *expr
1955627f7eb2Smrg 		    = gfc_get_constant_expr (BT_INTEGER,
1956627f7eb2Smrg 					     gfc_default_integer_kind,
1957627f7eb2Smrg 					     &gfc_current_locus);
1958627f7eb2Smrg 		  mpz_set_si (expr->value.integer, GOMP_ASYNC_NOVAL);
1959627f7eb2Smrg 		  gfc_expr_list **expr_list = &c->wait_list;
1960627f7eb2Smrg 		  while (*expr_list)
1961627f7eb2Smrg 		    expr_list = &(*expr_list)->next;
1962627f7eb2Smrg 		  *expr_list = gfc_get_expr_list ();
1963627f7eb2Smrg 		  (*expr_list)->expr = expr;
1964627f7eb2Smrg 		  needs_space = true;
1965627f7eb2Smrg 		}
1966627f7eb2Smrg 	      continue;
1967627f7eb2Smrg 	    }
1968627f7eb2Smrg 	  if ((mask & OMP_CLAUSE_WORKER)
1969627f7eb2Smrg 	      && !c->worker
1970627f7eb2Smrg 	      && gfc_match ("worker") == MATCH_YES)
1971627f7eb2Smrg 	    {
1972627f7eb2Smrg 	      c->worker = true;
1973627f7eb2Smrg 	      match m = match_oacc_clause_gwv (c, GOMP_DIM_WORKER);
1974627f7eb2Smrg 	      if (m == MATCH_ERROR)
1975627f7eb2Smrg 		{
1976627f7eb2Smrg 		  gfc_current_locus = old_loc;
1977627f7eb2Smrg 		  break;
1978627f7eb2Smrg 		}
1979627f7eb2Smrg 	      else if (m == MATCH_NO)
1980627f7eb2Smrg 		needs_space = true;
1981627f7eb2Smrg 	      continue;
1982627f7eb2Smrg 	    }
1983627f7eb2Smrg 	  break;
1984627f7eb2Smrg 	}
1985627f7eb2Smrg       break;
1986627f7eb2Smrg     }
1987627f7eb2Smrg 
1988627f7eb2Smrg   if (gfc_match_omp_eos () != MATCH_YES)
1989627f7eb2Smrg     {
1990*4c3eb207Smrg       if (!gfc_error_flag_test ())
1991*4c3eb207Smrg 	gfc_error ("Failed to match clause at %C");
1992627f7eb2Smrg       gfc_free_omp_clauses (c);
1993627f7eb2Smrg       return MATCH_ERROR;
1994627f7eb2Smrg     }
1995627f7eb2Smrg 
1996627f7eb2Smrg   *cp = c;
1997627f7eb2Smrg   return MATCH_YES;
1998627f7eb2Smrg }
1999627f7eb2Smrg 
2000627f7eb2Smrg 
2001627f7eb2Smrg #define OACC_PARALLEL_CLAUSES \
2002627f7eb2Smrg   (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_NUM_GANGS	      \
2003627f7eb2Smrg    | OMP_CLAUSE_NUM_WORKERS | OMP_CLAUSE_VECTOR_LENGTH | OMP_CLAUSE_REDUCTION \
2004627f7eb2Smrg    | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT		      \
2005*4c3eb207Smrg    | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT	      \
2006*4c3eb207Smrg    | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE      \
2007*4c3eb207Smrg    | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH)
2008627f7eb2Smrg #define OACC_KERNELS_CLAUSES \
2009627f7eb2Smrg   (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_NUM_GANGS	      \
2010627f7eb2Smrg    | OMP_CLAUSE_NUM_WORKERS | OMP_CLAUSE_VECTOR_LENGTH | OMP_CLAUSE_DEVICEPTR \
2011627f7eb2Smrg    | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT		      \
2012*4c3eb207Smrg    | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT	      \
2013*4c3eb207Smrg    | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH)
2014*4c3eb207Smrg #define OACC_SERIAL_CLAUSES \
2015*4c3eb207Smrg   (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_REDUCTION	      \
2016*4c3eb207Smrg    | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT		      \
2017*4c3eb207Smrg    | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT	      \
2018*4c3eb207Smrg    | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE      \
2019*4c3eb207Smrg    | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH)
2020627f7eb2Smrg #define OACC_DATA_CLAUSES \
2021627f7eb2Smrg   (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_DEVICEPTR  | OMP_CLAUSE_COPY	      \
2022627f7eb2Smrg    | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_CREATE		      \
2023*4c3eb207Smrg    | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT | OMP_CLAUSE_ATTACH)
2024627f7eb2Smrg #define OACC_LOOP_CLAUSES \
2025627f7eb2Smrg   (omp_mask (OMP_CLAUSE_COLLAPSE) | OMP_CLAUSE_GANG | OMP_CLAUSE_WORKER	      \
2026627f7eb2Smrg    | OMP_CLAUSE_VECTOR | OMP_CLAUSE_SEQ | OMP_CLAUSE_INDEPENDENT	      \
2027627f7eb2Smrg    | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_AUTO	      \
2028627f7eb2Smrg    | OMP_CLAUSE_TILE)
2029627f7eb2Smrg #define OACC_PARALLEL_LOOP_CLAUSES \
2030627f7eb2Smrg   (OACC_LOOP_CLAUSES | OACC_PARALLEL_CLAUSES)
2031627f7eb2Smrg #define OACC_KERNELS_LOOP_CLAUSES \
2032627f7eb2Smrg   (OACC_LOOP_CLAUSES | OACC_KERNELS_CLAUSES)
2033*4c3eb207Smrg #define OACC_SERIAL_LOOP_CLAUSES \
2034*4c3eb207Smrg   (OACC_LOOP_CLAUSES | OACC_SERIAL_CLAUSES)
2035*4c3eb207Smrg #define OACC_HOST_DATA_CLAUSES \
2036*4c3eb207Smrg   (omp_mask (OMP_CLAUSE_USE_DEVICE)					      \
2037*4c3eb207Smrg    | OMP_CLAUSE_IF							      \
2038*4c3eb207Smrg    | OMP_CLAUSE_IF_PRESENT)
2039627f7eb2Smrg #define OACC_DECLARE_CLAUSES \
2040627f7eb2Smrg   (omp_mask (OMP_CLAUSE_COPY) | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT	      \
2041627f7eb2Smrg    | OMP_CLAUSE_CREATE | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_DEVICE_RESIDENT    \
2042627f7eb2Smrg    | OMP_CLAUSE_PRESENT			      \
2043627f7eb2Smrg    | OMP_CLAUSE_LINK)
2044627f7eb2Smrg #define OACC_UPDATE_CLAUSES \
2045627f7eb2Smrg   (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_HOST_SELF	      \
2046627f7eb2Smrg    | OMP_CLAUSE_DEVICE | OMP_CLAUSE_WAIT | OMP_CLAUSE_IF_PRESENT)
2047627f7eb2Smrg #define OACC_ENTER_DATA_CLAUSES \
2048627f7eb2Smrg   (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_WAIT	      \
2049*4c3eb207Smrg    | OMP_CLAUSE_COPYIN | OMP_CLAUSE_CREATE | OMP_CLAUSE_ATTACH)
2050627f7eb2Smrg #define OACC_EXIT_DATA_CLAUSES \
2051627f7eb2Smrg   (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_WAIT	      \
2052*4c3eb207Smrg    | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_DELETE | OMP_CLAUSE_FINALIZE	      \
2053*4c3eb207Smrg    | OMP_CLAUSE_DETACH)
2054627f7eb2Smrg #define OACC_WAIT_CLAUSES \
2055627f7eb2Smrg   omp_mask (OMP_CLAUSE_ASYNC)
2056627f7eb2Smrg #define OACC_ROUTINE_CLAUSES \
2057627f7eb2Smrg   (omp_mask (OMP_CLAUSE_GANG) | OMP_CLAUSE_WORKER | OMP_CLAUSE_VECTOR	      \
2058627f7eb2Smrg    | OMP_CLAUSE_SEQ)
2059627f7eb2Smrg 
2060627f7eb2Smrg 
2061627f7eb2Smrg static match
match_acc(gfc_exec_op op,const omp_mask mask)2062627f7eb2Smrg match_acc (gfc_exec_op op, const omp_mask mask)
2063627f7eb2Smrg {
2064627f7eb2Smrg   gfc_omp_clauses *c;
2065627f7eb2Smrg   if (gfc_match_omp_clauses (&c, mask, false, false, true) != MATCH_YES)
2066627f7eb2Smrg     return MATCH_ERROR;
2067627f7eb2Smrg   new_st.op = op;
2068627f7eb2Smrg   new_st.ext.omp_clauses = c;
2069627f7eb2Smrg   return MATCH_YES;
2070627f7eb2Smrg }
2071627f7eb2Smrg 
2072627f7eb2Smrg match
gfc_match_oacc_parallel_loop(void)2073627f7eb2Smrg gfc_match_oacc_parallel_loop (void)
2074627f7eb2Smrg {
2075627f7eb2Smrg   return match_acc (EXEC_OACC_PARALLEL_LOOP, OACC_PARALLEL_LOOP_CLAUSES);
2076627f7eb2Smrg }
2077627f7eb2Smrg 
2078627f7eb2Smrg 
2079627f7eb2Smrg match
gfc_match_oacc_parallel(void)2080627f7eb2Smrg gfc_match_oacc_parallel (void)
2081627f7eb2Smrg {
2082627f7eb2Smrg   return match_acc (EXEC_OACC_PARALLEL, OACC_PARALLEL_CLAUSES);
2083627f7eb2Smrg }
2084627f7eb2Smrg 
2085627f7eb2Smrg 
2086627f7eb2Smrg match
gfc_match_oacc_kernels_loop(void)2087627f7eb2Smrg gfc_match_oacc_kernels_loop (void)
2088627f7eb2Smrg {
2089627f7eb2Smrg   return match_acc (EXEC_OACC_KERNELS_LOOP, OACC_KERNELS_LOOP_CLAUSES);
2090627f7eb2Smrg }
2091627f7eb2Smrg 
2092627f7eb2Smrg 
2093627f7eb2Smrg match
gfc_match_oacc_kernels(void)2094627f7eb2Smrg gfc_match_oacc_kernels (void)
2095627f7eb2Smrg {
2096627f7eb2Smrg   return match_acc (EXEC_OACC_KERNELS, OACC_KERNELS_CLAUSES);
2097627f7eb2Smrg }
2098627f7eb2Smrg 
2099627f7eb2Smrg 
2100627f7eb2Smrg match
gfc_match_oacc_serial_loop(void)2101*4c3eb207Smrg gfc_match_oacc_serial_loop (void)
2102*4c3eb207Smrg {
2103*4c3eb207Smrg   return match_acc (EXEC_OACC_SERIAL_LOOP, OACC_SERIAL_LOOP_CLAUSES);
2104*4c3eb207Smrg }
2105*4c3eb207Smrg 
2106*4c3eb207Smrg 
2107*4c3eb207Smrg match
gfc_match_oacc_serial(void)2108*4c3eb207Smrg gfc_match_oacc_serial (void)
2109*4c3eb207Smrg {
2110*4c3eb207Smrg   return match_acc (EXEC_OACC_SERIAL, OACC_SERIAL_CLAUSES);
2111*4c3eb207Smrg }
2112*4c3eb207Smrg 
2113*4c3eb207Smrg 
2114*4c3eb207Smrg match
gfc_match_oacc_data(void)2115627f7eb2Smrg gfc_match_oacc_data (void)
2116627f7eb2Smrg {
2117627f7eb2Smrg   return match_acc (EXEC_OACC_DATA, OACC_DATA_CLAUSES);
2118627f7eb2Smrg }
2119627f7eb2Smrg 
2120627f7eb2Smrg 
2121627f7eb2Smrg match
gfc_match_oacc_host_data(void)2122627f7eb2Smrg gfc_match_oacc_host_data (void)
2123627f7eb2Smrg {
2124627f7eb2Smrg   return match_acc (EXEC_OACC_HOST_DATA, OACC_HOST_DATA_CLAUSES);
2125627f7eb2Smrg }
2126627f7eb2Smrg 
2127627f7eb2Smrg 
2128627f7eb2Smrg match
gfc_match_oacc_loop(void)2129627f7eb2Smrg gfc_match_oacc_loop (void)
2130627f7eb2Smrg {
2131627f7eb2Smrg   return match_acc (EXEC_OACC_LOOP, OACC_LOOP_CLAUSES);
2132627f7eb2Smrg }
2133627f7eb2Smrg 
2134627f7eb2Smrg 
2135627f7eb2Smrg match
gfc_match_oacc_declare(void)2136627f7eb2Smrg gfc_match_oacc_declare (void)
2137627f7eb2Smrg {
2138627f7eb2Smrg   gfc_omp_clauses *c;
2139627f7eb2Smrg   gfc_omp_namelist *n;
2140627f7eb2Smrg   gfc_namespace *ns = gfc_current_ns;
2141627f7eb2Smrg   gfc_oacc_declare *new_oc;
2142627f7eb2Smrg   bool module_var = false;
2143627f7eb2Smrg   locus where = gfc_current_locus;
2144627f7eb2Smrg 
2145627f7eb2Smrg   if (gfc_match_omp_clauses (&c, OACC_DECLARE_CLAUSES, false, false, true)
2146627f7eb2Smrg       != MATCH_YES)
2147627f7eb2Smrg     return MATCH_ERROR;
2148627f7eb2Smrg 
2149627f7eb2Smrg   for (n = c->lists[OMP_LIST_DEVICE_RESIDENT]; n != NULL; n = n->next)
2150627f7eb2Smrg     n->sym->attr.oacc_declare_device_resident = 1;
2151627f7eb2Smrg 
2152627f7eb2Smrg   for (n = c->lists[OMP_LIST_LINK]; n != NULL; n = n->next)
2153627f7eb2Smrg     n->sym->attr.oacc_declare_link = 1;
2154627f7eb2Smrg 
2155627f7eb2Smrg   for (n = c->lists[OMP_LIST_MAP]; n != NULL; n = n->next)
2156627f7eb2Smrg     {
2157627f7eb2Smrg       gfc_symbol *s = n->sym;
2158627f7eb2Smrg 
2159*4c3eb207Smrg       if (gfc_current_ns->proc_name
2160*4c3eb207Smrg 	  && gfc_current_ns->proc_name->attr.flavor == FL_MODULE)
2161627f7eb2Smrg 	{
2162627f7eb2Smrg 	  if (n->u.map_op != OMP_MAP_ALLOC && n->u.map_op != OMP_MAP_TO)
2163627f7eb2Smrg 	    {
2164627f7eb2Smrg 	      gfc_error ("Invalid clause in module with !$ACC DECLARE at %L",
2165627f7eb2Smrg 			 &where);
2166627f7eb2Smrg 	      return MATCH_ERROR;
2167627f7eb2Smrg 	    }
2168627f7eb2Smrg 
2169627f7eb2Smrg 	  module_var = true;
2170627f7eb2Smrg 	}
2171627f7eb2Smrg 
2172627f7eb2Smrg       if (s->attr.use_assoc)
2173627f7eb2Smrg 	{
2174627f7eb2Smrg 	  gfc_error ("Variable is USE-associated with !$ACC DECLARE at %L",
2175627f7eb2Smrg 		     &where);
2176627f7eb2Smrg 	  return MATCH_ERROR;
2177627f7eb2Smrg 	}
2178627f7eb2Smrg 
2179*4c3eb207Smrg       if ((s->result == s && s->ns->contained != gfc_current_ns)
2180*4c3eb207Smrg 	  || ((s->attr.flavor == FL_UNKNOWN || s->attr.flavor == FL_VARIABLE)
2181*4c3eb207Smrg 	      && s->ns != gfc_current_ns))
2182*4c3eb207Smrg 	{
2183*4c3eb207Smrg 	  gfc_error ("Variable %qs shall be declared in the same scoping unit "
2184*4c3eb207Smrg 		     "as !$ACC DECLARE at %L", s->name, &where);
2185*4c3eb207Smrg 	  return MATCH_ERROR;
2186*4c3eb207Smrg 	}
2187*4c3eb207Smrg 
2188627f7eb2Smrg       if ((s->attr.dimension || s->attr.codimension)
2189627f7eb2Smrg 	  && s->attr.dummy && s->as->type != AS_EXPLICIT)
2190627f7eb2Smrg 	{
2191627f7eb2Smrg 	  gfc_error ("Assumed-size dummy array with !$ACC DECLARE at %L",
2192627f7eb2Smrg 		     &where);
2193627f7eb2Smrg 	  return MATCH_ERROR;
2194627f7eb2Smrg 	}
2195627f7eb2Smrg 
2196627f7eb2Smrg       switch (n->u.map_op)
2197627f7eb2Smrg 	{
2198627f7eb2Smrg 	  case OMP_MAP_FORCE_ALLOC:
2199627f7eb2Smrg 	  case OMP_MAP_ALLOC:
2200627f7eb2Smrg 	    s->attr.oacc_declare_create = 1;
2201627f7eb2Smrg 	    break;
2202627f7eb2Smrg 
2203627f7eb2Smrg 	  case OMP_MAP_FORCE_TO:
2204627f7eb2Smrg 	  case OMP_MAP_TO:
2205627f7eb2Smrg 	    s->attr.oacc_declare_copyin = 1;
2206627f7eb2Smrg 	    break;
2207627f7eb2Smrg 
2208627f7eb2Smrg 	  case OMP_MAP_FORCE_DEVICEPTR:
2209627f7eb2Smrg 	    s->attr.oacc_declare_deviceptr = 1;
2210627f7eb2Smrg 	    break;
2211627f7eb2Smrg 
2212627f7eb2Smrg 	  default:
2213627f7eb2Smrg 	    break;
2214627f7eb2Smrg 	}
2215627f7eb2Smrg     }
2216627f7eb2Smrg 
2217627f7eb2Smrg   new_oc = gfc_get_oacc_declare ();
2218627f7eb2Smrg   new_oc->next = ns->oacc_declare;
2219627f7eb2Smrg   new_oc->module_var = module_var;
2220627f7eb2Smrg   new_oc->clauses = c;
2221627f7eb2Smrg   new_oc->loc = gfc_current_locus;
2222627f7eb2Smrg   ns->oacc_declare = new_oc;
2223627f7eb2Smrg 
2224627f7eb2Smrg   return MATCH_YES;
2225627f7eb2Smrg }
2226627f7eb2Smrg 
2227627f7eb2Smrg 
2228627f7eb2Smrg match
gfc_match_oacc_update(void)2229627f7eb2Smrg gfc_match_oacc_update (void)
2230627f7eb2Smrg {
2231627f7eb2Smrg   gfc_omp_clauses *c;
2232627f7eb2Smrg   locus here = gfc_current_locus;
2233627f7eb2Smrg 
2234627f7eb2Smrg   if (gfc_match_omp_clauses (&c, OACC_UPDATE_CLAUSES, false, false, true)
2235627f7eb2Smrg       != MATCH_YES)
2236627f7eb2Smrg     return MATCH_ERROR;
2237627f7eb2Smrg 
2238627f7eb2Smrg   if (!c->lists[OMP_LIST_MAP])
2239627f7eb2Smrg     {
2240627f7eb2Smrg       gfc_error ("%<acc update%> must contain at least one "
2241627f7eb2Smrg 		 "%<device%> or %<host%> or %<self%> clause at %L", &here);
2242627f7eb2Smrg       return MATCH_ERROR;
2243627f7eb2Smrg     }
2244627f7eb2Smrg 
2245627f7eb2Smrg   new_st.op = EXEC_OACC_UPDATE;
2246627f7eb2Smrg   new_st.ext.omp_clauses = c;
2247627f7eb2Smrg   return MATCH_YES;
2248627f7eb2Smrg }
2249627f7eb2Smrg 
2250627f7eb2Smrg 
2251627f7eb2Smrg match
gfc_match_oacc_enter_data(void)2252627f7eb2Smrg gfc_match_oacc_enter_data (void)
2253627f7eb2Smrg {
2254627f7eb2Smrg   return match_acc (EXEC_OACC_ENTER_DATA, OACC_ENTER_DATA_CLAUSES);
2255627f7eb2Smrg }
2256627f7eb2Smrg 
2257627f7eb2Smrg 
2258627f7eb2Smrg match
gfc_match_oacc_exit_data(void)2259627f7eb2Smrg gfc_match_oacc_exit_data (void)
2260627f7eb2Smrg {
2261627f7eb2Smrg   return match_acc (EXEC_OACC_EXIT_DATA, OACC_EXIT_DATA_CLAUSES);
2262627f7eb2Smrg }
2263627f7eb2Smrg 
2264627f7eb2Smrg 
2265627f7eb2Smrg match
gfc_match_oacc_wait(void)2266627f7eb2Smrg gfc_match_oacc_wait (void)
2267627f7eb2Smrg {
2268627f7eb2Smrg   gfc_omp_clauses *c = gfc_get_omp_clauses ();
2269627f7eb2Smrg   gfc_expr_list *wait_list = NULL, *el;
2270627f7eb2Smrg   bool space = true;
2271627f7eb2Smrg   match m;
2272627f7eb2Smrg 
2273627f7eb2Smrg   m = match_oacc_expr_list (" (", &wait_list, true);
2274627f7eb2Smrg   if (m == MATCH_ERROR)
2275627f7eb2Smrg     return m;
2276627f7eb2Smrg   else if (m == MATCH_YES)
2277627f7eb2Smrg     space = false;
2278627f7eb2Smrg 
2279627f7eb2Smrg   if (gfc_match_omp_clauses (&c, OACC_WAIT_CLAUSES, space, space, true)
2280627f7eb2Smrg       == MATCH_ERROR)
2281627f7eb2Smrg     return MATCH_ERROR;
2282627f7eb2Smrg 
2283627f7eb2Smrg   if (wait_list)
2284627f7eb2Smrg     for (el = wait_list; el; el = el->next)
2285627f7eb2Smrg       {
2286627f7eb2Smrg 	if (el->expr == NULL)
2287627f7eb2Smrg 	  {
2288627f7eb2Smrg 	    gfc_error ("Invalid argument to !$ACC WAIT at %C");
2289627f7eb2Smrg 	    return MATCH_ERROR;
2290627f7eb2Smrg 	  }
2291627f7eb2Smrg 
2292627f7eb2Smrg 	if (!gfc_resolve_expr (el->expr)
2293627f7eb2Smrg 	    || el->expr->ts.type != BT_INTEGER || el->expr->rank != 0)
2294627f7eb2Smrg 	  {
2295627f7eb2Smrg 	    gfc_error ("WAIT clause at %L requires a scalar INTEGER expression",
2296627f7eb2Smrg 		       &el->expr->where);
2297627f7eb2Smrg 
2298627f7eb2Smrg 	    return MATCH_ERROR;
2299627f7eb2Smrg 	  }
2300627f7eb2Smrg       }
2301627f7eb2Smrg   c->wait_list = wait_list;
2302627f7eb2Smrg   new_st.op = EXEC_OACC_WAIT;
2303627f7eb2Smrg   new_st.ext.omp_clauses = c;
2304627f7eb2Smrg   return MATCH_YES;
2305627f7eb2Smrg }
2306627f7eb2Smrg 
2307627f7eb2Smrg 
2308627f7eb2Smrg match
gfc_match_oacc_cache(void)2309627f7eb2Smrg gfc_match_oacc_cache (void)
2310627f7eb2Smrg {
2311627f7eb2Smrg   gfc_omp_clauses *c = gfc_get_omp_clauses ();
2312627f7eb2Smrg   /* The OpenACC cache directive explicitly only allows "array elements or
2313627f7eb2Smrg      subarrays", which we're currently not checking here.  Either check this
2314627f7eb2Smrg      after the call of gfc_match_omp_variable_list, or add something like a
2315627f7eb2Smrg      only_sections variant next to its allow_sections parameter.  */
2316627f7eb2Smrg   match m = gfc_match_omp_variable_list (" (",
2317627f7eb2Smrg 					 &c->lists[OMP_LIST_CACHE], true,
2318627f7eb2Smrg 					 NULL, NULL, true);
2319627f7eb2Smrg   if (m != MATCH_YES)
2320627f7eb2Smrg     {
2321627f7eb2Smrg       gfc_free_omp_clauses(c);
2322627f7eb2Smrg       return m;
2323627f7eb2Smrg     }
2324627f7eb2Smrg 
2325627f7eb2Smrg   if (gfc_current_state() != COMP_DO
2326627f7eb2Smrg       && gfc_current_state() != COMP_DO_CONCURRENT)
2327627f7eb2Smrg     {
2328627f7eb2Smrg       gfc_error ("ACC CACHE directive must be inside of loop %C");
2329627f7eb2Smrg       gfc_free_omp_clauses(c);
2330627f7eb2Smrg       return MATCH_ERROR;
2331627f7eb2Smrg     }
2332627f7eb2Smrg 
2333627f7eb2Smrg   new_st.op = EXEC_OACC_CACHE;
2334627f7eb2Smrg   new_st.ext.omp_clauses = c;
2335627f7eb2Smrg   return MATCH_YES;
2336627f7eb2Smrg }
2337627f7eb2Smrg 
2338627f7eb2Smrg /* Determine the OpenACC 'routine' directive's level of parallelism.  */
2339627f7eb2Smrg 
2340627f7eb2Smrg static oacc_routine_lop
gfc_oacc_routine_lop(gfc_omp_clauses * clauses)2341627f7eb2Smrg gfc_oacc_routine_lop (gfc_omp_clauses *clauses)
2342627f7eb2Smrg {
2343627f7eb2Smrg   oacc_routine_lop ret = OACC_ROUTINE_LOP_SEQ;
2344627f7eb2Smrg 
2345627f7eb2Smrg   if (clauses)
2346627f7eb2Smrg     {
2347627f7eb2Smrg       unsigned n_lop_clauses = 0;
2348627f7eb2Smrg 
2349627f7eb2Smrg       if (clauses->gang)
2350627f7eb2Smrg 	{
2351627f7eb2Smrg 	  ++n_lop_clauses;
2352627f7eb2Smrg 	  ret = OACC_ROUTINE_LOP_GANG;
2353627f7eb2Smrg 	}
2354627f7eb2Smrg       if (clauses->worker)
2355627f7eb2Smrg 	{
2356627f7eb2Smrg 	  ++n_lop_clauses;
2357627f7eb2Smrg 	  ret = OACC_ROUTINE_LOP_WORKER;
2358627f7eb2Smrg 	}
2359627f7eb2Smrg       if (clauses->vector)
2360627f7eb2Smrg 	{
2361627f7eb2Smrg 	  ++n_lop_clauses;
2362627f7eb2Smrg 	  ret = OACC_ROUTINE_LOP_VECTOR;
2363627f7eb2Smrg 	}
2364627f7eb2Smrg       if (clauses->seq)
2365627f7eb2Smrg 	{
2366627f7eb2Smrg 	  ++n_lop_clauses;
2367627f7eb2Smrg 	  ret = OACC_ROUTINE_LOP_SEQ;
2368627f7eb2Smrg 	}
2369627f7eb2Smrg 
2370627f7eb2Smrg       if (n_lop_clauses > 1)
2371627f7eb2Smrg 	ret = OACC_ROUTINE_LOP_ERROR;
2372627f7eb2Smrg     }
2373627f7eb2Smrg 
2374627f7eb2Smrg   return ret;
2375627f7eb2Smrg }
2376627f7eb2Smrg 
2377627f7eb2Smrg match
gfc_match_oacc_routine(void)2378627f7eb2Smrg gfc_match_oacc_routine (void)
2379627f7eb2Smrg {
2380627f7eb2Smrg   locus old_loc;
2381627f7eb2Smrg   match m;
2382627f7eb2Smrg   gfc_intrinsic_sym *isym = NULL;
2383627f7eb2Smrg   gfc_symbol *sym = NULL;
2384627f7eb2Smrg   gfc_omp_clauses *c = NULL;
2385627f7eb2Smrg   gfc_oacc_routine_name *n = NULL;
2386627f7eb2Smrg   oacc_routine_lop lop = OACC_ROUTINE_LOP_NONE;
2387627f7eb2Smrg 
2388627f7eb2Smrg   old_loc = gfc_current_locus;
2389627f7eb2Smrg 
2390627f7eb2Smrg   m = gfc_match (" (");
2391627f7eb2Smrg 
2392627f7eb2Smrg   if (gfc_current_ns->proc_name
2393627f7eb2Smrg       && gfc_current_ns->proc_name->attr.if_source == IFSRC_IFBODY
2394627f7eb2Smrg       && m == MATCH_YES)
2395627f7eb2Smrg     {
2396627f7eb2Smrg       gfc_error ("Only the !$ACC ROUTINE form without "
2397627f7eb2Smrg 		 "list is allowed in interface block at %C");
2398627f7eb2Smrg       goto cleanup;
2399627f7eb2Smrg     }
2400627f7eb2Smrg 
2401627f7eb2Smrg   if (m == MATCH_YES)
2402627f7eb2Smrg     {
2403627f7eb2Smrg       char buffer[GFC_MAX_SYMBOL_LEN + 1];
2404627f7eb2Smrg 
2405627f7eb2Smrg       m = gfc_match_name (buffer);
2406627f7eb2Smrg       if (m == MATCH_YES)
2407627f7eb2Smrg 	{
2408627f7eb2Smrg 	  gfc_symtree *st = NULL;
2409627f7eb2Smrg 
2410627f7eb2Smrg 	  /* First look for an intrinsic symbol.  */
2411627f7eb2Smrg 	  isym = gfc_find_function (buffer);
2412627f7eb2Smrg 	  if (!isym)
2413627f7eb2Smrg 	    isym = gfc_find_subroutine (buffer);
2414627f7eb2Smrg 	  /* If no intrinsic symbol found, search the current namespace.  */
2415627f7eb2Smrg 	  if (!isym)
2416627f7eb2Smrg 	    st = gfc_find_symtree (gfc_current_ns->sym_root, buffer);
2417627f7eb2Smrg 	  if (st)
2418627f7eb2Smrg 	    {
2419627f7eb2Smrg 	      sym = st->n.sym;
2420627f7eb2Smrg 	      /* If the name in a 'routine' directive refers to the containing
2421627f7eb2Smrg 		 subroutine or function, then make sure that we'll later handle
2422627f7eb2Smrg 		 this accordingly.  */
2423627f7eb2Smrg 	      if (gfc_current_ns->proc_name != NULL
2424627f7eb2Smrg 		  && strcmp (sym->name, gfc_current_ns->proc_name->name) == 0)
2425627f7eb2Smrg 	        sym = NULL;
2426627f7eb2Smrg 	    }
2427627f7eb2Smrg 
2428627f7eb2Smrg 	  if (isym == NULL && st == NULL)
2429627f7eb2Smrg 	    {
2430627f7eb2Smrg 	      gfc_error ("Invalid NAME %qs in !$ACC ROUTINE ( NAME ) at %C",
2431627f7eb2Smrg 			 buffer);
2432627f7eb2Smrg 	      gfc_current_locus = old_loc;
2433627f7eb2Smrg 	      return MATCH_ERROR;
2434627f7eb2Smrg 	    }
2435627f7eb2Smrg 	}
2436627f7eb2Smrg       else
2437627f7eb2Smrg         {
2438627f7eb2Smrg 	  gfc_error ("Syntax error in !$ACC ROUTINE ( NAME ) at %C");
2439627f7eb2Smrg 	  gfc_current_locus = old_loc;
2440627f7eb2Smrg 	  return MATCH_ERROR;
2441627f7eb2Smrg 	}
2442627f7eb2Smrg 
2443627f7eb2Smrg       if (gfc_match_char (')') != MATCH_YES)
2444627f7eb2Smrg 	{
2445627f7eb2Smrg 	  gfc_error ("Syntax error in !$ACC ROUTINE ( NAME ) at %C, expecting"
2446627f7eb2Smrg 		     " ')' after NAME");
2447627f7eb2Smrg 	  gfc_current_locus = old_loc;
2448627f7eb2Smrg 	  return MATCH_ERROR;
2449627f7eb2Smrg 	}
2450627f7eb2Smrg     }
2451627f7eb2Smrg 
2452627f7eb2Smrg   if (gfc_match_omp_eos () != MATCH_YES
2453627f7eb2Smrg       && (gfc_match_omp_clauses (&c, OACC_ROUTINE_CLAUSES, false, false, true)
2454627f7eb2Smrg 	  != MATCH_YES))
2455627f7eb2Smrg     return MATCH_ERROR;
2456627f7eb2Smrg 
2457627f7eb2Smrg   lop = gfc_oacc_routine_lop (c);
2458627f7eb2Smrg   if (lop == OACC_ROUTINE_LOP_ERROR)
2459627f7eb2Smrg     {
2460627f7eb2Smrg       gfc_error ("Multiple loop axes specified for routine at %C");
2461627f7eb2Smrg       goto cleanup;
2462627f7eb2Smrg     }
2463627f7eb2Smrg 
2464627f7eb2Smrg   if (isym != NULL)
2465627f7eb2Smrg     {
2466627f7eb2Smrg       /* Diagnose any OpenACC 'routine' directive that doesn't match the
2467627f7eb2Smrg 	 (implicit) one with a 'seq' clause.  */
2468627f7eb2Smrg       if (c && (c->gang || c->worker || c->vector))
2469627f7eb2Smrg 	{
2470627f7eb2Smrg 	  gfc_error ("Intrinsic symbol specified in !$ACC ROUTINE ( NAME )"
2471627f7eb2Smrg 		     " at %C marked with incompatible GANG, WORKER, or VECTOR"
2472627f7eb2Smrg 		     " clause");
2473627f7eb2Smrg 	  goto cleanup;
2474627f7eb2Smrg 	}
2475627f7eb2Smrg     }
2476627f7eb2Smrg   else if (sym != NULL)
2477627f7eb2Smrg     {
2478627f7eb2Smrg       bool add = true;
2479627f7eb2Smrg 
2480627f7eb2Smrg       /* For a repeated OpenACC 'routine' directive, diagnose if it doesn't
2481627f7eb2Smrg 	 match the first one.  */
2482627f7eb2Smrg       for (gfc_oacc_routine_name *n_p = gfc_current_ns->oacc_routine_names;
2483627f7eb2Smrg 	   n_p;
2484627f7eb2Smrg 	   n_p = n_p->next)
2485627f7eb2Smrg 	if (n_p->sym == sym)
2486627f7eb2Smrg 	  {
2487627f7eb2Smrg 	    add = false;
2488627f7eb2Smrg 	    if (lop != gfc_oacc_routine_lop (n_p->clauses))
2489627f7eb2Smrg 	      {
2490627f7eb2Smrg 		gfc_error ("!$ACC ROUTINE already applied at %C");
2491627f7eb2Smrg 		goto cleanup;
2492627f7eb2Smrg 	      }
2493627f7eb2Smrg 	  }
2494627f7eb2Smrg 
2495627f7eb2Smrg       if (add)
2496627f7eb2Smrg 	{
2497627f7eb2Smrg 	  sym->attr.oacc_routine_lop = lop;
2498627f7eb2Smrg 
2499627f7eb2Smrg 	  n = gfc_get_oacc_routine_name ();
2500627f7eb2Smrg 	  n->sym = sym;
2501627f7eb2Smrg 	  n->clauses = c;
2502627f7eb2Smrg 	  n->next = gfc_current_ns->oacc_routine_names;
2503627f7eb2Smrg 	  n->loc = old_loc;
2504627f7eb2Smrg 	  gfc_current_ns->oacc_routine_names = n;
2505627f7eb2Smrg 	}
2506627f7eb2Smrg     }
2507627f7eb2Smrg   else if (gfc_current_ns->proc_name)
2508627f7eb2Smrg     {
2509627f7eb2Smrg       /* For a repeated OpenACC 'routine' directive, diagnose if it doesn't
2510627f7eb2Smrg 	 match the first one.  */
2511627f7eb2Smrg       oacc_routine_lop lop_p = gfc_current_ns->proc_name->attr.oacc_routine_lop;
2512627f7eb2Smrg       if (lop_p != OACC_ROUTINE_LOP_NONE
2513627f7eb2Smrg 	  && lop != lop_p)
2514627f7eb2Smrg 	{
2515627f7eb2Smrg 	  gfc_error ("!$ACC ROUTINE already applied at %C");
2516627f7eb2Smrg 	  goto cleanup;
2517627f7eb2Smrg 	}
2518627f7eb2Smrg 
2519627f7eb2Smrg       if (!gfc_add_omp_declare_target (&gfc_current_ns->proc_name->attr,
2520627f7eb2Smrg 				       gfc_current_ns->proc_name->name,
2521627f7eb2Smrg 				       &old_loc))
2522627f7eb2Smrg 	goto cleanup;
2523627f7eb2Smrg       gfc_current_ns->proc_name->attr.oacc_routine_lop = lop;
2524627f7eb2Smrg     }
2525627f7eb2Smrg   else
2526627f7eb2Smrg     /* Something has gone wrong, possibly a syntax error.  */
2527627f7eb2Smrg     goto cleanup;
2528627f7eb2Smrg 
2529627f7eb2Smrg   if (n)
2530627f7eb2Smrg     n->clauses = c;
2531627f7eb2Smrg   else if (gfc_current_ns->oacc_routine)
2532627f7eb2Smrg     gfc_current_ns->oacc_routine_clauses = c;
2533627f7eb2Smrg 
2534627f7eb2Smrg   new_st.op = EXEC_OACC_ROUTINE;
2535627f7eb2Smrg   new_st.ext.omp_clauses = c;
2536627f7eb2Smrg   return MATCH_YES;
2537627f7eb2Smrg 
2538627f7eb2Smrg cleanup:
2539627f7eb2Smrg   gfc_current_locus = old_loc;
2540627f7eb2Smrg   return MATCH_ERROR;
2541627f7eb2Smrg }
2542627f7eb2Smrg 
2543627f7eb2Smrg 
2544627f7eb2Smrg #define OMP_PARALLEL_CLAUSES \
2545627f7eb2Smrg   (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE		\
2546627f7eb2Smrg    | OMP_CLAUSE_SHARED | OMP_CLAUSE_COPYIN | OMP_CLAUSE_REDUCTION	\
2547627f7eb2Smrg    | OMP_CLAUSE_IF | OMP_CLAUSE_NUM_THREADS | OMP_CLAUSE_DEFAULT	\
2548627f7eb2Smrg    | OMP_CLAUSE_PROC_BIND)
2549627f7eb2Smrg #define OMP_DECLARE_SIMD_CLAUSES \
2550627f7eb2Smrg   (omp_mask (OMP_CLAUSE_SIMDLEN) | OMP_CLAUSE_LINEAR			\
2551627f7eb2Smrg    | OMP_CLAUSE_UNIFORM	| OMP_CLAUSE_ALIGNED | OMP_CLAUSE_INBRANCH	\
2552627f7eb2Smrg    | OMP_CLAUSE_NOTINBRANCH)
2553627f7eb2Smrg #define OMP_DO_CLAUSES \
2554627f7eb2Smrg   (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE		\
2555627f7eb2Smrg    | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION			\
2556627f7eb2Smrg    | OMP_CLAUSE_SCHEDULE | OMP_CLAUSE_ORDERED | OMP_CLAUSE_COLLAPSE	\
2557627f7eb2Smrg    | OMP_CLAUSE_LINEAR)
2558627f7eb2Smrg #define OMP_SECTIONS_CLAUSES \
2559627f7eb2Smrg   (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE		\
2560627f7eb2Smrg    | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION)
2561627f7eb2Smrg #define OMP_SIMD_CLAUSES \
2562627f7eb2Smrg   (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_LASTPRIVATE		\
2563627f7eb2Smrg    | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_SAFELEN	\
2564627f7eb2Smrg    | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ALIGNED | OMP_CLAUSE_SIMDLEN)
2565627f7eb2Smrg #define OMP_TASK_CLAUSES \
2566627f7eb2Smrg   (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE		\
2567627f7eb2Smrg    | OMP_CLAUSE_SHARED | OMP_CLAUSE_IF | OMP_CLAUSE_DEFAULT		\
2568627f7eb2Smrg    | OMP_CLAUSE_UNTIED | OMP_CLAUSE_FINAL | OMP_CLAUSE_MERGEABLE	\
2569627f7eb2Smrg    | OMP_CLAUSE_DEPEND | OMP_CLAUSE_PRIORITY)
2570627f7eb2Smrg #define OMP_TASKLOOP_CLAUSES \
2571627f7eb2Smrg   (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE		\
2572627f7eb2Smrg    | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_IF		\
2573627f7eb2Smrg    | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_UNTIED | OMP_CLAUSE_FINAL		\
2574627f7eb2Smrg    | OMP_CLAUSE_MERGEABLE | OMP_CLAUSE_PRIORITY | OMP_CLAUSE_GRAINSIZE	\
2575627f7eb2Smrg    | OMP_CLAUSE_NUM_TASKS | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_NOGROUP)
2576627f7eb2Smrg #define OMP_TARGET_CLAUSES \
2577627f7eb2Smrg   (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF	\
2578627f7eb2Smrg    | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_PRIVATE		\
2579627f7eb2Smrg    | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_DEFAULTMAP			\
2580627f7eb2Smrg    | OMP_CLAUSE_IS_DEVICE_PTR)
2581627f7eb2Smrg #define OMP_TARGET_DATA_CLAUSES \
2582627f7eb2Smrg   (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF	\
2583*4c3eb207Smrg    | OMP_CLAUSE_USE_DEVICE_PTR | OMP_CLAUSE_USE_DEVICE_ADDR)
2584627f7eb2Smrg #define OMP_TARGET_ENTER_DATA_CLAUSES \
2585627f7eb2Smrg   (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF	\
2586627f7eb2Smrg    | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT)
2587627f7eb2Smrg #define OMP_TARGET_EXIT_DATA_CLAUSES \
2588627f7eb2Smrg   (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF	\
2589627f7eb2Smrg    | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT)
2590627f7eb2Smrg #define OMP_TARGET_UPDATE_CLAUSES \
2591627f7eb2Smrg   (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_IF | OMP_CLAUSE_TO		\
2592627f7eb2Smrg    | OMP_CLAUSE_FROM | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT)
2593627f7eb2Smrg #define OMP_TEAMS_CLAUSES \
2594627f7eb2Smrg   (omp_mask (OMP_CLAUSE_NUM_TEAMS) | OMP_CLAUSE_THREAD_LIMIT		\
2595627f7eb2Smrg    | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE	\
2596627f7eb2Smrg    | OMP_CLAUSE_SHARED | OMP_CLAUSE_REDUCTION)
2597627f7eb2Smrg #define OMP_DISTRIBUTE_CLAUSES \
2598627f7eb2Smrg   (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE		\
2599627f7eb2Smrg    | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_DIST_SCHEDULE)
2600627f7eb2Smrg #define OMP_SINGLE_CLAUSES \
2601627f7eb2Smrg   (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE)
2602627f7eb2Smrg #define OMP_ORDERED_CLAUSES \
2603627f7eb2Smrg   (omp_mask (OMP_CLAUSE_THREADS) | OMP_CLAUSE_SIMD)
2604627f7eb2Smrg #define OMP_DECLARE_TARGET_CLAUSES \
2605627f7eb2Smrg   (omp_mask (OMP_CLAUSE_TO) | OMP_CLAUSE_LINK)
2606627f7eb2Smrg 
2607627f7eb2Smrg 
2608627f7eb2Smrg static match
match_omp(gfc_exec_op op,const omp_mask mask)2609627f7eb2Smrg match_omp (gfc_exec_op op, const omp_mask mask)
2610627f7eb2Smrg {
2611627f7eb2Smrg   gfc_omp_clauses *c;
2612627f7eb2Smrg   if (gfc_match_omp_clauses (&c, mask) != MATCH_YES)
2613627f7eb2Smrg     return MATCH_ERROR;
2614627f7eb2Smrg   new_st.op = op;
2615627f7eb2Smrg   new_st.ext.omp_clauses = c;
2616627f7eb2Smrg   return MATCH_YES;
2617627f7eb2Smrg }
2618627f7eb2Smrg 
2619627f7eb2Smrg 
2620627f7eb2Smrg match
gfc_match_omp_critical(void)2621627f7eb2Smrg gfc_match_omp_critical (void)
2622627f7eb2Smrg {
2623627f7eb2Smrg   char n[GFC_MAX_SYMBOL_LEN+1];
2624627f7eb2Smrg   gfc_omp_clauses *c = NULL;
2625627f7eb2Smrg 
2626627f7eb2Smrg   if (gfc_match (" ( %n )", n) != MATCH_YES)
2627627f7eb2Smrg     {
2628627f7eb2Smrg       n[0] = '\0';
2629627f7eb2Smrg       if (gfc_match_omp_eos () != MATCH_YES)
2630627f7eb2Smrg 	{
2631627f7eb2Smrg 	  gfc_error ("Unexpected junk after $OMP CRITICAL statement at %C");
2632627f7eb2Smrg 	  return MATCH_ERROR;
2633627f7eb2Smrg 	}
2634627f7eb2Smrg     }
2635627f7eb2Smrg   else if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_HINT)) != MATCH_YES)
2636627f7eb2Smrg     return MATCH_ERROR;
2637627f7eb2Smrg 
2638627f7eb2Smrg   new_st.op = EXEC_OMP_CRITICAL;
2639627f7eb2Smrg   new_st.ext.omp_clauses = c;
2640627f7eb2Smrg   if (n[0])
2641627f7eb2Smrg     c->critical_name = xstrdup (n);
2642627f7eb2Smrg   return MATCH_YES;
2643627f7eb2Smrg }
2644627f7eb2Smrg 
2645627f7eb2Smrg 
2646627f7eb2Smrg match
gfc_match_omp_end_critical(void)2647627f7eb2Smrg gfc_match_omp_end_critical (void)
2648627f7eb2Smrg {
2649627f7eb2Smrg   char n[GFC_MAX_SYMBOL_LEN+1];
2650627f7eb2Smrg 
2651627f7eb2Smrg   if (gfc_match (" ( %n )", n) != MATCH_YES)
2652627f7eb2Smrg     n[0] = '\0';
2653627f7eb2Smrg   if (gfc_match_omp_eos () != MATCH_YES)
2654627f7eb2Smrg     {
2655627f7eb2Smrg       gfc_error ("Unexpected junk after $OMP CRITICAL statement at %C");
2656627f7eb2Smrg       return MATCH_ERROR;
2657627f7eb2Smrg     }
2658627f7eb2Smrg 
2659627f7eb2Smrg   new_st.op = EXEC_OMP_END_CRITICAL;
2660627f7eb2Smrg   new_st.ext.omp_name = n[0] ? xstrdup (n) : NULL;
2661627f7eb2Smrg   return MATCH_YES;
2662627f7eb2Smrg }
2663627f7eb2Smrg 
2664627f7eb2Smrg 
2665627f7eb2Smrg match
gfc_match_omp_distribute(void)2666627f7eb2Smrg gfc_match_omp_distribute (void)
2667627f7eb2Smrg {
2668627f7eb2Smrg   return match_omp (EXEC_OMP_DISTRIBUTE, OMP_DISTRIBUTE_CLAUSES);
2669627f7eb2Smrg }
2670627f7eb2Smrg 
2671627f7eb2Smrg 
2672627f7eb2Smrg match
gfc_match_omp_distribute_parallel_do(void)2673627f7eb2Smrg gfc_match_omp_distribute_parallel_do (void)
2674627f7eb2Smrg {
2675627f7eb2Smrg   return match_omp (EXEC_OMP_DISTRIBUTE_PARALLEL_DO,
2676627f7eb2Smrg 		    (OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
2677627f7eb2Smrg 		     | OMP_DO_CLAUSES)
2678627f7eb2Smrg 		    & ~(omp_mask (OMP_CLAUSE_ORDERED))
2679627f7eb2Smrg 		    & ~(omp_mask (OMP_CLAUSE_LINEAR)));
2680627f7eb2Smrg }
2681627f7eb2Smrg 
2682627f7eb2Smrg 
2683627f7eb2Smrg match
gfc_match_omp_distribute_parallel_do_simd(void)2684627f7eb2Smrg gfc_match_omp_distribute_parallel_do_simd (void)
2685627f7eb2Smrg {
2686627f7eb2Smrg   return match_omp (EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD,
2687627f7eb2Smrg 		    (OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
2688627f7eb2Smrg 		     | OMP_DO_CLAUSES | OMP_SIMD_CLAUSES)
2689627f7eb2Smrg 		    & ~(omp_mask (OMP_CLAUSE_ORDERED)));
2690627f7eb2Smrg }
2691627f7eb2Smrg 
2692627f7eb2Smrg 
2693627f7eb2Smrg match
gfc_match_omp_distribute_simd(void)2694627f7eb2Smrg gfc_match_omp_distribute_simd (void)
2695627f7eb2Smrg {
2696627f7eb2Smrg   return match_omp (EXEC_OMP_DISTRIBUTE_SIMD,
2697627f7eb2Smrg 		    OMP_DISTRIBUTE_CLAUSES | OMP_SIMD_CLAUSES);
2698627f7eb2Smrg }
2699627f7eb2Smrg 
2700627f7eb2Smrg 
2701627f7eb2Smrg match
gfc_match_omp_do(void)2702627f7eb2Smrg gfc_match_omp_do (void)
2703627f7eb2Smrg {
2704627f7eb2Smrg   return match_omp (EXEC_OMP_DO, OMP_DO_CLAUSES);
2705627f7eb2Smrg }
2706627f7eb2Smrg 
2707627f7eb2Smrg 
2708627f7eb2Smrg match
gfc_match_omp_do_simd(void)2709627f7eb2Smrg gfc_match_omp_do_simd (void)
2710627f7eb2Smrg {
2711627f7eb2Smrg   return match_omp (EXEC_OMP_DO_SIMD, OMP_DO_CLAUSES | OMP_SIMD_CLAUSES);
2712627f7eb2Smrg }
2713627f7eb2Smrg 
2714627f7eb2Smrg 
2715627f7eb2Smrg match
gfc_match_omp_flush(void)2716627f7eb2Smrg gfc_match_omp_flush (void)
2717627f7eb2Smrg {
2718627f7eb2Smrg   gfc_omp_namelist *list = NULL;
2719627f7eb2Smrg   gfc_match_omp_variable_list (" (", &list, true);
2720627f7eb2Smrg   if (gfc_match_omp_eos () != MATCH_YES)
2721627f7eb2Smrg     {
2722627f7eb2Smrg       gfc_error ("Unexpected junk after $OMP FLUSH statement at %C");
2723627f7eb2Smrg       gfc_free_omp_namelist (list);
2724627f7eb2Smrg       return MATCH_ERROR;
2725627f7eb2Smrg     }
2726627f7eb2Smrg   new_st.op = EXEC_OMP_FLUSH;
2727627f7eb2Smrg   new_st.ext.omp_namelist = list;
2728627f7eb2Smrg   return MATCH_YES;
2729627f7eb2Smrg }
2730627f7eb2Smrg 
2731627f7eb2Smrg 
2732627f7eb2Smrg match
gfc_match_omp_declare_simd(void)2733627f7eb2Smrg gfc_match_omp_declare_simd (void)
2734627f7eb2Smrg {
2735627f7eb2Smrg   locus where = gfc_current_locus;
2736627f7eb2Smrg   gfc_symbol *proc_name;
2737627f7eb2Smrg   gfc_omp_clauses *c;
2738627f7eb2Smrg   gfc_omp_declare_simd *ods;
2739627f7eb2Smrg   bool needs_space = false;
2740627f7eb2Smrg 
2741627f7eb2Smrg   switch (gfc_match (" ( %s ) ", &proc_name))
2742627f7eb2Smrg     {
2743627f7eb2Smrg     case MATCH_YES: break;
2744627f7eb2Smrg     case MATCH_NO: proc_name = NULL; needs_space = true; break;
2745627f7eb2Smrg     case MATCH_ERROR: return MATCH_ERROR;
2746627f7eb2Smrg     }
2747627f7eb2Smrg 
2748627f7eb2Smrg   if (gfc_match_omp_clauses (&c, OMP_DECLARE_SIMD_CLAUSES, true,
2749627f7eb2Smrg 			     needs_space) != MATCH_YES)
2750627f7eb2Smrg     return MATCH_ERROR;
2751627f7eb2Smrg 
2752627f7eb2Smrg   if (gfc_current_ns->is_block_data)
2753627f7eb2Smrg     {
2754627f7eb2Smrg       gfc_free_omp_clauses (c);
2755627f7eb2Smrg       return MATCH_YES;
2756627f7eb2Smrg     }
2757627f7eb2Smrg 
2758627f7eb2Smrg   ods = gfc_get_omp_declare_simd ();
2759627f7eb2Smrg   ods->where = where;
2760627f7eb2Smrg   ods->proc_name = proc_name;
2761627f7eb2Smrg   ods->clauses = c;
2762627f7eb2Smrg   ods->next = gfc_current_ns->omp_declare_simd;
2763627f7eb2Smrg   gfc_current_ns->omp_declare_simd = ods;
2764627f7eb2Smrg   return MATCH_YES;
2765627f7eb2Smrg }
2766627f7eb2Smrg 
2767627f7eb2Smrg 
2768627f7eb2Smrg static bool
match_udr_expr(gfc_symtree * omp_sym1,gfc_symtree * omp_sym2)2769627f7eb2Smrg match_udr_expr (gfc_symtree *omp_sym1, gfc_symtree *omp_sym2)
2770627f7eb2Smrg {
2771627f7eb2Smrg   match m;
2772627f7eb2Smrg   locus old_loc = gfc_current_locus;
2773627f7eb2Smrg   char sname[GFC_MAX_SYMBOL_LEN + 1];
2774627f7eb2Smrg   gfc_symbol *sym;
2775627f7eb2Smrg   gfc_namespace *ns = gfc_current_ns;
2776627f7eb2Smrg   gfc_expr *lvalue = NULL, *rvalue = NULL;
2777627f7eb2Smrg   gfc_symtree *st;
2778627f7eb2Smrg   gfc_actual_arglist *arglist;
2779627f7eb2Smrg 
2780627f7eb2Smrg   m = gfc_match (" %v =", &lvalue);
2781627f7eb2Smrg   if (m != MATCH_YES)
2782627f7eb2Smrg     gfc_current_locus = old_loc;
2783627f7eb2Smrg   else
2784627f7eb2Smrg     {
2785627f7eb2Smrg       m = gfc_match (" %e )", &rvalue);
2786627f7eb2Smrg       if (m == MATCH_YES)
2787627f7eb2Smrg 	{
2788627f7eb2Smrg 	  ns->code = gfc_get_code (EXEC_ASSIGN);
2789627f7eb2Smrg 	  ns->code->expr1 = lvalue;
2790627f7eb2Smrg 	  ns->code->expr2 = rvalue;
2791627f7eb2Smrg 	  ns->code->loc = old_loc;
2792627f7eb2Smrg 	  return true;
2793627f7eb2Smrg 	}
2794627f7eb2Smrg 
2795627f7eb2Smrg       gfc_current_locus = old_loc;
2796627f7eb2Smrg       gfc_free_expr (lvalue);
2797627f7eb2Smrg     }
2798627f7eb2Smrg 
2799627f7eb2Smrg   m = gfc_match (" %n", sname);
2800627f7eb2Smrg   if (m != MATCH_YES)
2801627f7eb2Smrg     return false;
2802627f7eb2Smrg 
2803627f7eb2Smrg   if (strcmp (sname, omp_sym1->name) == 0
2804627f7eb2Smrg       || strcmp (sname, omp_sym2->name) == 0)
2805627f7eb2Smrg     return false;
2806627f7eb2Smrg 
2807627f7eb2Smrg   gfc_current_ns = ns->parent;
2808627f7eb2Smrg   if (gfc_get_ha_sym_tree (sname, &st))
2809627f7eb2Smrg     return false;
2810627f7eb2Smrg 
2811627f7eb2Smrg   sym = st->n.sym;
2812627f7eb2Smrg   if (sym->attr.flavor != FL_PROCEDURE
2813627f7eb2Smrg       && sym->attr.flavor != FL_UNKNOWN)
2814627f7eb2Smrg     return false;
2815627f7eb2Smrg 
2816627f7eb2Smrg   if (!sym->attr.generic
2817627f7eb2Smrg       && !sym->attr.subroutine
2818627f7eb2Smrg       && !sym->attr.function)
2819627f7eb2Smrg     {
2820627f7eb2Smrg       if (!(sym->attr.external && !sym->attr.referenced))
2821627f7eb2Smrg 	{
2822627f7eb2Smrg 	  /* ...create a symbol in this scope...  */
2823627f7eb2Smrg 	  if (sym->ns != gfc_current_ns
2824627f7eb2Smrg 	      && gfc_get_sym_tree (sname, NULL, &st, false) == 1)
2825627f7eb2Smrg 	    return false;
2826627f7eb2Smrg 
2827627f7eb2Smrg 	  if (sym != st->n.sym)
2828627f7eb2Smrg 	    sym = st->n.sym;
2829627f7eb2Smrg 	}
2830627f7eb2Smrg 
2831627f7eb2Smrg       /* ...and then to try to make the symbol into a subroutine.  */
2832627f7eb2Smrg       if (!gfc_add_subroutine (&sym->attr, sym->name, NULL))
2833627f7eb2Smrg 	return false;
2834627f7eb2Smrg     }
2835627f7eb2Smrg 
2836627f7eb2Smrg   gfc_set_sym_referenced (sym);
2837627f7eb2Smrg   gfc_gobble_whitespace ();
2838627f7eb2Smrg   if (gfc_peek_ascii_char () != '(')
2839627f7eb2Smrg     return false;
2840627f7eb2Smrg 
2841627f7eb2Smrg   gfc_current_ns = ns;
2842627f7eb2Smrg   m = gfc_match_actual_arglist (1, &arglist);
2843627f7eb2Smrg   if (m != MATCH_YES)
2844627f7eb2Smrg     return false;
2845627f7eb2Smrg 
2846627f7eb2Smrg   if (gfc_match_char (')') != MATCH_YES)
2847627f7eb2Smrg     return false;
2848627f7eb2Smrg 
2849627f7eb2Smrg   ns->code = gfc_get_code (EXEC_CALL);
2850627f7eb2Smrg   ns->code->symtree = st;
2851627f7eb2Smrg   ns->code->ext.actual = arglist;
2852627f7eb2Smrg   ns->code->loc = old_loc;
2853627f7eb2Smrg   return true;
2854627f7eb2Smrg }
2855627f7eb2Smrg 
2856627f7eb2Smrg static bool
gfc_omp_udr_predef(gfc_omp_reduction_op rop,const char * name,gfc_typespec * ts,const char ** n)2857627f7eb2Smrg gfc_omp_udr_predef (gfc_omp_reduction_op rop, const char *name,
2858627f7eb2Smrg 		    gfc_typespec *ts, const char **n)
2859627f7eb2Smrg {
2860627f7eb2Smrg   if (!gfc_numeric_ts (ts) && ts->type != BT_LOGICAL)
2861627f7eb2Smrg     return false;
2862627f7eb2Smrg 
2863627f7eb2Smrg   switch (rop)
2864627f7eb2Smrg     {
2865627f7eb2Smrg     case OMP_REDUCTION_PLUS:
2866627f7eb2Smrg     case OMP_REDUCTION_MINUS:
2867627f7eb2Smrg     case OMP_REDUCTION_TIMES:
2868627f7eb2Smrg       return ts->type != BT_LOGICAL;
2869627f7eb2Smrg     case OMP_REDUCTION_AND:
2870627f7eb2Smrg     case OMP_REDUCTION_OR:
2871627f7eb2Smrg     case OMP_REDUCTION_EQV:
2872627f7eb2Smrg     case OMP_REDUCTION_NEQV:
2873627f7eb2Smrg       return ts->type == BT_LOGICAL;
2874627f7eb2Smrg     case OMP_REDUCTION_USER:
2875627f7eb2Smrg       if (name[0] != '.' && (ts->type == BT_INTEGER || ts->type == BT_REAL))
2876627f7eb2Smrg 	{
2877627f7eb2Smrg 	  gfc_symbol *sym;
2878627f7eb2Smrg 
2879627f7eb2Smrg 	  gfc_find_symbol (name, NULL, 1, &sym);
2880627f7eb2Smrg 	  if (sym != NULL)
2881627f7eb2Smrg 	    {
2882627f7eb2Smrg 	      if (sym->attr.intrinsic)
2883627f7eb2Smrg 		*n = sym->name;
2884627f7eb2Smrg 	      else if ((sym->attr.flavor != FL_UNKNOWN
2885627f7eb2Smrg 			&& sym->attr.flavor != FL_PROCEDURE)
2886627f7eb2Smrg 		       || sym->attr.external
2887627f7eb2Smrg 		       || sym->attr.generic
2888627f7eb2Smrg 		       || sym->attr.entry
2889627f7eb2Smrg 		       || sym->attr.result
2890627f7eb2Smrg 		       || sym->attr.dummy
2891627f7eb2Smrg 		       || sym->attr.subroutine
2892627f7eb2Smrg 		       || sym->attr.pointer
2893627f7eb2Smrg 		       || sym->attr.target
2894627f7eb2Smrg 		       || sym->attr.cray_pointer
2895627f7eb2Smrg 		       || sym->attr.cray_pointee
2896627f7eb2Smrg 		       || (sym->attr.proc != PROC_UNKNOWN
2897627f7eb2Smrg 			   && sym->attr.proc != PROC_INTRINSIC)
2898627f7eb2Smrg 		       || sym->attr.if_source != IFSRC_UNKNOWN
2899627f7eb2Smrg 		       || sym == sym->ns->proc_name)
2900627f7eb2Smrg 		*n = NULL;
2901627f7eb2Smrg 	      else
2902627f7eb2Smrg 		*n = sym->name;
2903627f7eb2Smrg 	    }
2904627f7eb2Smrg 	  else
2905627f7eb2Smrg 	    *n = name;
2906627f7eb2Smrg 	  if (*n
2907627f7eb2Smrg 	      && (strcmp (*n, "max") == 0 || strcmp (*n, "min") == 0))
2908627f7eb2Smrg 	    return true;
2909627f7eb2Smrg 	  else if (*n
2910627f7eb2Smrg 		   && ts->type == BT_INTEGER
2911627f7eb2Smrg 		   && (strcmp (*n, "iand") == 0
2912627f7eb2Smrg 		       || strcmp (*n, "ior") == 0
2913627f7eb2Smrg 		       || strcmp (*n, "ieor") == 0))
2914627f7eb2Smrg 	    return true;
2915627f7eb2Smrg 	}
2916627f7eb2Smrg       break;
2917627f7eb2Smrg     default:
2918627f7eb2Smrg       break;
2919627f7eb2Smrg     }
2920627f7eb2Smrg   return false;
2921627f7eb2Smrg }
2922627f7eb2Smrg 
2923627f7eb2Smrg gfc_omp_udr *
gfc_omp_udr_find(gfc_symtree * st,gfc_typespec * ts)2924627f7eb2Smrg gfc_omp_udr_find (gfc_symtree *st, gfc_typespec *ts)
2925627f7eb2Smrg {
2926627f7eb2Smrg   gfc_omp_udr *omp_udr;
2927627f7eb2Smrg 
2928627f7eb2Smrg   if (st == NULL)
2929627f7eb2Smrg     return NULL;
2930627f7eb2Smrg 
2931627f7eb2Smrg   for (omp_udr = st->n.omp_udr; omp_udr; omp_udr = omp_udr->next)
2932627f7eb2Smrg     if (omp_udr->ts.type == ts->type
2933627f7eb2Smrg 	|| ((omp_udr->ts.type == BT_DERIVED || omp_udr->ts.type == BT_CLASS)
2934627f7eb2Smrg 	    && (ts->type == BT_DERIVED || ts->type == BT_CLASS)))
2935627f7eb2Smrg       {
2936627f7eb2Smrg 	if (omp_udr->ts.type == BT_DERIVED || omp_udr->ts.type == BT_CLASS)
2937627f7eb2Smrg 	  {
2938627f7eb2Smrg 	    if (strcmp (omp_udr->ts.u.derived->name, ts->u.derived->name) == 0)
2939627f7eb2Smrg 	      return omp_udr;
2940627f7eb2Smrg 	  }
2941627f7eb2Smrg 	else if (omp_udr->ts.kind == ts->kind)
2942627f7eb2Smrg 	  {
2943627f7eb2Smrg 	    if (omp_udr->ts.type == BT_CHARACTER)
2944627f7eb2Smrg 	      {
2945627f7eb2Smrg 		if (omp_udr->ts.u.cl->length == NULL
2946627f7eb2Smrg 		    || ts->u.cl->length == NULL)
2947627f7eb2Smrg 		  return omp_udr;
2948627f7eb2Smrg 		if (omp_udr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
2949627f7eb2Smrg 		  return omp_udr;
2950627f7eb2Smrg 		if (ts->u.cl->length->expr_type != EXPR_CONSTANT)
2951627f7eb2Smrg 		  return omp_udr;
2952627f7eb2Smrg 		if (omp_udr->ts.u.cl->length->ts.type != BT_INTEGER)
2953627f7eb2Smrg 		  return omp_udr;
2954627f7eb2Smrg 		if (ts->u.cl->length->ts.type != BT_INTEGER)
2955627f7eb2Smrg 		  return omp_udr;
2956627f7eb2Smrg 		if (gfc_compare_expr (omp_udr->ts.u.cl->length,
2957627f7eb2Smrg 				      ts->u.cl->length, INTRINSIC_EQ) != 0)
2958627f7eb2Smrg 		  continue;
2959627f7eb2Smrg 	      }
2960627f7eb2Smrg 	    return omp_udr;
2961627f7eb2Smrg 	  }
2962627f7eb2Smrg       }
2963627f7eb2Smrg   return NULL;
2964627f7eb2Smrg }
2965627f7eb2Smrg 
2966627f7eb2Smrg match
gfc_match_omp_declare_reduction(void)2967627f7eb2Smrg gfc_match_omp_declare_reduction (void)
2968627f7eb2Smrg {
2969627f7eb2Smrg   match m;
2970627f7eb2Smrg   gfc_intrinsic_op op;
2971627f7eb2Smrg   char name[GFC_MAX_SYMBOL_LEN + 3];
2972627f7eb2Smrg   auto_vec<gfc_typespec, 5> tss;
2973627f7eb2Smrg   gfc_typespec ts;
2974627f7eb2Smrg   unsigned int i;
2975627f7eb2Smrg   gfc_symtree *st;
2976627f7eb2Smrg   locus where = gfc_current_locus;
2977627f7eb2Smrg   locus end_loc = gfc_current_locus;
2978627f7eb2Smrg   bool end_loc_set = false;
2979627f7eb2Smrg   gfc_omp_reduction_op rop = OMP_REDUCTION_NONE;
2980627f7eb2Smrg 
2981627f7eb2Smrg   if (gfc_match_char ('(') != MATCH_YES)
2982627f7eb2Smrg     return MATCH_ERROR;
2983627f7eb2Smrg 
2984627f7eb2Smrg   m = gfc_match (" %o : ", &op);
2985627f7eb2Smrg   if (m == MATCH_ERROR)
2986627f7eb2Smrg     return MATCH_ERROR;
2987627f7eb2Smrg   if (m == MATCH_YES)
2988627f7eb2Smrg     {
2989627f7eb2Smrg       snprintf (name, sizeof name, "operator %s", gfc_op2string (op));
2990627f7eb2Smrg       rop = (gfc_omp_reduction_op) op;
2991627f7eb2Smrg     }
2992627f7eb2Smrg   else
2993627f7eb2Smrg     {
2994627f7eb2Smrg       m = gfc_match_defined_op_name (name + 1, 1);
2995627f7eb2Smrg       if (m == MATCH_ERROR)
2996627f7eb2Smrg 	return MATCH_ERROR;
2997627f7eb2Smrg       if (m == MATCH_YES)
2998627f7eb2Smrg 	{
2999627f7eb2Smrg 	  name[0] = '.';
3000627f7eb2Smrg 	  strcat (name, ".");
3001627f7eb2Smrg 	  if (gfc_match (" : ") != MATCH_YES)
3002627f7eb2Smrg 	    return MATCH_ERROR;
3003627f7eb2Smrg 	}
3004627f7eb2Smrg       else
3005627f7eb2Smrg 	{
3006627f7eb2Smrg 	  if (gfc_match (" %n : ", name) != MATCH_YES)
3007627f7eb2Smrg 	    return MATCH_ERROR;
3008627f7eb2Smrg 	}
3009627f7eb2Smrg       rop = OMP_REDUCTION_USER;
3010627f7eb2Smrg     }
3011627f7eb2Smrg 
3012627f7eb2Smrg   m = gfc_match_type_spec (&ts);
3013627f7eb2Smrg   if (m != MATCH_YES)
3014627f7eb2Smrg     return MATCH_ERROR;
3015627f7eb2Smrg   /* Treat len=: the same as len=*.  */
3016627f7eb2Smrg   if (ts.type == BT_CHARACTER)
3017627f7eb2Smrg     ts.deferred = false;
3018627f7eb2Smrg   tss.safe_push (ts);
3019627f7eb2Smrg 
3020627f7eb2Smrg   while (gfc_match_char (',') == MATCH_YES)
3021627f7eb2Smrg     {
3022627f7eb2Smrg       m = gfc_match_type_spec (&ts);
3023627f7eb2Smrg       if (m != MATCH_YES)
3024627f7eb2Smrg 	return MATCH_ERROR;
3025627f7eb2Smrg       tss.safe_push (ts);
3026627f7eb2Smrg     }
3027627f7eb2Smrg   if (gfc_match_char (':') != MATCH_YES)
3028627f7eb2Smrg     return MATCH_ERROR;
3029627f7eb2Smrg 
3030627f7eb2Smrg   st = gfc_find_symtree (gfc_current_ns->omp_udr_root, name);
3031627f7eb2Smrg   for (i = 0; i < tss.length (); i++)
3032627f7eb2Smrg     {
3033627f7eb2Smrg       gfc_symtree *omp_out, *omp_in;
3034627f7eb2Smrg       gfc_symtree *omp_priv = NULL, *omp_orig = NULL;
3035627f7eb2Smrg       gfc_namespace *combiner_ns, *initializer_ns = NULL;
3036627f7eb2Smrg       gfc_omp_udr *prev_udr, *omp_udr;
3037627f7eb2Smrg       const char *predef_name = NULL;
3038627f7eb2Smrg 
3039627f7eb2Smrg       omp_udr = gfc_get_omp_udr ();
3040627f7eb2Smrg       omp_udr->name = gfc_get_string ("%s", name);
3041627f7eb2Smrg       omp_udr->rop = rop;
3042627f7eb2Smrg       omp_udr->ts = tss[i];
3043627f7eb2Smrg       omp_udr->where = where;
3044627f7eb2Smrg 
3045627f7eb2Smrg       gfc_current_ns = combiner_ns = gfc_get_namespace (gfc_current_ns, 1);
3046627f7eb2Smrg       combiner_ns->proc_name = combiner_ns->parent->proc_name;
3047627f7eb2Smrg 
3048627f7eb2Smrg       gfc_get_sym_tree ("omp_out", combiner_ns, &omp_out, false);
3049627f7eb2Smrg       gfc_get_sym_tree ("omp_in", combiner_ns, &omp_in, false);
3050627f7eb2Smrg       combiner_ns->omp_udr_ns = 1;
3051627f7eb2Smrg       omp_out->n.sym->ts = tss[i];
3052627f7eb2Smrg       omp_in->n.sym->ts = tss[i];
3053627f7eb2Smrg       omp_out->n.sym->attr.omp_udr_artificial_var = 1;
3054627f7eb2Smrg       omp_in->n.sym->attr.omp_udr_artificial_var = 1;
3055627f7eb2Smrg       omp_out->n.sym->attr.flavor = FL_VARIABLE;
3056627f7eb2Smrg       omp_in->n.sym->attr.flavor = FL_VARIABLE;
3057627f7eb2Smrg       gfc_commit_symbols ();
3058627f7eb2Smrg       omp_udr->combiner_ns = combiner_ns;
3059627f7eb2Smrg       omp_udr->omp_out = omp_out->n.sym;
3060627f7eb2Smrg       omp_udr->omp_in = omp_in->n.sym;
3061627f7eb2Smrg 
3062627f7eb2Smrg       locus old_loc = gfc_current_locus;
3063627f7eb2Smrg 
3064627f7eb2Smrg       if (!match_udr_expr (omp_out, omp_in))
3065627f7eb2Smrg 	{
3066627f7eb2Smrg 	 syntax:
3067627f7eb2Smrg 	  gfc_current_locus = old_loc;
3068627f7eb2Smrg 	  gfc_current_ns = combiner_ns->parent;
3069627f7eb2Smrg 	  gfc_undo_symbols ();
3070627f7eb2Smrg 	  gfc_free_omp_udr (omp_udr);
3071627f7eb2Smrg 	  return MATCH_ERROR;
3072627f7eb2Smrg 	}
3073627f7eb2Smrg 
3074627f7eb2Smrg       if (gfc_match (" initializer ( ") == MATCH_YES)
3075627f7eb2Smrg 	{
3076627f7eb2Smrg 	  gfc_current_ns = combiner_ns->parent;
3077627f7eb2Smrg 	  initializer_ns = gfc_get_namespace (gfc_current_ns, 1);
3078627f7eb2Smrg 	  gfc_current_ns = initializer_ns;
3079627f7eb2Smrg 	  initializer_ns->proc_name = initializer_ns->parent->proc_name;
3080627f7eb2Smrg 
3081627f7eb2Smrg 	  gfc_get_sym_tree ("omp_priv", initializer_ns, &omp_priv, false);
3082627f7eb2Smrg 	  gfc_get_sym_tree ("omp_orig", initializer_ns, &omp_orig, false);
3083627f7eb2Smrg 	  initializer_ns->omp_udr_ns = 1;
3084627f7eb2Smrg 	  omp_priv->n.sym->ts = tss[i];
3085627f7eb2Smrg 	  omp_orig->n.sym->ts = tss[i];
3086627f7eb2Smrg 	  omp_priv->n.sym->attr.omp_udr_artificial_var = 1;
3087627f7eb2Smrg 	  omp_orig->n.sym->attr.omp_udr_artificial_var = 1;
3088627f7eb2Smrg 	  omp_priv->n.sym->attr.flavor = FL_VARIABLE;
3089627f7eb2Smrg 	  omp_orig->n.sym->attr.flavor = FL_VARIABLE;
3090627f7eb2Smrg 	  gfc_commit_symbols ();
3091627f7eb2Smrg 	  omp_udr->initializer_ns = initializer_ns;
3092627f7eb2Smrg 	  omp_udr->omp_priv = omp_priv->n.sym;
3093627f7eb2Smrg 	  omp_udr->omp_orig = omp_orig->n.sym;
3094627f7eb2Smrg 
3095627f7eb2Smrg 	  if (!match_udr_expr (omp_priv, omp_orig))
3096627f7eb2Smrg 	    goto syntax;
3097627f7eb2Smrg 	}
3098627f7eb2Smrg 
3099627f7eb2Smrg       gfc_current_ns = combiner_ns->parent;
3100627f7eb2Smrg       if (!end_loc_set)
3101627f7eb2Smrg 	{
3102627f7eb2Smrg 	  end_loc_set = true;
3103627f7eb2Smrg 	  end_loc = gfc_current_locus;
3104627f7eb2Smrg 	}
3105627f7eb2Smrg       gfc_current_locus = old_loc;
3106627f7eb2Smrg 
3107627f7eb2Smrg       prev_udr = gfc_omp_udr_find (st, &tss[i]);
3108627f7eb2Smrg       if (gfc_omp_udr_predef (rop, name, &tss[i], &predef_name)
3109627f7eb2Smrg 	  /* Don't error on !$omp declare reduction (min : integer : ...)
3110627f7eb2Smrg 	     just yet, there could be integer :: min afterwards,
3111627f7eb2Smrg 	     making it valid.  When the UDR is resolved, we'll get
3112627f7eb2Smrg 	     to it again.  */
3113627f7eb2Smrg 	  && (rop != OMP_REDUCTION_USER || name[0] == '.'))
3114627f7eb2Smrg 	{
3115627f7eb2Smrg 	  if (predef_name)
3116627f7eb2Smrg 	    gfc_error_now ("Redefinition of predefined %s "
3117627f7eb2Smrg 			   "!$OMP DECLARE REDUCTION at %L",
3118627f7eb2Smrg 			   predef_name, &where);
3119627f7eb2Smrg 	  else
3120627f7eb2Smrg 	    gfc_error_now ("Redefinition of predefined "
3121627f7eb2Smrg 			   "!$OMP DECLARE REDUCTION at %L", &where);
3122627f7eb2Smrg 	}
3123627f7eb2Smrg       else if (prev_udr)
3124627f7eb2Smrg 	{
3125627f7eb2Smrg 	  gfc_error_now ("Redefinition of !$OMP DECLARE REDUCTION at %L",
3126627f7eb2Smrg 			 &where);
3127627f7eb2Smrg 	  gfc_error_now ("Previous !$OMP DECLARE REDUCTION at %L",
3128627f7eb2Smrg 			 &prev_udr->where);
3129627f7eb2Smrg 	}
3130627f7eb2Smrg       else if (st)
3131627f7eb2Smrg 	{
3132627f7eb2Smrg 	  omp_udr->next = st->n.omp_udr;
3133627f7eb2Smrg 	  st->n.omp_udr = omp_udr;
3134627f7eb2Smrg 	}
3135627f7eb2Smrg       else
3136627f7eb2Smrg 	{
3137627f7eb2Smrg 	  st = gfc_new_symtree (&gfc_current_ns->omp_udr_root, name);
3138627f7eb2Smrg 	  st->n.omp_udr = omp_udr;
3139627f7eb2Smrg 	}
3140627f7eb2Smrg     }
3141627f7eb2Smrg 
3142627f7eb2Smrg   if (end_loc_set)
3143627f7eb2Smrg     {
3144627f7eb2Smrg       gfc_current_locus = end_loc;
3145627f7eb2Smrg       if (gfc_match_omp_eos () != MATCH_YES)
3146627f7eb2Smrg 	{
3147627f7eb2Smrg 	  gfc_error ("Unexpected junk after !$OMP DECLARE REDUCTION at %C");
3148627f7eb2Smrg 	  gfc_current_locus = where;
3149627f7eb2Smrg 	  return MATCH_ERROR;
3150627f7eb2Smrg 	}
3151627f7eb2Smrg 
3152627f7eb2Smrg       return MATCH_YES;
3153627f7eb2Smrg     }
3154627f7eb2Smrg   gfc_clear_error ();
3155627f7eb2Smrg   return MATCH_ERROR;
3156627f7eb2Smrg }
3157627f7eb2Smrg 
3158627f7eb2Smrg 
3159627f7eb2Smrg match
gfc_match_omp_declare_target(void)3160627f7eb2Smrg gfc_match_omp_declare_target (void)
3161627f7eb2Smrg {
3162627f7eb2Smrg   locus old_loc;
3163627f7eb2Smrg   match m;
3164627f7eb2Smrg   gfc_omp_clauses *c = NULL;
3165627f7eb2Smrg   int list;
3166627f7eb2Smrg   gfc_omp_namelist *n;
3167627f7eb2Smrg   gfc_symbol *s;
3168627f7eb2Smrg 
3169627f7eb2Smrg   old_loc = gfc_current_locus;
3170627f7eb2Smrg 
3171627f7eb2Smrg   if (gfc_current_ns->proc_name
3172627f7eb2Smrg       && gfc_match_omp_eos () == MATCH_YES)
3173627f7eb2Smrg     {
3174627f7eb2Smrg       if (!gfc_add_omp_declare_target (&gfc_current_ns->proc_name->attr,
3175627f7eb2Smrg 				       gfc_current_ns->proc_name->name,
3176627f7eb2Smrg 				       &old_loc))
3177627f7eb2Smrg 	goto cleanup;
3178627f7eb2Smrg       return MATCH_YES;
3179627f7eb2Smrg     }
3180627f7eb2Smrg 
3181627f7eb2Smrg   if (gfc_current_ns->proc_name
3182627f7eb2Smrg       && gfc_current_ns->proc_name->attr.if_source == IFSRC_IFBODY)
3183627f7eb2Smrg     {
3184627f7eb2Smrg       gfc_error ("Only the !$OMP DECLARE TARGET form without "
3185627f7eb2Smrg 		 "clauses is allowed in interface block at %C");
3186627f7eb2Smrg       goto cleanup;
3187627f7eb2Smrg     }
3188627f7eb2Smrg 
3189627f7eb2Smrg   m = gfc_match (" (");
3190627f7eb2Smrg   if (m == MATCH_YES)
3191627f7eb2Smrg     {
3192627f7eb2Smrg       c = gfc_get_omp_clauses ();
3193627f7eb2Smrg       gfc_current_locus = old_loc;
3194627f7eb2Smrg       m = gfc_match_omp_to_link (" (", &c->lists[OMP_LIST_TO]);
3195627f7eb2Smrg       if (m != MATCH_YES)
3196627f7eb2Smrg 	goto syntax;
3197627f7eb2Smrg       if (gfc_match_omp_eos () != MATCH_YES)
3198627f7eb2Smrg 	{
3199627f7eb2Smrg 	  gfc_error ("Unexpected junk after !$OMP DECLARE TARGET at %C");
3200627f7eb2Smrg 	  goto cleanup;
3201627f7eb2Smrg 	}
3202627f7eb2Smrg     }
3203627f7eb2Smrg   else if (gfc_match_omp_clauses (&c, OMP_DECLARE_TARGET_CLAUSES) != MATCH_YES)
3204627f7eb2Smrg     return MATCH_ERROR;
3205627f7eb2Smrg 
3206627f7eb2Smrg   gfc_buffer_error (false);
3207627f7eb2Smrg 
3208627f7eb2Smrg   for (list = OMP_LIST_TO; list != OMP_LIST_NUM;
3209627f7eb2Smrg        list = (list == OMP_LIST_TO ? OMP_LIST_LINK : OMP_LIST_NUM))
3210627f7eb2Smrg     for (n = c->lists[list]; n; n = n->next)
3211627f7eb2Smrg       if (n->sym)
3212627f7eb2Smrg 	n->sym->mark = 0;
3213627f7eb2Smrg       else if (n->u.common->head)
3214627f7eb2Smrg 	n->u.common->head->mark = 0;
3215627f7eb2Smrg 
3216627f7eb2Smrg   for (list = OMP_LIST_TO; list != OMP_LIST_NUM;
3217627f7eb2Smrg        list = (list == OMP_LIST_TO ? OMP_LIST_LINK : OMP_LIST_NUM))
3218627f7eb2Smrg     for (n = c->lists[list]; n; n = n->next)
3219627f7eb2Smrg       if (n->sym)
3220627f7eb2Smrg 	{
3221627f7eb2Smrg 	  if (n->sym->attr.in_common)
3222627f7eb2Smrg 	    gfc_error_now ("OMP DECLARE TARGET variable at %L is an "
3223627f7eb2Smrg 			   "element of a COMMON block", &n->where);
3224627f7eb2Smrg 	  else if (n->sym->attr.omp_declare_target
3225627f7eb2Smrg 		   && n->sym->attr.omp_declare_target_link
3226627f7eb2Smrg 		   && list != OMP_LIST_LINK)
3227627f7eb2Smrg 	    gfc_error_now ("OMP DECLARE TARGET variable at %L previously "
3228627f7eb2Smrg 			   "mentioned in LINK clause and later in TO clause",
3229627f7eb2Smrg 			   &n->where);
3230627f7eb2Smrg 	  else if (n->sym->attr.omp_declare_target
3231627f7eb2Smrg 		   && !n->sym->attr.omp_declare_target_link
3232627f7eb2Smrg 		   && list == OMP_LIST_LINK)
3233627f7eb2Smrg 	    gfc_error_now ("OMP DECLARE TARGET variable at %L previously "
3234627f7eb2Smrg 			   "mentioned in TO clause and later in LINK clause",
3235627f7eb2Smrg 			   &n->where);
3236627f7eb2Smrg 	  else if (n->sym->mark)
3237627f7eb2Smrg 	    gfc_error_now ("Variable at %L mentioned multiple times in "
3238627f7eb2Smrg 			   "clauses of the same OMP DECLARE TARGET directive",
3239627f7eb2Smrg 			   &n->where);
3240627f7eb2Smrg 	  else if (gfc_add_omp_declare_target (&n->sym->attr, n->sym->name,
3241627f7eb2Smrg 					       &n->sym->declared_at))
3242627f7eb2Smrg 	    {
3243627f7eb2Smrg 	      if (list == OMP_LIST_LINK)
3244627f7eb2Smrg 		gfc_add_omp_declare_target_link (&n->sym->attr, n->sym->name,
3245627f7eb2Smrg 						 &n->sym->declared_at);
3246627f7eb2Smrg 	    }
3247627f7eb2Smrg 	  n->sym->mark = 1;
3248627f7eb2Smrg 	}
3249627f7eb2Smrg       else if (n->u.common->omp_declare_target
3250627f7eb2Smrg 	       && n->u.common->omp_declare_target_link
3251627f7eb2Smrg 	       && list != OMP_LIST_LINK)
3252627f7eb2Smrg 	gfc_error_now ("OMP DECLARE TARGET COMMON at %L previously "
3253627f7eb2Smrg 		       "mentioned in LINK clause and later in TO clause",
3254627f7eb2Smrg 		       &n->where);
3255627f7eb2Smrg       else if (n->u.common->omp_declare_target
3256627f7eb2Smrg 	       && !n->u.common->omp_declare_target_link
3257627f7eb2Smrg 	       && list == OMP_LIST_LINK)
3258627f7eb2Smrg 	gfc_error_now ("OMP DECLARE TARGET COMMON at %L previously "
3259627f7eb2Smrg 		       "mentioned in TO clause and later in LINK clause",
3260627f7eb2Smrg 		       &n->where);
3261627f7eb2Smrg       else if (n->u.common->head && n->u.common->head->mark)
3262627f7eb2Smrg 	gfc_error_now ("COMMON at %L mentioned multiple times in "
3263627f7eb2Smrg 		       "clauses of the same OMP DECLARE TARGET directive",
3264627f7eb2Smrg 		       &n->where);
3265627f7eb2Smrg       else
3266627f7eb2Smrg 	{
3267627f7eb2Smrg 	  n->u.common->omp_declare_target = 1;
3268627f7eb2Smrg 	  n->u.common->omp_declare_target_link = (list == OMP_LIST_LINK);
3269627f7eb2Smrg 	  for (s = n->u.common->head; s; s = s->common_next)
3270627f7eb2Smrg 	    {
3271627f7eb2Smrg 	      s->mark = 1;
3272627f7eb2Smrg 	      if (gfc_add_omp_declare_target (&s->attr, s->name,
3273627f7eb2Smrg 					      &s->declared_at))
3274627f7eb2Smrg 		{
3275627f7eb2Smrg 		  if (list == OMP_LIST_LINK)
3276627f7eb2Smrg 		    gfc_add_omp_declare_target_link (&s->attr, s->name,
3277627f7eb2Smrg 						     &s->declared_at);
3278627f7eb2Smrg 		}
3279627f7eb2Smrg 	    }
3280627f7eb2Smrg 	}
3281627f7eb2Smrg 
3282627f7eb2Smrg   gfc_buffer_error (true);
3283627f7eb2Smrg 
3284627f7eb2Smrg   if (c)
3285627f7eb2Smrg     gfc_free_omp_clauses (c);
3286627f7eb2Smrg   return MATCH_YES;
3287627f7eb2Smrg 
3288627f7eb2Smrg syntax:
3289627f7eb2Smrg   gfc_error ("Syntax error in !$OMP DECLARE TARGET list at %C");
3290627f7eb2Smrg 
3291627f7eb2Smrg cleanup:
3292627f7eb2Smrg   gfc_current_locus = old_loc;
3293627f7eb2Smrg   if (c)
3294627f7eb2Smrg     gfc_free_omp_clauses (c);
3295627f7eb2Smrg   return MATCH_ERROR;
3296627f7eb2Smrg }
3297627f7eb2Smrg 
3298627f7eb2Smrg 
3299627f7eb2Smrg match
gfc_match_omp_threadprivate(void)3300627f7eb2Smrg gfc_match_omp_threadprivate (void)
3301627f7eb2Smrg {
3302627f7eb2Smrg   locus old_loc;
3303627f7eb2Smrg   char n[GFC_MAX_SYMBOL_LEN+1];
3304627f7eb2Smrg   gfc_symbol *sym;
3305627f7eb2Smrg   match m;
3306627f7eb2Smrg   gfc_symtree *st;
3307627f7eb2Smrg 
3308627f7eb2Smrg   old_loc = gfc_current_locus;
3309627f7eb2Smrg 
3310627f7eb2Smrg   m = gfc_match (" (");
3311627f7eb2Smrg   if (m != MATCH_YES)
3312627f7eb2Smrg     return m;
3313627f7eb2Smrg 
3314627f7eb2Smrg   for (;;)
3315627f7eb2Smrg     {
3316627f7eb2Smrg       m = gfc_match_symbol (&sym, 0);
3317627f7eb2Smrg       switch (m)
3318627f7eb2Smrg 	{
3319627f7eb2Smrg 	case MATCH_YES:
3320627f7eb2Smrg 	  if (sym->attr.in_common)
3321627f7eb2Smrg 	    gfc_error_now ("Threadprivate variable at %C is an element of "
3322627f7eb2Smrg 			   "a COMMON block");
3323627f7eb2Smrg 	  else if (!gfc_add_threadprivate (&sym->attr, sym->name, &sym->declared_at))
3324627f7eb2Smrg 	    goto cleanup;
3325627f7eb2Smrg 	  goto next_item;
3326627f7eb2Smrg 	case MATCH_NO:
3327627f7eb2Smrg 	  break;
3328627f7eb2Smrg 	case MATCH_ERROR:
3329627f7eb2Smrg 	  goto cleanup;
3330627f7eb2Smrg 	}
3331627f7eb2Smrg 
3332627f7eb2Smrg       m = gfc_match (" / %n /", n);
3333627f7eb2Smrg       if (m == MATCH_ERROR)
3334627f7eb2Smrg 	goto cleanup;
3335627f7eb2Smrg       if (m == MATCH_NO || n[0] == '\0')
3336627f7eb2Smrg 	goto syntax;
3337627f7eb2Smrg 
3338627f7eb2Smrg       st = gfc_find_symtree (gfc_current_ns->common_root, n);
3339627f7eb2Smrg       if (st == NULL)
3340627f7eb2Smrg 	{
3341627f7eb2Smrg 	  gfc_error ("COMMON block /%s/ not found at %C", n);
3342627f7eb2Smrg 	  goto cleanup;
3343627f7eb2Smrg 	}
3344627f7eb2Smrg       st->n.common->threadprivate = 1;
3345627f7eb2Smrg       for (sym = st->n.common->head; sym; sym = sym->common_next)
3346627f7eb2Smrg 	if (!gfc_add_threadprivate (&sym->attr, sym->name, &sym->declared_at))
3347627f7eb2Smrg 	  goto cleanup;
3348627f7eb2Smrg 
3349627f7eb2Smrg     next_item:
3350627f7eb2Smrg       if (gfc_match_char (')') == MATCH_YES)
3351627f7eb2Smrg 	break;
3352627f7eb2Smrg       if (gfc_match_char (',') != MATCH_YES)
3353627f7eb2Smrg 	goto syntax;
3354627f7eb2Smrg     }
3355627f7eb2Smrg 
3356627f7eb2Smrg   if (gfc_match_omp_eos () != MATCH_YES)
3357627f7eb2Smrg     {
3358627f7eb2Smrg       gfc_error ("Unexpected junk after OMP THREADPRIVATE at %C");
3359627f7eb2Smrg       goto cleanup;
3360627f7eb2Smrg     }
3361627f7eb2Smrg 
3362627f7eb2Smrg   return MATCH_YES;
3363627f7eb2Smrg 
3364627f7eb2Smrg syntax:
3365627f7eb2Smrg   gfc_error ("Syntax error in !$OMP THREADPRIVATE list at %C");
3366627f7eb2Smrg 
3367627f7eb2Smrg cleanup:
3368627f7eb2Smrg   gfc_current_locus = old_loc;
3369627f7eb2Smrg   return MATCH_ERROR;
3370627f7eb2Smrg }
3371627f7eb2Smrg 
3372627f7eb2Smrg 
3373627f7eb2Smrg match
gfc_match_omp_parallel(void)3374627f7eb2Smrg gfc_match_omp_parallel (void)
3375627f7eb2Smrg {
3376627f7eb2Smrg   return match_omp (EXEC_OMP_PARALLEL, OMP_PARALLEL_CLAUSES);
3377627f7eb2Smrg }
3378627f7eb2Smrg 
3379627f7eb2Smrg 
3380627f7eb2Smrg match
gfc_match_omp_parallel_do(void)3381627f7eb2Smrg gfc_match_omp_parallel_do (void)
3382627f7eb2Smrg {
3383627f7eb2Smrg   return match_omp (EXEC_OMP_PARALLEL_DO,
3384627f7eb2Smrg 		    OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES);
3385627f7eb2Smrg }
3386627f7eb2Smrg 
3387627f7eb2Smrg 
3388627f7eb2Smrg match
gfc_match_omp_parallel_do_simd(void)3389627f7eb2Smrg gfc_match_omp_parallel_do_simd (void)
3390627f7eb2Smrg {
3391627f7eb2Smrg   return match_omp (EXEC_OMP_PARALLEL_DO_SIMD,
3392627f7eb2Smrg 		    OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES | OMP_SIMD_CLAUSES);
3393627f7eb2Smrg }
3394627f7eb2Smrg 
3395627f7eb2Smrg 
3396627f7eb2Smrg match
gfc_match_omp_parallel_sections(void)3397627f7eb2Smrg gfc_match_omp_parallel_sections (void)
3398627f7eb2Smrg {
3399627f7eb2Smrg   return match_omp (EXEC_OMP_PARALLEL_SECTIONS,
3400627f7eb2Smrg 		    OMP_PARALLEL_CLAUSES | OMP_SECTIONS_CLAUSES);
3401627f7eb2Smrg }
3402627f7eb2Smrg 
3403627f7eb2Smrg 
3404627f7eb2Smrg match
gfc_match_omp_parallel_workshare(void)3405627f7eb2Smrg gfc_match_omp_parallel_workshare (void)
3406627f7eb2Smrg {
3407627f7eb2Smrg   return match_omp (EXEC_OMP_PARALLEL_WORKSHARE, OMP_PARALLEL_CLAUSES);
3408627f7eb2Smrg }
3409627f7eb2Smrg 
3410627f7eb2Smrg 
3411627f7eb2Smrg match
gfc_match_omp_sections(void)3412627f7eb2Smrg gfc_match_omp_sections (void)
3413627f7eb2Smrg {
3414627f7eb2Smrg   return match_omp (EXEC_OMP_SECTIONS, OMP_SECTIONS_CLAUSES);
3415627f7eb2Smrg }
3416627f7eb2Smrg 
3417627f7eb2Smrg 
3418627f7eb2Smrg match
gfc_match_omp_simd(void)3419627f7eb2Smrg gfc_match_omp_simd (void)
3420627f7eb2Smrg {
3421627f7eb2Smrg   return match_omp (EXEC_OMP_SIMD, OMP_SIMD_CLAUSES);
3422627f7eb2Smrg }
3423627f7eb2Smrg 
3424627f7eb2Smrg 
3425627f7eb2Smrg match
gfc_match_omp_single(void)3426627f7eb2Smrg gfc_match_omp_single (void)
3427627f7eb2Smrg {
3428627f7eb2Smrg   return match_omp (EXEC_OMP_SINGLE, OMP_SINGLE_CLAUSES);
3429627f7eb2Smrg }
3430627f7eb2Smrg 
3431627f7eb2Smrg 
3432627f7eb2Smrg match
gfc_match_omp_target(void)3433627f7eb2Smrg gfc_match_omp_target (void)
3434627f7eb2Smrg {
3435627f7eb2Smrg   return match_omp (EXEC_OMP_TARGET, OMP_TARGET_CLAUSES);
3436627f7eb2Smrg }
3437627f7eb2Smrg 
3438627f7eb2Smrg 
3439627f7eb2Smrg match
gfc_match_omp_target_data(void)3440627f7eb2Smrg gfc_match_omp_target_data (void)
3441627f7eb2Smrg {
3442627f7eb2Smrg   return match_omp (EXEC_OMP_TARGET_DATA, OMP_TARGET_DATA_CLAUSES);
3443627f7eb2Smrg }
3444627f7eb2Smrg 
3445627f7eb2Smrg 
3446627f7eb2Smrg match
gfc_match_omp_target_enter_data(void)3447627f7eb2Smrg gfc_match_omp_target_enter_data (void)
3448627f7eb2Smrg {
3449627f7eb2Smrg   return match_omp (EXEC_OMP_TARGET_ENTER_DATA, OMP_TARGET_ENTER_DATA_CLAUSES);
3450627f7eb2Smrg }
3451627f7eb2Smrg 
3452627f7eb2Smrg 
3453627f7eb2Smrg match
gfc_match_omp_target_exit_data(void)3454627f7eb2Smrg gfc_match_omp_target_exit_data (void)
3455627f7eb2Smrg {
3456627f7eb2Smrg   return match_omp (EXEC_OMP_TARGET_EXIT_DATA, OMP_TARGET_EXIT_DATA_CLAUSES);
3457627f7eb2Smrg }
3458627f7eb2Smrg 
3459627f7eb2Smrg 
3460627f7eb2Smrg match
gfc_match_omp_target_parallel(void)3461627f7eb2Smrg gfc_match_omp_target_parallel (void)
3462627f7eb2Smrg {
3463627f7eb2Smrg   return match_omp (EXEC_OMP_TARGET_PARALLEL,
3464627f7eb2Smrg 		    (OMP_TARGET_CLAUSES | OMP_PARALLEL_CLAUSES)
3465627f7eb2Smrg 		    & ~(omp_mask (OMP_CLAUSE_COPYIN)));
3466627f7eb2Smrg }
3467627f7eb2Smrg 
3468627f7eb2Smrg 
3469627f7eb2Smrg match
gfc_match_omp_target_parallel_do(void)3470627f7eb2Smrg gfc_match_omp_target_parallel_do (void)
3471627f7eb2Smrg {
3472627f7eb2Smrg   return match_omp (EXEC_OMP_TARGET_PARALLEL_DO,
3473627f7eb2Smrg 		    (OMP_TARGET_CLAUSES | OMP_PARALLEL_CLAUSES
3474627f7eb2Smrg 		     | OMP_DO_CLAUSES) & ~(omp_mask (OMP_CLAUSE_COPYIN)));
3475627f7eb2Smrg }
3476627f7eb2Smrg 
3477627f7eb2Smrg 
3478627f7eb2Smrg match
gfc_match_omp_target_parallel_do_simd(void)3479627f7eb2Smrg gfc_match_omp_target_parallel_do_simd (void)
3480627f7eb2Smrg {
3481627f7eb2Smrg   return match_omp (EXEC_OMP_TARGET_PARALLEL_DO_SIMD,
3482627f7eb2Smrg 		    (OMP_TARGET_CLAUSES | OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES
3483627f7eb2Smrg 		     | OMP_SIMD_CLAUSES) & ~(omp_mask (OMP_CLAUSE_COPYIN)));
3484627f7eb2Smrg }
3485627f7eb2Smrg 
3486627f7eb2Smrg 
3487627f7eb2Smrg match
gfc_match_omp_target_simd(void)3488627f7eb2Smrg gfc_match_omp_target_simd (void)
3489627f7eb2Smrg {
3490627f7eb2Smrg   return match_omp (EXEC_OMP_TARGET_SIMD,
3491627f7eb2Smrg 		    OMP_TARGET_CLAUSES | OMP_SIMD_CLAUSES);
3492627f7eb2Smrg }
3493627f7eb2Smrg 
3494627f7eb2Smrg 
3495627f7eb2Smrg match
gfc_match_omp_target_teams(void)3496627f7eb2Smrg gfc_match_omp_target_teams (void)
3497627f7eb2Smrg {
3498627f7eb2Smrg   return match_omp (EXEC_OMP_TARGET_TEAMS,
3499627f7eb2Smrg 		    OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES);
3500627f7eb2Smrg }
3501627f7eb2Smrg 
3502627f7eb2Smrg 
3503627f7eb2Smrg match
gfc_match_omp_target_teams_distribute(void)3504627f7eb2Smrg gfc_match_omp_target_teams_distribute (void)
3505627f7eb2Smrg {
3506627f7eb2Smrg   return match_omp (EXEC_OMP_TARGET_TEAMS_DISTRIBUTE,
3507627f7eb2Smrg 		    OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES
3508627f7eb2Smrg 		    | OMP_DISTRIBUTE_CLAUSES);
3509627f7eb2Smrg }
3510627f7eb2Smrg 
3511627f7eb2Smrg 
3512627f7eb2Smrg match
gfc_match_omp_target_teams_distribute_parallel_do(void)3513627f7eb2Smrg gfc_match_omp_target_teams_distribute_parallel_do (void)
3514627f7eb2Smrg {
3515627f7eb2Smrg   return match_omp (EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO,
3516627f7eb2Smrg 		    (OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES
3517627f7eb2Smrg 		     | OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
3518627f7eb2Smrg 		     | OMP_DO_CLAUSES)
3519627f7eb2Smrg 		    & ~(omp_mask (OMP_CLAUSE_ORDERED))
3520627f7eb2Smrg 		    & ~(omp_mask (OMP_CLAUSE_LINEAR)));
3521627f7eb2Smrg }
3522627f7eb2Smrg 
3523627f7eb2Smrg 
3524627f7eb2Smrg match
gfc_match_omp_target_teams_distribute_parallel_do_simd(void)3525627f7eb2Smrg gfc_match_omp_target_teams_distribute_parallel_do_simd (void)
3526627f7eb2Smrg {
3527627f7eb2Smrg   return match_omp (EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD,
3528627f7eb2Smrg 		    (OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES
3529627f7eb2Smrg 		     | OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
3530627f7eb2Smrg 		     | OMP_DO_CLAUSES | OMP_SIMD_CLAUSES)
3531627f7eb2Smrg 		    & ~(omp_mask (OMP_CLAUSE_ORDERED)));
3532627f7eb2Smrg }
3533627f7eb2Smrg 
3534627f7eb2Smrg 
3535627f7eb2Smrg match
gfc_match_omp_target_teams_distribute_simd(void)3536627f7eb2Smrg gfc_match_omp_target_teams_distribute_simd (void)
3537627f7eb2Smrg {
3538627f7eb2Smrg   return match_omp (EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD,
3539627f7eb2Smrg 		    OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES
3540627f7eb2Smrg 		    | OMP_DISTRIBUTE_CLAUSES | OMP_SIMD_CLAUSES);
3541627f7eb2Smrg }
3542627f7eb2Smrg 
3543627f7eb2Smrg 
3544627f7eb2Smrg match
gfc_match_omp_target_update(void)3545627f7eb2Smrg gfc_match_omp_target_update (void)
3546627f7eb2Smrg {
3547627f7eb2Smrg   return match_omp (EXEC_OMP_TARGET_UPDATE, OMP_TARGET_UPDATE_CLAUSES);
3548627f7eb2Smrg }
3549627f7eb2Smrg 
3550627f7eb2Smrg 
3551627f7eb2Smrg match
gfc_match_omp_task(void)3552627f7eb2Smrg gfc_match_omp_task (void)
3553627f7eb2Smrg {
3554627f7eb2Smrg   return match_omp (EXEC_OMP_TASK, OMP_TASK_CLAUSES);
3555627f7eb2Smrg }
3556627f7eb2Smrg 
3557627f7eb2Smrg 
3558627f7eb2Smrg match
gfc_match_omp_taskloop(void)3559627f7eb2Smrg gfc_match_omp_taskloop (void)
3560627f7eb2Smrg {
3561627f7eb2Smrg   return match_omp (EXEC_OMP_TASKLOOP, OMP_TASKLOOP_CLAUSES);
3562627f7eb2Smrg }
3563627f7eb2Smrg 
3564627f7eb2Smrg 
3565627f7eb2Smrg match
gfc_match_omp_taskloop_simd(void)3566627f7eb2Smrg gfc_match_omp_taskloop_simd (void)
3567627f7eb2Smrg {
3568627f7eb2Smrg   return match_omp (EXEC_OMP_TASKLOOP_SIMD,
3569627f7eb2Smrg 		    (OMP_TASKLOOP_CLAUSES | OMP_SIMD_CLAUSES)
3570627f7eb2Smrg 		    & ~(omp_mask (OMP_CLAUSE_REDUCTION)));
3571627f7eb2Smrg }
3572627f7eb2Smrg 
3573627f7eb2Smrg 
3574627f7eb2Smrg match
gfc_match_omp_taskwait(void)3575627f7eb2Smrg gfc_match_omp_taskwait (void)
3576627f7eb2Smrg {
3577627f7eb2Smrg   if (gfc_match_omp_eos () != MATCH_YES)
3578627f7eb2Smrg     {
3579627f7eb2Smrg       gfc_error ("Unexpected junk after TASKWAIT clause at %C");
3580627f7eb2Smrg       return MATCH_ERROR;
3581627f7eb2Smrg     }
3582627f7eb2Smrg   new_st.op = EXEC_OMP_TASKWAIT;
3583627f7eb2Smrg   new_st.ext.omp_clauses = NULL;
3584627f7eb2Smrg   return MATCH_YES;
3585627f7eb2Smrg }
3586627f7eb2Smrg 
3587627f7eb2Smrg 
3588627f7eb2Smrg match
gfc_match_omp_taskyield(void)3589627f7eb2Smrg gfc_match_omp_taskyield (void)
3590627f7eb2Smrg {
3591627f7eb2Smrg   if (gfc_match_omp_eos () != MATCH_YES)
3592627f7eb2Smrg     {
3593627f7eb2Smrg       gfc_error ("Unexpected junk after TASKYIELD clause at %C");
3594627f7eb2Smrg       return MATCH_ERROR;
3595627f7eb2Smrg     }
3596627f7eb2Smrg   new_st.op = EXEC_OMP_TASKYIELD;
3597627f7eb2Smrg   new_st.ext.omp_clauses = NULL;
3598627f7eb2Smrg   return MATCH_YES;
3599627f7eb2Smrg }
3600627f7eb2Smrg 
3601627f7eb2Smrg 
3602627f7eb2Smrg match
gfc_match_omp_teams(void)3603627f7eb2Smrg gfc_match_omp_teams (void)
3604627f7eb2Smrg {
3605627f7eb2Smrg   return match_omp (EXEC_OMP_TEAMS, OMP_TEAMS_CLAUSES);
3606627f7eb2Smrg }
3607627f7eb2Smrg 
3608627f7eb2Smrg 
3609627f7eb2Smrg match
gfc_match_omp_teams_distribute(void)3610627f7eb2Smrg gfc_match_omp_teams_distribute (void)
3611627f7eb2Smrg {
3612627f7eb2Smrg   return match_omp (EXEC_OMP_TEAMS_DISTRIBUTE,
3613627f7eb2Smrg 		    OMP_TEAMS_CLAUSES | OMP_DISTRIBUTE_CLAUSES);
3614627f7eb2Smrg }
3615627f7eb2Smrg 
3616627f7eb2Smrg 
3617627f7eb2Smrg match
gfc_match_omp_teams_distribute_parallel_do(void)3618627f7eb2Smrg gfc_match_omp_teams_distribute_parallel_do (void)
3619627f7eb2Smrg {
3620627f7eb2Smrg   return match_omp (EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO,
3621627f7eb2Smrg 		    (OMP_TEAMS_CLAUSES | OMP_DISTRIBUTE_CLAUSES
3622627f7eb2Smrg 		     | OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES)
3623627f7eb2Smrg 		    & ~(omp_mask (OMP_CLAUSE_ORDERED))
3624627f7eb2Smrg 		    & ~(omp_mask (OMP_CLAUSE_LINEAR)));
3625627f7eb2Smrg }
3626627f7eb2Smrg 
3627627f7eb2Smrg 
3628627f7eb2Smrg match
gfc_match_omp_teams_distribute_parallel_do_simd(void)3629627f7eb2Smrg gfc_match_omp_teams_distribute_parallel_do_simd (void)
3630627f7eb2Smrg {
3631627f7eb2Smrg   return match_omp (EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD,
3632627f7eb2Smrg 		    (OMP_TEAMS_CLAUSES | OMP_DISTRIBUTE_CLAUSES
3633627f7eb2Smrg 		     | OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES
3634627f7eb2Smrg 		     | OMP_SIMD_CLAUSES) & ~(omp_mask (OMP_CLAUSE_ORDERED)));
3635627f7eb2Smrg }
3636627f7eb2Smrg 
3637627f7eb2Smrg 
3638627f7eb2Smrg match
gfc_match_omp_teams_distribute_simd(void)3639627f7eb2Smrg gfc_match_omp_teams_distribute_simd (void)
3640627f7eb2Smrg {
3641627f7eb2Smrg   return match_omp (EXEC_OMP_TEAMS_DISTRIBUTE_SIMD,
3642627f7eb2Smrg 		    OMP_TEAMS_CLAUSES | OMP_DISTRIBUTE_CLAUSES
3643627f7eb2Smrg 		    | OMP_SIMD_CLAUSES);
3644627f7eb2Smrg }
3645627f7eb2Smrg 
3646627f7eb2Smrg 
3647627f7eb2Smrg match
gfc_match_omp_workshare(void)3648627f7eb2Smrg gfc_match_omp_workshare (void)
3649627f7eb2Smrg {
3650627f7eb2Smrg   if (gfc_match_omp_eos () != MATCH_YES)
3651627f7eb2Smrg     {
3652627f7eb2Smrg       gfc_error ("Unexpected junk after $OMP WORKSHARE statement at %C");
3653627f7eb2Smrg       return MATCH_ERROR;
3654627f7eb2Smrg     }
3655627f7eb2Smrg   new_st.op = EXEC_OMP_WORKSHARE;
3656627f7eb2Smrg   new_st.ext.omp_clauses = gfc_get_omp_clauses ();
3657627f7eb2Smrg   return MATCH_YES;
3658627f7eb2Smrg }
3659627f7eb2Smrg 
3660627f7eb2Smrg 
3661627f7eb2Smrg match
gfc_match_omp_master(void)3662627f7eb2Smrg gfc_match_omp_master (void)
3663627f7eb2Smrg {
3664627f7eb2Smrg   if (gfc_match_omp_eos () != MATCH_YES)
3665627f7eb2Smrg     {
3666627f7eb2Smrg       gfc_error ("Unexpected junk after $OMP MASTER statement at %C");
3667627f7eb2Smrg       return MATCH_ERROR;
3668627f7eb2Smrg     }
3669627f7eb2Smrg   new_st.op = EXEC_OMP_MASTER;
3670627f7eb2Smrg   new_st.ext.omp_clauses = NULL;
3671627f7eb2Smrg   return MATCH_YES;
3672627f7eb2Smrg }
3673627f7eb2Smrg 
3674627f7eb2Smrg 
3675627f7eb2Smrg match
gfc_match_omp_ordered(void)3676627f7eb2Smrg gfc_match_omp_ordered (void)
3677627f7eb2Smrg {
3678627f7eb2Smrg   return match_omp (EXEC_OMP_ORDERED, OMP_ORDERED_CLAUSES);
3679627f7eb2Smrg }
3680627f7eb2Smrg 
3681627f7eb2Smrg 
3682627f7eb2Smrg match
gfc_match_omp_ordered_depend(void)3683627f7eb2Smrg gfc_match_omp_ordered_depend (void)
3684627f7eb2Smrg {
3685627f7eb2Smrg   return match_omp (EXEC_OMP_ORDERED, omp_mask (OMP_CLAUSE_DEPEND));
3686627f7eb2Smrg }
3687627f7eb2Smrg 
3688627f7eb2Smrg 
3689627f7eb2Smrg static match
gfc_match_omp_oacc_atomic(bool omp_p)3690627f7eb2Smrg gfc_match_omp_oacc_atomic (bool omp_p)
3691627f7eb2Smrg {
3692627f7eb2Smrg   gfc_omp_atomic_op op = GFC_OMP_ATOMIC_UPDATE;
3693627f7eb2Smrg   int seq_cst = 0;
3694627f7eb2Smrg   if (gfc_match ("% seq_cst") == MATCH_YES)
3695627f7eb2Smrg     seq_cst = 1;
3696627f7eb2Smrg   locus old_loc = gfc_current_locus;
3697627f7eb2Smrg   if (seq_cst && gfc_match_char (',') == MATCH_YES)
3698627f7eb2Smrg     seq_cst = 2;
3699627f7eb2Smrg   if (seq_cst == 2
3700627f7eb2Smrg       || gfc_match_space () == MATCH_YES)
3701627f7eb2Smrg     {
3702627f7eb2Smrg       gfc_gobble_whitespace ();
3703627f7eb2Smrg       if (gfc_match ("update") == MATCH_YES)
3704627f7eb2Smrg 	op = GFC_OMP_ATOMIC_UPDATE;
3705627f7eb2Smrg       else if (gfc_match ("read") == MATCH_YES)
3706627f7eb2Smrg 	op = GFC_OMP_ATOMIC_READ;
3707627f7eb2Smrg       else if (gfc_match ("write") == MATCH_YES)
3708627f7eb2Smrg 	op = GFC_OMP_ATOMIC_WRITE;
3709627f7eb2Smrg       else if (gfc_match ("capture") == MATCH_YES)
3710627f7eb2Smrg 	op = GFC_OMP_ATOMIC_CAPTURE;
3711627f7eb2Smrg       else
3712627f7eb2Smrg 	{
3713627f7eb2Smrg 	  if (seq_cst == 2)
3714627f7eb2Smrg 	    gfc_current_locus = old_loc;
3715627f7eb2Smrg 	  goto finish;
3716627f7eb2Smrg 	}
3717627f7eb2Smrg       if (!seq_cst
3718627f7eb2Smrg 	  && (gfc_match (", seq_cst") == MATCH_YES
3719627f7eb2Smrg 	      || gfc_match ("% seq_cst") == MATCH_YES))
3720627f7eb2Smrg 	seq_cst = 1;
3721627f7eb2Smrg     }
3722627f7eb2Smrg  finish:
3723627f7eb2Smrg   if (gfc_match_omp_eos () != MATCH_YES)
3724627f7eb2Smrg     {
3725627f7eb2Smrg       gfc_error ("Unexpected junk after $OMP ATOMIC statement at %C");
3726627f7eb2Smrg       return MATCH_ERROR;
3727627f7eb2Smrg     }
3728627f7eb2Smrg   new_st.op = (omp_p ? EXEC_OMP_ATOMIC : EXEC_OACC_ATOMIC);
3729627f7eb2Smrg   if (seq_cst)
3730627f7eb2Smrg     op = (gfc_omp_atomic_op) (op | GFC_OMP_ATOMIC_SEQ_CST);
3731627f7eb2Smrg   new_st.ext.omp_atomic = op;
3732627f7eb2Smrg   return MATCH_YES;
3733627f7eb2Smrg }
3734627f7eb2Smrg 
3735627f7eb2Smrg match
gfc_match_oacc_atomic(void)3736627f7eb2Smrg gfc_match_oacc_atomic (void)
3737627f7eb2Smrg {
3738627f7eb2Smrg   return gfc_match_omp_oacc_atomic (false);
3739627f7eb2Smrg }
3740627f7eb2Smrg 
3741627f7eb2Smrg match
gfc_match_omp_atomic(void)3742627f7eb2Smrg gfc_match_omp_atomic (void)
3743627f7eb2Smrg {
3744627f7eb2Smrg   return gfc_match_omp_oacc_atomic (true);
3745627f7eb2Smrg }
3746627f7eb2Smrg 
3747627f7eb2Smrg match
gfc_match_omp_barrier(void)3748627f7eb2Smrg gfc_match_omp_barrier (void)
3749627f7eb2Smrg {
3750627f7eb2Smrg   if (gfc_match_omp_eos () != MATCH_YES)
3751627f7eb2Smrg     {
3752627f7eb2Smrg       gfc_error ("Unexpected junk after $OMP BARRIER statement at %C");
3753627f7eb2Smrg       return MATCH_ERROR;
3754627f7eb2Smrg     }
3755627f7eb2Smrg   new_st.op = EXEC_OMP_BARRIER;
3756627f7eb2Smrg   new_st.ext.omp_clauses = NULL;
3757627f7eb2Smrg   return MATCH_YES;
3758627f7eb2Smrg }
3759627f7eb2Smrg 
3760627f7eb2Smrg 
3761627f7eb2Smrg match
gfc_match_omp_taskgroup(void)3762627f7eb2Smrg gfc_match_omp_taskgroup (void)
3763627f7eb2Smrg {
3764627f7eb2Smrg   if (gfc_match_omp_eos () != MATCH_YES)
3765627f7eb2Smrg     {
3766627f7eb2Smrg       gfc_error ("Unexpected junk after $OMP TASKGROUP statement at %C");
3767627f7eb2Smrg       return MATCH_ERROR;
3768627f7eb2Smrg     }
3769627f7eb2Smrg   new_st.op = EXEC_OMP_TASKGROUP;
3770627f7eb2Smrg   return MATCH_YES;
3771627f7eb2Smrg }
3772627f7eb2Smrg 
3773627f7eb2Smrg 
3774627f7eb2Smrg static enum gfc_omp_cancel_kind
gfc_match_omp_cancel_kind(void)3775627f7eb2Smrg gfc_match_omp_cancel_kind (void)
3776627f7eb2Smrg {
3777627f7eb2Smrg   if (gfc_match_space () != MATCH_YES)
3778627f7eb2Smrg     return OMP_CANCEL_UNKNOWN;
3779627f7eb2Smrg   if (gfc_match ("parallel") == MATCH_YES)
3780627f7eb2Smrg     return OMP_CANCEL_PARALLEL;
3781627f7eb2Smrg   if (gfc_match ("sections") == MATCH_YES)
3782627f7eb2Smrg     return OMP_CANCEL_SECTIONS;
3783627f7eb2Smrg   if (gfc_match ("do") == MATCH_YES)
3784627f7eb2Smrg     return OMP_CANCEL_DO;
3785627f7eb2Smrg   if (gfc_match ("taskgroup") == MATCH_YES)
3786627f7eb2Smrg     return OMP_CANCEL_TASKGROUP;
3787627f7eb2Smrg   return OMP_CANCEL_UNKNOWN;
3788627f7eb2Smrg }
3789627f7eb2Smrg 
3790627f7eb2Smrg 
3791627f7eb2Smrg match
gfc_match_omp_cancel(void)3792627f7eb2Smrg gfc_match_omp_cancel (void)
3793627f7eb2Smrg {
3794627f7eb2Smrg   gfc_omp_clauses *c;
3795627f7eb2Smrg   enum gfc_omp_cancel_kind kind = gfc_match_omp_cancel_kind ();
3796627f7eb2Smrg   if (kind == OMP_CANCEL_UNKNOWN)
3797627f7eb2Smrg     return MATCH_ERROR;
3798627f7eb2Smrg   if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_IF), false) != MATCH_YES)
3799627f7eb2Smrg     return MATCH_ERROR;
3800627f7eb2Smrg   c->cancel = kind;
3801627f7eb2Smrg   new_st.op = EXEC_OMP_CANCEL;
3802627f7eb2Smrg   new_st.ext.omp_clauses = c;
3803627f7eb2Smrg   return MATCH_YES;
3804627f7eb2Smrg }
3805627f7eb2Smrg 
3806627f7eb2Smrg 
3807627f7eb2Smrg match
gfc_match_omp_cancellation_point(void)3808627f7eb2Smrg gfc_match_omp_cancellation_point (void)
3809627f7eb2Smrg {
3810627f7eb2Smrg   gfc_omp_clauses *c;
3811627f7eb2Smrg   enum gfc_omp_cancel_kind kind = gfc_match_omp_cancel_kind ();
3812627f7eb2Smrg   if (kind == OMP_CANCEL_UNKNOWN)
3813627f7eb2Smrg     return MATCH_ERROR;
3814627f7eb2Smrg   if (gfc_match_omp_eos () != MATCH_YES)
3815627f7eb2Smrg     {
3816627f7eb2Smrg       gfc_error ("Unexpected junk after $OMP CANCELLATION POINT statement "
3817627f7eb2Smrg 		 "at %C");
3818627f7eb2Smrg       return MATCH_ERROR;
3819627f7eb2Smrg     }
3820627f7eb2Smrg   c = gfc_get_omp_clauses ();
3821627f7eb2Smrg   c->cancel = kind;
3822627f7eb2Smrg   new_st.op = EXEC_OMP_CANCELLATION_POINT;
3823627f7eb2Smrg   new_st.ext.omp_clauses = c;
3824627f7eb2Smrg   return MATCH_YES;
3825627f7eb2Smrg }
3826627f7eb2Smrg 
3827627f7eb2Smrg 
3828627f7eb2Smrg match
gfc_match_omp_end_nowait(void)3829627f7eb2Smrg gfc_match_omp_end_nowait (void)
3830627f7eb2Smrg {
3831627f7eb2Smrg   bool nowait = false;
3832627f7eb2Smrg   if (gfc_match ("% nowait") == MATCH_YES)
3833627f7eb2Smrg     nowait = true;
3834627f7eb2Smrg   if (gfc_match_omp_eos () != MATCH_YES)
3835627f7eb2Smrg     {
3836627f7eb2Smrg       gfc_error ("Unexpected junk after NOWAIT clause at %C");
3837627f7eb2Smrg       return MATCH_ERROR;
3838627f7eb2Smrg     }
3839627f7eb2Smrg   new_st.op = EXEC_OMP_END_NOWAIT;
3840627f7eb2Smrg   new_st.ext.omp_bool = nowait;
3841627f7eb2Smrg   return MATCH_YES;
3842627f7eb2Smrg }
3843627f7eb2Smrg 
3844627f7eb2Smrg 
3845627f7eb2Smrg match
gfc_match_omp_end_single(void)3846627f7eb2Smrg gfc_match_omp_end_single (void)
3847627f7eb2Smrg {
3848627f7eb2Smrg   gfc_omp_clauses *c;
3849627f7eb2Smrg   if (gfc_match ("% nowait") == MATCH_YES)
3850627f7eb2Smrg     {
3851627f7eb2Smrg       new_st.op = EXEC_OMP_END_NOWAIT;
3852627f7eb2Smrg       new_st.ext.omp_bool = true;
3853627f7eb2Smrg       return MATCH_YES;
3854627f7eb2Smrg     }
3855627f7eb2Smrg   if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_COPYPRIVATE))
3856627f7eb2Smrg       != MATCH_YES)
3857627f7eb2Smrg     return MATCH_ERROR;
3858627f7eb2Smrg   new_st.op = EXEC_OMP_END_SINGLE;
3859627f7eb2Smrg   new_st.ext.omp_clauses = c;
3860627f7eb2Smrg   return MATCH_YES;
3861627f7eb2Smrg }
3862627f7eb2Smrg 
3863627f7eb2Smrg 
3864627f7eb2Smrg static bool
oacc_is_loop(gfc_code * code)3865627f7eb2Smrg oacc_is_loop (gfc_code *code)
3866627f7eb2Smrg {
3867627f7eb2Smrg   return code->op == EXEC_OACC_PARALLEL_LOOP
3868627f7eb2Smrg 	 || code->op == EXEC_OACC_KERNELS_LOOP
3869*4c3eb207Smrg 	 || code->op == EXEC_OACC_SERIAL_LOOP
3870627f7eb2Smrg 	 || code->op == EXEC_OACC_LOOP;
3871627f7eb2Smrg }
3872627f7eb2Smrg 
3873627f7eb2Smrg static void
resolve_scalar_int_expr(gfc_expr * expr,const char * clause)3874627f7eb2Smrg resolve_scalar_int_expr (gfc_expr *expr, const char *clause)
3875627f7eb2Smrg {
3876627f7eb2Smrg   if (!gfc_resolve_expr (expr)
3877627f7eb2Smrg       || expr->ts.type != BT_INTEGER
3878627f7eb2Smrg       || expr->rank != 0)
3879627f7eb2Smrg     gfc_error ("%s clause at %L requires a scalar INTEGER expression",
3880627f7eb2Smrg 	       clause, &expr->where);
3881627f7eb2Smrg }
3882627f7eb2Smrg 
3883627f7eb2Smrg static void
resolve_positive_int_expr(gfc_expr * expr,const char * clause)3884627f7eb2Smrg resolve_positive_int_expr (gfc_expr *expr, const char *clause)
3885627f7eb2Smrg {
3886627f7eb2Smrg   resolve_scalar_int_expr (expr, clause);
3887627f7eb2Smrg   if (expr->expr_type == EXPR_CONSTANT
3888627f7eb2Smrg       && expr->ts.type == BT_INTEGER
3889627f7eb2Smrg       && mpz_sgn (expr->value.integer) <= 0)
3890627f7eb2Smrg     gfc_warning (0, "INTEGER expression of %s clause at %L must be positive",
3891627f7eb2Smrg 		 clause, &expr->where);
3892627f7eb2Smrg }
3893627f7eb2Smrg 
3894627f7eb2Smrg static void
resolve_nonnegative_int_expr(gfc_expr * expr,const char * clause)3895627f7eb2Smrg resolve_nonnegative_int_expr (gfc_expr *expr, const char *clause)
3896627f7eb2Smrg {
3897627f7eb2Smrg   resolve_scalar_int_expr (expr, clause);
3898627f7eb2Smrg   if (expr->expr_type == EXPR_CONSTANT
3899627f7eb2Smrg       && expr->ts.type == BT_INTEGER
3900627f7eb2Smrg       && mpz_sgn (expr->value.integer) < 0)
3901627f7eb2Smrg     gfc_warning (0, "INTEGER expression of %s clause at %L must be "
3902627f7eb2Smrg 		 "non-negative", clause, &expr->where);
3903627f7eb2Smrg }
3904627f7eb2Smrg 
3905627f7eb2Smrg /* Emits error when symbol is pointer, cray pointer or cray pointee
3906627f7eb2Smrg    of derived of polymorphic type.  */
3907627f7eb2Smrg 
3908627f7eb2Smrg static void
check_symbol_not_pointer(gfc_symbol * sym,locus loc,const char * name)3909627f7eb2Smrg check_symbol_not_pointer (gfc_symbol *sym, locus loc, const char *name)
3910627f7eb2Smrg {
3911627f7eb2Smrg   if (sym->ts.type == BT_DERIVED && sym->attr.cray_pointer)
3912627f7eb2Smrg     gfc_error ("Cray pointer object %qs of derived type in %s clause at %L",
3913627f7eb2Smrg 	       sym->name, name, &loc);
3914627f7eb2Smrg   if (sym->ts.type == BT_DERIVED && sym->attr.cray_pointee)
3915627f7eb2Smrg     gfc_error ("Cray pointee object %qs of derived type in %s clause at %L",
3916627f7eb2Smrg 	       sym->name, name, &loc);
3917627f7eb2Smrg 
3918627f7eb2Smrg   if ((sym->ts.type == BT_ASSUMED && sym->attr.pointer)
3919627f7eb2Smrg       || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
3920627f7eb2Smrg 	  && CLASS_DATA (sym)->attr.pointer))
3921627f7eb2Smrg     gfc_error ("POINTER object %qs of polymorphic type in %s clause at %L",
3922627f7eb2Smrg 	       sym->name, name, &loc);
3923627f7eb2Smrg   if ((sym->ts.type == BT_ASSUMED && sym->attr.cray_pointer)
3924627f7eb2Smrg       || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
3925627f7eb2Smrg 	  && CLASS_DATA (sym)->attr.cray_pointer))
3926627f7eb2Smrg     gfc_error ("Cray pointer object %qs of polymorphic type in %s clause at %L",
3927627f7eb2Smrg 	       sym->name, name, &loc);
3928627f7eb2Smrg   if ((sym->ts.type == BT_ASSUMED && sym->attr.cray_pointee)
3929627f7eb2Smrg       || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
3930627f7eb2Smrg 	  && CLASS_DATA (sym)->attr.cray_pointee))
3931627f7eb2Smrg     gfc_error ("Cray pointee object %qs of polymorphic type in %s clause at %L",
3932627f7eb2Smrg 	       sym->name, name, &loc);
3933627f7eb2Smrg }
3934627f7eb2Smrg 
3935627f7eb2Smrg /* Emits error when symbol represents assumed size/rank array.  */
3936627f7eb2Smrg 
3937627f7eb2Smrg static void
check_array_not_assumed(gfc_symbol * sym,locus loc,const char * name)3938627f7eb2Smrg check_array_not_assumed (gfc_symbol *sym, locus loc, const char *name)
3939627f7eb2Smrg {
3940627f7eb2Smrg   if (sym->as && sym->as->type == AS_ASSUMED_SIZE)
3941627f7eb2Smrg     gfc_error ("Assumed size array %qs in %s clause at %L",
3942627f7eb2Smrg 	       sym->name, name, &loc);
3943627f7eb2Smrg   if (sym->as && sym->as->type == AS_ASSUMED_RANK)
3944627f7eb2Smrg     gfc_error ("Assumed rank array %qs in %s clause at %L",
3945627f7eb2Smrg 	       sym->name, name, &loc);
3946627f7eb2Smrg }
3947627f7eb2Smrg 
3948627f7eb2Smrg static void
resolve_oacc_data_clauses(gfc_symbol * sym,locus loc,const char * name)3949627f7eb2Smrg resolve_oacc_data_clauses (gfc_symbol *sym, locus loc, const char *name)
3950627f7eb2Smrg {
3951627f7eb2Smrg   check_array_not_assumed (sym, loc, name);
3952627f7eb2Smrg }
3953627f7eb2Smrg 
3954627f7eb2Smrg static void
resolve_oacc_deviceptr_clause(gfc_symbol * sym,locus loc,const char * name)3955627f7eb2Smrg resolve_oacc_deviceptr_clause (gfc_symbol *sym, locus loc, const char *name)
3956627f7eb2Smrg {
3957627f7eb2Smrg   if (sym->attr.pointer
3958627f7eb2Smrg       || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
3959627f7eb2Smrg 	  && CLASS_DATA (sym)->attr.class_pointer))
3960627f7eb2Smrg     gfc_error ("POINTER object %qs in %s clause at %L",
3961627f7eb2Smrg 	       sym->name, name, &loc);
3962627f7eb2Smrg   if (sym->attr.cray_pointer
3963627f7eb2Smrg       || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
3964627f7eb2Smrg 	  && CLASS_DATA (sym)->attr.cray_pointer))
3965627f7eb2Smrg     gfc_error ("Cray pointer object %qs in %s clause at %L",
3966627f7eb2Smrg 	       sym->name, name, &loc);
3967627f7eb2Smrg   if (sym->attr.cray_pointee
3968627f7eb2Smrg       || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
3969627f7eb2Smrg 	  && CLASS_DATA (sym)->attr.cray_pointee))
3970627f7eb2Smrg     gfc_error ("Cray pointee object %qs in %s clause at %L",
3971627f7eb2Smrg 	       sym->name, name, &loc);
3972627f7eb2Smrg   if (sym->attr.allocatable
3973627f7eb2Smrg       || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
3974627f7eb2Smrg 	  && CLASS_DATA (sym)->attr.allocatable))
3975627f7eb2Smrg     gfc_error ("ALLOCATABLE object %qs in %s clause at %L",
3976627f7eb2Smrg 	       sym->name, name, &loc);
3977627f7eb2Smrg   if (sym->attr.value)
3978627f7eb2Smrg     gfc_error ("VALUE object %qs in %s clause at %L",
3979627f7eb2Smrg 	       sym->name, name, &loc);
3980627f7eb2Smrg   check_array_not_assumed (sym, loc, name);
3981627f7eb2Smrg }
3982627f7eb2Smrg 
3983627f7eb2Smrg 
3984627f7eb2Smrg struct resolve_omp_udr_callback_data
3985627f7eb2Smrg {
3986627f7eb2Smrg   gfc_symbol *sym1, *sym2;
3987627f7eb2Smrg };
3988627f7eb2Smrg 
3989627f7eb2Smrg 
3990627f7eb2Smrg static int
resolve_omp_udr_callback(gfc_expr ** e,int *,void * data)3991627f7eb2Smrg resolve_omp_udr_callback (gfc_expr **e, int *, void *data)
3992627f7eb2Smrg {
3993627f7eb2Smrg   struct resolve_omp_udr_callback_data *rcd
3994627f7eb2Smrg     = (struct resolve_omp_udr_callback_data *) data;
3995627f7eb2Smrg   if ((*e)->expr_type == EXPR_VARIABLE
3996627f7eb2Smrg       && ((*e)->symtree->n.sym == rcd->sym1
3997627f7eb2Smrg 	  || (*e)->symtree->n.sym == rcd->sym2))
3998627f7eb2Smrg     {
3999627f7eb2Smrg       gfc_ref *ref = gfc_get_ref ();
4000627f7eb2Smrg       ref->type = REF_ARRAY;
4001627f7eb2Smrg       ref->u.ar.where = (*e)->where;
4002627f7eb2Smrg       ref->u.ar.as = (*e)->symtree->n.sym->as;
4003627f7eb2Smrg       ref->u.ar.type = AR_FULL;
4004627f7eb2Smrg       ref->u.ar.dimen = 0;
4005627f7eb2Smrg       ref->next = (*e)->ref;
4006627f7eb2Smrg       (*e)->ref = ref;
4007627f7eb2Smrg     }
4008627f7eb2Smrg   return 0;
4009627f7eb2Smrg }
4010627f7eb2Smrg 
4011627f7eb2Smrg 
4012627f7eb2Smrg static int
resolve_omp_udr_callback2(gfc_expr ** e,int *,void *)4013627f7eb2Smrg resolve_omp_udr_callback2 (gfc_expr **e, int *, void *)
4014627f7eb2Smrg {
4015627f7eb2Smrg   if ((*e)->expr_type == EXPR_FUNCTION
4016627f7eb2Smrg       && (*e)->value.function.isym == NULL)
4017627f7eb2Smrg     {
4018627f7eb2Smrg       gfc_symbol *sym = (*e)->symtree->n.sym;
4019627f7eb2Smrg       if (!sym->attr.intrinsic
4020627f7eb2Smrg 	  && sym->attr.if_source == IFSRC_UNKNOWN)
4021627f7eb2Smrg 	gfc_error ("Implicitly declared function %s used in "
4022627f7eb2Smrg 		   "!$OMP DECLARE REDUCTION at %L", sym->name, &(*e)->where);
4023627f7eb2Smrg     }
4024627f7eb2Smrg   return 0;
4025627f7eb2Smrg }
4026627f7eb2Smrg 
4027627f7eb2Smrg 
4028627f7eb2Smrg static gfc_code *
resolve_omp_udr_clause(gfc_omp_namelist * n,gfc_namespace * ns,gfc_symbol * sym1,gfc_symbol * sym2)4029627f7eb2Smrg resolve_omp_udr_clause (gfc_omp_namelist *n, gfc_namespace *ns,
4030627f7eb2Smrg 			gfc_symbol *sym1, gfc_symbol *sym2)
4031627f7eb2Smrg {
4032627f7eb2Smrg   gfc_code *copy;
4033627f7eb2Smrg   gfc_symbol sym1_copy, sym2_copy;
4034627f7eb2Smrg 
4035627f7eb2Smrg   if (ns->code->op == EXEC_ASSIGN)
4036627f7eb2Smrg     {
4037627f7eb2Smrg       copy = gfc_get_code (EXEC_ASSIGN);
4038627f7eb2Smrg       copy->expr1 = gfc_copy_expr (ns->code->expr1);
4039627f7eb2Smrg       copy->expr2 = gfc_copy_expr (ns->code->expr2);
4040627f7eb2Smrg     }
4041627f7eb2Smrg   else
4042627f7eb2Smrg     {
4043627f7eb2Smrg       copy = gfc_get_code (EXEC_CALL);
4044627f7eb2Smrg       copy->symtree = ns->code->symtree;
4045627f7eb2Smrg       copy->ext.actual = gfc_copy_actual_arglist (ns->code->ext.actual);
4046627f7eb2Smrg     }
4047627f7eb2Smrg   copy->loc = ns->code->loc;
4048627f7eb2Smrg   sym1_copy = *sym1;
4049627f7eb2Smrg   sym2_copy = *sym2;
4050627f7eb2Smrg   *sym1 = *n->sym;
4051627f7eb2Smrg   *sym2 = *n->sym;
4052627f7eb2Smrg   sym1->name = sym1_copy.name;
4053627f7eb2Smrg   sym2->name = sym2_copy.name;
4054627f7eb2Smrg   ns->proc_name = ns->parent->proc_name;
4055627f7eb2Smrg   if (n->sym->attr.dimension)
4056627f7eb2Smrg     {
4057627f7eb2Smrg       struct resolve_omp_udr_callback_data rcd;
4058627f7eb2Smrg       rcd.sym1 = sym1;
4059627f7eb2Smrg       rcd.sym2 = sym2;
4060627f7eb2Smrg       gfc_code_walker (&copy, gfc_dummy_code_callback,
4061627f7eb2Smrg 		       resolve_omp_udr_callback, &rcd);
4062627f7eb2Smrg     }
4063627f7eb2Smrg   gfc_resolve_code (copy, gfc_current_ns);
4064627f7eb2Smrg   if (copy->op == EXEC_CALL && copy->resolved_isym == NULL)
4065627f7eb2Smrg     {
4066627f7eb2Smrg       gfc_symbol *sym = copy->resolved_sym;
4067627f7eb2Smrg       if (sym
4068627f7eb2Smrg 	  && !sym->attr.intrinsic
4069627f7eb2Smrg 	  && sym->attr.if_source == IFSRC_UNKNOWN)
4070627f7eb2Smrg 	gfc_error ("Implicitly declared subroutine %s used in "
4071627f7eb2Smrg 		   "!$OMP DECLARE REDUCTION at %L", sym->name,
4072627f7eb2Smrg 		   &copy->loc);
4073627f7eb2Smrg     }
4074627f7eb2Smrg   gfc_code_walker (&copy, gfc_dummy_code_callback,
4075627f7eb2Smrg 		   resolve_omp_udr_callback2, NULL);
4076627f7eb2Smrg   *sym1 = sym1_copy;
4077627f7eb2Smrg   *sym2 = sym2_copy;
4078627f7eb2Smrg   return copy;
4079627f7eb2Smrg }
4080627f7eb2Smrg 
4081627f7eb2Smrg /* OpenMP directive resolving routines.  */
4082627f7eb2Smrg 
4083627f7eb2Smrg static void
4084627f7eb2Smrg resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
4085627f7eb2Smrg 		     gfc_namespace *ns, bool openacc = false)
4086627f7eb2Smrg {
4087627f7eb2Smrg   gfc_omp_namelist *n;
4088627f7eb2Smrg   gfc_expr_list *el;
4089627f7eb2Smrg   int list;
4090627f7eb2Smrg   int ifc;
4091627f7eb2Smrg   bool if_without_mod = false;
4092627f7eb2Smrg   gfc_omp_linear_op linear_op = OMP_LINEAR_DEFAULT;
4093627f7eb2Smrg   static const char *clause_names[]
4094627f7eb2Smrg     = { "PRIVATE", "FIRSTPRIVATE", "LASTPRIVATE", "COPYPRIVATE", "SHARED",
4095627f7eb2Smrg 	"COPYIN", "UNIFORM", "ALIGNED", "LINEAR", "DEPEND", "MAP",
4096627f7eb2Smrg 	"TO", "FROM", "REDUCTION", "DEVICE_RESIDENT", "LINK", "USE_DEVICE",
4097*4c3eb207Smrg 	"CACHE", "IS_DEVICE_PTR", "USE_DEVICE_PTR", "USE_DEVICE_ADDR" };
4098627f7eb2Smrg 
4099627f7eb2Smrg   if (omp_clauses == NULL)
4100627f7eb2Smrg     return;
4101627f7eb2Smrg 
4102627f7eb2Smrg   if (omp_clauses->orderedc && omp_clauses->orderedc < omp_clauses->collapse)
4103627f7eb2Smrg     gfc_error ("ORDERED clause parameter is less than COLLAPSE at %L",
4104627f7eb2Smrg 	       &code->loc);
4105627f7eb2Smrg 
4106627f7eb2Smrg   if (omp_clauses->if_expr)
4107627f7eb2Smrg     {
4108627f7eb2Smrg       gfc_expr *expr = omp_clauses->if_expr;
4109627f7eb2Smrg       if (!gfc_resolve_expr (expr)
4110627f7eb2Smrg 	  || expr->ts.type != BT_LOGICAL || expr->rank != 0)
4111627f7eb2Smrg 	gfc_error ("IF clause at %L requires a scalar LOGICAL expression",
4112627f7eb2Smrg 		   &expr->where);
4113627f7eb2Smrg       if_without_mod = true;
4114627f7eb2Smrg     }
4115627f7eb2Smrg   for (ifc = 0; ifc < OMP_IF_LAST; ifc++)
4116627f7eb2Smrg     if (omp_clauses->if_exprs[ifc])
4117627f7eb2Smrg       {
4118627f7eb2Smrg 	gfc_expr *expr = omp_clauses->if_exprs[ifc];
4119627f7eb2Smrg 	bool ok = true;
4120627f7eb2Smrg 	if (!gfc_resolve_expr (expr)
4121627f7eb2Smrg 	    || expr->ts.type != BT_LOGICAL || expr->rank != 0)
4122627f7eb2Smrg 	  gfc_error ("IF clause at %L requires a scalar LOGICAL expression",
4123627f7eb2Smrg 		     &expr->where);
4124627f7eb2Smrg 	else if (if_without_mod)
4125627f7eb2Smrg 	  {
4126627f7eb2Smrg 	    gfc_error ("IF clause without modifier at %L used together with "
4127627f7eb2Smrg 		       "IF clauses with modifiers",
4128627f7eb2Smrg 		       &omp_clauses->if_expr->where);
4129627f7eb2Smrg 	    if_without_mod = false;
4130627f7eb2Smrg 	  }
4131627f7eb2Smrg 	else
4132627f7eb2Smrg 	  switch (code->op)
4133627f7eb2Smrg 	    {
4134627f7eb2Smrg 	    case EXEC_OMP_PARALLEL:
4135627f7eb2Smrg 	    case EXEC_OMP_PARALLEL_DO:
4136627f7eb2Smrg 	    case EXEC_OMP_PARALLEL_SECTIONS:
4137627f7eb2Smrg 	    case EXEC_OMP_PARALLEL_WORKSHARE:
4138627f7eb2Smrg 	    case EXEC_OMP_PARALLEL_DO_SIMD:
4139627f7eb2Smrg 	    case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
4140627f7eb2Smrg 	    case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
4141627f7eb2Smrg 	    case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
4142627f7eb2Smrg 	    case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
4143627f7eb2Smrg 	      ok = ifc == OMP_IF_PARALLEL;
4144627f7eb2Smrg 	      break;
4145627f7eb2Smrg 
4146627f7eb2Smrg 	    case EXEC_OMP_TASK:
4147627f7eb2Smrg 	      ok = ifc == OMP_IF_TASK;
4148627f7eb2Smrg 	      break;
4149627f7eb2Smrg 
4150627f7eb2Smrg 	    case EXEC_OMP_TASKLOOP:
4151627f7eb2Smrg 	    case EXEC_OMP_TASKLOOP_SIMD:
4152627f7eb2Smrg 	      ok = ifc == OMP_IF_TASKLOOP;
4153627f7eb2Smrg 	      break;
4154627f7eb2Smrg 
4155627f7eb2Smrg 	    case EXEC_OMP_TARGET:
4156627f7eb2Smrg 	    case EXEC_OMP_TARGET_TEAMS:
4157627f7eb2Smrg 	    case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
4158627f7eb2Smrg 	    case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
4159627f7eb2Smrg 	    case EXEC_OMP_TARGET_SIMD:
4160627f7eb2Smrg 	      ok = ifc == OMP_IF_TARGET;
4161627f7eb2Smrg 	      break;
4162627f7eb2Smrg 
4163627f7eb2Smrg 	    case EXEC_OMP_TARGET_DATA:
4164627f7eb2Smrg 	      ok = ifc == OMP_IF_TARGET_DATA;
4165627f7eb2Smrg 	      break;
4166627f7eb2Smrg 
4167627f7eb2Smrg 	    case EXEC_OMP_TARGET_UPDATE:
4168627f7eb2Smrg 	      ok = ifc == OMP_IF_TARGET_UPDATE;
4169627f7eb2Smrg 	      break;
4170627f7eb2Smrg 
4171627f7eb2Smrg 	    case EXEC_OMP_TARGET_ENTER_DATA:
4172627f7eb2Smrg 	      ok = ifc == OMP_IF_TARGET_ENTER_DATA;
4173627f7eb2Smrg 	      break;
4174627f7eb2Smrg 
4175627f7eb2Smrg 	    case EXEC_OMP_TARGET_EXIT_DATA:
4176627f7eb2Smrg 	      ok = ifc == OMP_IF_TARGET_EXIT_DATA;
4177627f7eb2Smrg 	      break;
4178627f7eb2Smrg 
4179627f7eb2Smrg 	    case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
4180627f7eb2Smrg 	    case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
4181627f7eb2Smrg 	    case EXEC_OMP_TARGET_PARALLEL:
4182627f7eb2Smrg 	    case EXEC_OMP_TARGET_PARALLEL_DO:
4183627f7eb2Smrg 	    case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
4184627f7eb2Smrg 	      ok = ifc == OMP_IF_TARGET || ifc == OMP_IF_PARALLEL;
4185627f7eb2Smrg 	      break;
4186627f7eb2Smrg 
4187627f7eb2Smrg 	    default:
4188627f7eb2Smrg 	      ok = false;
4189627f7eb2Smrg 	      break;
4190627f7eb2Smrg 	  }
4191627f7eb2Smrg 	if (!ok)
4192627f7eb2Smrg 	  {
4193627f7eb2Smrg 	    static const char *ifs[] = {
4194627f7eb2Smrg 	      "PARALLEL",
4195627f7eb2Smrg 	      "TASK",
4196627f7eb2Smrg 	      "TASKLOOP",
4197627f7eb2Smrg 	      "TARGET",
4198627f7eb2Smrg 	      "TARGET DATA",
4199627f7eb2Smrg 	      "TARGET UPDATE",
4200627f7eb2Smrg 	      "TARGET ENTER DATA",
4201627f7eb2Smrg 	      "TARGET EXIT DATA"
4202627f7eb2Smrg 	    };
4203627f7eb2Smrg 	    gfc_error ("IF clause modifier %s at %L not appropriate for "
4204627f7eb2Smrg 		       "the current OpenMP construct", ifs[ifc], &expr->where);
4205627f7eb2Smrg 	  }
4206627f7eb2Smrg       }
4207627f7eb2Smrg 
4208627f7eb2Smrg   if (omp_clauses->final_expr)
4209627f7eb2Smrg     {
4210627f7eb2Smrg       gfc_expr *expr = omp_clauses->final_expr;
4211627f7eb2Smrg       if (!gfc_resolve_expr (expr)
4212627f7eb2Smrg 	  || expr->ts.type != BT_LOGICAL || expr->rank != 0)
4213627f7eb2Smrg 	gfc_error ("FINAL clause at %L requires a scalar LOGICAL expression",
4214627f7eb2Smrg 		   &expr->where);
4215627f7eb2Smrg     }
4216627f7eb2Smrg   if (omp_clauses->num_threads)
4217627f7eb2Smrg     resolve_positive_int_expr (omp_clauses->num_threads, "NUM_THREADS");
4218627f7eb2Smrg   if (omp_clauses->chunk_size)
4219627f7eb2Smrg     {
4220627f7eb2Smrg       gfc_expr *expr = omp_clauses->chunk_size;
4221627f7eb2Smrg       if (!gfc_resolve_expr (expr)
4222627f7eb2Smrg 	  || expr->ts.type != BT_INTEGER || expr->rank != 0)
4223627f7eb2Smrg 	gfc_error ("SCHEDULE clause's chunk_size at %L requires "
4224627f7eb2Smrg 		   "a scalar INTEGER expression", &expr->where);
4225627f7eb2Smrg       else if (expr->expr_type == EXPR_CONSTANT
4226627f7eb2Smrg 	       && expr->ts.type == BT_INTEGER
4227627f7eb2Smrg 	       && mpz_sgn (expr->value.integer) <= 0)
4228627f7eb2Smrg 	gfc_warning (0, "INTEGER expression of SCHEDULE clause's chunk_size "
4229627f7eb2Smrg 		     "at %L must be positive", &expr->where);
4230627f7eb2Smrg     }
4231627f7eb2Smrg   if (omp_clauses->sched_kind != OMP_SCHED_NONE
4232627f7eb2Smrg       && omp_clauses->sched_nonmonotonic)
4233627f7eb2Smrg     {
4234627f7eb2Smrg       if (omp_clauses->sched_kind != OMP_SCHED_DYNAMIC
4235627f7eb2Smrg 	  && omp_clauses->sched_kind != OMP_SCHED_GUIDED)
4236627f7eb2Smrg 	{
4237627f7eb2Smrg 	  const char *p;
4238627f7eb2Smrg 	  switch (omp_clauses->sched_kind)
4239627f7eb2Smrg 	    {
4240627f7eb2Smrg 	    case OMP_SCHED_STATIC: p = "STATIC"; break;
4241627f7eb2Smrg 	    case OMP_SCHED_RUNTIME: p = "RUNTIME"; break;
4242627f7eb2Smrg 	    case OMP_SCHED_AUTO: p = "AUTO"; break;
4243627f7eb2Smrg 	    default: gcc_unreachable ();
4244627f7eb2Smrg 	    }
4245627f7eb2Smrg 	  gfc_error ("NONMONOTONIC modifier specified for %s schedule kind "
4246627f7eb2Smrg 		     "at %L", p, &code->loc);
4247627f7eb2Smrg 	}
4248627f7eb2Smrg       else if (omp_clauses->sched_monotonic)
4249627f7eb2Smrg 	gfc_error ("Both MONOTONIC and NONMONOTONIC schedule modifiers "
4250627f7eb2Smrg 		   "specified at %L", &code->loc);
4251627f7eb2Smrg       else if (omp_clauses->ordered)
4252627f7eb2Smrg 	gfc_error ("NONMONOTONIC schedule modifier specified with ORDERED "
4253627f7eb2Smrg 		   "clause at %L", &code->loc);
4254627f7eb2Smrg     }
4255627f7eb2Smrg 
4256627f7eb2Smrg   /* Check that no symbol appears on multiple clauses, except that
4257627f7eb2Smrg      a symbol can appear on both firstprivate and lastprivate.  */
4258627f7eb2Smrg   for (list = 0; list < OMP_LIST_NUM; list++)
4259627f7eb2Smrg     for (n = omp_clauses->lists[list]; n; n = n->next)
4260627f7eb2Smrg       {
4261627f7eb2Smrg 	n->sym->mark = 0;
4262*4c3eb207Smrg 	n->sym->comp_mark = 0;
4263627f7eb2Smrg 	if (n->sym->attr.flavor == FL_VARIABLE
4264627f7eb2Smrg 	    || n->sym->attr.proc_pointer
4265627f7eb2Smrg 	    || (!code && (!n->sym->attr.dummy || n->sym->ns != ns)))
4266627f7eb2Smrg 	  {
4267627f7eb2Smrg 	    if (!code && (!n->sym->attr.dummy || n->sym->ns != ns))
4268627f7eb2Smrg 	      gfc_error ("Variable %qs is not a dummy argument at %L",
4269627f7eb2Smrg 			 n->sym->name, &n->where);
4270627f7eb2Smrg 	    continue;
4271627f7eb2Smrg 	  }
4272627f7eb2Smrg 	if (n->sym->attr.flavor == FL_PROCEDURE
4273627f7eb2Smrg 	    && n->sym->result == n->sym
4274627f7eb2Smrg 	    && n->sym->attr.function)
4275627f7eb2Smrg 	  {
4276627f7eb2Smrg 	    if (gfc_current_ns->proc_name == n->sym
4277627f7eb2Smrg 		|| (gfc_current_ns->parent
4278627f7eb2Smrg 		    && gfc_current_ns->parent->proc_name == n->sym))
4279627f7eb2Smrg 	      continue;
4280627f7eb2Smrg 	    if (gfc_current_ns->proc_name->attr.entry_master)
4281627f7eb2Smrg 	      {
4282627f7eb2Smrg 		gfc_entry_list *el = gfc_current_ns->entries;
4283627f7eb2Smrg 		for (; el; el = el->next)
4284627f7eb2Smrg 		  if (el->sym == n->sym)
4285627f7eb2Smrg 		    break;
4286627f7eb2Smrg 		if (el)
4287627f7eb2Smrg 		  continue;
4288627f7eb2Smrg 	      }
4289627f7eb2Smrg 	    if (gfc_current_ns->parent
4290627f7eb2Smrg 		&& gfc_current_ns->parent->proc_name->attr.entry_master)
4291627f7eb2Smrg 	      {
4292627f7eb2Smrg 		gfc_entry_list *el = gfc_current_ns->parent->entries;
4293627f7eb2Smrg 		for (; el; el = el->next)
4294627f7eb2Smrg 		  if (el->sym == n->sym)
4295627f7eb2Smrg 		    break;
4296627f7eb2Smrg 		if (el)
4297627f7eb2Smrg 		  continue;
4298627f7eb2Smrg 	      }
4299627f7eb2Smrg 	  }
4300*4c3eb207Smrg 	if (list == OMP_LIST_MAP
4301*4c3eb207Smrg 	    && n->sym->attr.flavor == FL_PARAMETER)
4302*4c3eb207Smrg 	  {
4303*4c3eb207Smrg 	    if (openacc)
4304*4c3eb207Smrg 	      gfc_error ("Object %qs is not a variable at %L; parameters"
4305*4c3eb207Smrg 			 " cannot be and need not be copied", n->sym->name,
4306*4c3eb207Smrg 			 &n->where);
4307*4c3eb207Smrg 	    else
4308*4c3eb207Smrg 	      gfc_error ("Object %qs is not a variable at %L; parameters"
4309*4c3eb207Smrg 			 " cannot be and need not be mapped", n->sym->name,
4310*4c3eb207Smrg 			 &n->where);
4311*4c3eb207Smrg 	  }
4312*4c3eb207Smrg 	else
4313627f7eb2Smrg 	  gfc_error ("Object %qs is not a variable at %L", n->sym->name,
4314627f7eb2Smrg 		     &n->where);
4315627f7eb2Smrg       }
4316627f7eb2Smrg 
4317627f7eb2Smrg   for (list = 0; list < OMP_LIST_NUM; list++)
4318627f7eb2Smrg     if (list != OMP_LIST_FIRSTPRIVATE
4319627f7eb2Smrg 	&& list != OMP_LIST_LASTPRIVATE
4320627f7eb2Smrg 	&& list != OMP_LIST_ALIGNED
4321627f7eb2Smrg 	&& list != OMP_LIST_DEPEND
4322627f7eb2Smrg 	&& (list != OMP_LIST_MAP || openacc)
4323627f7eb2Smrg 	&& list != OMP_LIST_FROM
4324627f7eb2Smrg 	&& list != OMP_LIST_TO
4325627f7eb2Smrg 	&& (list != OMP_LIST_REDUCTION || !openacc))
4326627f7eb2Smrg       for (n = omp_clauses->lists[list]; n; n = n->next)
4327627f7eb2Smrg 	{
4328*4c3eb207Smrg 	  bool component_ref_p = false;
4329*4c3eb207Smrg 
4330*4c3eb207Smrg 	  /* Allow multiple components of the same (e.g. derived-type)
4331*4c3eb207Smrg 	     variable here.  Duplicate components are detected elsewhere.  */
4332*4c3eb207Smrg 	  if (n->expr && n->expr->expr_type == EXPR_VARIABLE)
4333*4c3eb207Smrg 	    for (gfc_ref *ref = n->expr->ref; ref; ref = ref->next)
4334*4c3eb207Smrg 	      if (ref->type == REF_COMPONENT)
4335*4c3eb207Smrg 		component_ref_p = true;
4336*4c3eb207Smrg 	  if ((!component_ref_p && n->sym->comp_mark)
4337*4c3eb207Smrg 	      || (component_ref_p && n->sym->mark))
4338*4c3eb207Smrg 	    gfc_error ("Symbol %qs has mixed component and non-component "
4339*4c3eb207Smrg 		       "accesses at %L", n->sym->name, &n->where);
4340*4c3eb207Smrg 	  else if (n->sym->mark)
4341627f7eb2Smrg 	    gfc_error ("Symbol %qs present on multiple clauses at %L",
4342627f7eb2Smrg 		       n->sym->name, &n->where);
4343627f7eb2Smrg 	  else
4344*4c3eb207Smrg 	    {
4345*4c3eb207Smrg 	      if (component_ref_p)
4346*4c3eb207Smrg 		n->sym->comp_mark = 1;
4347*4c3eb207Smrg 	      else
4348627f7eb2Smrg 		n->sym->mark = 1;
4349627f7eb2Smrg 	    }
4350*4c3eb207Smrg 	}
4351627f7eb2Smrg 
4352627f7eb2Smrg   gcc_assert (OMP_LIST_LASTPRIVATE == OMP_LIST_FIRSTPRIVATE + 1);
4353627f7eb2Smrg   for (list = OMP_LIST_FIRSTPRIVATE; list <= OMP_LIST_LASTPRIVATE; list++)
4354627f7eb2Smrg     for (n = omp_clauses->lists[list]; n; n = n->next)
4355627f7eb2Smrg       if (n->sym->mark)
4356627f7eb2Smrg 	{
4357627f7eb2Smrg 	  gfc_error ("Symbol %qs present on multiple clauses at %L",
4358627f7eb2Smrg 		     n->sym->name, &n->where);
4359627f7eb2Smrg 	  n->sym->mark = 0;
4360627f7eb2Smrg 	}
4361627f7eb2Smrg 
4362627f7eb2Smrg   for (n = omp_clauses->lists[OMP_LIST_FIRSTPRIVATE]; n; n = n->next)
4363627f7eb2Smrg     {
4364627f7eb2Smrg       if (n->sym->mark)
4365627f7eb2Smrg 	gfc_error ("Symbol %qs present on multiple clauses at %L",
4366627f7eb2Smrg 		   n->sym->name, &n->where);
4367627f7eb2Smrg       else
4368627f7eb2Smrg 	n->sym->mark = 1;
4369627f7eb2Smrg     }
4370627f7eb2Smrg   for (n = omp_clauses->lists[OMP_LIST_LASTPRIVATE]; n; n = n->next)
4371627f7eb2Smrg     n->sym->mark = 0;
4372627f7eb2Smrg 
4373627f7eb2Smrg   for (n = omp_clauses->lists[OMP_LIST_LASTPRIVATE]; n; n = n->next)
4374627f7eb2Smrg     {
4375627f7eb2Smrg       if (n->sym->mark)
4376627f7eb2Smrg 	gfc_error ("Symbol %qs present on multiple clauses at %L",
4377627f7eb2Smrg 		   n->sym->name, &n->where);
4378627f7eb2Smrg       else
4379627f7eb2Smrg 	n->sym->mark = 1;
4380627f7eb2Smrg     }
4381627f7eb2Smrg 
4382627f7eb2Smrg   for (n = omp_clauses->lists[OMP_LIST_ALIGNED]; n; n = n->next)
4383627f7eb2Smrg     n->sym->mark = 0;
4384627f7eb2Smrg 
4385627f7eb2Smrg   for (n = omp_clauses->lists[OMP_LIST_ALIGNED]; n; n = n->next)
4386627f7eb2Smrg     {
4387627f7eb2Smrg       if (n->sym->mark)
4388627f7eb2Smrg 	gfc_error ("Symbol %qs present on multiple clauses at %L",
4389627f7eb2Smrg 		   n->sym->name, &n->where);
4390627f7eb2Smrg       else
4391627f7eb2Smrg 	n->sym->mark = 1;
4392627f7eb2Smrg     }
4393627f7eb2Smrg 
4394627f7eb2Smrg   /* OpenACC reductions.  */
4395627f7eb2Smrg   if (openacc)
4396627f7eb2Smrg     {
4397627f7eb2Smrg       for (n = omp_clauses->lists[OMP_LIST_REDUCTION]; n; n = n->next)
4398627f7eb2Smrg 	n->sym->mark = 0;
4399627f7eb2Smrg 
4400627f7eb2Smrg       for (n = omp_clauses->lists[OMP_LIST_REDUCTION]; n; n = n->next)
4401627f7eb2Smrg 	{
4402627f7eb2Smrg 	  if (n->sym->mark)
4403627f7eb2Smrg 	    gfc_error ("Symbol %qs present on multiple clauses at %L",
4404627f7eb2Smrg 		       n->sym->name, &n->where);
4405627f7eb2Smrg 	  else
4406627f7eb2Smrg 	    n->sym->mark = 1;
4407627f7eb2Smrg 
4408627f7eb2Smrg 	  /* OpenACC does not support reductions on arrays.  */
4409627f7eb2Smrg 	  if (n->sym->as)
4410627f7eb2Smrg 	    gfc_error ("Array %qs is not permitted in reduction at %L",
4411627f7eb2Smrg 		       n->sym->name, &n->where);
4412627f7eb2Smrg 	}
4413627f7eb2Smrg     }
4414627f7eb2Smrg 
4415627f7eb2Smrg   for (n = omp_clauses->lists[OMP_LIST_TO]; n; n = n->next)
4416627f7eb2Smrg     n->sym->mark = 0;
4417627f7eb2Smrg   for (n = omp_clauses->lists[OMP_LIST_FROM]; n; n = n->next)
4418627f7eb2Smrg     if (n->expr == NULL)
4419627f7eb2Smrg       n->sym->mark = 1;
4420627f7eb2Smrg   for (n = omp_clauses->lists[OMP_LIST_TO]; n; n = n->next)
4421627f7eb2Smrg     {
4422627f7eb2Smrg       if (n->expr == NULL && n->sym->mark)
4423627f7eb2Smrg 	gfc_error ("Symbol %qs present on both FROM and TO clauses at %L",
4424627f7eb2Smrg 		   n->sym->name, &n->where);
4425627f7eb2Smrg       else
4426627f7eb2Smrg 	n->sym->mark = 1;
4427627f7eb2Smrg     }
4428627f7eb2Smrg 
4429627f7eb2Smrg   for (list = 0; list < OMP_LIST_NUM; list++)
4430627f7eb2Smrg     if ((n = omp_clauses->lists[list]) != NULL)
4431627f7eb2Smrg       {
4432627f7eb2Smrg 	const char *name;
4433627f7eb2Smrg 
4434627f7eb2Smrg 	if (list < OMP_LIST_NUM)
4435627f7eb2Smrg 	  name = clause_names[list];
4436627f7eb2Smrg 	else
4437627f7eb2Smrg 	  gcc_unreachable ();
4438627f7eb2Smrg 
4439627f7eb2Smrg 	switch (list)
4440627f7eb2Smrg 	  {
4441627f7eb2Smrg 	  case OMP_LIST_COPYIN:
4442627f7eb2Smrg 	    for (; n != NULL; n = n->next)
4443627f7eb2Smrg 	      {
4444627f7eb2Smrg 		if (!n->sym->attr.threadprivate)
4445627f7eb2Smrg 		  gfc_error ("Non-THREADPRIVATE object %qs in COPYIN clause"
4446627f7eb2Smrg 			     " at %L", n->sym->name, &n->where);
4447627f7eb2Smrg 	      }
4448627f7eb2Smrg 	    break;
4449627f7eb2Smrg 	  case OMP_LIST_COPYPRIVATE:
4450627f7eb2Smrg 	    for (; n != NULL; n = n->next)
4451627f7eb2Smrg 	      {
4452627f7eb2Smrg 		if (n->sym->as && n->sym->as->type == AS_ASSUMED_SIZE)
4453627f7eb2Smrg 		  gfc_error ("Assumed size array %qs in COPYPRIVATE clause "
4454627f7eb2Smrg 			     "at %L", n->sym->name, &n->where);
4455627f7eb2Smrg 		if (n->sym->attr.pointer && n->sym->attr.intent == INTENT_IN)
4456627f7eb2Smrg 		  gfc_error ("INTENT(IN) POINTER %qs in COPYPRIVATE clause "
4457627f7eb2Smrg 			     "at %L", n->sym->name, &n->where);
4458627f7eb2Smrg 	      }
4459627f7eb2Smrg 	    break;
4460627f7eb2Smrg 	  case OMP_LIST_SHARED:
4461627f7eb2Smrg 	    for (; n != NULL; n = n->next)
4462627f7eb2Smrg 	      {
4463627f7eb2Smrg 		if (n->sym->attr.threadprivate)
4464627f7eb2Smrg 		  gfc_error ("THREADPRIVATE object %qs in SHARED clause at "
4465627f7eb2Smrg 			     "%L", n->sym->name, &n->where);
4466627f7eb2Smrg 		if (n->sym->attr.cray_pointee)
4467627f7eb2Smrg 		  gfc_error ("Cray pointee %qs in SHARED clause at %L",
4468627f7eb2Smrg 			    n->sym->name, &n->where);
4469627f7eb2Smrg 		if (n->sym->attr.associate_var)
4470627f7eb2Smrg 		  gfc_error ("ASSOCIATE name %qs in SHARED clause at %L",
4471627f7eb2Smrg 			     n->sym->name, &n->where);
4472627f7eb2Smrg 	      }
4473627f7eb2Smrg 	    break;
4474627f7eb2Smrg 	  case OMP_LIST_ALIGNED:
4475627f7eb2Smrg 	    for (; n != NULL; n = n->next)
4476627f7eb2Smrg 	      {
4477627f7eb2Smrg 		if (!n->sym->attr.pointer
4478627f7eb2Smrg 		    && !n->sym->attr.allocatable
4479627f7eb2Smrg 		    && !n->sym->attr.cray_pointer
4480627f7eb2Smrg 		    && (n->sym->ts.type != BT_DERIVED
4481627f7eb2Smrg 			|| (n->sym->ts.u.derived->from_intmod
4482627f7eb2Smrg 			    != INTMOD_ISO_C_BINDING)
4483627f7eb2Smrg 			|| (n->sym->ts.u.derived->intmod_sym_id
4484627f7eb2Smrg 			    != ISOCBINDING_PTR)))
4485627f7eb2Smrg 		  gfc_error ("%qs in ALIGNED clause must be POINTER, "
4486627f7eb2Smrg 			     "ALLOCATABLE, Cray pointer or C_PTR at %L",
4487627f7eb2Smrg 			     n->sym->name, &n->where);
4488627f7eb2Smrg 		else if (n->expr)
4489627f7eb2Smrg 		  {
4490627f7eb2Smrg 		    gfc_expr *expr = n->expr;
4491627f7eb2Smrg 		    int alignment = 0;
4492627f7eb2Smrg 		    if (!gfc_resolve_expr (expr)
4493627f7eb2Smrg 			|| expr->ts.type != BT_INTEGER
4494627f7eb2Smrg 			|| expr->rank != 0
4495627f7eb2Smrg 			|| gfc_extract_int (expr, &alignment)
4496627f7eb2Smrg 			|| alignment <= 0)
4497627f7eb2Smrg 		      gfc_error ("%qs in ALIGNED clause at %L requires a scalar "
4498627f7eb2Smrg 				 "positive constant integer alignment "
4499627f7eb2Smrg 				 "expression", n->sym->name, &n->where);
4500627f7eb2Smrg 		  }
4501627f7eb2Smrg 	      }
4502627f7eb2Smrg 	    break;
4503627f7eb2Smrg 	  case OMP_LIST_DEPEND:
4504627f7eb2Smrg 	  case OMP_LIST_MAP:
4505627f7eb2Smrg 	  case OMP_LIST_TO:
4506627f7eb2Smrg 	  case OMP_LIST_FROM:
4507627f7eb2Smrg 	  case OMP_LIST_CACHE:
4508627f7eb2Smrg 	    for (; n != NULL; n = n->next)
4509627f7eb2Smrg 	      {
4510627f7eb2Smrg 		if (list == OMP_LIST_DEPEND)
4511627f7eb2Smrg 		  {
4512627f7eb2Smrg 		    if (n->u.depend_op == OMP_DEPEND_SINK_FIRST
4513627f7eb2Smrg 			|| n->u.depend_op == OMP_DEPEND_SINK)
4514627f7eb2Smrg 		      {
4515627f7eb2Smrg 			if (code->op != EXEC_OMP_ORDERED)
4516627f7eb2Smrg 			  gfc_error ("SINK dependence type only allowed "
4517627f7eb2Smrg 				     "on ORDERED directive at %L", &n->where);
4518627f7eb2Smrg 			else if (omp_clauses->depend_source)
4519627f7eb2Smrg 			  {
4520627f7eb2Smrg 			    gfc_error ("DEPEND SINK used together with "
4521627f7eb2Smrg 				       "DEPEND SOURCE on the same construct "
4522627f7eb2Smrg 				       "at %L", &n->where);
4523627f7eb2Smrg 			    omp_clauses->depend_source = false;
4524627f7eb2Smrg 			  }
4525627f7eb2Smrg 			else if (n->expr)
4526627f7eb2Smrg 			  {
4527627f7eb2Smrg 			    if (!gfc_resolve_expr (n->expr)
4528627f7eb2Smrg 				|| n->expr->ts.type != BT_INTEGER
4529627f7eb2Smrg 				|| n->expr->rank != 0)
4530627f7eb2Smrg 			      gfc_error ("SINK addend not a constant integer "
4531627f7eb2Smrg 					 "at %L", &n->where);
4532627f7eb2Smrg 			  }
4533627f7eb2Smrg 			continue;
4534627f7eb2Smrg 		      }
4535627f7eb2Smrg 		    else if (code->op == EXEC_OMP_ORDERED)
4536627f7eb2Smrg 		      gfc_error ("Only SOURCE or SINK dependence types "
4537627f7eb2Smrg 				 "are allowed on ORDERED directive at %L",
4538627f7eb2Smrg 				 &n->where);
4539627f7eb2Smrg 		  }
4540*4c3eb207Smrg 		gfc_ref *array_ref = NULL;
4541*4c3eb207Smrg 		bool resolved = false;
4542627f7eb2Smrg 		if (n->expr)
4543627f7eb2Smrg 		  {
4544*4c3eb207Smrg 		    array_ref = n->expr->ref;
4545*4c3eb207Smrg 		    resolved = gfc_resolve_expr (n->expr);
4546*4c3eb207Smrg 
4547*4c3eb207Smrg 		    /* Look through component refs to find last array
4548*4c3eb207Smrg 		       reference.  */
4549*4c3eb207Smrg 		    if (openacc && resolved)
4550*4c3eb207Smrg 		      {
4551*4c3eb207Smrg 			/* The "!$acc cache" directive allows rectangular
4552*4c3eb207Smrg 			   subarrays to be specified, with some restrictions
4553*4c3eb207Smrg 			   on the form of bounds (not implemented).
4554*4c3eb207Smrg 			   Only raise an error here if we're really sure the
4555*4c3eb207Smrg 			   array isn't contiguous.  An expression such as
4556*4c3eb207Smrg 			   arr(-n:n,-n:n) could be contiguous even if it looks
4557*4c3eb207Smrg 			   like it may not be.  */
4558*4c3eb207Smrg 			if (list != OMP_LIST_CACHE
4559*4c3eb207Smrg 			    && !gfc_is_simply_contiguous (n->expr, false, true)
4560*4c3eb207Smrg 			    && gfc_is_not_contiguous (n->expr))
4561*4c3eb207Smrg 			  gfc_error ("Array is not contiguous at %L",
4562*4c3eb207Smrg 				     &n->where);
4563*4c3eb207Smrg 
4564*4c3eb207Smrg 			while (array_ref
4565*4c3eb207Smrg 			       && (array_ref->type == REF_COMPONENT
4566*4c3eb207Smrg 				   || (array_ref->type == REF_ARRAY
4567*4c3eb207Smrg 				       && array_ref->next
4568*4c3eb207Smrg 				       && (array_ref->next->type
4569*4c3eb207Smrg 					   == REF_COMPONENT))))
4570*4c3eb207Smrg 			  array_ref = array_ref->next;
4571*4c3eb207Smrg 		      }
4572*4c3eb207Smrg 		  }
4573*4c3eb207Smrg 		if (array_ref
4574*4c3eb207Smrg 		    || (n->expr
4575*4c3eb207Smrg 			&& (!resolved || n->expr->expr_type != EXPR_VARIABLE)))
4576*4c3eb207Smrg 		  {
4577*4c3eb207Smrg 		    if (!resolved
4578627f7eb2Smrg 			|| n->expr->expr_type != EXPR_VARIABLE
4579*4c3eb207Smrg 			|| array_ref->next
4580*4c3eb207Smrg 			|| array_ref->type != REF_ARRAY)
4581627f7eb2Smrg 		      gfc_error ("%qs in %s clause at %L is not a proper "
4582627f7eb2Smrg 				 "array section", n->sym->name, name,
4583627f7eb2Smrg 				 &n->where);
4584627f7eb2Smrg 		    else
4585627f7eb2Smrg 		      {
4586627f7eb2Smrg 			int i;
4587*4c3eb207Smrg 			gfc_array_ref *ar = &array_ref->u.ar;
4588627f7eb2Smrg 			for (i = 0; i < ar->dimen; i++)
4589627f7eb2Smrg 			  if (ar->stride[i])
4590627f7eb2Smrg 			    {
4591627f7eb2Smrg 			      gfc_error ("Stride should not be specified for "
4592627f7eb2Smrg 					 "array section in %s clause at %L",
4593627f7eb2Smrg 					 name, &n->where);
4594627f7eb2Smrg 			      break;
4595627f7eb2Smrg 			    }
4596627f7eb2Smrg 			  else if (ar->dimen_type[i] != DIMEN_ELEMENT
4597627f7eb2Smrg 				   && ar->dimen_type[i] != DIMEN_RANGE)
4598627f7eb2Smrg 			    {
4599627f7eb2Smrg 			      gfc_error ("%qs in %s clause at %L is not a "
4600627f7eb2Smrg 					 "proper array section",
4601627f7eb2Smrg 					 n->sym->name, name, &n->where);
4602627f7eb2Smrg 			      break;
4603627f7eb2Smrg 			    }
4604627f7eb2Smrg 			  else if (list == OMP_LIST_DEPEND
4605627f7eb2Smrg 				   && ar->start[i]
4606627f7eb2Smrg 				   && ar->start[i]->expr_type == EXPR_CONSTANT
4607627f7eb2Smrg 				   && ar->end[i]
4608627f7eb2Smrg 				   && ar->end[i]->expr_type == EXPR_CONSTANT
4609627f7eb2Smrg 				   && mpz_cmp (ar->start[i]->value.integer,
4610627f7eb2Smrg 					       ar->end[i]->value.integer) > 0)
4611627f7eb2Smrg 			    {
4612627f7eb2Smrg 			      gfc_error ("%qs in DEPEND clause at %L is a "
4613627f7eb2Smrg 					 "zero size array section",
4614627f7eb2Smrg 					 n->sym->name, &n->where);
4615627f7eb2Smrg 			      break;
4616627f7eb2Smrg 			    }
4617627f7eb2Smrg 		      }
4618627f7eb2Smrg 		  }
4619627f7eb2Smrg 		else if (openacc)
4620627f7eb2Smrg 		  {
4621627f7eb2Smrg 		    if (list == OMP_LIST_MAP
4622627f7eb2Smrg 			&& n->u.map_op == OMP_MAP_FORCE_DEVICEPTR)
4623627f7eb2Smrg 		      resolve_oacc_deviceptr_clause (n->sym, n->where, name);
4624627f7eb2Smrg 		    else
4625627f7eb2Smrg 		      resolve_oacc_data_clauses (n->sym, n->where, name);
4626627f7eb2Smrg 		  }
4627627f7eb2Smrg 		else if (list != OMP_LIST_DEPEND
4628627f7eb2Smrg 			 && n->sym->as
4629627f7eb2Smrg 			 && n->sym->as->type == AS_ASSUMED_SIZE)
4630627f7eb2Smrg 		  gfc_error ("Assumed size array %qs in %s clause at %L",
4631627f7eb2Smrg 			     n->sym->name, name, &n->where);
4632627f7eb2Smrg 		if (list == OMP_LIST_MAP && !openacc)
4633627f7eb2Smrg 		  switch (code->op)
4634627f7eb2Smrg 		    {
4635627f7eb2Smrg 		    case EXEC_OMP_TARGET:
4636627f7eb2Smrg 		    case EXEC_OMP_TARGET_DATA:
4637627f7eb2Smrg 		      switch (n->u.map_op)
4638627f7eb2Smrg 			{
4639627f7eb2Smrg 			case OMP_MAP_TO:
4640627f7eb2Smrg 			case OMP_MAP_ALWAYS_TO:
4641627f7eb2Smrg 			case OMP_MAP_FROM:
4642627f7eb2Smrg 			case OMP_MAP_ALWAYS_FROM:
4643627f7eb2Smrg 			case OMP_MAP_TOFROM:
4644627f7eb2Smrg 			case OMP_MAP_ALWAYS_TOFROM:
4645627f7eb2Smrg 			case OMP_MAP_ALLOC:
4646627f7eb2Smrg 			  break;
4647627f7eb2Smrg 			default:
4648627f7eb2Smrg 			  gfc_error ("TARGET%s with map-type other than TO, "
4649627f7eb2Smrg 				     "FROM, TOFROM, or ALLOC on MAP clause "
4650627f7eb2Smrg 				     "at %L",
4651627f7eb2Smrg 				     code->op == EXEC_OMP_TARGET
4652627f7eb2Smrg 				     ? "" : " DATA", &n->where);
4653627f7eb2Smrg 			  break;
4654627f7eb2Smrg 			}
4655627f7eb2Smrg 		      break;
4656627f7eb2Smrg 		    case EXEC_OMP_TARGET_ENTER_DATA:
4657627f7eb2Smrg 		      switch (n->u.map_op)
4658627f7eb2Smrg 			{
4659627f7eb2Smrg 			case OMP_MAP_TO:
4660627f7eb2Smrg 			case OMP_MAP_ALWAYS_TO:
4661627f7eb2Smrg 			case OMP_MAP_ALLOC:
4662627f7eb2Smrg 			  break;
4663627f7eb2Smrg 			default:
4664627f7eb2Smrg 			  gfc_error ("TARGET ENTER DATA with map-type other "
4665627f7eb2Smrg 				     "than TO, or ALLOC on MAP clause at %L",
4666627f7eb2Smrg 				     &n->where);
4667627f7eb2Smrg 			  break;
4668627f7eb2Smrg 			}
4669627f7eb2Smrg 		      break;
4670627f7eb2Smrg 		    case EXEC_OMP_TARGET_EXIT_DATA:
4671627f7eb2Smrg 		      switch (n->u.map_op)
4672627f7eb2Smrg 			{
4673627f7eb2Smrg 			case OMP_MAP_FROM:
4674627f7eb2Smrg 			case OMP_MAP_ALWAYS_FROM:
4675627f7eb2Smrg 			case OMP_MAP_RELEASE:
4676627f7eb2Smrg 			case OMP_MAP_DELETE:
4677627f7eb2Smrg 			  break;
4678627f7eb2Smrg 			default:
4679627f7eb2Smrg 			  gfc_error ("TARGET EXIT DATA with map-type other "
4680627f7eb2Smrg 				     "than FROM, RELEASE, or DELETE on MAP "
4681627f7eb2Smrg 				     "clause at %L", &n->where);
4682627f7eb2Smrg 			  break;
4683627f7eb2Smrg 			}
4684627f7eb2Smrg 		      break;
4685627f7eb2Smrg 		    default:
4686627f7eb2Smrg 		      break;
4687627f7eb2Smrg 		    }
4688627f7eb2Smrg 	      }
4689627f7eb2Smrg 
4690627f7eb2Smrg 	    if (list != OMP_LIST_DEPEND)
4691627f7eb2Smrg 	      for (n = omp_clauses->lists[list]; n != NULL; n = n->next)
4692627f7eb2Smrg 		{
4693627f7eb2Smrg 		  n->sym->attr.referenced = 1;
4694627f7eb2Smrg 		  if (n->sym->attr.threadprivate)
4695627f7eb2Smrg 		    gfc_error ("THREADPRIVATE object %qs in %s clause at %L",
4696627f7eb2Smrg 			       n->sym->name, name, &n->where);
4697627f7eb2Smrg 		  if (n->sym->attr.cray_pointee)
4698627f7eb2Smrg 		    gfc_error ("Cray pointee %qs in %s clause at %L",
4699627f7eb2Smrg 			       n->sym->name, name, &n->where);
4700627f7eb2Smrg 		}
4701627f7eb2Smrg 	    break;
4702627f7eb2Smrg 	  case OMP_LIST_IS_DEVICE_PTR:
4703*4c3eb207Smrg 	    if (!n->sym->attr.dummy)
4704*4c3eb207Smrg 	      gfc_error ("Non-dummy object %qs in %s clause at %L",
4705*4c3eb207Smrg 			 n->sym->name, name, &n->where);
4706*4c3eb207Smrg 	    if (n->sym->attr.allocatable
4707*4c3eb207Smrg 		|| (n->sym->ts.type == BT_CLASS
4708*4c3eb207Smrg 		    && CLASS_DATA (n->sym)->attr.allocatable))
4709*4c3eb207Smrg 	      gfc_error ("ALLOCATABLE object %qs in %s clause at %L",
4710*4c3eb207Smrg 			 n->sym->name, name, &n->where);
4711*4c3eb207Smrg 	    if (n->sym->attr.pointer
4712*4c3eb207Smrg 		|| (n->sym->ts.type == BT_CLASS
4713*4c3eb207Smrg 		    && CLASS_DATA (n->sym)->attr.pointer))
4714*4c3eb207Smrg 	      gfc_error ("POINTER object %qs in %s clause at %L",
4715*4c3eb207Smrg 			 n->sym->name, name, &n->where);
4716*4c3eb207Smrg 	    if (n->sym->attr.value)
4717*4c3eb207Smrg 	      gfc_error ("VALUE object %qs in %s clause at %L",
4718*4c3eb207Smrg 			 n->sym->name, name, &n->where);
4719*4c3eb207Smrg 	    break;
4720627f7eb2Smrg 	  case OMP_LIST_USE_DEVICE_PTR:
4721*4c3eb207Smrg 	  case OMP_LIST_USE_DEVICE_ADDR:
4722*4c3eb207Smrg 	    /* FIXME: Handle OMP_LIST_USE_DEVICE_PTR.  */
4723627f7eb2Smrg 	    break;
4724627f7eb2Smrg 	  default:
4725627f7eb2Smrg 	    for (; n != NULL; n = n->next)
4726627f7eb2Smrg 	      {
4727627f7eb2Smrg 		bool bad = false;
4728627f7eb2Smrg 		if (n->sym->attr.threadprivate)
4729627f7eb2Smrg 		  gfc_error ("THREADPRIVATE object %qs in %s clause at %L",
4730627f7eb2Smrg 			     n->sym->name, name, &n->where);
4731627f7eb2Smrg 		if (n->sym->attr.cray_pointee)
4732627f7eb2Smrg 		  gfc_error ("Cray pointee %qs in %s clause at %L",
4733627f7eb2Smrg 			    n->sym->name, name, &n->where);
4734627f7eb2Smrg 		if (n->sym->attr.associate_var)
4735627f7eb2Smrg 		  gfc_error ("ASSOCIATE name %qs in %s clause at %L",
4736627f7eb2Smrg 			     n->sym->name, name, &n->where);
4737627f7eb2Smrg 		if (list != OMP_LIST_PRIVATE)
4738627f7eb2Smrg 		  {
4739627f7eb2Smrg 		    if (n->sym->attr.proc_pointer && list == OMP_LIST_REDUCTION)
4740627f7eb2Smrg 		      gfc_error ("Procedure pointer %qs in %s clause at %L",
4741627f7eb2Smrg 				 n->sym->name, name, &n->where);
4742627f7eb2Smrg 		    if (n->sym->attr.pointer && list == OMP_LIST_REDUCTION)
4743627f7eb2Smrg 		      gfc_error ("POINTER object %qs in %s clause at %L",
4744627f7eb2Smrg 				 n->sym->name, name, &n->where);
4745627f7eb2Smrg 		    if (n->sym->attr.cray_pointer && list == OMP_LIST_REDUCTION)
4746627f7eb2Smrg 		      gfc_error ("Cray pointer %qs in %s clause at %L",
4747627f7eb2Smrg 				 n->sym->name, name, &n->where);
4748627f7eb2Smrg 		  }
4749627f7eb2Smrg 		if (code
4750*4c3eb207Smrg 		    && (oacc_is_loop (code)
4751*4c3eb207Smrg 			|| code->op == EXEC_OACC_PARALLEL
4752*4c3eb207Smrg 			|| code->op == EXEC_OACC_SERIAL))
4753627f7eb2Smrg 		  check_array_not_assumed (n->sym, n->where, name);
4754627f7eb2Smrg 		else if (n->sym->as && n->sym->as->type == AS_ASSUMED_SIZE)
4755627f7eb2Smrg 		  gfc_error ("Assumed size array %qs in %s clause at %L",
4756627f7eb2Smrg 			     n->sym->name, name, &n->where);
4757627f7eb2Smrg 		if (n->sym->attr.in_namelist && list != OMP_LIST_REDUCTION)
4758627f7eb2Smrg 		  gfc_error ("Variable %qs in %s clause is used in "
4759627f7eb2Smrg 			     "NAMELIST statement at %L",
4760627f7eb2Smrg 			     n->sym->name, name, &n->where);
4761627f7eb2Smrg 		if (n->sym->attr.pointer && n->sym->attr.intent == INTENT_IN)
4762627f7eb2Smrg 		  switch (list)
4763627f7eb2Smrg 		    {
4764627f7eb2Smrg 		    case OMP_LIST_PRIVATE:
4765627f7eb2Smrg 		    case OMP_LIST_LASTPRIVATE:
4766627f7eb2Smrg 		    case OMP_LIST_LINEAR:
4767627f7eb2Smrg 		    /* case OMP_LIST_REDUCTION: */
4768627f7eb2Smrg 		      gfc_error ("INTENT(IN) POINTER %qs in %s clause at %L",
4769627f7eb2Smrg 				 n->sym->name, name, &n->where);
4770627f7eb2Smrg 		      break;
4771627f7eb2Smrg 		    default:
4772627f7eb2Smrg 		      break;
4773627f7eb2Smrg 		    }
4774627f7eb2Smrg 
4775627f7eb2Smrg 		switch (list)
4776627f7eb2Smrg 		  {
4777627f7eb2Smrg 		  case OMP_LIST_REDUCTION:
4778627f7eb2Smrg 		    switch (n->u.reduction_op)
4779627f7eb2Smrg 		      {
4780627f7eb2Smrg 		      case OMP_REDUCTION_PLUS:
4781627f7eb2Smrg 		      case OMP_REDUCTION_TIMES:
4782627f7eb2Smrg 		      case OMP_REDUCTION_MINUS:
4783627f7eb2Smrg 			if (!gfc_numeric_ts (&n->sym->ts))
4784627f7eb2Smrg 			  bad = true;
4785627f7eb2Smrg 			break;
4786627f7eb2Smrg 		      case OMP_REDUCTION_AND:
4787627f7eb2Smrg 		      case OMP_REDUCTION_OR:
4788627f7eb2Smrg 		      case OMP_REDUCTION_EQV:
4789627f7eb2Smrg 		      case OMP_REDUCTION_NEQV:
4790627f7eb2Smrg 			if (n->sym->ts.type != BT_LOGICAL)
4791627f7eb2Smrg 			  bad = true;
4792627f7eb2Smrg 			break;
4793627f7eb2Smrg 		      case OMP_REDUCTION_MAX:
4794627f7eb2Smrg 		      case OMP_REDUCTION_MIN:
4795627f7eb2Smrg 			if (n->sym->ts.type != BT_INTEGER
4796627f7eb2Smrg 			    && n->sym->ts.type != BT_REAL)
4797627f7eb2Smrg 			  bad = true;
4798627f7eb2Smrg 			break;
4799627f7eb2Smrg 		      case OMP_REDUCTION_IAND:
4800627f7eb2Smrg 		      case OMP_REDUCTION_IOR:
4801627f7eb2Smrg 		      case OMP_REDUCTION_IEOR:
4802627f7eb2Smrg 			if (n->sym->ts.type != BT_INTEGER)
4803627f7eb2Smrg 			  bad = true;
4804627f7eb2Smrg 			break;
4805627f7eb2Smrg 		      case OMP_REDUCTION_USER:
4806627f7eb2Smrg 			bad = true;
4807627f7eb2Smrg 			break;
4808627f7eb2Smrg 		      default:
4809627f7eb2Smrg 			break;
4810627f7eb2Smrg 		      }
4811627f7eb2Smrg 		    if (!bad)
4812627f7eb2Smrg 		      n->udr = NULL;
4813627f7eb2Smrg 		    else
4814627f7eb2Smrg 		      {
4815627f7eb2Smrg 			const char *udr_name = NULL;
4816627f7eb2Smrg 			if (n->udr)
4817627f7eb2Smrg 			  {
4818627f7eb2Smrg 			    udr_name = n->udr->udr->name;
4819627f7eb2Smrg 			    n->udr->udr
4820627f7eb2Smrg 			      = gfc_find_omp_udr (NULL, udr_name,
4821627f7eb2Smrg 						  &n->sym->ts);
4822627f7eb2Smrg 			    if (n->udr->udr == NULL)
4823627f7eb2Smrg 			      {
4824627f7eb2Smrg 				free (n->udr);
4825627f7eb2Smrg 				n->udr = NULL;
4826627f7eb2Smrg 			      }
4827627f7eb2Smrg 			  }
4828627f7eb2Smrg 			if (n->udr == NULL)
4829627f7eb2Smrg 			  {
4830627f7eb2Smrg 			    if (udr_name == NULL)
4831627f7eb2Smrg 			      switch (n->u.reduction_op)
4832627f7eb2Smrg 				{
4833627f7eb2Smrg 				case OMP_REDUCTION_PLUS:
4834627f7eb2Smrg 				case OMP_REDUCTION_TIMES:
4835627f7eb2Smrg 				case OMP_REDUCTION_MINUS:
4836627f7eb2Smrg 				case OMP_REDUCTION_AND:
4837627f7eb2Smrg 				case OMP_REDUCTION_OR:
4838627f7eb2Smrg 				case OMP_REDUCTION_EQV:
4839627f7eb2Smrg 				case OMP_REDUCTION_NEQV:
4840627f7eb2Smrg 				  udr_name = gfc_op2string ((gfc_intrinsic_op)
4841627f7eb2Smrg 							    n->u.reduction_op);
4842627f7eb2Smrg 				  break;
4843627f7eb2Smrg 				case OMP_REDUCTION_MAX:
4844627f7eb2Smrg 				  udr_name = "max";
4845627f7eb2Smrg 				  break;
4846627f7eb2Smrg 				case OMP_REDUCTION_MIN:
4847627f7eb2Smrg 				  udr_name = "min";
4848627f7eb2Smrg 				  break;
4849627f7eb2Smrg 				case OMP_REDUCTION_IAND:
4850627f7eb2Smrg 				  udr_name = "iand";
4851627f7eb2Smrg 				  break;
4852627f7eb2Smrg 				case OMP_REDUCTION_IOR:
4853627f7eb2Smrg 				  udr_name = "ior";
4854627f7eb2Smrg 				  break;
4855627f7eb2Smrg 				case OMP_REDUCTION_IEOR:
4856627f7eb2Smrg 				  udr_name = "ieor";
4857627f7eb2Smrg 				  break;
4858627f7eb2Smrg 				default:
4859627f7eb2Smrg 				  gcc_unreachable ();
4860627f7eb2Smrg 				}
4861627f7eb2Smrg 			    gfc_error ("!$OMP DECLARE REDUCTION %s not found "
4862627f7eb2Smrg 				       "for type %s at %L", udr_name,
4863627f7eb2Smrg 				       gfc_typename (&n->sym->ts), &n->where);
4864627f7eb2Smrg 			  }
4865627f7eb2Smrg 			else
4866627f7eb2Smrg 			  {
4867627f7eb2Smrg 			    gfc_omp_udr *udr = n->udr->udr;
4868627f7eb2Smrg 			    n->u.reduction_op = OMP_REDUCTION_USER;
4869627f7eb2Smrg 			    n->udr->combiner
4870627f7eb2Smrg 			      = resolve_omp_udr_clause (n, udr->combiner_ns,
4871627f7eb2Smrg 							udr->omp_out,
4872627f7eb2Smrg 							udr->omp_in);
4873627f7eb2Smrg 			    if (udr->initializer_ns)
4874627f7eb2Smrg 			      n->udr->initializer
4875627f7eb2Smrg 				= resolve_omp_udr_clause (n,
4876627f7eb2Smrg 							  udr->initializer_ns,
4877627f7eb2Smrg 							  udr->omp_priv,
4878627f7eb2Smrg 							  udr->omp_orig);
4879627f7eb2Smrg 			  }
4880627f7eb2Smrg 		      }
4881627f7eb2Smrg 		    break;
4882627f7eb2Smrg 		  case OMP_LIST_LINEAR:
4883627f7eb2Smrg 		    if (code
4884627f7eb2Smrg 			&& n->u.linear_op != OMP_LINEAR_DEFAULT
4885627f7eb2Smrg 			&& n->u.linear_op != linear_op)
4886627f7eb2Smrg 		      {
4887627f7eb2Smrg 			gfc_error ("LINEAR clause modifier used on DO or SIMD"
4888627f7eb2Smrg 				   " construct at %L", &n->where);
4889627f7eb2Smrg 			linear_op = n->u.linear_op;
4890627f7eb2Smrg 		      }
4891627f7eb2Smrg 		    else if (omp_clauses->orderedc)
4892627f7eb2Smrg 		      gfc_error ("LINEAR clause specified together with "
4893627f7eb2Smrg 				 "ORDERED clause with argument at %L",
4894627f7eb2Smrg 				 &n->where);
4895627f7eb2Smrg 		    else if (n->u.linear_op != OMP_LINEAR_REF
4896627f7eb2Smrg 			     && n->sym->ts.type != BT_INTEGER)
4897627f7eb2Smrg 		      gfc_error ("LINEAR variable %qs must be INTEGER "
4898627f7eb2Smrg 				 "at %L", n->sym->name, &n->where);
4899627f7eb2Smrg 		    else if ((n->u.linear_op == OMP_LINEAR_REF
4900627f7eb2Smrg 			      || n->u.linear_op == OMP_LINEAR_UVAL)
4901627f7eb2Smrg 			     && n->sym->attr.value)
4902627f7eb2Smrg 		      gfc_error ("LINEAR dummy argument %qs with VALUE "
4903627f7eb2Smrg 				 "attribute with %s modifier at %L",
4904627f7eb2Smrg 				 n->sym->name,
4905627f7eb2Smrg 				 n->u.linear_op == OMP_LINEAR_REF
4906627f7eb2Smrg 				 ? "REF" : "UVAL", &n->where);
4907627f7eb2Smrg 		    else if (n->expr)
4908627f7eb2Smrg 		      {
4909627f7eb2Smrg 			gfc_expr *expr = n->expr;
4910627f7eb2Smrg 			if (!gfc_resolve_expr (expr)
4911627f7eb2Smrg 			    || expr->ts.type != BT_INTEGER
4912627f7eb2Smrg 			    || expr->rank != 0)
4913627f7eb2Smrg 			  gfc_error ("%qs in LINEAR clause at %L requires "
4914627f7eb2Smrg 				     "a scalar integer linear-step expression",
4915627f7eb2Smrg 				     n->sym->name, &n->where);
4916627f7eb2Smrg 			else if (!code && expr->expr_type != EXPR_CONSTANT)
4917627f7eb2Smrg 			  {
4918627f7eb2Smrg 			    if (expr->expr_type == EXPR_VARIABLE
4919627f7eb2Smrg 				&& expr->symtree->n.sym->attr.dummy
4920627f7eb2Smrg 				&& expr->symtree->n.sym->ns == ns)
4921627f7eb2Smrg 			      {
4922627f7eb2Smrg 				gfc_omp_namelist *n2;
4923627f7eb2Smrg 				for (n2 = omp_clauses->lists[OMP_LIST_UNIFORM];
4924627f7eb2Smrg 				     n2; n2 = n2->next)
4925627f7eb2Smrg 				  if (n2->sym == expr->symtree->n.sym)
4926627f7eb2Smrg 				    break;
4927627f7eb2Smrg 				if (n2)
4928627f7eb2Smrg 				  break;
4929627f7eb2Smrg 			      }
4930627f7eb2Smrg 			    gfc_error ("%qs in LINEAR clause at %L requires "
4931627f7eb2Smrg 				       "a constant integer linear-step "
4932627f7eb2Smrg 				       "expression or dummy argument "
4933627f7eb2Smrg 				       "specified in UNIFORM clause",
4934627f7eb2Smrg 				       n->sym->name, &n->where);
4935627f7eb2Smrg 			  }
4936627f7eb2Smrg 		      }
4937627f7eb2Smrg 		    break;
4938627f7eb2Smrg 		  /* Workaround for PR middle-end/26316, nothing really needs
4939627f7eb2Smrg 		     to be done here for OMP_LIST_PRIVATE.  */
4940627f7eb2Smrg 		  case OMP_LIST_PRIVATE:
4941627f7eb2Smrg 		    gcc_assert (code && code->op != EXEC_NOP);
4942627f7eb2Smrg 		    break;
4943627f7eb2Smrg 		  case OMP_LIST_USE_DEVICE:
4944627f7eb2Smrg 		      if (n->sym->attr.allocatable
4945627f7eb2Smrg 			  || (n->sym->ts.type == BT_CLASS && CLASS_DATA (n->sym)
4946627f7eb2Smrg 			      && CLASS_DATA (n->sym)->attr.allocatable))
4947627f7eb2Smrg 			gfc_error ("ALLOCATABLE object %qs in %s clause at %L",
4948627f7eb2Smrg 				   n->sym->name, name, &n->where);
4949627f7eb2Smrg 		      if (n->sym->ts.type == BT_CLASS
4950627f7eb2Smrg 			  && CLASS_DATA (n->sym)
4951627f7eb2Smrg 			  && CLASS_DATA (n->sym)->attr.class_pointer)
4952627f7eb2Smrg 			gfc_error ("POINTER object %qs of polymorphic type in "
4953627f7eb2Smrg 				   "%s clause at %L", n->sym->name, name,
4954627f7eb2Smrg 				   &n->where);
4955627f7eb2Smrg 		      if (n->sym->attr.cray_pointer)
4956627f7eb2Smrg 			gfc_error ("Cray pointer object %qs in %s clause at %L",
4957627f7eb2Smrg 				   n->sym->name, name, &n->where);
4958627f7eb2Smrg 		      else if (n->sym->attr.cray_pointee)
4959627f7eb2Smrg 			gfc_error ("Cray pointee object %qs in %s clause at %L",
4960627f7eb2Smrg 				   n->sym->name, name, &n->where);
4961627f7eb2Smrg 		      else if (n->sym->attr.flavor == FL_VARIABLE
4962627f7eb2Smrg 			       && !n->sym->as
4963627f7eb2Smrg 			       && !n->sym->attr.pointer)
4964627f7eb2Smrg 			gfc_error ("%s clause variable %qs at %L is neither "
4965627f7eb2Smrg 				   "a POINTER nor an array", name,
4966627f7eb2Smrg 				   n->sym->name, &n->where);
4967627f7eb2Smrg 		      /* FALLTHRU */
4968627f7eb2Smrg 		  case OMP_LIST_DEVICE_RESIDENT:
4969627f7eb2Smrg 		    check_symbol_not_pointer (n->sym, n->where, name);
4970627f7eb2Smrg 		    check_array_not_assumed (n->sym, n->where, name);
4971627f7eb2Smrg 		    break;
4972627f7eb2Smrg 		  default:
4973627f7eb2Smrg 		    break;
4974627f7eb2Smrg 		  }
4975627f7eb2Smrg 	      }
4976627f7eb2Smrg 	    break;
4977627f7eb2Smrg 	  }
4978627f7eb2Smrg       }
4979627f7eb2Smrg   if (omp_clauses->safelen_expr)
4980627f7eb2Smrg     resolve_positive_int_expr (omp_clauses->safelen_expr, "SAFELEN");
4981627f7eb2Smrg   if (omp_clauses->simdlen_expr)
4982627f7eb2Smrg     resolve_positive_int_expr (omp_clauses->simdlen_expr, "SIMDLEN");
4983627f7eb2Smrg   if (omp_clauses->num_teams)
4984627f7eb2Smrg     resolve_positive_int_expr (omp_clauses->num_teams, "NUM_TEAMS");
4985627f7eb2Smrg   if (omp_clauses->device)
4986627f7eb2Smrg     resolve_nonnegative_int_expr (omp_clauses->device, "DEVICE");
4987627f7eb2Smrg   if (omp_clauses->hint)
4988627f7eb2Smrg     resolve_scalar_int_expr (omp_clauses->hint, "HINT");
4989627f7eb2Smrg   if (omp_clauses->priority)
4990627f7eb2Smrg     resolve_nonnegative_int_expr (omp_clauses->priority, "PRIORITY");
4991627f7eb2Smrg   if (omp_clauses->dist_chunk_size)
4992627f7eb2Smrg     {
4993627f7eb2Smrg       gfc_expr *expr = omp_clauses->dist_chunk_size;
4994627f7eb2Smrg       if (!gfc_resolve_expr (expr)
4995627f7eb2Smrg 	  || expr->ts.type != BT_INTEGER || expr->rank != 0)
4996627f7eb2Smrg 	gfc_error ("DIST_SCHEDULE clause's chunk_size at %L requires "
4997627f7eb2Smrg 		   "a scalar INTEGER expression", &expr->where);
4998627f7eb2Smrg     }
4999627f7eb2Smrg   if (omp_clauses->thread_limit)
5000627f7eb2Smrg     resolve_positive_int_expr (omp_clauses->thread_limit, "THREAD_LIMIT");
5001627f7eb2Smrg   if (omp_clauses->grainsize)
5002627f7eb2Smrg     resolve_positive_int_expr (omp_clauses->grainsize, "GRAINSIZE");
5003627f7eb2Smrg   if (omp_clauses->num_tasks)
5004627f7eb2Smrg     resolve_positive_int_expr (omp_clauses->num_tasks, "NUM_TASKS");
5005627f7eb2Smrg   if (omp_clauses->async)
5006627f7eb2Smrg     if (omp_clauses->async_expr)
5007627f7eb2Smrg       resolve_scalar_int_expr (omp_clauses->async_expr, "ASYNC");
5008627f7eb2Smrg   if (omp_clauses->num_gangs_expr)
5009627f7eb2Smrg     resolve_positive_int_expr (omp_clauses->num_gangs_expr, "NUM_GANGS");
5010627f7eb2Smrg   if (omp_clauses->num_workers_expr)
5011627f7eb2Smrg     resolve_positive_int_expr (omp_clauses->num_workers_expr, "NUM_WORKERS");
5012627f7eb2Smrg   if (omp_clauses->vector_length_expr)
5013627f7eb2Smrg     resolve_positive_int_expr (omp_clauses->vector_length_expr,
5014627f7eb2Smrg 			       "VECTOR_LENGTH");
5015627f7eb2Smrg   if (omp_clauses->gang_num_expr)
5016627f7eb2Smrg     resolve_positive_int_expr (omp_clauses->gang_num_expr, "GANG");
5017627f7eb2Smrg   if (omp_clauses->gang_static_expr)
5018627f7eb2Smrg     resolve_positive_int_expr (omp_clauses->gang_static_expr, "GANG");
5019627f7eb2Smrg   if (omp_clauses->worker_expr)
5020627f7eb2Smrg     resolve_positive_int_expr (omp_clauses->worker_expr, "WORKER");
5021627f7eb2Smrg   if (omp_clauses->vector_expr)
5022627f7eb2Smrg     resolve_positive_int_expr (omp_clauses->vector_expr, "VECTOR");
5023627f7eb2Smrg   for (el = omp_clauses->wait_list; el; el = el->next)
5024627f7eb2Smrg     resolve_scalar_int_expr (el->expr, "WAIT");
5025627f7eb2Smrg   if (omp_clauses->collapse && omp_clauses->tile_list)
5026627f7eb2Smrg     gfc_error ("Incompatible use of TILE and COLLAPSE at %L", &code->loc);
5027627f7eb2Smrg   if (omp_clauses->depend_source && code->op != EXEC_OMP_ORDERED)
5028627f7eb2Smrg     gfc_error ("SOURCE dependence type only allowed "
5029627f7eb2Smrg 	       "on ORDERED directive at %L", &code->loc);
5030627f7eb2Smrg   if (!openacc && code && omp_clauses->lists[OMP_LIST_MAP] == NULL)
5031627f7eb2Smrg     {
5032627f7eb2Smrg       const char *p = NULL;
5033627f7eb2Smrg       switch (code->op)
5034627f7eb2Smrg 	{
5035627f7eb2Smrg 	case EXEC_OMP_TARGET_DATA: p = "TARGET DATA"; break;
5036627f7eb2Smrg 	case EXEC_OMP_TARGET_ENTER_DATA: p = "TARGET ENTER DATA"; break;
5037627f7eb2Smrg 	case EXEC_OMP_TARGET_EXIT_DATA: p = "TARGET EXIT DATA"; break;
5038627f7eb2Smrg 	default: break;
5039627f7eb2Smrg 	}
5040627f7eb2Smrg       if (p)
5041627f7eb2Smrg 	gfc_error ("%s must contain at least one MAP clause at %L",
5042627f7eb2Smrg 		   p, &code->loc);
5043627f7eb2Smrg     }
5044627f7eb2Smrg }
5045627f7eb2Smrg 
5046627f7eb2Smrg 
5047627f7eb2Smrg /* Return true if SYM is ever referenced in EXPR except in the SE node.  */
5048627f7eb2Smrg 
5049627f7eb2Smrg static bool
expr_references_sym(gfc_expr * e,gfc_symbol * s,gfc_expr * se)5050627f7eb2Smrg expr_references_sym (gfc_expr *e, gfc_symbol *s, gfc_expr *se)
5051627f7eb2Smrg {
5052627f7eb2Smrg   gfc_actual_arglist *arg;
5053627f7eb2Smrg   if (e == NULL || e == se)
5054627f7eb2Smrg     return false;
5055627f7eb2Smrg   switch (e->expr_type)
5056627f7eb2Smrg     {
5057627f7eb2Smrg     case EXPR_CONSTANT:
5058627f7eb2Smrg     case EXPR_NULL:
5059627f7eb2Smrg     case EXPR_VARIABLE:
5060627f7eb2Smrg     case EXPR_STRUCTURE:
5061627f7eb2Smrg     case EXPR_ARRAY:
5062627f7eb2Smrg       if (e->symtree != NULL
5063627f7eb2Smrg 	  && e->symtree->n.sym == s)
5064627f7eb2Smrg 	return true;
5065627f7eb2Smrg       return false;
5066627f7eb2Smrg     case EXPR_SUBSTRING:
5067627f7eb2Smrg       if (e->ref != NULL
5068627f7eb2Smrg 	  && (expr_references_sym (e->ref->u.ss.start, s, se)
5069627f7eb2Smrg 	      || expr_references_sym (e->ref->u.ss.end, s, se)))
5070627f7eb2Smrg 	return true;
5071627f7eb2Smrg       return false;
5072627f7eb2Smrg     case EXPR_OP:
5073627f7eb2Smrg       if (expr_references_sym (e->value.op.op2, s, se))
5074627f7eb2Smrg 	return true;
5075627f7eb2Smrg       return expr_references_sym (e->value.op.op1, s, se);
5076627f7eb2Smrg     case EXPR_FUNCTION:
5077627f7eb2Smrg       for (arg = e->value.function.actual; arg; arg = arg->next)
5078627f7eb2Smrg 	if (expr_references_sym (arg->expr, s, se))
5079627f7eb2Smrg 	  return true;
5080627f7eb2Smrg       return false;
5081627f7eb2Smrg     default:
5082627f7eb2Smrg       gcc_unreachable ();
5083627f7eb2Smrg     }
5084627f7eb2Smrg }
5085627f7eb2Smrg 
5086627f7eb2Smrg 
5087627f7eb2Smrg /* If EXPR is a conversion function that widens the type
5088627f7eb2Smrg    if WIDENING is true or narrows the type if WIDENING is false,
5089627f7eb2Smrg    return the inner expression, otherwise return NULL.  */
5090627f7eb2Smrg 
5091627f7eb2Smrg static gfc_expr *
is_conversion(gfc_expr * expr,bool widening)5092627f7eb2Smrg is_conversion (gfc_expr *expr, bool widening)
5093627f7eb2Smrg {
5094627f7eb2Smrg   gfc_typespec *ts1, *ts2;
5095627f7eb2Smrg 
5096627f7eb2Smrg   if (expr->expr_type != EXPR_FUNCTION
5097627f7eb2Smrg       || expr->value.function.isym == NULL
5098627f7eb2Smrg       || expr->value.function.esym != NULL
5099627f7eb2Smrg       || expr->value.function.isym->id != GFC_ISYM_CONVERSION)
5100627f7eb2Smrg     return NULL;
5101627f7eb2Smrg 
5102627f7eb2Smrg   if (widening)
5103627f7eb2Smrg     {
5104627f7eb2Smrg       ts1 = &expr->ts;
5105627f7eb2Smrg       ts2 = &expr->value.function.actual->expr->ts;
5106627f7eb2Smrg     }
5107627f7eb2Smrg   else
5108627f7eb2Smrg     {
5109627f7eb2Smrg       ts1 = &expr->value.function.actual->expr->ts;
5110627f7eb2Smrg       ts2 = &expr->ts;
5111627f7eb2Smrg     }
5112627f7eb2Smrg 
5113627f7eb2Smrg   if (ts1->type > ts2->type
5114627f7eb2Smrg       || (ts1->type == ts2->type && ts1->kind > ts2->kind))
5115627f7eb2Smrg     return expr->value.function.actual->expr;
5116627f7eb2Smrg 
5117627f7eb2Smrg   return NULL;
5118627f7eb2Smrg }
5119627f7eb2Smrg 
5120627f7eb2Smrg 
5121627f7eb2Smrg static void
resolve_omp_atomic(gfc_code * code)5122627f7eb2Smrg resolve_omp_atomic (gfc_code *code)
5123627f7eb2Smrg {
5124627f7eb2Smrg   gfc_code *atomic_code = code;
5125627f7eb2Smrg   gfc_symbol *var;
5126627f7eb2Smrg   gfc_expr *expr2, *expr2_tmp;
5127627f7eb2Smrg   gfc_omp_atomic_op aop
5128627f7eb2Smrg     = (gfc_omp_atomic_op) (atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_MASK);
5129627f7eb2Smrg 
5130627f7eb2Smrg   code = code->block->next;
5131627f7eb2Smrg   /* resolve_blocks asserts this is initially EXEC_ASSIGN.
5132627f7eb2Smrg      If it changed to EXEC_NOP, assume an error has been emitted already.  */
5133627f7eb2Smrg   if (code->op == EXEC_NOP)
5134627f7eb2Smrg     return;
5135627f7eb2Smrg   if (code->op != EXEC_ASSIGN)
5136627f7eb2Smrg     {
5137627f7eb2Smrg     unexpected:
5138627f7eb2Smrg       gfc_error ("unexpected !$OMP ATOMIC expression at %L", &code->loc);
5139627f7eb2Smrg       return;
5140627f7eb2Smrg     }
5141627f7eb2Smrg   if (aop != GFC_OMP_ATOMIC_CAPTURE)
5142627f7eb2Smrg     {
5143627f7eb2Smrg       if (code->next != NULL)
5144627f7eb2Smrg 	goto unexpected;
5145627f7eb2Smrg     }
5146627f7eb2Smrg   else
5147627f7eb2Smrg     {
5148627f7eb2Smrg       if (code->next == NULL)
5149627f7eb2Smrg 	goto unexpected;
5150627f7eb2Smrg       if (code->next->op == EXEC_NOP)
5151627f7eb2Smrg 	return;
5152627f7eb2Smrg       if (code->next->op != EXEC_ASSIGN || code->next->next)
5153627f7eb2Smrg 	{
5154627f7eb2Smrg 	  code = code->next;
5155627f7eb2Smrg 	  goto unexpected;
5156627f7eb2Smrg 	}
5157627f7eb2Smrg     }
5158627f7eb2Smrg 
5159627f7eb2Smrg   if (code->expr1->expr_type != EXPR_VARIABLE
5160627f7eb2Smrg       || code->expr1->symtree == NULL
5161627f7eb2Smrg       || code->expr1->rank != 0
5162627f7eb2Smrg       || (code->expr1->ts.type != BT_INTEGER
5163627f7eb2Smrg 	  && code->expr1->ts.type != BT_REAL
5164627f7eb2Smrg 	  && code->expr1->ts.type != BT_COMPLEX
5165627f7eb2Smrg 	  && code->expr1->ts.type != BT_LOGICAL))
5166627f7eb2Smrg     {
5167627f7eb2Smrg       gfc_error ("!$OMP ATOMIC statement must set a scalar variable of "
5168627f7eb2Smrg 		 "intrinsic type at %L", &code->loc);
5169627f7eb2Smrg       return;
5170627f7eb2Smrg     }
5171627f7eb2Smrg 
5172627f7eb2Smrg   var = code->expr1->symtree->n.sym;
5173627f7eb2Smrg   expr2 = is_conversion (code->expr2, false);
5174627f7eb2Smrg   if (expr2 == NULL)
5175627f7eb2Smrg     {
5176627f7eb2Smrg       if (aop == GFC_OMP_ATOMIC_READ || aop == GFC_OMP_ATOMIC_WRITE)
5177627f7eb2Smrg 	expr2 = is_conversion (code->expr2, true);
5178627f7eb2Smrg       if (expr2 == NULL)
5179627f7eb2Smrg 	expr2 = code->expr2;
5180627f7eb2Smrg     }
5181627f7eb2Smrg 
5182627f7eb2Smrg   switch (aop)
5183627f7eb2Smrg     {
5184627f7eb2Smrg     case GFC_OMP_ATOMIC_READ:
5185627f7eb2Smrg       if (expr2->expr_type != EXPR_VARIABLE
5186627f7eb2Smrg 	  || expr2->symtree == NULL
5187627f7eb2Smrg 	  || expr2->rank != 0
5188627f7eb2Smrg 	  || (expr2->ts.type != BT_INTEGER
5189627f7eb2Smrg 	      && expr2->ts.type != BT_REAL
5190627f7eb2Smrg 	      && expr2->ts.type != BT_COMPLEX
5191627f7eb2Smrg 	      && expr2->ts.type != BT_LOGICAL))
5192627f7eb2Smrg 	gfc_error ("!$OMP ATOMIC READ statement must read from a scalar "
5193627f7eb2Smrg 		   "variable of intrinsic type at %L", &expr2->where);
5194627f7eb2Smrg       return;
5195627f7eb2Smrg     case GFC_OMP_ATOMIC_WRITE:
5196627f7eb2Smrg       if (expr2->rank != 0 || expr_references_sym (code->expr2, var, NULL))
5197627f7eb2Smrg 	gfc_error ("expr in !$OMP ATOMIC WRITE assignment var = expr "
5198627f7eb2Smrg 		   "must be scalar and cannot reference var at %L",
5199627f7eb2Smrg 		   &expr2->where);
5200627f7eb2Smrg       return;
5201627f7eb2Smrg     case GFC_OMP_ATOMIC_CAPTURE:
5202627f7eb2Smrg       expr2_tmp = expr2;
5203627f7eb2Smrg       if (expr2 == code->expr2)
5204627f7eb2Smrg 	{
5205627f7eb2Smrg 	  expr2_tmp = is_conversion (code->expr2, true);
5206627f7eb2Smrg 	  if (expr2_tmp == NULL)
5207627f7eb2Smrg 	    expr2_tmp = expr2;
5208627f7eb2Smrg 	}
5209627f7eb2Smrg       if (expr2_tmp->expr_type == EXPR_VARIABLE)
5210627f7eb2Smrg 	{
5211627f7eb2Smrg 	  if (expr2_tmp->symtree == NULL
5212627f7eb2Smrg 	      || expr2_tmp->rank != 0
5213627f7eb2Smrg 	      || (expr2_tmp->ts.type != BT_INTEGER
5214627f7eb2Smrg 		  && expr2_tmp->ts.type != BT_REAL
5215627f7eb2Smrg 		  && expr2_tmp->ts.type != BT_COMPLEX
5216627f7eb2Smrg 		  && expr2_tmp->ts.type != BT_LOGICAL)
5217627f7eb2Smrg 	      || expr2_tmp->symtree->n.sym == var)
5218627f7eb2Smrg 	    {
5219627f7eb2Smrg 	      gfc_error ("!$OMP ATOMIC CAPTURE capture statement must read from "
5220627f7eb2Smrg 			 "a scalar variable of intrinsic type at %L",
5221627f7eb2Smrg 			 &expr2_tmp->where);
5222627f7eb2Smrg 	      return;
5223627f7eb2Smrg 	    }
5224627f7eb2Smrg 	  var = expr2_tmp->symtree->n.sym;
5225627f7eb2Smrg 	  code = code->next;
5226627f7eb2Smrg 	  if (code->expr1->expr_type != EXPR_VARIABLE
5227627f7eb2Smrg 	      || code->expr1->symtree == NULL
5228627f7eb2Smrg 	      || code->expr1->rank != 0
5229627f7eb2Smrg 	      || (code->expr1->ts.type != BT_INTEGER
5230627f7eb2Smrg 		  && code->expr1->ts.type != BT_REAL
5231627f7eb2Smrg 		  && code->expr1->ts.type != BT_COMPLEX
5232627f7eb2Smrg 		  && code->expr1->ts.type != BT_LOGICAL))
5233627f7eb2Smrg 	    {
5234627f7eb2Smrg 	      gfc_error ("!$OMP ATOMIC CAPTURE update statement must set "
5235627f7eb2Smrg 			 "a scalar variable of intrinsic type at %L",
5236627f7eb2Smrg 			 &code->expr1->where);
5237627f7eb2Smrg 	      return;
5238627f7eb2Smrg 	    }
5239627f7eb2Smrg 	  if (code->expr1->symtree->n.sym != var)
5240627f7eb2Smrg 	    {
5241627f7eb2Smrg 	      gfc_error ("!$OMP ATOMIC CAPTURE capture statement reads from "
5242627f7eb2Smrg 			 "different variable than update statement writes "
5243627f7eb2Smrg 			 "into at %L", &code->expr1->where);
5244627f7eb2Smrg 	      return;
5245627f7eb2Smrg 	    }
5246627f7eb2Smrg 	  expr2 = is_conversion (code->expr2, false);
5247627f7eb2Smrg 	  if (expr2 == NULL)
5248627f7eb2Smrg 	    expr2 = code->expr2;
5249627f7eb2Smrg 	}
5250627f7eb2Smrg       break;
5251627f7eb2Smrg     default:
5252627f7eb2Smrg       break;
5253627f7eb2Smrg     }
5254627f7eb2Smrg 
5255627f7eb2Smrg   if (gfc_expr_attr (code->expr1).allocatable)
5256627f7eb2Smrg     {
5257627f7eb2Smrg       gfc_error ("!$OMP ATOMIC with ALLOCATABLE variable at %L",
5258627f7eb2Smrg 		 &code->loc);
5259627f7eb2Smrg       return;
5260627f7eb2Smrg     }
5261627f7eb2Smrg 
5262627f7eb2Smrg   if (aop == GFC_OMP_ATOMIC_CAPTURE
5263627f7eb2Smrg       && code->next == NULL
5264627f7eb2Smrg       && code->expr2->rank == 0
5265627f7eb2Smrg       && !expr_references_sym (code->expr2, var, NULL))
5266627f7eb2Smrg     atomic_code->ext.omp_atomic
5267627f7eb2Smrg       = (gfc_omp_atomic_op) (atomic_code->ext.omp_atomic
5268627f7eb2Smrg 			     | GFC_OMP_ATOMIC_SWAP);
5269627f7eb2Smrg   else if (expr2->expr_type == EXPR_OP)
5270627f7eb2Smrg     {
5271627f7eb2Smrg       gfc_expr *v = NULL, *e, *c;
5272627f7eb2Smrg       gfc_intrinsic_op op = expr2->value.op.op;
5273627f7eb2Smrg       gfc_intrinsic_op alt_op = INTRINSIC_NONE;
5274627f7eb2Smrg 
5275627f7eb2Smrg       switch (op)
5276627f7eb2Smrg 	{
5277627f7eb2Smrg 	case INTRINSIC_PLUS:
5278627f7eb2Smrg 	  alt_op = INTRINSIC_MINUS;
5279627f7eb2Smrg 	  break;
5280627f7eb2Smrg 	case INTRINSIC_TIMES:
5281627f7eb2Smrg 	  alt_op = INTRINSIC_DIVIDE;
5282627f7eb2Smrg 	  break;
5283627f7eb2Smrg 	case INTRINSIC_MINUS:
5284627f7eb2Smrg 	  alt_op = INTRINSIC_PLUS;
5285627f7eb2Smrg 	  break;
5286627f7eb2Smrg 	case INTRINSIC_DIVIDE:
5287627f7eb2Smrg 	  alt_op = INTRINSIC_TIMES;
5288627f7eb2Smrg 	  break;
5289627f7eb2Smrg 	case INTRINSIC_AND:
5290627f7eb2Smrg 	case INTRINSIC_OR:
5291627f7eb2Smrg 	  break;
5292627f7eb2Smrg 	case INTRINSIC_EQV:
5293627f7eb2Smrg 	  alt_op = INTRINSIC_NEQV;
5294627f7eb2Smrg 	  break;
5295627f7eb2Smrg 	case INTRINSIC_NEQV:
5296627f7eb2Smrg 	  alt_op = INTRINSIC_EQV;
5297627f7eb2Smrg 	  break;
5298627f7eb2Smrg 	default:
5299627f7eb2Smrg 	  gfc_error ("!$OMP ATOMIC assignment operator must be binary "
5300627f7eb2Smrg 		     "+, *, -, /, .AND., .OR., .EQV. or .NEQV. at %L",
5301627f7eb2Smrg 		     &expr2->where);
5302627f7eb2Smrg 	  return;
5303627f7eb2Smrg 	}
5304627f7eb2Smrg 
5305627f7eb2Smrg       /* Check for var = var op expr resp. var = expr op var where
5306627f7eb2Smrg 	 expr doesn't reference var and var op expr is mathematically
5307627f7eb2Smrg 	 equivalent to var op (expr) resp. expr op var equivalent to
5308627f7eb2Smrg 	 (expr) op var.  We rely here on the fact that the matcher
5309627f7eb2Smrg 	 for x op1 y op2 z where op1 and op2 have equal precedence
5310627f7eb2Smrg 	 returns (x op1 y) op2 z.  */
5311627f7eb2Smrg       e = expr2->value.op.op2;
5312627f7eb2Smrg       if (e->expr_type == EXPR_VARIABLE
5313627f7eb2Smrg 	  && e->symtree != NULL
5314627f7eb2Smrg 	  && e->symtree->n.sym == var)
5315627f7eb2Smrg 	v = e;
5316627f7eb2Smrg       else if ((c = is_conversion (e, true)) != NULL
5317627f7eb2Smrg 	       && c->expr_type == EXPR_VARIABLE
5318627f7eb2Smrg 	       && c->symtree != NULL
5319627f7eb2Smrg 	       && c->symtree->n.sym == var)
5320627f7eb2Smrg 	v = c;
5321627f7eb2Smrg       else
5322627f7eb2Smrg 	{
5323627f7eb2Smrg 	  gfc_expr **p = NULL, **q;
5324627f7eb2Smrg 	  for (q = &expr2->value.op.op1; (e = *q) != NULL; )
5325627f7eb2Smrg 	    if (e->expr_type == EXPR_VARIABLE
5326627f7eb2Smrg 		&& e->symtree != NULL
5327627f7eb2Smrg 		&& e->symtree->n.sym == var)
5328627f7eb2Smrg 	      {
5329627f7eb2Smrg 		v = e;
5330627f7eb2Smrg 		break;
5331627f7eb2Smrg 	      }
5332627f7eb2Smrg 	    else if ((c = is_conversion (e, true)) != NULL)
5333627f7eb2Smrg 	      q = &e->value.function.actual->expr;
5334627f7eb2Smrg 	    else if (e->expr_type != EXPR_OP
5335627f7eb2Smrg 		     || (e->value.op.op != op
5336627f7eb2Smrg 			 && e->value.op.op != alt_op)
5337627f7eb2Smrg 		     || e->rank != 0)
5338627f7eb2Smrg 	      break;
5339627f7eb2Smrg 	    else
5340627f7eb2Smrg 	      {
5341627f7eb2Smrg 		p = q;
5342627f7eb2Smrg 		q = &e->value.op.op1;
5343627f7eb2Smrg 	      }
5344627f7eb2Smrg 
5345627f7eb2Smrg 	  if (v == NULL)
5346627f7eb2Smrg 	    {
5347627f7eb2Smrg 	      gfc_error ("!$OMP ATOMIC assignment must be var = var op expr "
5348627f7eb2Smrg 			 "or var = expr op var at %L", &expr2->where);
5349627f7eb2Smrg 	      return;
5350627f7eb2Smrg 	    }
5351627f7eb2Smrg 
5352627f7eb2Smrg 	  if (p != NULL)
5353627f7eb2Smrg 	    {
5354627f7eb2Smrg 	      e = *p;
5355627f7eb2Smrg 	      switch (e->value.op.op)
5356627f7eb2Smrg 		{
5357627f7eb2Smrg 		case INTRINSIC_MINUS:
5358627f7eb2Smrg 		case INTRINSIC_DIVIDE:
5359627f7eb2Smrg 		case INTRINSIC_EQV:
5360627f7eb2Smrg 		case INTRINSIC_NEQV:
5361627f7eb2Smrg 		  gfc_error ("!$OMP ATOMIC var = var op expr not "
5362627f7eb2Smrg 			     "mathematically equivalent to var = var op "
5363627f7eb2Smrg 			     "(expr) at %L", &expr2->where);
5364627f7eb2Smrg 		  break;
5365627f7eb2Smrg 		default:
5366627f7eb2Smrg 		  break;
5367627f7eb2Smrg 		}
5368627f7eb2Smrg 
5369627f7eb2Smrg 	      /* Canonicalize into var = var op (expr).  */
5370627f7eb2Smrg 	      *p = e->value.op.op2;
5371627f7eb2Smrg 	      e->value.op.op2 = expr2;
5372627f7eb2Smrg 	      e->ts = expr2->ts;
5373627f7eb2Smrg 	      if (code->expr2 == expr2)
5374627f7eb2Smrg 		code->expr2 = expr2 = e;
5375627f7eb2Smrg 	      else
5376627f7eb2Smrg 		code->expr2->value.function.actual->expr = expr2 = e;
5377627f7eb2Smrg 
5378627f7eb2Smrg 	      if (!gfc_compare_types (&expr2->value.op.op1->ts, &expr2->ts))
5379627f7eb2Smrg 		{
5380627f7eb2Smrg 		  for (p = &expr2->value.op.op1; *p != v;
5381627f7eb2Smrg 		       p = &(*p)->value.function.actual->expr)
5382627f7eb2Smrg 		    ;
5383627f7eb2Smrg 		  *p = NULL;
5384627f7eb2Smrg 		  gfc_free_expr (expr2->value.op.op1);
5385627f7eb2Smrg 		  expr2->value.op.op1 = v;
5386627f7eb2Smrg 		  gfc_convert_type (v, &expr2->ts, 2);
5387627f7eb2Smrg 		}
5388627f7eb2Smrg 	    }
5389627f7eb2Smrg 	}
5390627f7eb2Smrg 
5391627f7eb2Smrg       if (e->rank != 0 || expr_references_sym (code->expr2, var, v))
5392627f7eb2Smrg 	{
5393627f7eb2Smrg 	  gfc_error ("expr in !$OMP ATOMIC assignment var = var op expr "
5394627f7eb2Smrg 		     "must be scalar and cannot reference var at %L",
5395627f7eb2Smrg 		     &expr2->where);
5396627f7eb2Smrg 	  return;
5397627f7eb2Smrg 	}
5398627f7eb2Smrg     }
5399627f7eb2Smrg   else if (expr2->expr_type == EXPR_FUNCTION
5400627f7eb2Smrg 	   && expr2->value.function.isym != NULL
5401627f7eb2Smrg 	   && expr2->value.function.esym == NULL
5402627f7eb2Smrg 	   && expr2->value.function.actual != NULL
5403627f7eb2Smrg 	   && expr2->value.function.actual->next != NULL)
5404627f7eb2Smrg     {
5405627f7eb2Smrg       gfc_actual_arglist *arg, *var_arg;
5406627f7eb2Smrg 
5407627f7eb2Smrg       switch (expr2->value.function.isym->id)
5408627f7eb2Smrg 	{
5409627f7eb2Smrg 	case GFC_ISYM_MIN:
5410627f7eb2Smrg 	case GFC_ISYM_MAX:
5411627f7eb2Smrg 	  break;
5412627f7eb2Smrg 	case GFC_ISYM_IAND:
5413627f7eb2Smrg 	case GFC_ISYM_IOR:
5414627f7eb2Smrg 	case GFC_ISYM_IEOR:
5415627f7eb2Smrg 	  if (expr2->value.function.actual->next->next != NULL)
5416627f7eb2Smrg 	    {
5417627f7eb2Smrg 	      gfc_error ("!$OMP ATOMIC assignment intrinsic IAND, IOR "
5418627f7eb2Smrg 			 "or IEOR must have two arguments at %L",
5419627f7eb2Smrg 			 &expr2->where);
5420627f7eb2Smrg 	      return;
5421627f7eb2Smrg 	    }
5422627f7eb2Smrg 	  break;
5423627f7eb2Smrg 	default:
5424627f7eb2Smrg 	  gfc_error ("!$OMP ATOMIC assignment intrinsic must be "
5425627f7eb2Smrg 		     "MIN, MAX, IAND, IOR or IEOR at %L",
5426627f7eb2Smrg 		     &expr2->where);
5427627f7eb2Smrg 	  return;
5428627f7eb2Smrg 	}
5429627f7eb2Smrg 
5430627f7eb2Smrg       var_arg = NULL;
5431627f7eb2Smrg       for (arg = expr2->value.function.actual; arg; arg = arg->next)
5432627f7eb2Smrg 	{
5433627f7eb2Smrg 	  if ((arg == expr2->value.function.actual
5434627f7eb2Smrg 	       || (var_arg == NULL && arg->next == NULL))
5435627f7eb2Smrg 	      && arg->expr->expr_type == EXPR_VARIABLE
5436627f7eb2Smrg 	      && arg->expr->symtree != NULL
5437627f7eb2Smrg 	      && arg->expr->symtree->n.sym == var)
5438627f7eb2Smrg 	    var_arg = arg;
5439627f7eb2Smrg 	  else if (expr_references_sym (arg->expr, var, NULL))
5440627f7eb2Smrg 	    {
5441627f7eb2Smrg 	      gfc_error ("!$OMP ATOMIC intrinsic arguments except one must "
5442627f7eb2Smrg 			 "not reference %qs at %L",
5443627f7eb2Smrg 			 var->name, &arg->expr->where);
5444627f7eb2Smrg 	      return;
5445627f7eb2Smrg 	    }
5446627f7eb2Smrg 	  if (arg->expr->rank != 0)
5447627f7eb2Smrg 	    {
5448627f7eb2Smrg 	      gfc_error ("!$OMP ATOMIC intrinsic arguments must be scalar "
5449627f7eb2Smrg 			 "at %L", &arg->expr->where);
5450627f7eb2Smrg 	      return;
5451627f7eb2Smrg 	    }
5452627f7eb2Smrg 	}
5453627f7eb2Smrg 
5454627f7eb2Smrg       if (var_arg == NULL)
5455627f7eb2Smrg 	{
5456627f7eb2Smrg 	  gfc_error ("First or last !$OMP ATOMIC intrinsic argument must "
5457627f7eb2Smrg 		     "be %qs at %L", var->name, &expr2->where);
5458627f7eb2Smrg 	  return;
5459627f7eb2Smrg 	}
5460627f7eb2Smrg 
5461627f7eb2Smrg       if (var_arg != expr2->value.function.actual)
5462627f7eb2Smrg 	{
5463627f7eb2Smrg 	  /* Canonicalize, so that var comes first.  */
5464627f7eb2Smrg 	  gcc_assert (var_arg->next == NULL);
5465627f7eb2Smrg 	  for (arg = expr2->value.function.actual;
5466627f7eb2Smrg 	       arg->next != var_arg; arg = arg->next)
5467627f7eb2Smrg 	    ;
5468627f7eb2Smrg 	  var_arg->next = expr2->value.function.actual;
5469627f7eb2Smrg 	  expr2->value.function.actual = var_arg;
5470627f7eb2Smrg 	  arg->next = NULL;
5471627f7eb2Smrg 	}
5472627f7eb2Smrg     }
5473627f7eb2Smrg   else
5474627f7eb2Smrg     gfc_error ("!$OMP ATOMIC assignment must have an operator or "
5475627f7eb2Smrg 	       "intrinsic on right hand side at %L", &expr2->where);
5476627f7eb2Smrg 
5477627f7eb2Smrg   if (aop == GFC_OMP_ATOMIC_CAPTURE && code->next)
5478627f7eb2Smrg     {
5479627f7eb2Smrg       code = code->next;
5480627f7eb2Smrg       if (code->expr1->expr_type != EXPR_VARIABLE
5481627f7eb2Smrg 	  || code->expr1->symtree == NULL
5482627f7eb2Smrg 	  || code->expr1->rank != 0
5483627f7eb2Smrg 	  || (code->expr1->ts.type != BT_INTEGER
5484627f7eb2Smrg 	      && code->expr1->ts.type != BT_REAL
5485627f7eb2Smrg 	      && code->expr1->ts.type != BT_COMPLEX
5486627f7eb2Smrg 	      && code->expr1->ts.type != BT_LOGICAL))
5487627f7eb2Smrg 	{
5488627f7eb2Smrg 	  gfc_error ("!$OMP ATOMIC CAPTURE capture statement must set "
5489627f7eb2Smrg 		     "a scalar variable of intrinsic type at %L",
5490627f7eb2Smrg 		     &code->expr1->where);
5491627f7eb2Smrg 	  return;
5492627f7eb2Smrg 	}
5493627f7eb2Smrg 
5494627f7eb2Smrg       expr2 = is_conversion (code->expr2, false);
5495627f7eb2Smrg       if (expr2 == NULL)
5496627f7eb2Smrg 	{
5497627f7eb2Smrg 	  expr2 = is_conversion (code->expr2, true);
5498627f7eb2Smrg 	  if (expr2 == NULL)
5499627f7eb2Smrg 	    expr2 = code->expr2;
5500627f7eb2Smrg 	}
5501627f7eb2Smrg 
5502627f7eb2Smrg       if (expr2->expr_type != EXPR_VARIABLE
5503627f7eb2Smrg 	  || expr2->symtree == NULL
5504627f7eb2Smrg 	  || expr2->rank != 0
5505627f7eb2Smrg 	  || (expr2->ts.type != BT_INTEGER
5506627f7eb2Smrg 	      && expr2->ts.type != BT_REAL
5507627f7eb2Smrg 	      && expr2->ts.type != BT_COMPLEX
5508627f7eb2Smrg 	      && expr2->ts.type != BT_LOGICAL))
5509627f7eb2Smrg 	{
5510627f7eb2Smrg 	  gfc_error ("!$OMP ATOMIC CAPTURE capture statement must read "
5511627f7eb2Smrg 		     "from a scalar variable of intrinsic type at %L",
5512627f7eb2Smrg 		     &expr2->where);
5513627f7eb2Smrg 	  return;
5514627f7eb2Smrg 	}
5515627f7eb2Smrg       if (expr2->symtree->n.sym != var)
5516627f7eb2Smrg 	{
5517627f7eb2Smrg 	  gfc_error ("!$OMP ATOMIC CAPTURE capture statement reads from "
5518627f7eb2Smrg 		     "different variable than update statement writes "
5519627f7eb2Smrg 		     "into at %L", &expr2->where);
5520627f7eb2Smrg 	  return;
5521627f7eb2Smrg 	}
5522627f7eb2Smrg     }
5523627f7eb2Smrg }
5524627f7eb2Smrg 
5525627f7eb2Smrg 
5526627f7eb2Smrg static struct fortran_omp_context
5527627f7eb2Smrg {
5528627f7eb2Smrg   gfc_code *code;
5529627f7eb2Smrg   hash_set<gfc_symbol *> *sharing_clauses;
5530627f7eb2Smrg   hash_set<gfc_symbol *> *private_iterators;
5531627f7eb2Smrg   struct fortran_omp_context *previous;
5532627f7eb2Smrg   bool is_openmp;
5533627f7eb2Smrg } *omp_current_ctx;
5534627f7eb2Smrg static gfc_code *omp_current_do_code;
5535627f7eb2Smrg static int omp_current_do_collapse;
5536627f7eb2Smrg 
5537627f7eb2Smrg void
gfc_resolve_omp_do_blocks(gfc_code * code,gfc_namespace * ns)5538627f7eb2Smrg gfc_resolve_omp_do_blocks (gfc_code *code, gfc_namespace *ns)
5539627f7eb2Smrg {
5540627f7eb2Smrg   if (code->block->next && code->block->next->op == EXEC_DO)
5541627f7eb2Smrg     {
5542627f7eb2Smrg       int i;
5543627f7eb2Smrg       gfc_code *c;
5544627f7eb2Smrg 
5545627f7eb2Smrg       omp_current_do_code = code->block->next;
5546627f7eb2Smrg       if (code->ext.omp_clauses->orderedc)
5547627f7eb2Smrg 	omp_current_do_collapse = code->ext.omp_clauses->orderedc;
5548627f7eb2Smrg       else
5549627f7eb2Smrg 	omp_current_do_collapse = code->ext.omp_clauses->collapse;
5550627f7eb2Smrg       for (i = 1, c = omp_current_do_code; i < omp_current_do_collapse; i++)
5551627f7eb2Smrg 	{
5552627f7eb2Smrg 	  c = c->block;
5553627f7eb2Smrg 	  if (c->op != EXEC_DO || c->next == NULL)
5554627f7eb2Smrg 	    break;
5555627f7eb2Smrg 	  c = c->next;
5556627f7eb2Smrg 	  if (c->op != EXEC_DO)
5557627f7eb2Smrg 	    break;
5558627f7eb2Smrg 	}
5559627f7eb2Smrg       if (i < omp_current_do_collapse || omp_current_do_collapse <= 0)
5560627f7eb2Smrg 	omp_current_do_collapse = 1;
5561627f7eb2Smrg     }
5562627f7eb2Smrg   gfc_resolve_blocks (code->block, ns);
5563627f7eb2Smrg   omp_current_do_collapse = 0;
5564627f7eb2Smrg   omp_current_do_code = NULL;
5565627f7eb2Smrg }
5566627f7eb2Smrg 
5567627f7eb2Smrg 
5568627f7eb2Smrg void
gfc_resolve_omp_parallel_blocks(gfc_code * code,gfc_namespace * ns)5569627f7eb2Smrg gfc_resolve_omp_parallel_blocks (gfc_code *code, gfc_namespace *ns)
5570627f7eb2Smrg {
5571627f7eb2Smrg   struct fortran_omp_context ctx;
5572627f7eb2Smrg   gfc_omp_clauses *omp_clauses = code->ext.omp_clauses;
5573627f7eb2Smrg   gfc_omp_namelist *n;
5574627f7eb2Smrg   int list;
5575627f7eb2Smrg 
5576627f7eb2Smrg   ctx.code = code;
5577627f7eb2Smrg   ctx.sharing_clauses = new hash_set<gfc_symbol *>;
5578627f7eb2Smrg   ctx.private_iterators = new hash_set<gfc_symbol *>;
5579627f7eb2Smrg   ctx.previous = omp_current_ctx;
5580627f7eb2Smrg   ctx.is_openmp = true;
5581627f7eb2Smrg   omp_current_ctx = &ctx;
5582627f7eb2Smrg 
5583627f7eb2Smrg   for (list = 0; list < OMP_LIST_NUM; list++)
5584627f7eb2Smrg     switch (list)
5585627f7eb2Smrg       {
5586627f7eb2Smrg       case OMP_LIST_SHARED:
5587627f7eb2Smrg       case OMP_LIST_PRIVATE:
5588627f7eb2Smrg       case OMP_LIST_FIRSTPRIVATE:
5589627f7eb2Smrg       case OMP_LIST_LASTPRIVATE:
5590627f7eb2Smrg       case OMP_LIST_REDUCTION:
5591627f7eb2Smrg       case OMP_LIST_LINEAR:
5592627f7eb2Smrg 	for (n = omp_clauses->lists[list]; n; n = n->next)
5593627f7eb2Smrg 	  ctx.sharing_clauses->add (n->sym);
5594627f7eb2Smrg 	break;
5595627f7eb2Smrg       default:
5596627f7eb2Smrg 	break;
5597627f7eb2Smrg       }
5598627f7eb2Smrg 
5599627f7eb2Smrg   switch (code->op)
5600627f7eb2Smrg     {
5601*4c3eb207Smrg     case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
5602*4c3eb207Smrg     case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
5603627f7eb2Smrg     case EXEC_OMP_PARALLEL_DO:
5604627f7eb2Smrg     case EXEC_OMP_PARALLEL_DO_SIMD:
5605627f7eb2Smrg     case EXEC_OMP_TARGET_PARALLEL_DO:
5606627f7eb2Smrg     case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
5607627f7eb2Smrg     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
5608627f7eb2Smrg     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
5609627f7eb2Smrg     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
5610627f7eb2Smrg     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
5611627f7eb2Smrg     case EXEC_OMP_TASKLOOP:
5612627f7eb2Smrg     case EXEC_OMP_TASKLOOP_SIMD:
5613627f7eb2Smrg     case EXEC_OMP_TEAMS_DISTRIBUTE:
5614627f7eb2Smrg     case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
5615627f7eb2Smrg     case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
5616627f7eb2Smrg     case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
5617627f7eb2Smrg       gfc_resolve_omp_do_blocks (code, ns);
5618627f7eb2Smrg       break;
5619627f7eb2Smrg     default:
5620627f7eb2Smrg       gfc_resolve_blocks (code->block, ns);
5621627f7eb2Smrg     }
5622627f7eb2Smrg 
5623627f7eb2Smrg   omp_current_ctx = ctx.previous;
5624627f7eb2Smrg   delete ctx.sharing_clauses;
5625627f7eb2Smrg   delete ctx.private_iterators;
5626627f7eb2Smrg }
5627627f7eb2Smrg 
5628627f7eb2Smrg 
5629627f7eb2Smrg /* Save and clear openmp.c private state.  */
5630627f7eb2Smrg 
5631627f7eb2Smrg void
gfc_omp_save_and_clear_state(struct gfc_omp_saved_state * state)5632627f7eb2Smrg gfc_omp_save_and_clear_state (struct gfc_omp_saved_state *state)
5633627f7eb2Smrg {
5634627f7eb2Smrg   state->ptrs[0] = omp_current_ctx;
5635627f7eb2Smrg   state->ptrs[1] = omp_current_do_code;
5636627f7eb2Smrg   state->ints[0] = omp_current_do_collapse;
5637627f7eb2Smrg   omp_current_ctx = NULL;
5638627f7eb2Smrg   omp_current_do_code = NULL;
5639627f7eb2Smrg   omp_current_do_collapse = 0;
5640627f7eb2Smrg }
5641627f7eb2Smrg 
5642627f7eb2Smrg 
5643627f7eb2Smrg /* Restore openmp.c private state from the saved state.  */
5644627f7eb2Smrg 
5645627f7eb2Smrg void
gfc_omp_restore_state(struct gfc_omp_saved_state * state)5646627f7eb2Smrg gfc_omp_restore_state (struct gfc_omp_saved_state *state)
5647627f7eb2Smrg {
5648627f7eb2Smrg   omp_current_ctx = (struct fortran_omp_context *) state->ptrs[0];
5649627f7eb2Smrg   omp_current_do_code = (gfc_code *) state->ptrs[1];
5650627f7eb2Smrg   omp_current_do_collapse = state->ints[0];
5651627f7eb2Smrg }
5652627f7eb2Smrg 
5653627f7eb2Smrg 
5654627f7eb2Smrg /* Note a DO iterator variable.  This is special in !$omp parallel
5655627f7eb2Smrg    construct, where they are predetermined private.  */
5656627f7eb2Smrg 
5657627f7eb2Smrg void
gfc_resolve_do_iterator(gfc_code * code,gfc_symbol * sym,bool add_clause)5658627f7eb2Smrg gfc_resolve_do_iterator (gfc_code *code, gfc_symbol *sym, bool add_clause)
5659627f7eb2Smrg {
5660627f7eb2Smrg   if (omp_current_ctx == NULL)
5661627f7eb2Smrg     return;
5662627f7eb2Smrg 
5663627f7eb2Smrg   int i = omp_current_do_collapse;
5664627f7eb2Smrg   gfc_code *c = omp_current_do_code;
5665627f7eb2Smrg 
5666627f7eb2Smrg   if (sym->attr.threadprivate)
5667627f7eb2Smrg     return;
5668627f7eb2Smrg 
5669627f7eb2Smrg   /* !$omp do and !$omp parallel do iteration variable is predetermined
5670627f7eb2Smrg      private just in the !$omp do resp. !$omp parallel do construct,
5671627f7eb2Smrg      with no implications for the outer parallel constructs.  */
5672627f7eb2Smrg 
5673627f7eb2Smrg   while (i-- >= 1)
5674627f7eb2Smrg     {
5675627f7eb2Smrg       if (code == c)
5676627f7eb2Smrg 	return;
5677627f7eb2Smrg 
5678627f7eb2Smrg       c = c->block->next;
5679627f7eb2Smrg     }
5680627f7eb2Smrg 
5681627f7eb2Smrg   /* An openacc context may represent a data clause.  Abort if so.  */
5682627f7eb2Smrg   if (!omp_current_ctx->is_openmp && !oacc_is_loop (omp_current_ctx->code))
5683627f7eb2Smrg     return;
5684627f7eb2Smrg 
5685627f7eb2Smrg   if (omp_current_ctx->sharing_clauses->contains (sym))
5686627f7eb2Smrg     return;
5687627f7eb2Smrg 
5688627f7eb2Smrg   if (! omp_current_ctx->private_iterators->add (sym) && add_clause)
5689627f7eb2Smrg     {
5690627f7eb2Smrg       gfc_omp_clauses *omp_clauses = omp_current_ctx->code->ext.omp_clauses;
5691627f7eb2Smrg       gfc_omp_namelist *p;
5692627f7eb2Smrg 
5693627f7eb2Smrg       p = gfc_get_omp_namelist ();
5694627f7eb2Smrg       p->sym = sym;
5695627f7eb2Smrg       p->next = omp_clauses->lists[OMP_LIST_PRIVATE];
5696627f7eb2Smrg       omp_clauses->lists[OMP_LIST_PRIVATE] = p;
5697627f7eb2Smrg     }
5698627f7eb2Smrg }
5699627f7eb2Smrg 
5700627f7eb2Smrg static void
handle_local_var(gfc_symbol * sym)5701627f7eb2Smrg handle_local_var (gfc_symbol *sym)
5702627f7eb2Smrg {
5703627f7eb2Smrg   if (sym->attr.flavor != FL_VARIABLE
5704627f7eb2Smrg       || sym->as != NULL
5705627f7eb2Smrg       || (sym->ts.type != BT_INTEGER && sym->ts.type != BT_REAL))
5706627f7eb2Smrg     return;
5707627f7eb2Smrg   gfc_resolve_do_iterator (sym->ns->code, sym, false);
5708627f7eb2Smrg }
5709627f7eb2Smrg 
5710627f7eb2Smrg void
gfc_resolve_omp_local_vars(gfc_namespace * ns)5711627f7eb2Smrg gfc_resolve_omp_local_vars (gfc_namespace *ns)
5712627f7eb2Smrg {
5713627f7eb2Smrg   if (omp_current_ctx)
5714627f7eb2Smrg     gfc_traverse_ns (ns, handle_local_var);
5715627f7eb2Smrg }
5716627f7eb2Smrg 
5717627f7eb2Smrg static void
resolve_omp_do(gfc_code * code)5718627f7eb2Smrg resolve_omp_do (gfc_code *code)
5719627f7eb2Smrg {
5720627f7eb2Smrg   gfc_code *do_code, *c;
5721627f7eb2Smrg   int list, i, collapse;
5722627f7eb2Smrg   gfc_omp_namelist *n;
5723627f7eb2Smrg   gfc_symbol *dovar;
5724627f7eb2Smrg   const char *name;
5725627f7eb2Smrg   bool is_simd = false;
5726627f7eb2Smrg 
5727627f7eb2Smrg   switch (code->op)
5728627f7eb2Smrg     {
5729627f7eb2Smrg     case EXEC_OMP_DISTRIBUTE: name = "!$OMP DISTRIBUTE"; break;
5730627f7eb2Smrg     case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
5731627f7eb2Smrg       name = "!$OMP DISTRIBUTE PARALLEL DO";
5732627f7eb2Smrg       break;
5733627f7eb2Smrg     case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
5734627f7eb2Smrg       name = "!$OMP DISTRIBUTE PARALLEL DO SIMD";
5735627f7eb2Smrg       is_simd = true;
5736627f7eb2Smrg       break;
5737627f7eb2Smrg     case EXEC_OMP_DISTRIBUTE_SIMD:
5738627f7eb2Smrg       name = "!$OMP DISTRIBUTE SIMD";
5739627f7eb2Smrg       is_simd = true;
5740627f7eb2Smrg       break;
5741627f7eb2Smrg     case EXEC_OMP_DO: name = "!$OMP DO"; break;
5742627f7eb2Smrg     case EXEC_OMP_DO_SIMD: name = "!$OMP DO SIMD"; is_simd = true; break;
5743627f7eb2Smrg     case EXEC_OMP_PARALLEL_DO: name = "!$OMP PARALLEL DO"; break;
5744627f7eb2Smrg     case EXEC_OMP_PARALLEL_DO_SIMD:
5745627f7eb2Smrg       name = "!$OMP PARALLEL DO SIMD";
5746627f7eb2Smrg       is_simd = true;
5747627f7eb2Smrg       break;
5748627f7eb2Smrg     case EXEC_OMP_SIMD: name = "!$OMP SIMD"; is_simd = true; break;
5749627f7eb2Smrg     case EXEC_OMP_TARGET_PARALLEL_DO: name = "!$OMP TARGET PARALLEL DO"; break;
5750627f7eb2Smrg     case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
5751627f7eb2Smrg       name = "!$OMP TARGET PARALLEL DO SIMD";
5752627f7eb2Smrg       is_simd = true;
5753627f7eb2Smrg       break;
5754627f7eb2Smrg     case EXEC_OMP_TARGET_SIMD:
5755627f7eb2Smrg       name = "!$OMP TARGET SIMD";
5756627f7eb2Smrg       is_simd = true;
5757627f7eb2Smrg       break;
5758627f7eb2Smrg     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
5759627f7eb2Smrg       name = "!$OMP TARGET TEAMS DISTRIBUTE";
5760627f7eb2Smrg       break;
5761627f7eb2Smrg     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
5762627f7eb2Smrg       name = "!$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO";
5763627f7eb2Smrg       break;
5764627f7eb2Smrg     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
5765627f7eb2Smrg       name = "!$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD";
5766627f7eb2Smrg       is_simd = true;
5767627f7eb2Smrg       break;
5768627f7eb2Smrg     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
5769627f7eb2Smrg       name = "!$OMP TARGET TEAMS DISTRIBUTE SIMD";
5770627f7eb2Smrg       is_simd = true;
5771627f7eb2Smrg       break;
5772627f7eb2Smrg     case EXEC_OMP_TASKLOOP: name = "!$OMP TASKLOOP"; break;
5773627f7eb2Smrg     case EXEC_OMP_TASKLOOP_SIMD:
5774627f7eb2Smrg       name = "!$OMP TASKLOOP SIMD";
5775627f7eb2Smrg       is_simd = true;
5776627f7eb2Smrg       break;
5777627f7eb2Smrg     case EXEC_OMP_TEAMS_DISTRIBUTE: name = "!$OMP TEAMS DISTRIBUTE"; break;
5778627f7eb2Smrg     case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
5779627f7eb2Smrg       name = "!$OMP TEAMS DISTRIBUTE PARALLEL DO";
5780627f7eb2Smrg       break;
5781627f7eb2Smrg     case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
5782627f7eb2Smrg       name = "!$OMP TEAMS DISTRIBUTE PARALLEL DO SIMD";
5783627f7eb2Smrg       is_simd = true;
5784627f7eb2Smrg       break;
5785627f7eb2Smrg     case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
5786627f7eb2Smrg       name = "!$OMP TEAMS DISTRIBUTE SIMD";
5787627f7eb2Smrg       is_simd = true;
5788627f7eb2Smrg       break;
5789627f7eb2Smrg     default: gcc_unreachable ();
5790627f7eb2Smrg     }
5791627f7eb2Smrg 
5792627f7eb2Smrg   if (code->ext.omp_clauses)
5793627f7eb2Smrg     resolve_omp_clauses (code, code->ext.omp_clauses, NULL);
5794627f7eb2Smrg 
5795627f7eb2Smrg   do_code = code->block->next;
5796627f7eb2Smrg   if (code->ext.omp_clauses->orderedc)
5797627f7eb2Smrg     collapse = code->ext.omp_clauses->orderedc;
5798627f7eb2Smrg   else
5799627f7eb2Smrg     {
5800627f7eb2Smrg       collapse = code->ext.omp_clauses->collapse;
5801627f7eb2Smrg       if (collapse <= 0)
5802627f7eb2Smrg 	collapse = 1;
5803627f7eb2Smrg     }
5804627f7eb2Smrg   for (i = 1; i <= collapse; i++)
5805627f7eb2Smrg     {
5806627f7eb2Smrg       if (do_code->op == EXEC_DO_WHILE)
5807627f7eb2Smrg 	{
5808627f7eb2Smrg 	  gfc_error ("%s cannot be a DO WHILE or DO without loop control "
5809627f7eb2Smrg 		     "at %L", name, &do_code->loc);
5810627f7eb2Smrg 	  break;
5811627f7eb2Smrg 	}
5812627f7eb2Smrg       if (do_code->op == EXEC_DO_CONCURRENT)
5813627f7eb2Smrg 	{
5814627f7eb2Smrg 	  gfc_error ("%s cannot be a DO CONCURRENT loop at %L", name,
5815627f7eb2Smrg 		     &do_code->loc);
5816627f7eb2Smrg 	  break;
5817627f7eb2Smrg 	}
5818627f7eb2Smrg       gcc_assert (do_code->op == EXEC_DO);
5819627f7eb2Smrg       if (do_code->ext.iterator->var->ts.type != BT_INTEGER)
5820627f7eb2Smrg 	gfc_error ("%s iteration variable must be of type integer at %L",
5821627f7eb2Smrg 		   name, &do_code->loc);
5822627f7eb2Smrg       dovar = do_code->ext.iterator->var->symtree->n.sym;
5823627f7eb2Smrg       if (dovar->attr.threadprivate)
5824627f7eb2Smrg 	gfc_error ("%s iteration variable must not be THREADPRIVATE "
5825627f7eb2Smrg 		   "at %L", name, &do_code->loc);
5826627f7eb2Smrg       if (code->ext.omp_clauses)
5827627f7eb2Smrg 	for (list = 0; list < OMP_LIST_NUM; list++)
5828627f7eb2Smrg 	  if (!is_simd
5829627f7eb2Smrg 	      ? (list != OMP_LIST_PRIVATE && list != OMP_LIST_LASTPRIVATE)
5830627f7eb2Smrg 	      : code->ext.omp_clauses->collapse > 1
5831627f7eb2Smrg 	      ? (list != OMP_LIST_LASTPRIVATE)
5832627f7eb2Smrg 	      : (list != OMP_LIST_LINEAR))
5833627f7eb2Smrg 	    for (n = code->ext.omp_clauses->lists[list]; n; n = n->next)
5834627f7eb2Smrg 	      if (dovar == n->sym)
5835627f7eb2Smrg 		{
5836627f7eb2Smrg 		  if (!is_simd)
5837627f7eb2Smrg 		    gfc_error ("%s iteration variable present on clause "
5838627f7eb2Smrg 			       "other than PRIVATE or LASTPRIVATE at %L",
5839627f7eb2Smrg 			       name, &do_code->loc);
5840627f7eb2Smrg 		  else if (code->ext.omp_clauses->collapse > 1)
5841627f7eb2Smrg 		    gfc_error ("%s iteration variable present on clause "
5842627f7eb2Smrg 			       "other than LASTPRIVATE at %L",
5843627f7eb2Smrg 			       name, &do_code->loc);
5844627f7eb2Smrg 		  else
5845627f7eb2Smrg 		    gfc_error ("%s iteration variable present on clause "
5846627f7eb2Smrg 			       "other than LINEAR at %L",
5847627f7eb2Smrg 			       name, &do_code->loc);
5848627f7eb2Smrg 		  break;
5849627f7eb2Smrg 		}
5850627f7eb2Smrg       if (i > 1)
5851627f7eb2Smrg 	{
5852627f7eb2Smrg 	  gfc_code *do_code2 = code->block->next;
5853627f7eb2Smrg 	  int j;
5854627f7eb2Smrg 
5855627f7eb2Smrg 	  for (j = 1; j < i; j++)
5856627f7eb2Smrg 	    {
5857627f7eb2Smrg 	      gfc_symbol *ivar = do_code2->ext.iterator->var->symtree->n.sym;
5858627f7eb2Smrg 	      if (dovar == ivar
5859627f7eb2Smrg 		  || gfc_find_sym_in_expr (ivar, do_code->ext.iterator->start)
5860627f7eb2Smrg 		  || gfc_find_sym_in_expr (ivar, do_code->ext.iterator->end)
5861627f7eb2Smrg 		  || gfc_find_sym_in_expr (ivar, do_code->ext.iterator->step))
5862627f7eb2Smrg 		{
5863627f7eb2Smrg 		  gfc_error ("%s collapsed loops don't form rectangular "
5864627f7eb2Smrg 			     "iteration space at %L", name, &do_code->loc);
5865627f7eb2Smrg 		  break;
5866627f7eb2Smrg 		}
5867627f7eb2Smrg 	      do_code2 = do_code2->block->next;
5868627f7eb2Smrg 	    }
5869627f7eb2Smrg 	}
5870627f7eb2Smrg       if (i == collapse)
5871627f7eb2Smrg 	break;
5872627f7eb2Smrg       for (c = do_code->next; c; c = c->next)
5873627f7eb2Smrg 	if (c->op != EXEC_NOP && c->op != EXEC_CONTINUE)
5874627f7eb2Smrg 	  {
5875627f7eb2Smrg 	    gfc_error ("collapsed %s loops not perfectly nested at %L",
5876627f7eb2Smrg 		       name, &c->loc);
5877627f7eb2Smrg 	    break;
5878627f7eb2Smrg 	  }
5879627f7eb2Smrg       if (c)
5880627f7eb2Smrg 	break;
5881627f7eb2Smrg       do_code = do_code->block;
5882627f7eb2Smrg       if (do_code->op != EXEC_DO && do_code->op != EXEC_DO_WHILE)
5883627f7eb2Smrg 	{
5884627f7eb2Smrg 	  gfc_error ("not enough DO loops for collapsed %s at %L",
5885627f7eb2Smrg 		     name, &code->loc);
5886627f7eb2Smrg 	  break;
5887627f7eb2Smrg 	}
5888627f7eb2Smrg       do_code = do_code->next;
5889627f7eb2Smrg       if (do_code == NULL
5890627f7eb2Smrg 	  || (do_code->op != EXEC_DO && do_code->op != EXEC_DO_WHILE))
5891627f7eb2Smrg 	{
5892627f7eb2Smrg 	  gfc_error ("not enough DO loops for collapsed %s at %L",
5893627f7eb2Smrg 		     name, &code->loc);
5894627f7eb2Smrg 	  break;
5895627f7eb2Smrg 	}
5896627f7eb2Smrg     }
5897627f7eb2Smrg }
5898627f7eb2Smrg 
5899627f7eb2Smrg 
5900627f7eb2Smrg static gfc_statement
omp_code_to_statement(gfc_code * code)5901627f7eb2Smrg omp_code_to_statement (gfc_code *code)
5902627f7eb2Smrg {
5903627f7eb2Smrg   switch (code->op)
5904627f7eb2Smrg     {
5905627f7eb2Smrg     case EXEC_OMP_PARALLEL:
5906627f7eb2Smrg       return ST_OMP_PARALLEL;
5907627f7eb2Smrg     case EXEC_OMP_PARALLEL_SECTIONS:
5908627f7eb2Smrg       return ST_OMP_PARALLEL_SECTIONS;
5909627f7eb2Smrg     case EXEC_OMP_SECTIONS:
5910627f7eb2Smrg       return ST_OMP_SECTIONS;
5911627f7eb2Smrg     case EXEC_OMP_ORDERED:
5912627f7eb2Smrg       return ST_OMP_ORDERED;
5913627f7eb2Smrg     case EXEC_OMP_CRITICAL:
5914627f7eb2Smrg       return ST_OMP_CRITICAL;
5915627f7eb2Smrg     case EXEC_OMP_MASTER:
5916627f7eb2Smrg       return ST_OMP_MASTER;
5917627f7eb2Smrg     case EXEC_OMP_SINGLE:
5918627f7eb2Smrg       return ST_OMP_SINGLE;
5919627f7eb2Smrg     case EXEC_OMP_TASK:
5920627f7eb2Smrg       return ST_OMP_TASK;
5921627f7eb2Smrg     case EXEC_OMP_WORKSHARE:
5922627f7eb2Smrg       return ST_OMP_WORKSHARE;
5923627f7eb2Smrg     case EXEC_OMP_PARALLEL_WORKSHARE:
5924627f7eb2Smrg       return ST_OMP_PARALLEL_WORKSHARE;
5925627f7eb2Smrg     case EXEC_OMP_DO:
5926627f7eb2Smrg       return ST_OMP_DO;
5927627f7eb2Smrg     case EXEC_OMP_ATOMIC:
5928627f7eb2Smrg       return ST_OMP_ATOMIC;
5929627f7eb2Smrg     case EXEC_OMP_BARRIER:
5930627f7eb2Smrg       return ST_OMP_BARRIER;
5931627f7eb2Smrg     case EXEC_OMP_CANCEL:
5932627f7eb2Smrg       return ST_OMP_CANCEL;
5933627f7eb2Smrg     case EXEC_OMP_CANCELLATION_POINT:
5934627f7eb2Smrg       return ST_OMP_CANCELLATION_POINT;
5935627f7eb2Smrg     case EXEC_OMP_FLUSH:
5936627f7eb2Smrg       return ST_OMP_FLUSH;
5937627f7eb2Smrg     case EXEC_OMP_DISTRIBUTE:
5938627f7eb2Smrg       return ST_OMP_DISTRIBUTE;
5939627f7eb2Smrg     case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
5940627f7eb2Smrg       return ST_OMP_DISTRIBUTE_PARALLEL_DO;
5941627f7eb2Smrg     case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
5942627f7eb2Smrg       return ST_OMP_DISTRIBUTE_PARALLEL_DO_SIMD;
5943627f7eb2Smrg     case EXEC_OMP_DISTRIBUTE_SIMD:
5944627f7eb2Smrg       return ST_OMP_DISTRIBUTE_SIMD;
5945627f7eb2Smrg     case EXEC_OMP_DO_SIMD:
5946627f7eb2Smrg       return ST_OMP_DO_SIMD;
5947627f7eb2Smrg     case EXEC_OMP_SIMD:
5948627f7eb2Smrg       return ST_OMP_SIMD;
5949627f7eb2Smrg     case EXEC_OMP_TARGET:
5950627f7eb2Smrg       return ST_OMP_TARGET;
5951627f7eb2Smrg     case EXEC_OMP_TARGET_DATA:
5952627f7eb2Smrg       return ST_OMP_TARGET_DATA;
5953627f7eb2Smrg     case EXEC_OMP_TARGET_ENTER_DATA:
5954627f7eb2Smrg       return ST_OMP_TARGET_ENTER_DATA;
5955627f7eb2Smrg     case EXEC_OMP_TARGET_EXIT_DATA:
5956627f7eb2Smrg       return ST_OMP_TARGET_EXIT_DATA;
5957627f7eb2Smrg     case EXEC_OMP_TARGET_PARALLEL:
5958627f7eb2Smrg       return ST_OMP_TARGET_PARALLEL;
5959627f7eb2Smrg     case EXEC_OMP_TARGET_PARALLEL_DO:
5960627f7eb2Smrg       return ST_OMP_TARGET_PARALLEL_DO;
5961627f7eb2Smrg     case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
5962627f7eb2Smrg       return ST_OMP_TARGET_PARALLEL_DO_SIMD;
5963627f7eb2Smrg     case EXEC_OMP_TARGET_SIMD:
5964627f7eb2Smrg       return ST_OMP_TARGET_SIMD;
5965627f7eb2Smrg     case EXEC_OMP_TARGET_TEAMS:
5966627f7eb2Smrg       return ST_OMP_TARGET_TEAMS;
5967627f7eb2Smrg     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
5968627f7eb2Smrg       return ST_OMP_TARGET_TEAMS_DISTRIBUTE;
5969627f7eb2Smrg     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
5970627f7eb2Smrg       return ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO;
5971627f7eb2Smrg     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
5972627f7eb2Smrg       return ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD;
5973627f7eb2Smrg     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
5974627f7eb2Smrg       return ST_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD;
5975627f7eb2Smrg     case EXEC_OMP_TARGET_UPDATE:
5976627f7eb2Smrg       return ST_OMP_TARGET_UPDATE;
5977627f7eb2Smrg     case EXEC_OMP_TASKGROUP:
5978627f7eb2Smrg       return ST_OMP_TASKGROUP;
5979627f7eb2Smrg     case EXEC_OMP_TASKLOOP:
5980627f7eb2Smrg       return ST_OMP_TASKLOOP;
5981627f7eb2Smrg     case EXEC_OMP_TASKLOOP_SIMD:
5982627f7eb2Smrg       return ST_OMP_TASKLOOP_SIMD;
5983627f7eb2Smrg     case EXEC_OMP_TASKWAIT:
5984627f7eb2Smrg       return ST_OMP_TASKWAIT;
5985627f7eb2Smrg     case EXEC_OMP_TASKYIELD:
5986627f7eb2Smrg       return ST_OMP_TASKYIELD;
5987627f7eb2Smrg     case EXEC_OMP_TEAMS:
5988627f7eb2Smrg       return ST_OMP_TEAMS;
5989627f7eb2Smrg     case EXEC_OMP_TEAMS_DISTRIBUTE:
5990627f7eb2Smrg       return ST_OMP_TEAMS_DISTRIBUTE;
5991627f7eb2Smrg     case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
5992627f7eb2Smrg       return ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO;
5993627f7eb2Smrg     case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
5994627f7eb2Smrg       return ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD;
5995627f7eb2Smrg     case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
5996627f7eb2Smrg       return ST_OMP_TEAMS_DISTRIBUTE_SIMD;
5997627f7eb2Smrg     case EXEC_OMP_PARALLEL_DO:
5998627f7eb2Smrg       return ST_OMP_PARALLEL_DO;
5999627f7eb2Smrg     case EXEC_OMP_PARALLEL_DO_SIMD:
6000627f7eb2Smrg       return ST_OMP_PARALLEL_DO_SIMD;
6001627f7eb2Smrg 
6002627f7eb2Smrg     default:
6003627f7eb2Smrg       gcc_unreachable ();
6004627f7eb2Smrg     }
6005627f7eb2Smrg }
6006627f7eb2Smrg 
6007627f7eb2Smrg static gfc_statement
oacc_code_to_statement(gfc_code * code)6008627f7eb2Smrg oacc_code_to_statement (gfc_code *code)
6009627f7eb2Smrg {
6010627f7eb2Smrg   switch (code->op)
6011627f7eb2Smrg     {
6012627f7eb2Smrg     case EXEC_OACC_PARALLEL:
6013627f7eb2Smrg       return ST_OACC_PARALLEL;
6014627f7eb2Smrg     case EXEC_OACC_KERNELS:
6015627f7eb2Smrg       return ST_OACC_KERNELS;
6016*4c3eb207Smrg     case EXEC_OACC_SERIAL:
6017*4c3eb207Smrg       return ST_OACC_SERIAL;
6018627f7eb2Smrg     case EXEC_OACC_DATA:
6019627f7eb2Smrg       return ST_OACC_DATA;
6020627f7eb2Smrg     case EXEC_OACC_HOST_DATA:
6021627f7eb2Smrg       return ST_OACC_HOST_DATA;
6022627f7eb2Smrg     case EXEC_OACC_PARALLEL_LOOP:
6023627f7eb2Smrg       return ST_OACC_PARALLEL_LOOP;
6024627f7eb2Smrg     case EXEC_OACC_KERNELS_LOOP:
6025627f7eb2Smrg       return ST_OACC_KERNELS_LOOP;
6026*4c3eb207Smrg     case EXEC_OACC_SERIAL_LOOP:
6027*4c3eb207Smrg       return ST_OACC_SERIAL_LOOP;
6028627f7eb2Smrg     case EXEC_OACC_LOOP:
6029627f7eb2Smrg       return ST_OACC_LOOP;
6030627f7eb2Smrg     case EXEC_OACC_ATOMIC:
6031627f7eb2Smrg       return ST_OACC_ATOMIC;
6032627f7eb2Smrg     case EXEC_OACC_ROUTINE:
6033627f7eb2Smrg       return ST_OACC_ROUTINE;
6034627f7eb2Smrg     case EXEC_OACC_UPDATE:
6035627f7eb2Smrg       return ST_OACC_UPDATE;
6036627f7eb2Smrg     case EXEC_OACC_WAIT:
6037627f7eb2Smrg       return ST_OACC_WAIT;
6038627f7eb2Smrg     case EXEC_OACC_CACHE:
6039627f7eb2Smrg       return ST_OACC_CACHE;
6040627f7eb2Smrg     case EXEC_OACC_ENTER_DATA:
6041627f7eb2Smrg       return ST_OACC_ENTER_DATA;
6042627f7eb2Smrg     case EXEC_OACC_EXIT_DATA:
6043627f7eb2Smrg       return ST_OACC_EXIT_DATA;
6044627f7eb2Smrg     case EXEC_OACC_DECLARE:
6045627f7eb2Smrg       return ST_OACC_DECLARE;
6046627f7eb2Smrg     default:
6047627f7eb2Smrg       gcc_unreachable ();
6048627f7eb2Smrg     }
6049627f7eb2Smrg }
6050627f7eb2Smrg 
6051627f7eb2Smrg static void
resolve_oacc_directive_inside_omp_region(gfc_code * code)6052627f7eb2Smrg resolve_oacc_directive_inside_omp_region (gfc_code *code)
6053627f7eb2Smrg {
6054627f7eb2Smrg   if (omp_current_ctx != NULL && omp_current_ctx->is_openmp)
6055627f7eb2Smrg     {
6056627f7eb2Smrg       gfc_statement st = omp_code_to_statement (omp_current_ctx->code);
6057627f7eb2Smrg       gfc_statement oacc_st = oacc_code_to_statement (code);
6058627f7eb2Smrg       gfc_error ("The %s directive cannot be specified within "
6059627f7eb2Smrg 		 "a %s region at %L", gfc_ascii_statement (oacc_st),
6060627f7eb2Smrg 		 gfc_ascii_statement (st), &code->loc);
6061627f7eb2Smrg     }
6062627f7eb2Smrg }
6063627f7eb2Smrg 
6064627f7eb2Smrg static void
resolve_omp_directive_inside_oacc_region(gfc_code * code)6065627f7eb2Smrg resolve_omp_directive_inside_oacc_region (gfc_code *code)
6066627f7eb2Smrg {
6067627f7eb2Smrg   if (omp_current_ctx != NULL && !omp_current_ctx->is_openmp)
6068627f7eb2Smrg     {
6069627f7eb2Smrg       gfc_statement st = oacc_code_to_statement (omp_current_ctx->code);
6070627f7eb2Smrg       gfc_statement omp_st = omp_code_to_statement (code);
6071627f7eb2Smrg       gfc_error ("The %s directive cannot be specified within "
6072627f7eb2Smrg 		 "a %s region at %L", gfc_ascii_statement (omp_st),
6073627f7eb2Smrg 		 gfc_ascii_statement (st), &code->loc);
6074627f7eb2Smrg     }
6075627f7eb2Smrg }
6076627f7eb2Smrg 
6077627f7eb2Smrg 
6078627f7eb2Smrg static void
resolve_oacc_nested_loops(gfc_code * code,gfc_code * do_code,int collapse,const char * clause)6079627f7eb2Smrg resolve_oacc_nested_loops (gfc_code *code, gfc_code* do_code, int collapse,
6080627f7eb2Smrg 			  const char *clause)
6081627f7eb2Smrg {
6082627f7eb2Smrg   gfc_symbol *dovar;
6083627f7eb2Smrg   gfc_code *c;
6084627f7eb2Smrg   int i;
6085627f7eb2Smrg 
6086627f7eb2Smrg   for (i = 1; i <= collapse; i++)
6087627f7eb2Smrg     {
6088627f7eb2Smrg       if (do_code->op == EXEC_DO_WHILE)
6089627f7eb2Smrg 	{
6090627f7eb2Smrg 	  gfc_error ("!$ACC LOOP cannot be a DO WHILE or DO without loop control "
6091627f7eb2Smrg 		     "at %L", &do_code->loc);
6092627f7eb2Smrg 	  break;
6093627f7eb2Smrg 	}
6094627f7eb2Smrg       if (do_code->op == EXEC_DO_CONCURRENT)
6095627f7eb2Smrg 	{
6096627f7eb2Smrg 	  gfc_error ("!$ACC LOOP cannot be a DO CONCURRENT loop at %L",
6097627f7eb2Smrg 		     &do_code->loc);
6098627f7eb2Smrg 	  break;
6099627f7eb2Smrg 	}
6100627f7eb2Smrg       gcc_assert (do_code->op == EXEC_DO);
6101627f7eb2Smrg       if (do_code->ext.iterator->var->ts.type != BT_INTEGER)
6102627f7eb2Smrg 	gfc_error ("!$ACC LOOP iteration variable must be of type integer at %L",
6103627f7eb2Smrg 		   &do_code->loc);
6104627f7eb2Smrg       dovar = do_code->ext.iterator->var->symtree->n.sym;
6105627f7eb2Smrg       if (i > 1)
6106627f7eb2Smrg 	{
6107627f7eb2Smrg 	  gfc_code *do_code2 = code->block->next;
6108627f7eb2Smrg 	  int j;
6109627f7eb2Smrg 
6110627f7eb2Smrg 	  for (j = 1; j < i; j++)
6111627f7eb2Smrg 	    {
6112627f7eb2Smrg 	      gfc_symbol *ivar = do_code2->ext.iterator->var->symtree->n.sym;
6113627f7eb2Smrg 	      if (dovar == ivar
6114627f7eb2Smrg 		  || gfc_find_sym_in_expr (ivar, do_code->ext.iterator->start)
6115627f7eb2Smrg 		  || gfc_find_sym_in_expr (ivar, do_code->ext.iterator->end)
6116627f7eb2Smrg 		  || gfc_find_sym_in_expr (ivar, do_code->ext.iterator->step))
6117627f7eb2Smrg 		{
6118627f7eb2Smrg 		  gfc_error ("!$ACC LOOP %s loops don't form rectangular "
6119627f7eb2Smrg 			     "iteration space at %L", clause, &do_code->loc);
6120627f7eb2Smrg 		  break;
6121627f7eb2Smrg 		}
6122627f7eb2Smrg 	      do_code2 = do_code2->block->next;
6123627f7eb2Smrg 	    }
6124627f7eb2Smrg 	}
6125627f7eb2Smrg       if (i == collapse)
6126627f7eb2Smrg 	break;
6127627f7eb2Smrg       for (c = do_code->next; c; c = c->next)
6128627f7eb2Smrg 	if (c->op != EXEC_NOP && c->op != EXEC_CONTINUE)
6129627f7eb2Smrg 	  {
6130627f7eb2Smrg 	    gfc_error ("%s !$ACC LOOP loops not perfectly nested at %L",
6131627f7eb2Smrg 		       clause, &c->loc);
6132627f7eb2Smrg 	    break;
6133627f7eb2Smrg 	  }
6134627f7eb2Smrg       if (c)
6135627f7eb2Smrg 	break;
6136627f7eb2Smrg       do_code = do_code->block;
6137627f7eb2Smrg       if (do_code->op != EXEC_DO && do_code->op != EXEC_DO_WHILE
6138627f7eb2Smrg 	  && do_code->op != EXEC_DO_CONCURRENT)
6139627f7eb2Smrg 	{
6140627f7eb2Smrg 	  gfc_error ("not enough DO loops for %s !$ACC LOOP at %L",
6141627f7eb2Smrg 		     clause, &code->loc);
6142627f7eb2Smrg 	  break;
6143627f7eb2Smrg 	}
6144627f7eb2Smrg       do_code = do_code->next;
6145627f7eb2Smrg       if (do_code == NULL
6146627f7eb2Smrg 	  || (do_code->op != EXEC_DO && do_code->op != EXEC_DO_WHILE
6147627f7eb2Smrg 	      && do_code->op != EXEC_DO_CONCURRENT))
6148627f7eb2Smrg 	{
6149627f7eb2Smrg 	  gfc_error ("not enough DO loops for %s !$ACC LOOP at %L",
6150627f7eb2Smrg 		     clause, &code->loc);
6151627f7eb2Smrg 	  break;
6152627f7eb2Smrg 	}
6153627f7eb2Smrg     }
6154627f7eb2Smrg }
6155627f7eb2Smrg 
6156627f7eb2Smrg 
6157627f7eb2Smrg static void
resolve_oacc_loop_blocks(gfc_code * code)6158627f7eb2Smrg resolve_oacc_loop_blocks (gfc_code *code)
6159627f7eb2Smrg {
6160627f7eb2Smrg   if (!oacc_is_loop (code))
6161627f7eb2Smrg     return;
6162627f7eb2Smrg 
6163627f7eb2Smrg   if (code->ext.omp_clauses->tile_list && code->ext.omp_clauses->gang
6164627f7eb2Smrg       && code->ext.omp_clauses->worker && code->ext.omp_clauses->vector)
6165627f7eb2Smrg     gfc_error ("Tiled loop cannot be parallelized across gangs, workers and "
6166627f7eb2Smrg 	       "vectors at the same time at %L", &code->loc);
6167627f7eb2Smrg 
6168627f7eb2Smrg   if (code->ext.omp_clauses->tile_list)
6169627f7eb2Smrg     {
6170627f7eb2Smrg       gfc_expr_list *el;
6171627f7eb2Smrg       for (el = code->ext.omp_clauses->tile_list; el; el = el->next)
6172627f7eb2Smrg 	{
6173627f7eb2Smrg 	  if (el->expr == NULL)
6174627f7eb2Smrg 	    {
6175627f7eb2Smrg 	      /* NULL expressions are used to represent '*' arguments.
6176627f7eb2Smrg 		 Convert those to a 0 expressions.  */
6177627f7eb2Smrg 	      el->expr = gfc_get_constant_expr (BT_INTEGER,
6178627f7eb2Smrg 						gfc_default_integer_kind,
6179627f7eb2Smrg 						&code->loc);
6180627f7eb2Smrg 	      mpz_set_si (el->expr->value.integer, 0);
6181627f7eb2Smrg 	    }
6182627f7eb2Smrg 	  else
6183627f7eb2Smrg 	    {
6184627f7eb2Smrg 	      resolve_positive_int_expr (el->expr, "TILE");
6185627f7eb2Smrg 	      if (el->expr->expr_type != EXPR_CONSTANT)
6186627f7eb2Smrg 		gfc_error ("TILE requires constant expression at %L",
6187627f7eb2Smrg 			   &code->loc);
6188627f7eb2Smrg 	    }
6189627f7eb2Smrg 	}
6190627f7eb2Smrg     }
6191627f7eb2Smrg }
6192627f7eb2Smrg 
6193627f7eb2Smrg 
6194627f7eb2Smrg void
gfc_resolve_oacc_blocks(gfc_code * code,gfc_namespace * ns)6195627f7eb2Smrg gfc_resolve_oacc_blocks (gfc_code *code, gfc_namespace *ns)
6196627f7eb2Smrg {
6197627f7eb2Smrg   fortran_omp_context ctx;
6198627f7eb2Smrg   gfc_omp_clauses *omp_clauses = code->ext.omp_clauses;
6199627f7eb2Smrg   gfc_omp_namelist *n;
6200627f7eb2Smrg   int list;
6201627f7eb2Smrg 
6202627f7eb2Smrg   resolve_oacc_loop_blocks (code);
6203627f7eb2Smrg 
6204627f7eb2Smrg   ctx.code = code;
6205627f7eb2Smrg   ctx.sharing_clauses = new hash_set<gfc_symbol *>;
6206627f7eb2Smrg   ctx.private_iterators = new hash_set<gfc_symbol *>;
6207627f7eb2Smrg   ctx.previous = omp_current_ctx;
6208627f7eb2Smrg   ctx.is_openmp = false;
6209627f7eb2Smrg   omp_current_ctx = &ctx;
6210627f7eb2Smrg 
6211627f7eb2Smrg   for (list = 0; list < OMP_LIST_NUM; list++)
6212627f7eb2Smrg     switch (list)
6213627f7eb2Smrg       {
6214627f7eb2Smrg       case OMP_LIST_PRIVATE:
6215627f7eb2Smrg 	for (n = omp_clauses->lists[list]; n; n = n->next)
6216627f7eb2Smrg 	  ctx.sharing_clauses->add (n->sym);
6217627f7eb2Smrg 	break;
6218627f7eb2Smrg       default:
6219627f7eb2Smrg 	break;
6220627f7eb2Smrg       }
6221627f7eb2Smrg 
6222627f7eb2Smrg   gfc_resolve_blocks (code->block, ns);
6223627f7eb2Smrg 
6224627f7eb2Smrg   omp_current_ctx = ctx.previous;
6225627f7eb2Smrg   delete ctx.sharing_clauses;
6226627f7eb2Smrg   delete ctx.private_iterators;
6227627f7eb2Smrg }
6228627f7eb2Smrg 
6229627f7eb2Smrg 
6230627f7eb2Smrg static void
resolve_oacc_loop(gfc_code * code)6231627f7eb2Smrg resolve_oacc_loop (gfc_code *code)
6232627f7eb2Smrg {
6233627f7eb2Smrg   gfc_code *do_code;
6234627f7eb2Smrg   int collapse;
6235627f7eb2Smrg 
6236627f7eb2Smrg   if (code->ext.omp_clauses)
6237627f7eb2Smrg     resolve_omp_clauses (code, code->ext.omp_clauses, NULL, true);
6238627f7eb2Smrg 
6239627f7eb2Smrg   do_code = code->block->next;
6240627f7eb2Smrg   collapse = code->ext.omp_clauses->collapse;
6241627f7eb2Smrg 
6242*4c3eb207Smrg   /* Both collapsed and tiled loops are lowered the same way, but are not
6243*4c3eb207Smrg      compatible.  In gfc_trans_omp_do, the tile is prioritized.  */
6244*4c3eb207Smrg   if (code->ext.omp_clauses->tile_list)
6245*4c3eb207Smrg     {
6246*4c3eb207Smrg       int num = 0;
6247*4c3eb207Smrg       gfc_expr_list *el;
6248*4c3eb207Smrg       for (el = code->ext.omp_clauses->tile_list; el; el = el->next)
6249*4c3eb207Smrg 	++num;
6250*4c3eb207Smrg       resolve_oacc_nested_loops (code, code->block->next, num, "tiled");
6251*4c3eb207Smrg       return;
6252*4c3eb207Smrg     }
6253*4c3eb207Smrg 
6254627f7eb2Smrg   if (collapse <= 0)
6255627f7eb2Smrg     collapse = 1;
6256627f7eb2Smrg   resolve_oacc_nested_loops (code, do_code, collapse, "collapsed");
6257627f7eb2Smrg }
6258627f7eb2Smrg 
6259627f7eb2Smrg void
gfc_resolve_oacc_declare(gfc_namespace * ns)6260627f7eb2Smrg gfc_resolve_oacc_declare (gfc_namespace *ns)
6261627f7eb2Smrg {
6262627f7eb2Smrg   int list;
6263627f7eb2Smrg   gfc_omp_namelist *n;
6264627f7eb2Smrg   gfc_oacc_declare *oc;
6265627f7eb2Smrg 
6266627f7eb2Smrg   if (ns->oacc_declare == NULL)
6267627f7eb2Smrg     return;
6268627f7eb2Smrg 
6269627f7eb2Smrg   for (oc = ns->oacc_declare; oc; oc = oc->next)
6270627f7eb2Smrg     {
6271627f7eb2Smrg       for (list = 0; list < OMP_LIST_NUM; list++)
6272627f7eb2Smrg 	for (n = oc->clauses->lists[list]; n; n = n->next)
6273627f7eb2Smrg 	  {
6274627f7eb2Smrg 	    n->sym->mark = 0;
6275*4c3eb207Smrg 	    if (n->sym->attr.flavor != FL_VARIABLE
6276*4c3eb207Smrg 		&& (n->sym->attr.flavor != FL_PROCEDURE
6277*4c3eb207Smrg 		    || n->sym->result != n->sym))
6278627f7eb2Smrg 	      {
6279627f7eb2Smrg 		gfc_error ("Object %qs is not a variable at %L",
6280627f7eb2Smrg 			   n->sym->name, &oc->loc);
6281627f7eb2Smrg 		continue;
6282627f7eb2Smrg 	      }
6283627f7eb2Smrg 
6284627f7eb2Smrg 	    if (n->expr && n->expr->ref->type == REF_ARRAY)
6285627f7eb2Smrg 	      {
6286627f7eb2Smrg 		gfc_error ("Array sections: %qs not allowed in"
6287627f7eb2Smrg 			   " !$ACC DECLARE at %L", n->sym->name, &oc->loc);
6288627f7eb2Smrg 		continue;
6289627f7eb2Smrg 	      }
6290627f7eb2Smrg 	  }
6291627f7eb2Smrg 
6292627f7eb2Smrg       for (n = oc->clauses->lists[OMP_LIST_DEVICE_RESIDENT]; n; n = n->next)
6293627f7eb2Smrg 	check_array_not_assumed (n->sym, oc->loc, "DEVICE_RESIDENT");
6294627f7eb2Smrg     }
6295627f7eb2Smrg 
6296627f7eb2Smrg   for (oc = ns->oacc_declare; oc; oc = oc->next)
6297627f7eb2Smrg     {
6298627f7eb2Smrg       for (list = 0; list < OMP_LIST_NUM; list++)
6299627f7eb2Smrg 	for (n = oc->clauses->lists[list]; n; n = n->next)
6300627f7eb2Smrg 	  {
6301627f7eb2Smrg 	    if (n->sym->mark)
6302627f7eb2Smrg 	      {
6303627f7eb2Smrg 		gfc_error ("Symbol %qs present on multiple clauses at %L",
6304627f7eb2Smrg 			   n->sym->name, &oc->loc);
6305627f7eb2Smrg 		continue;
6306627f7eb2Smrg 	      }
6307627f7eb2Smrg 	    else
6308627f7eb2Smrg 	      n->sym->mark = 1;
6309627f7eb2Smrg 	  }
6310627f7eb2Smrg     }
6311627f7eb2Smrg 
6312627f7eb2Smrg   for (oc = ns->oacc_declare; oc; oc = oc->next)
6313627f7eb2Smrg     {
6314627f7eb2Smrg       for (list = 0; list < OMP_LIST_NUM; list++)
6315627f7eb2Smrg 	for (n = oc->clauses->lists[list]; n; n = n->next)
6316627f7eb2Smrg 	  n->sym->mark = 0;
6317627f7eb2Smrg     }
6318627f7eb2Smrg }
6319627f7eb2Smrg 
6320627f7eb2Smrg 
6321627f7eb2Smrg void
gfc_resolve_oacc_routines(gfc_namespace * ns)6322627f7eb2Smrg gfc_resolve_oacc_routines (gfc_namespace *ns)
6323627f7eb2Smrg {
6324627f7eb2Smrg   for (gfc_oacc_routine_name *orn = ns->oacc_routine_names;
6325627f7eb2Smrg        orn;
6326627f7eb2Smrg        orn = orn->next)
6327627f7eb2Smrg     {
6328627f7eb2Smrg       gfc_symbol *sym = orn->sym;
6329627f7eb2Smrg       if (!sym->attr.external
6330627f7eb2Smrg 	  && !sym->attr.function
6331627f7eb2Smrg 	  && !sym->attr.subroutine)
6332627f7eb2Smrg 	{
6333627f7eb2Smrg 	  gfc_error ("NAME %qs does not refer to a subroutine or function"
6334627f7eb2Smrg 		     " in !$ACC ROUTINE ( NAME ) at %L", sym->name, &orn->loc);
6335627f7eb2Smrg 	  continue;
6336627f7eb2Smrg 	}
6337627f7eb2Smrg       if (!gfc_add_omp_declare_target (&sym->attr, sym->name, &orn->loc))
6338627f7eb2Smrg 	{
6339627f7eb2Smrg 	  gfc_error ("NAME %qs invalid"
6340627f7eb2Smrg 		     " in !$ACC ROUTINE ( NAME ) at %L", sym->name, &orn->loc);
6341627f7eb2Smrg 	  continue;
6342627f7eb2Smrg 	}
6343627f7eb2Smrg     }
6344627f7eb2Smrg }
6345627f7eb2Smrg 
6346627f7eb2Smrg 
6347627f7eb2Smrg void
gfc_resolve_oacc_directive(gfc_code * code,gfc_namespace * ns ATTRIBUTE_UNUSED)6348627f7eb2Smrg gfc_resolve_oacc_directive (gfc_code *code, gfc_namespace *ns ATTRIBUTE_UNUSED)
6349627f7eb2Smrg {
6350627f7eb2Smrg   resolve_oacc_directive_inside_omp_region (code);
6351627f7eb2Smrg 
6352627f7eb2Smrg   switch (code->op)
6353627f7eb2Smrg     {
6354627f7eb2Smrg     case EXEC_OACC_PARALLEL:
6355627f7eb2Smrg     case EXEC_OACC_KERNELS:
6356*4c3eb207Smrg     case EXEC_OACC_SERIAL:
6357627f7eb2Smrg     case EXEC_OACC_DATA:
6358627f7eb2Smrg     case EXEC_OACC_HOST_DATA:
6359627f7eb2Smrg     case EXEC_OACC_UPDATE:
6360627f7eb2Smrg     case EXEC_OACC_ENTER_DATA:
6361627f7eb2Smrg     case EXEC_OACC_EXIT_DATA:
6362627f7eb2Smrg     case EXEC_OACC_WAIT:
6363627f7eb2Smrg     case EXEC_OACC_CACHE:
6364627f7eb2Smrg       resolve_omp_clauses (code, code->ext.omp_clauses, NULL, true);
6365627f7eb2Smrg       break;
6366627f7eb2Smrg     case EXEC_OACC_PARALLEL_LOOP:
6367627f7eb2Smrg     case EXEC_OACC_KERNELS_LOOP:
6368*4c3eb207Smrg     case EXEC_OACC_SERIAL_LOOP:
6369627f7eb2Smrg     case EXEC_OACC_LOOP:
6370627f7eb2Smrg       resolve_oacc_loop (code);
6371627f7eb2Smrg       break;
6372627f7eb2Smrg     case EXEC_OACC_ATOMIC:
6373627f7eb2Smrg       resolve_omp_atomic (code);
6374627f7eb2Smrg       break;
6375627f7eb2Smrg     default:
6376627f7eb2Smrg       break;
6377627f7eb2Smrg     }
6378627f7eb2Smrg }
6379627f7eb2Smrg 
6380627f7eb2Smrg 
6381627f7eb2Smrg /* Resolve OpenMP directive clauses and check various requirements
6382627f7eb2Smrg    of each directive.  */
6383627f7eb2Smrg 
6384627f7eb2Smrg void
gfc_resolve_omp_directive(gfc_code * code,gfc_namespace * ns ATTRIBUTE_UNUSED)6385627f7eb2Smrg gfc_resolve_omp_directive (gfc_code *code, gfc_namespace *ns ATTRIBUTE_UNUSED)
6386627f7eb2Smrg {
6387627f7eb2Smrg   resolve_omp_directive_inside_oacc_region (code);
6388627f7eb2Smrg 
6389627f7eb2Smrg   if (code->op != EXEC_OMP_ATOMIC)
6390627f7eb2Smrg     gfc_maybe_initialize_eh ();
6391627f7eb2Smrg 
6392627f7eb2Smrg   switch (code->op)
6393627f7eb2Smrg     {
6394627f7eb2Smrg     case EXEC_OMP_DISTRIBUTE:
6395627f7eb2Smrg     case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
6396627f7eb2Smrg     case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
6397627f7eb2Smrg     case EXEC_OMP_DISTRIBUTE_SIMD:
6398627f7eb2Smrg     case EXEC_OMP_DO:
6399627f7eb2Smrg     case EXEC_OMP_DO_SIMD:
6400627f7eb2Smrg     case EXEC_OMP_PARALLEL_DO:
6401627f7eb2Smrg     case EXEC_OMP_PARALLEL_DO_SIMD:
6402627f7eb2Smrg     case EXEC_OMP_SIMD:
6403627f7eb2Smrg     case EXEC_OMP_TARGET_PARALLEL_DO:
6404627f7eb2Smrg     case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
6405627f7eb2Smrg     case EXEC_OMP_TARGET_SIMD:
6406627f7eb2Smrg     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
6407627f7eb2Smrg     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
6408627f7eb2Smrg     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
6409627f7eb2Smrg     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
6410627f7eb2Smrg     case EXEC_OMP_TASKLOOP:
6411627f7eb2Smrg     case EXEC_OMP_TASKLOOP_SIMD:
6412627f7eb2Smrg     case EXEC_OMP_TEAMS_DISTRIBUTE:
6413627f7eb2Smrg     case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
6414627f7eb2Smrg     case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
6415627f7eb2Smrg     case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
6416627f7eb2Smrg       resolve_omp_do (code);
6417627f7eb2Smrg       break;
6418627f7eb2Smrg     case EXEC_OMP_CANCEL:
6419627f7eb2Smrg     case EXEC_OMP_PARALLEL_WORKSHARE:
6420627f7eb2Smrg     case EXEC_OMP_PARALLEL:
6421627f7eb2Smrg     case EXEC_OMP_PARALLEL_SECTIONS:
6422627f7eb2Smrg     case EXEC_OMP_SECTIONS:
6423627f7eb2Smrg     case EXEC_OMP_SINGLE:
6424627f7eb2Smrg     case EXEC_OMP_TARGET:
6425627f7eb2Smrg     case EXEC_OMP_TARGET_DATA:
6426627f7eb2Smrg     case EXEC_OMP_TARGET_ENTER_DATA:
6427627f7eb2Smrg     case EXEC_OMP_TARGET_EXIT_DATA:
6428627f7eb2Smrg     case EXEC_OMP_TARGET_PARALLEL:
6429627f7eb2Smrg     case EXEC_OMP_TARGET_TEAMS:
6430627f7eb2Smrg     case EXEC_OMP_TASK:
6431627f7eb2Smrg     case EXEC_OMP_TEAMS:
6432627f7eb2Smrg     case EXEC_OMP_WORKSHARE:
6433627f7eb2Smrg       if (code->ext.omp_clauses)
6434627f7eb2Smrg 	resolve_omp_clauses (code, code->ext.omp_clauses, NULL);
6435627f7eb2Smrg       break;
6436627f7eb2Smrg     case EXEC_OMP_TARGET_UPDATE:
6437627f7eb2Smrg       if (code->ext.omp_clauses)
6438627f7eb2Smrg 	resolve_omp_clauses (code, code->ext.omp_clauses, NULL);
6439627f7eb2Smrg       if (code->ext.omp_clauses == NULL
6440627f7eb2Smrg 	  || (code->ext.omp_clauses->lists[OMP_LIST_TO] == NULL
6441627f7eb2Smrg 	      && code->ext.omp_clauses->lists[OMP_LIST_FROM] == NULL))
6442627f7eb2Smrg 	gfc_error ("OMP TARGET UPDATE at %L requires at least one TO or "
6443627f7eb2Smrg 		   "FROM clause", &code->loc);
6444627f7eb2Smrg       break;
6445627f7eb2Smrg     case EXEC_OMP_ATOMIC:
6446627f7eb2Smrg       resolve_omp_atomic (code);
6447627f7eb2Smrg       break;
6448627f7eb2Smrg     default:
6449627f7eb2Smrg       break;
6450627f7eb2Smrg     }
6451627f7eb2Smrg }
6452627f7eb2Smrg 
6453627f7eb2Smrg /* Resolve !$omp declare simd constructs in NS.  */
6454627f7eb2Smrg 
6455627f7eb2Smrg void
gfc_resolve_omp_declare_simd(gfc_namespace * ns)6456627f7eb2Smrg gfc_resolve_omp_declare_simd (gfc_namespace *ns)
6457627f7eb2Smrg {
6458627f7eb2Smrg   gfc_omp_declare_simd *ods;
6459627f7eb2Smrg 
6460627f7eb2Smrg   for (ods = ns->omp_declare_simd; ods; ods = ods->next)
6461627f7eb2Smrg     {
6462627f7eb2Smrg       if (ods->proc_name != NULL
6463627f7eb2Smrg 	  && ods->proc_name != ns->proc_name)
6464627f7eb2Smrg 	gfc_error ("!$OMP DECLARE SIMD should refer to containing procedure "
6465627f7eb2Smrg 		   "%qs at %L", ns->proc_name->name, &ods->where);
6466627f7eb2Smrg       if (ods->clauses)
6467627f7eb2Smrg 	resolve_omp_clauses (NULL, ods->clauses, ns);
6468627f7eb2Smrg     }
6469627f7eb2Smrg }
6470627f7eb2Smrg 
6471627f7eb2Smrg struct omp_udr_callback_data
6472627f7eb2Smrg {
6473627f7eb2Smrg   gfc_omp_udr *omp_udr;
6474627f7eb2Smrg   bool is_initializer;
6475627f7eb2Smrg };
6476627f7eb2Smrg 
6477627f7eb2Smrg static int
omp_udr_callback(gfc_expr ** e,int * walk_subtrees ATTRIBUTE_UNUSED,void * data)6478627f7eb2Smrg omp_udr_callback (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
6479627f7eb2Smrg 		  void *data)
6480627f7eb2Smrg {
6481627f7eb2Smrg   struct omp_udr_callback_data *cd = (struct omp_udr_callback_data *) data;
6482627f7eb2Smrg   if ((*e)->expr_type == EXPR_VARIABLE)
6483627f7eb2Smrg     {
6484627f7eb2Smrg       if (cd->is_initializer)
6485627f7eb2Smrg 	{
6486627f7eb2Smrg 	  if ((*e)->symtree->n.sym != cd->omp_udr->omp_priv
6487627f7eb2Smrg 	      && (*e)->symtree->n.sym != cd->omp_udr->omp_orig)
6488627f7eb2Smrg 	    gfc_error ("Variable other than OMP_PRIV or OMP_ORIG used in "
6489627f7eb2Smrg 		       "INITIALIZER clause of !$OMP DECLARE REDUCTION at %L",
6490627f7eb2Smrg 		       &(*e)->where);
6491627f7eb2Smrg 	}
6492627f7eb2Smrg       else
6493627f7eb2Smrg 	{
6494627f7eb2Smrg 	  if ((*e)->symtree->n.sym != cd->omp_udr->omp_out
6495627f7eb2Smrg 	      && (*e)->symtree->n.sym != cd->omp_udr->omp_in)
6496627f7eb2Smrg 	    gfc_error ("Variable other than OMP_OUT or OMP_IN used in "
6497627f7eb2Smrg 		       "combiner of !$OMP DECLARE REDUCTION at %L",
6498627f7eb2Smrg 		       &(*e)->where);
6499627f7eb2Smrg 	}
6500627f7eb2Smrg     }
6501627f7eb2Smrg   return 0;
6502627f7eb2Smrg }
6503627f7eb2Smrg 
6504627f7eb2Smrg /* Resolve !$omp declare reduction constructs.  */
6505627f7eb2Smrg 
6506627f7eb2Smrg static void
gfc_resolve_omp_udr(gfc_omp_udr * omp_udr)6507627f7eb2Smrg gfc_resolve_omp_udr (gfc_omp_udr *omp_udr)
6508627f7eb2Smrg {
6509627f7eb2Smrg   gfc_actual_arglist *a;
6510627f7eb2Smrg   const char *predef_name = NULL;
6511627f7eb2Smrg 
6512627f7eb2Smrg   switch (omp_udr->rop)
6513627f7eb2Smrg     {
6514627f7eb2Smrg     case OMP_REDUCTION_PLUS:
6515627f7eb2Smrg     case OMP_REDUCTION_TIMES:
6516627f7eb2Smrg     case OMP_REDUCTION_MINUS:
6517627f7eb2Smrg     case OMP_REDUCTION_AND:
6518627f7eb2Smrg     case OMP_REDUCTION_OR:
6519627f7eb2Smrg     case OMP_REDUCTION_EQV:
6520627f7eb2Smrg     case OMP_REDUCTION_NEQV:
6521627f7eb2Smrg     case OMP_REDUCTION_MAX:
6522627f7eb2Smrg     case OMP_REDUCTION_USER:
6523627f7eb2Smrg       break;
6524627f7eb2Smrg     default:
6525627f7eb2Smrg       gfc_error ("Invalid operator for !$OMP DECLARE REDUCTION %s at %L",
6526627f7eb2Smrg 		 omp_udr->name, &omp_udr->where);
6527627f7eb2Smrg       return;
6528627f7eb2Smrg     }
6529627f7eb2Smrg 
6530627f7eb2Smrg   if (gfc_omp_udr_predef (omp_udr->rop, omp_udr->name,
6531627f7eb2Smrg 			  &omp_udr->ts, &predef_name))
6532627f7eb2Smrg     {
6533627f7eb2Smrg       if (predef_name)
6534627f7eb2Smrg 	gfc_error_now ("Redefinition of predefined %s "
6535627f7eb2Smrg 		       "!$OMP DECLARE REDUCTION at %L",
6536627f7eb2Smrg 		       predef_name, &omp_udr->where);
6537627f7eb2Smrg       else
6538627f7eb2Smrg 	gfc_error_now ("Redefinition of predefined "
6539627f7eb2Smrg 		       "!$OMP DECLARE REDUCTION at %L", &omp_udr->where);
6540627f7eb2Smrg       return;
6541627f7eb2Smrg     }
6542627f7eb2Smrg 
6543627f7eb2Smrg   if (omp_udr->ts.type == BT_CHARACTER
6544627f7eb2Smrg       && omp_udr->ts.u.cl->length
6545627f7eb2Smrg       && omp_udr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
6546627f7eb2Smrg     {
6547627f7eb2Smrg       gfc_error ("CHARACTER length in !$OMP DECLARE REDUCTION %s not "
6548627f7eb2Smrg 		 "constant at %L", omp_udr->name, &omp_udr->where);
6549627f7eb2Smrg       return;
6550627f7eb2Smrg     }
6551627f7eb2Smrg 
6552627f7eb2Smrg   struct omp_udr_callback_data cd;
6553627f7eb2Smrg   cd.omp_udr = omp_udr;
6554627f7eb2Smrg   cd.is_initializer = false;
6555627f7eb2Smrg   gfc_code_walker (&omp_udr->combiner_ns->code, gfc_dummy_code_callback,
6556627f7eb2Smrg 		   omp_udr_callback, &cd);
6557627f7eb2Smrg   if (omp_udr->combiner_ns->code->op == EXEC_CALL)
6558627f7eb2Smrg     {
6559627f7eb2Smrg       for (a = omp_udr->combiner_ns->code->ext.actual; a; a = a->next)
6560627f7eb2Smrg 	if (a->expr == NULL)
6561627f7eb2Smrg 	  break;
6562627f7eb2Smrg       if (a)
6563627f7eb2Smrg 	gfc_error ("Subroutine call with alternate returns in combiner "
6564627f7eb2Smrg 		   "of !$OMP DECLARE REDUCTION at %L",
6565627f7eb2Smrg 		   &omp_udr->combiner_ns->code->loc);
6566627f7eb2Smrg     }
6567627f7eb2Smrg   if (omp_udr->initializer_ns)
6568627f7eb2Smrg     {
6569627f7eb2Smrg       cd.is_initializer = true;
6570627f7eb2Smrg       gfc_code_walker (&omp_udr->initializer_ns->code, gfc_dummy_code_callback,
6571627f7eb2Smrg 		       omp_udr_callback, &cd);
6572627f7eb2Smrg       if (omp_udr->initializer_ns->code->op == EXEC_CALL)
6573627f7eb2Smrg 	{
6574627f7eb2Smrg 	  for (a = omp_udr->initializer_ns->code->ext.actual; a; a = a->next)
6575627f7eb2Smrg 	    if (a->expr == NULL)
6576627f7eb2Smrg 	      break;
6577627f7eb2Smrg 	  if (a)
6578627f7eb2Smrg 	    gfc_error ("Subroutine call with alternate returns in "
6579627f7eb2Smrg 		       "INITIALIZER clause of !$OMP DECLARE REDUCTION "
6580627f7eb2Smrg 		       "at %L", &omp_udr->initializer_ns->code->loc);
6581627f7eb2Smrg 	  for (a = omp_udr->initializer_ns->code->ext.actual; a; a = a->next)
6582627f7eb2Smrg 	    if (a->expr
6583627f7eb2Smrg 		&& a->expr->expr_type == EXPR_VARIABLE
6584627f7eb2Smrg 		&& a->expr->symtree->n.sym == omp_udr->omp_priv
6585627f7eb2Smrg 		&& a->expr->ref == NULL)
6586627f7eb2Smrg 	      break;
6587627f7eb2Smrg 	  if (a == NULL)
6588627f7eb2Smrg 	    gfc_error ("One of actual subroutine arguments in INITIALIZER "
6589627f7eb2Smrg 		       "clause of !$OMP DECLARE REDUCTION must be OMP_PRIV "
6590627f7eb2Smrg 		       "at %L", &omp_udr->initializer_ns->code->loc);
6591627f7eb2Smrg 	}
6592627f7eb2Smrg     }
6593627f7eb2Smrg   else if (omp_udr->ts.type == BT_DERIVED
6594627f7eb2Smrg 	   && !gfc_has_default_initializer (omp_udr->ts.u.derived))
6595627f7eb2Smrg     {
6596627f7eb2Smrg       gfc_error ("Missing INITIALIZER clause for !$OMP DECLARE REDUCTION "
6597627f7eb2Smrg 		 "of derived type without default initializer at %L",
6598627f7eb2Smrg 		 &omp_udr->where);
6599627f7eb2Smrg       return;
6600627f7eb2Smrg     }
6601627f7eb2Smrg }
6602627f7eb2Smrg 
6603627f7eb2Smrg void
gfc_resolve_omp_udrs(gfc_symtree * st)6604627f7eb2Smrg gfc_resolve_omp_udrs (gfc_symtree *st)
6605627f7eb2Smrg {
6606627f7eb2Smrg   gfc_omp_udr *omp_udr;
6607627f7eb2Smrg 
6608627f7eb2Smrg   if (st == NULL)
6609627f7eb2Smrg     return;
6610627f7eb2Smrg   gfc_resolve_omp_udrs (st->left);
6611627f7eb2Smrg   gfc_resolve_omp_udrs (st->right);
6612627f7eb2Smrg   for (omp_udr = st->n.omp_udr; omp_udr; omp_udr = omp_udr->next)
6613627f7eb2Smrg     gfc_resolve_omp_udr (omp_udr);
6614627f7eb2Smrg }
6615