LCOV - code coverage report
Current view: top level - gcc/fortran - openmp.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 93.5 % 8052 7529
Test Date: 2026-10-03 16:17:38 Functions: 100.0 % 236 236
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* OpenMP directive matching and resolving.
       2              :    Copyright (C) 2005-2026 Free Software Foundation, Inc.
       3              :    Contributed by Jakub Jelinek
       4              : 
       5              : This file is part of GCC.
       6              : 
       7              : GCC is free software; you can redistribute it and/or modify it under
       8              : the terms of the GNU General Public License as published by the Free
       9              : Software Foundation; either version 3, or (at your option) any later
      10              : version.
      11              : 
      12              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      13              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      14              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      15              : for more details.
      16              : 
      17              : You should have received a copy of the GNU General Public License
      18              : along with GCC; see the file COPYING3.  If not see
      19              : <http://www.gnu.org/licenses/>.  */
      20              : 
      21              : #define INCLUDE_VECTOR
      22              : #define INCLUDE_STRING
      23              : #include "config.h"
      24              : #include "system.h"
      25              : #include "coretypes.h"
      26              : #include "options.h"
      27              : #include "gfortran.h"
      28              : #include "arith.h"
      29              : #include "match.h"
      30              : #include "parse.h"
      31              : #include "constructor.h"
      32              : #include "diagnostic.h"
      33              : #include "gomp-constants.h"
      34              : #include "target-memory.h"  /* For gfc_encode_character.  */
      35              : #include "bitmap.h"
      36              : #include "omp-api.h"  /* For omp_runtime_api_procname.  */
      37              : 
      38              : location_t gfc_get_location (locus *);
      39              : 
      40              : static gfc_statement omp_code_to_statement (gfc_code *);
      41              : 
      42              : enum gfc_omp_directive_kind {
      43              :   GFC_OMP_DIR_DECLARATIVE,
      44              :   GFC_OMP_DIR_EXECUTABLE,
      45              :   GFC_OMP_DIR_INFORMATIONAL,
      46              :   GFC_OMP_DIR_META,
      47              :   GFC_OMP_DIR_SUBSIDIARY,
      48              :   GFC_OMP_DIR_UTILITY
      49              : };
      50              : 
      51              : struct gfc_omp_directive {
      52              :   const char *name;
      53              :   enum gfc_omp_directive_kind kind;
      54              :   gfc_statement st;
      55              : };
      56              : 
      57              : /* Alphabetically sorted OpenMP clauses, except that longer strings are before
      58              :    substrings; excludes combined/composite directives. See note for "ordered"
      59              :    and "nothing".  */
      60              : 
      61              : static const struct gfc_omp_directive gfc_omp_directives[] = {
      62              :   /* allocate as alias for allocators is also executive. */
      63              :   {"allocate", GFC_OMP_DIR_DECLARATIVE, ST_OMP_ALLOCATE},
      64              :   {"allocators", GFC_OMP_DIR_EXECUTABLE, ST_OMP_ALLOCATORS},
      65              :   {"assumes", GFC_OMP_DIR_INFORMATIONAL, ST_OMP_ASSUMES},
      66              :   {"assume", GFC_OMP_DIR_INFORMATIONAL, ST_OMP_ASSUME},
      67              :   {"atomic", GFC_OMP_DIR_EXECUTABLE, ST_OMP_ATOMIC},
      68              :   {"barrier", GFC_OMP_DIR_EXECUTABLE, ST_OMP_BARRIER},
      69              :   {"cancellation point", GFC_OMP_DIR_EXECUTABLE, ST_OMP_CANCELLATION_POINT},
      70              :   {"cancellation_point", GFC_OMP_DIR_EXECUTABLE, ST_OMP_CANCELLATION_POINT},
      71              :   {"cancel", GFC_OMP_DIR_EXECUTABLE, ST_OMP_CANCEL},
      72              :   {"critical", GFC_OMP_DIR_EXECUTABLE, ST_OMP_CRITICAL},
      73              :   /* {"declare induction", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_INDUCTION}, */
      74              :   /* {"declare_induction", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_INDUCTION}, */
      75              :   {"declare mapper", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_MAPPER},
      76              :   {"declare_mapper", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_MAPPER},
      77              :   {"declare reduction", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_REDUCTION},
      78              :   {"declare_reduction", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_REDUCTION},
      79              :   {"declare simd", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_SIMD},
      80              :   {"declare_simd", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_SIMD},
      81              :   {"declare target", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_TARGET},
      82              :   {"declare_target", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_TARGET},
      83              :   {"declare variant", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_VARIANT},
      84              :   {"declare_variant", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_VARIANT},
      85              :   {"depobj", GFC_OMP_DIR_EXECUTABLE, ST_OMP_DEPOBJ},
      86              :   {"dispatch", GFC_OMP_DIR_EXECUTABLE, ST_OMP_DISPATCH},
      87              :   {"distribute", GFC_OMP_DIR_EXECUTABLE, ST_OMP_DISTRIBUTE},
      88              :   {"do", GFC_OMP_DIR_EXECUTABLE, ST_OMP_DO},
      89              :   /* "error" becomes GFC_OMP_DIR_EXECUTABLE with at(execution) */
      90              :   {"error", GFC_OMP_DIR_UTILITY, ST_OMP_ERROR},
      91              :   /* {"flatten", GFC_OMP_DIR_EXECUTABLE, ST_OMP_FLATTEN}, */
      92              :   {"flush", GFC_OMP_DIR_EXECUTABLE, ST_OMP_FLUSH},
      93              :   /* {"fuse", GFC_OMP_DIR_EXECUTABLE, ST_OMP_FLUSE}, */
      94              :   {"groupprivate", GFC_OMP_DIR_DECLARATIVE, ST_OMP_GROUPPRIVATE},
      95              :   /* {"interchange", GFC_OMP_DIR_EXECUTABLE, ST_OMP_INTERCHANGE}, */
      96              :   {"interop", GFC_OMP_DIR_EXECUTABLE, ST_OMP_INTEROP},
      97              :   {"loop", GFC_OMP_DIR_EXECUTABLE, ST_OMP_LOOP},
      98              :   {"masked", GFC_OMP_DIR_EXECUTABLE, ST_OMP_MASKED},
      99              :   {"metadirective", GFC_OMP_DIR_META, ST_OMP_METADIRECTIVE},
     100              :   /* Note: gfc_match_omp_nothing returns ST_NONE.  */
     101              :   {"nothing", GFC_OMP_DIR_UTILITY, ST_OMP_NOTHING},
     102              :   /* Special case; for now map to the first one.
     103              :      ordered-blockassoc = ST_OMP_ORDERED
     104              :      ordered-standalone = ST_OMP_ORDERED_DEPEND + depend/doacross.  */
     105              :   {"ordered", GFC_OMP_DIR_EXECUTABLE, ST_OMP_ORDERED},
     106              :   {"parallel", GFC_OMP_DIR_EXECUTABLE, ST_OMP_PARALLEL},
     107              :   {"requires", GFC_OMP_DIR_INFORMATIONAL, ST_OMP_REQUIRES},
     108              :   {"scan", GFC_OMP_DIR_SUBSIDIARY, ST_OMP_SCAN},
     109              :   {"scope", GFC_OMP_DIR_EXECUTABLE, ST_OMP_SCOPE},
     110              :   {"sections", GFC_OMP_DIR_EXECUTABLE, ST_OMP_SECTIONS},
     111              :   {"section", GFC_OMP_DIR_SUBSIDIARY, ST_OMP_SECTION},
     112              :   {"simd", GFC_OMP_DIR_EXECUTABLE, ST_OMP_SIMD},
     113              :   {"single", GFC_OMP_DIR_EXECUTABLE, ST_OMP_SINGLE},
     114              :   /* {"split", GFC_OMP_DIR_EXECUTABLE, ST_OMP_SPLIT}, */
     115              :   /* {"strip", GFC_OMP_DIR_EXECUTABLE, ST_OMP_STRIP}, */
     116              :   {"target data", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TARGET_DATA},
     117              :   {"target_data", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TARGET_DATA},
     118              :   {"target enter data", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TARGET_ENTER_DATA},
     119              :   {"target_enter_data", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TARGET_ENTER_DATA},
     120              :   {"target exit data", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TARGET_EXIT_DATA},
     121              :   {"target_exit_data", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TARGET_EXIT_DATA},
     122              :   {"target update", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TARGET_UPDATE},
     123              :   {"target_update", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TARGET_UPDATE},
     124              :   {"target", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TARGET},
     125              :   /* {"taskgraph", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TASKGRAPH}, */
     126              :   /* {"task iteration", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TASK_ITERATION}, */
     127              :   {"taskloop", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TASKLOOP},
     128              :   {"taskwait", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TASKWAIT},
     129              :   {"taskyield", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TASKYIELD},
     130              :   {"task", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TASK},
     131              :   {"teams", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TEAMS},
     132              :   {"threadprivate", GFC_OMP_DIR_DECLARATIVE, ST_OMP_THREADPRIVATE},
     133              :   {"tile", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TILE},
     134              :   {"unroll", GFC_OMP_DIR_EXECUTABLE, ST_OMP_UNROLL},
     135              :   /* {"workdistribute", GFC_OMP_DIR_EXECUTABLE, ST_OMP_WORKDISTRIBUTE}, */
     136              :   {"workshare", GFC_OMP_DIR_EXECUTABLE, ST_OMP_WORKSHARE},
     137              : };
     138              : 
     139              : 
     140              : /* Match an end of OpenMP directive.  End of OpenMP directive is optional
     141              :    whitespace, followed by '\n' or comment '!'.  In the special case where a
     142              :    context selector is being matched, match against ')' instead.  */
     143              : 
     144              : static match
     145        56281 : gfc_match_omp_eos (void)
     146              : {
     147        56281 :   locus old_loc;
     148        56281 :   char c;
     149              : 
     150        56281 :   old_loc = gfc_current_locus;
     151        56281 :   gfc_gobble_whitespace ();
     152              : 
     153        56281 :   if (gfc_matching_omp_context_selector)
     154              :     {
     155          276 :       if (gfc_peek_ascii_char () == ')')
     156              :         return MATCH_YES;
     157              :     }
     158              :   else
     159              :     {
     160        56005 :       c = gfc_next_ascii_char ();
     161        56005 :       switch (c)
     162              :         {
     163            0 :         case '!':
     164            0 :           do
     165            0 :             c = gfc_next_ascii_char ();
     166            0 :           while (c != '\n');
     167              :           /* Fall through */
     168              : 
     169              :         case '\n':
     170              :           return MATCH_YES;
     171              :         }
     172              :     }
     173              : 
     174         1791 :   gfc_current_locus = old_loc;
     175         1791 :   return MATCH_NO;
     176              : }
     177              : 
     178              : match
     179        13225 : gfc_match_omp_eos_error (void)
     180              : {
     181        13225 :   if (gfc_match_omp_eos() == MATCH_YES)
     182              :     return MATCH_YES;
     183              : 
     184           35 :   gfc_error ("Unexpected junk at %C");
     185           35 :   return MATCH_ERROR;
     186              : }
     187              : 
     188              : 
     189              : /* Free an omp_clauses structure.  */
     190              : 
     191              : void
     192        83730 : gfc_free_omp_clauses (gfc_omp_clauses *c)
     193              : {
     194        83730 :   if (c == NULL)
     195              :     return;
     196              : 
     197        56698 :   gfc_free_expr (c->if_expr);
     198       680376 :   for (int i = 0; i < OMP_IF_LAST; i++)
     199       566980 :     gfc_free_expr (c->if_exprs[i]);
     200        56698 :   gfc_free_expr (c->self_expr);
     201        56698 :   gfc_free_expr (c->final_expr);
     202        56698 :   gfc_free_expr (c->chunk_size);
     203        56698 :   gfc_free_expr (c->safelen_expr);
     204        56698 :   gfc_free_expr (c->simdlen_expr);
     205        56698 :   gfc_free_expr (c->device);
     206        56698 :   gfc_free_expr (c->dyn_groupprivate);
     207        56698 :   gfc_free_expr (c->dist_chunk_size);
     208        56698 :   gfc_free_expr (c->grainsize);
     209        56698 :   gfc_free_expr (c->hint);
     210        56698 :   gfc_free_expr (c->num_tasks);
     211        56698 :   gfc_free_expr (c->priority);
     212        56698 :   gfc_free_expr (c->detach);
     213        56698 :   gfc_free_expr (c->novariants);
     214        56698 :   gfc_free_expr (c->nocontext);
     215        56698 :   gfc_free_expr (c->async_expr);
     216        56698 :   gfc_free_expr (c->gang_num_expr);
     217        56698 :   gfc_free_expr (c->gang_static_expr);
     218        56698 :   gfc_free_expr (c->worker_expr);
     219        56698 :   gfc_free_expr (c->vector_expr);
     220        56698 :   gfc_free_expr (c->num_gangs_expr);
     221        56698 :   gfc_free_expr (c->num_workers_expr);
     222        56698 :   gfc_free_expr (c->vector_length_expr);
     223        56698 :   gfc_free_expr (c->device_num_expr);
     224      2324618 :   for (enum gfc_omp_list_type t = OMP_LIST_FIRST; t < OMP_LIST_NUM;
     225      2211222 :        t = gfc_omp_list_type (t + 1))
     226      2211222 :     gfc_free_omp_namelist (c->lists[t], t);
     227        56698 :   gfc_free_expr_list (c->num_teams_list);
     228        56698 :   gfc_free_expr_list (c->thread_limit_list);
     229        56698 :   gfc_free_expr_list (c->num_threads_list);
     230        56698 :   gfc_free_expr_list (c->wait_list);
     231        56698 :   gfc_free_expr_list (c->tile_list);
     232        56698 :   gfc_free_expr_list (c->sizes_list);
     233        56698 :   free (const_cast<char *> (c->critical_name));
     234        56698 :   if (c->assume)
     235              :     {
     236           33 :       free (c->assume->absent);
     237           33 :       free (c->assume->contains);
     238           33 :       gfc_free_expr_list (c->assume->holds);
     239           33 :       free (c->assume);
     240              :     }
     241        56698 :   free (c);
     242              : }
     243              : 
     244              : /* Free oacc_declare structures.  */
     245              : 
     246              : void
     247           76 : gfc_free_oacc_declare_clauses (struct gfc_oacc_declare *oc)
     248              : {
     249           76 :   struct gfc_oacc_declare *decl = oc;
     250              : 
     251           76 :   do
     252              :     {
     253           76 :       struct gfc_oacc_declare *next;
     254              : 
     255           76 :       next = decl->next;
     256           76 :       gfc_free_omp_clauses (decl->clauses);
     257           76 :       free (decl);
     258           76 :       decl = next;
     259              :     }
     260           76 :   while (decl);
     261           76 : }
     262              : 
     263              : /* Free expression list. */
     264              : void
     265       341435 : gfc_free_expr_list (gfc_expr_list *list)
     266              : {
     267       341435 :   gfc_expr_list *n;
     268              : 
     269       344226 :   for (; list; list = n)
     270              :     {
     271         2791 :       n = list->next;
     272         2791 :       free (list);
     273              :     }
     274       341435 : }
     275              : 
     276              : /* Free an !$omp declare simd construct list.  */
     277              : 
     278              : void
     279          247 : gfc_free_omp_declare_simd (gfc_omp_declare_simd *ods)
     280              : {
     281          247 :   if (ods)
     282              :     {
     283          247 :       gfc_free_omp_clauses (ods->clauses);
     284          247 :       free (ods);
     285              :     }
     286          247 : }
     287              : 
     288              : void
     289       548089 : gfc_free_omp_declare_simd_list (gfc_omp_declare_simd *list)
     290              : {
     291       548336 :   while (list)
     292              :     {
     293          247 :       gfc_omp_declare_simd *current = list;
     294          247 :       list = list->next;
     295          247 :       gfc_free_omp_declare_simd (current);
     296              :     }
     297       548089 : }
     298              : 
     299              : static void
     300          738 : gfc_free_omp_trait_property_list (gfc_omp_trait_property *list)
     301              : {
     302         1150 :   while (list)
     303              :     {
     304          412 :       gfc_omp_trait_property *current = list;
     305          412 :       list = list->next;
     306          412 :       switch (current->property_kind)
     307              :         {
     308           24 :         case OMP_TRAIT_PROPERTY_ID:
     309           24 :           free (current->name);
     310           24 :           break;
     311          261 :         case OMP_TRAIT_PROPERTY_NAME_LIST:
     312          261 :           if (current->is_name)
     313          168 :             free (current->name);
     314              :           break;
     315           15 :         case OMP_TRAIT_PROPERTY_CLAUSE_LIST:
     316           15 :           gfc_free_omp_clauses (current->clauses);
     317           15 :           break;
     318              :         default:
     319              :           break;
     320              :         }
     321          412 :       free (current);
     322              :     }
     323          738 : }
     324              : 
     325              : static void
     326          609 : gfc_free_omp_selector_list (gfc_omp_selector *list)
     327              : {
     328         1347 :   while (list)
     329              :     {
     330          738 :       gfc_omp_selector *current = list;
     331          738 :       list = list->next;
     332          738 :       gfc_free_omp_trait_property_list (current->properties);
     333          738 :       free (current);
     334              :     }
     335          609 : }
     336              : 
     337              : static void
     338          681 : gfc_free_omp_set_selector_list (gfc_omp_set_selector *list)
     339              : {
     340         1290 :   while (list)
     341              :     {
     342          609 :       gfc_omp_set_selector *current = list;
     343          609 :       list = list->next;
     344          609 :       gfc_free_omp_selector_list (current->trait_selectors);
     345          609 :       free (current);
     346              :     }
     347          681 : }
     348              : 
     349              : /* Free an !$omp declare variant construct list.  */
     350              : 
     351              : void
     352       548089 : gfc_free_omp_declare_variant_list (gfc_omp_declare_variant *list)
     353              : {
     354       548550 :   while (list)
     355              :     {
     356          461 :       gfc_omp_declare_variant *current = list;
     357          461 :       list = list->next;
     358          461 :       gfc_free_omp_set_selector_list (current->set_selectors);
     359          461 :       gfc_free_omp_namelist (current->adjust_args_list, OMP_LIST_NONE);
     360          461 :       free (current);
     361              :     }
     362       548089 : }
     363              : 
     364              : /* Free an !$omp declare reduction.  */
     365              : 
     366              : void
     367         1285 : gfc_free_omp_udr (gfc_omp_udr *omp_udr)
     368              : {
     369         1285 :   if (omp_udr)
     370              :     {
     371          692 :       gfc_free_omp_udr (omp_udr->next);
     372          692 :       gfc_free_namespace (omp_udr->combiner_ns);
     373          692 :       if (omp_udr->initializer_ns)
     374          392 :         gfc_free_namespace (omp_udr->initializer_ns);
     375          692 :       free (omp_udr);
     376              :     }
     377         1285 : }
     378              : 
     379              : /* Free variants of an !$omp metadirective construct.  */
     380              : 
     381              : void
     382           96 : gfc_free_omp_variants (gfc_omp_variant *variant)
     383              : {
     384          293 :   while (variant)
     385              :     {
     386          197 :       gfc_omp_variant *next_variant = variant->next;
     387          197 :       gfc_free_omp_set_selector_list (variant->selectors);
     388          197 :       free (variant);
     389          197 :       variant = next_variant;
     390              :     }
     391           96 : }
     392              : 
     393              : /* Free an !$omp declare mapper.  */
     394              : 
     395              : void
     396           60 : gfc_free_omp_udm (gfc_omp_udm *omp_udm)
     397              : {
     398           60 :   if (omp_udm)
     399              :     {
     400           30 :       gfc_free_omp_udm (omp_udm->next);
     401           30 :       gfc_free_namespace (omp_udm->mapper_ns);
     402           30 :       free (omp_udm);
     403              :     }
     404           60 : }
     405              : 
     406              : static gfc_omp_udr *
     407         4718 : gfc_find_omp_udr (gfc_namespace *ns, const char *name, gfc_typespec *ts)
     408              : {
     409         4718 :   gfc_symtree *st;
     410              : 
     411         4718 :   if (ns == NULL)
     412          471 :     ns = gfc_current_ns;
     413         5668 :   do
     414              :     {
     415         5668 :       gfc_omp_udr *omp_udr;
     416              : 
     417         5668 :       st = gfc_find_symtree (ns->omp_udr_root, name);
     418         5668 :       if (st != NULL)
     419              :         {
     420          943 :           for (omp_udr = st->n.omp_udr; omp_udr; omp_udr = omp_udr->next)
     421          943 :             if (ts == NULL)
     422              :               return omp_udr;
     423          572 :             else if (gfc_compare_types (&omp_udr->ts, ts))
     424              :               {
     425          483 :                 if (ts->type == BT_CHARACTER)
     426              :                   {
     427           60 :                     if (omp_udr->ts.u.cl->length == NULL)
     428              :                       return omp_udr;
     429           36 :                     if (ts->u.cl->length == NULL)
     430            0 :                       continue;
     431           36 :                     if (gfc_compare_expr (omp_udr->ts.u.cl->length,
     432              :                                           ts->u.cl->length,
     433              :                                           INTRINSIC_EQ) != 0)
     434           12 :                       continue;
     435              :                   }
     436              :                 return omp_udr;
     437              :               }
     438              :         }
     439              : 
     440              :       /* Don't escape an interface block.  */
     441         4826 :       if (ns && !ns->has_import_set
     442         4826 :           && ns->proc_name && ns->proc_name->attr.if_source == IFSRC_IFBODY)
     443              :         break;
     444              : 
     445         4826 :       ns = ns->parent;
     446              :     }
     447         4826 :   while (ns != NULL);
     448              : 
     449              :   return NULL;
     450              : }
     451              : 
     452              : 
     453              : /* Match a variable/common block list and construct a namelist from it;
     454              :    if has_all_memory != NULL, *has_all_memory is set and omp_all_memory
     455              :    yields a list->sym NULL entry. */
     456              : 
     457              : static match
     458        31851 : gfc_match_omp_variable_list (const char *str, gfc_omp_namelist **list,
     459              :                              bool allow_common, bool *end_colon = NULL,
     460              :                              gfc_omp_namelist ***headp = NULL,
     461              :                              bool allow_sections = false,
     462              :                              bool allow_derived = false,
     463              :                              bool *has_all_memory = NULL,
     464              :                              bool reject_common_vars = false,
     465              :                              bool reverse_order = false)
     466              : {
     467        31851 :   gfc_omp_namelist *head, *tail, *p;
     468        31851 :   locus old_loc, cur_loc;
     469        31851 :   char n[GFC_MAX_SYMBOL_LEN+1];
     470        31851 :   gfc_symbol *sym;
     471        31851 :   match m;
     472        31851 :   gfc_symtree *st;
     473              : 
     474        31851 :   head = tail = NULL;
     475              : 
     476        31851 :   old_loc = gfc_current_locus;
     477        31851 :   if (has_all_memory)
     478          709 :     *has_all_memory = false;
     479        31851 :   m = gfc_match (str);
     480        31851 :   if (m != MATCH_YES)
     481              :     return m;
     482              : 
     483        38531 :   for (;;)
     484              :     {
     485        38531 :       gfc_gobble_whitespace ();
     486        38531 :       cur_loc = gfc_current_locus;
     487              : 
     488        38531 :       m = gfc_match_name (n);
     489        38531 :       if (m == MATCH_YES && strcmp (n, "omp_all_memory") == 0)
     490              :         {
     491           23 :           locus loc = gfc_get_location_range (NULL, 0, &cur_loc, 1,
     492              :                                               &gfc_current_locus);
     493           23 :           if (!has_all_memory)
     494              :             {
     495            2 :               gfc_error ("%<omp_all_memory%> at %L not permitted in this "
     496              :                          "clause", &loc);
     497            2 :               goto cleanup;
     498              :             }
     499           21 :           *has_all_memory = true;
     500           21 :           p = gfc_get_omp_namelist ();
     501           21 :           if (head == NULL)
     502              :             head = tail = p;
     503              :           else
     504              :             {
     505            3 :               tail->next = p;
     506            3 :               tail = tail->next;
     507              :             }
     508           21 :           tail->where = loc;
     509           21 :           goto next_item;
     510              :         }
     511        38252 :       if (m == MATCH_YES)
     512              :         {
     513        38252 :           gfc_symtree *st;
     514        38252 :           if ((m = gfc_get_ha_sym_tree (n, &st) ? MATCH_ERROR : MATCH_YES)
     515              :               == MATCH_YES)
     516        38252 :             sym = st->n.sym;
     517              :         }
     518        38508 :       switch (m)
     519              :         {
     520        38252 :         case MATCH_YES:
     521        38252 :           gfc_expr *expr;
     522        38252 :           expr = NULL;
     523        38252 :           gfc_gobble_whitespace ();
     524        23548 :           if ((allow_sections && gfc_peek_ascii_char () == '(')
     525        57438 :               || (allow_derived && gfc_peek_ascii_char () == '%'))
     526              :             {
     527         6609 :               gfc_current_locus = cur_loc;
     528         6609 :               m = gfc_match_variable (&expr, 0);
     529         6609 :               switch (m)
     530              :                 {
     531            4 :                 case MATCH_ERROR:
     532           12 :                   goto cleanup;
     533            0 :                 case MATCH_NO:
     534            0 :                   goto syntax;
     535         6605 :                 default:
     536         6605 :                   break;
     537              :                 }
     538         6605 :               if (gfc_is_coindexed (expr))
     539              :                 {
     540            5 :                   gfc_error ("List item shall not be coindexed at %L",
     541            5 :                              &expr->where);
     542            5 :                   goto cleanup;
     543              :                 }
     544              :             }
     545        38243 :           gfc_set_sym_referenced (sym);
     546        38243 :           p = gfc_get_omp_namelist ();
     547        38243 :           if (head == NULL)
     548              :             head = tail = p;
     549        10161 :           else if (reverse_order)
     550              :             {
     551           57 :               p->next = head;
     552           57 :               head = p;
     553              :             }
     554              :           else
     555              :             {
     556        10104 :               tail->next = p;
     557        10104 :               tail = tail->next;
     558              :             }
     559        38243 :           p->sym = sym;
     560        38243 :           p->expr = expr;
     561        38243 :           p->where = gfc_get_location_range (NULL, 0, &cur_loc, 1,
     562              :                                              &gfc_current_locus);
     563        38243 :           if (reject_common_vars && sym->attr.in_common)
     564              :             {
     565            3 :               gcc_assert (allow_common);
     566            3 :               gfc_error ("%qs at %L is part of the common block %</%s/%> and "
     567              :                          "may only be specified implicitly via the named "
     568              :                          "common block", sym->name, &cur_loc,
     569            3 :                          sym->common_head->name);
     570            3 :               goto cleanup;
     571              :             }
     572        38240 :           goto next_item;
     573          256 :         case MATCH_NO:
     574          256 :           break;
     575            0 :         case MATCH_ERROR:
     576            0 :           goto cleanup;
     577              :         }
     578              : 
     579          256 :       if (!allow_common)
     580           12 :         goto syntax;
     581              : 
     582          244 :       m = gfc_match ("/ %n /", n);
     583          244 :       if (m == MATCH_ERROR)
     584            0 :         goto cleanup;
     585          244 :       if (m == MATCH_NO)
     586           19 :         goto syntax;
     587              : 
     588          225 :       cur_loc = gfc_get_location_range (NULL, 0, &cur_loc, 1,
     589              :                                         &gfc_current_locus);
     590          225 :       st = gfc_find_symtree (gfc_current_ns->common_root, n);
     591          225 :       if (st == NULL)
     592              :         {
     593            2 :           gfc_error ("COMMON block %</%s/%> not found at %L", n, &cur_loc);
     594            2 :           goto cleanup;
     595              :         }
     596          724 :       for (sym = st->n.common->head; sym; sym = sym->common_next)
     597              :         {
     598          501 :           gfc_set_sym_referenced (sym);
     599          501 :           p = gfc_get_omp_namelist ();
     600          501 :           if (head == NULL)
     601              :             head = tail = p;
     602          325 :           else if (reverse_order)
     603              :             {
     604            0 :               p->next = head;
     605            0 :               head = p;
     606              :             }
     607              :           else
     608              :             {
     609          325 :               tail->next = p;
     610          325 :               tail = tail->next;
     611              :             }
     612          501 :           p->sym = sym;
     613          501 :           p->where = cur_loc;
     614              :         }
     615              : 
     616          223 :     next_item:
     617        38484 :       if (end_colon && gfc_match_char (':') == MATCH_YES)
     618              :         {
     619          806 :           *end_colon = true;
     620          806 :           break;
     621              :         }
     622        37678 :       if (gfc_match_char (')') == MATCH_YES)
     623              :         break;
     624        10232 :       if (gfc_match_char (',') != MATCH_YES)
     625           21 :         goto syntax;
     626              :     }
     627              : 
     628        38296 :   while (*list)
     629        10044 :     list = &(*list)->next;
     630              : 
     631        28252 :   *list = head;
     632        28252 :   if (headp)
     633        22351 :     *headp = list;
     634              :   return MATCH_YES;
     635              : 
     636           52 : syntax:
     637           52 :   gfc_error ("Syntax error in OpenMP variable list at %C");
     638              : 
     639           68 : cleanup:
     640           68 :   gfc_free_omp_namelist (head, OMP_LIST_NONE);
     641           68 :   gfc_current_locus = old_loc;
     642           68 :   return MATCH_ERROR;
     643              : }
     644              : 
     645              : /* Match a variable/procedure/common block list and construct a namelist
     646              :    from it.  */
     647              : 
     648              : static match
     649          392 : gfc_match_omp_to_link (const char *str, gfc_omp_namelist **list)
     650              : {
     651          392 :   gfc_omp_namelist *head, *tail, *p;
     652          392 :   locus old_loc, cur_loc;
     653          392 :   char n[GFC_MAX_SYMBOL_LEN+1];
     654          392 :   gfc_symbol *sym;
     655          392 :   match m;
     656          392 :   gfc_symtree *st;
     657              : 
     658          392 :   head = tail = NULL;
     659              : 
     660          392 :   old_loc = gfc_current_locus;
     661              : 
     662          392 :   m = gfc_match (str);
     663          392 :   if (m != MATCH_YES)
     664              :     return m;
     665              : 
     666          569 :   for (;;)
     667              :     {
     668          569 :       cur_loc = gfc_current_locus;
     669          569 :       m = gfc_match_symbol (&sym, 1);
     670          569 :       switch (m)
     671              :         {
     672          527 :         case MATCH_YES:
     673          527 :           p = gfc_get_omp_namelist ();
     674          527 :           if (head == NULL)
     675              :             head = tail = p;
     676              :           else
     677              :             {
     678          194 :               tail->next = p;
     679          194 :               tail = tail->next;
     680              :             }
     681          527 :           tail->sym = sym;
     682          527 :           tail->where = cur_loc;
     683          527 :           goto next_item;
     684              :         case MATCH_NO:
     685              :           break;
     686            0 :         case MATCH_ERROR:
     687            0 :           goto cleanup;
     688              :         }
     689              : 
     690           42 :       m = gfc_match (" / %n /", n);
     691           42 :       if (m == MATCH_ERROR)
     692            0 :         goto cleanup;
     693           42 :       if (m == MATCH_NO)
     694            0 :         goto syntax;
     695              : 
     696           42 :       st = gfc_find_symtree (gfc_current_ns->common_root, n);
     697           42 :       if (st == NULL)
     698              :         {
     699            0 :           gfc_error ("COMMON block /%s/ not found at %C", n);
     700            0 :           goto cleanup;
     701              :         }
     702           42 :       p = gfc_get_omp_namelist ();
     703           42 :       if (head == NULL)
     704              :         head = tail = p;
     705              :       else
     706              :         {
     707            4 :           tail->next = p;
     708            4 :           tail = tail->next;
     709              :         }
     710           42 :       tail->u.common = st->n.common;
     711           42 :       tail->where = cur_loc;
     712              : 
     713          569 :     next_item:
     714          569 :       if (gfc_match_char (')') == MATCH_YES)
     715              :         break;
     716          198 :       if (gfc_match_char (',') != MATCH_YES)
     717            0 :         goto syntax;
     718              :     }
     719              : 
     720          383 :   while (*list)
     721           12 :     list = &(*list)->next;
     722              : 
     723          371 :   *list = head;
     724          371 :   return MATCH_YES;
     725              : 
     726            0 : syntax:
     727            0 :   gfc_error ("Syntax error in OpenMP variable list at %C");
     728              : 
     729            0 : cleanup:
     730            0 :   gfc_free_omp_namelist (head, OMP_LIST_NONE);
     731            0 :   gfc_current_locus = old_loc;
     732            0 :   return MATCH_ERROR;
     733              : }
     734              : 
     735              : /* Match detach(event-handle).  */
     736              : 
     737              : static match
     738          126 : gfc_match_omp_detach (gfc_expr **expr)
     739              : {
     740          126 :   locus old_loc = gfc_current_locus;
     741              : 
     742          126 :   if (gfc_match ("detach ( ") != MATCH_YES)
     743            0 :     goto syntax_error;
     744              : 
     745          126 :   if (gfc_match_variable (expr, 0) != MATCH_YES)
     746            0 :     goto syntax_error;
     747              : 
     748          126 :   if (gfc_match_char (')') != MATCH_YES)
     749            0 :     goto syntax_error;
     750              : 
     751              :   return MATCH_YES;
     752              : 
     753            0 : syntax_error:
     754            0 :    gfc_error ("Syntax error in OpenMP detach clause at %C");
     755            0 :    gfc_current_locus = old_loc;
     756            0 :    return MATCH_ERROR;
     757              : 
     758              : }
     759              : 
     760              : /* Match doacross(sink : ...) construct a namelist from it;
     761              :    if depend is true, match legacy 'depend(sink : ...)'.  */
     762              : 
     763              : static match
     764          241 : gfc_match_omp_doacross_sink (gfc_omp_namelist **list, bool depend)
     765              : {
     766          241 :   char n[GFC_MAX_SYMBOL_LEN+1];
     767          241 :   gfc_omp_namelist *head, *tail, *p;
     768          241 :   locus old_loc, cur_loc;
     769          241 :   gfc_symbol *sym;
     770              : 
     771          241 :   head = tail = NULL;
     772              : 
     773          241 :   old_loc = gfc_current_locus;
     774              : 
     775         2231 :   for (;;)
     776              :     {
     777         1236 :       gfc_gobble_whitespace ();
     778         1236 :       cur_loc = gfc_current_locus;
     779              : 
     780         1236 :       if (gfc_match_name (n) != MATCH_YES)
     781            1 :         goto syntax;
     782         1235 :       locus loc = gfc_get_location_range (NULL, 0, &cur_loc, 1,
     783              :                                           &gfc_current_locus);
     784         1235 :       if (UNLIKELY (strcmp (n, "omp_all_memory") == 0))
     785              :         {
     786            1 :           gfc_error ("%<omp_all_memory%> used with dependence-type "
     787              :                      "other than OUT or INOUT at %L", &loc);
     788            1 :           goto cleanup;
     789              :         }
     790         1234 :       sym = NULL;
     791         1234 :       if (!(strcmp (n, "omp_cur_iteration") == 0))
     792              :         {
     793         1229 :           gfc_symtree *st;
     794         1229 :           if (gfc_get_ha_sym_tree (n, &st))
     795            0 :             goto syntax;
     796         1229 :           sym = st->n.sym;
     797         1229 :           gfc_set_sym_referenced (sym);
     798              :         }
     799         1234 :       p = gfc_get_omp_namelist ();
     800         1234 :       if (head == NULL)
     801              :         {
     802          239 :           head = tail = p;
     803          253 :           head->u.depend_doacross_op = (depend ? OMP_DEPEND_SINK_FIRST
     804              :                                                : OMP_DOACROSS_SINK_FIRST);
     805              :         }
     806              :       else
     807              :         {
     808          995 :           tail->next = p;
     809          995 :           tail = tail->next;
     810          995 :           tail->u.depend_doacross_op = OMP_DOACROSS_SINK;
     811              :         }
     812         1234 :       tail->sym = sym;
     813         1234 :       tail->expr = NULL;
     814         1234 :       tail->where = loc;
     815         1234 :       if (gfc_match_char ('+') == MATCH_YES)
     816              :         {
     817          154 :           if (gfc_match_literal_constant (&tail->expr, 0) != MATCH_YES)
     818            0 :             goto syntax;
     819              :         }
     820         1080 :       else if (gfc_match_char ('-') == MATCH_YES)
     821              :         {
     822          418 :           if (gfc_match_literal_constant (&tail->expr, 0) != MATCH_YES)
     823            1 :             goto syntax;
     824          417 :           tail->expr = gfc_uminus (tail->expr);
     825              :         }
     826         1233 :       if (gfc_match_char (')') == MATCH_YES)
     827              :         break;
     828          995 :       if (gfc_match_char (',') != MATCH_YES)
     829            0 :         goto syntax;
     830          995 :     }
     831              : 
     832         1030 :   while (*list)
     833          792 :     list = &(*list)->next;
     834              : 
     835          238 :   *list = head;
     836          238 :   return MATCH_YES;
     837              : 
     838            2 : syntax:
     839            2 :   gfc_error ("Syntax error in OpenMP SINK dependence-type list at %C");
     840              : 
     841            3 : cleanup:
     842            3 :   gfc_free_omp_namelist (head, OMP_LIST_DEPEND);
     843            3 :   gfc_current_locus = old_loc;
     844            3 :   return MATCH_ERROR;
     845              : }
     846              : 
     847              : static int
     848          332 : match_oacc_device_type_kind (void)
     849              : {
     850          332 :   char name[GFC_MAX_SYMBOL_LEN + 1];
     851              : 
     852              :   /* Since device_type arg accept * as all,
     853              :      we need to check first the case when
     854              :      the user inputs * as the parameter.  */
     855          332 :   gfc_gobble_whitespace ();
     856          332 :   name[0] = (char) gfc_next_char ();
     857              : 
     858          332 :   if (name[0] == '*')
     859              :     return GOMP_DEVICE_NONE;
     860              : 
     861              :   /* If is not *, we try to match the
     862              :      pre-defined names.  */
     863              : 
     864          332 :   match m = gfc_match (" %n ", name + 1);
     865              : 
     866          332 :   if (m != MATCH_YES)
     867              :     return -1;
     868              : 
     869          332 :   if (strcmp (name ,"host") == 0)
     870              :     return GOMP_DEVICE_HOST;
     871          144 :   if (strcmp (name, "nvidia") == 0)
     872              :     return GOMP_DEVICE_NVIDIA_PTX;
     873           72 :   if (strcmp (name, "radeon") == 0)
     874           69 :     return GOMP_DEVICE_GCN;
     875              : 
     876              :   return -1;
     877              : }
     878              : 
     879              : static match
     880          332 : match_oacc_device_type (gfc_omp_clauses *c)
     881              : {
     882          332 :   locus old_loc = gfc_current_locus;
     883              : 
     884          332 :   int result = match_oacc_device_type_kind ();
     885          332 :   match m;
     886              : 
     887          332 :   if (result == -1)
     888            3 :     goto syntax;
     889              : 
     890          329 :   m = gfc_match_char (')', true);
     891              : 
     892          329 :   if (m != MATCH_YES)
     893            3 :     goto single_argument;
     894              : 
     895          326 :   c->oacc_device_type = (unsigned) result;
     896          326 :   c->oacc_device_type_present = 1;
     897              : 
     898          326 :   return MATCH_YES;
     899              : 
     900            3 : single_argument:
     901            3 :   gfc_error ("OpenACC %<DEVICE_TYPE%> clause only accepts one argument, "
     902              :              "unexpected char at %C");
     903            3 :   goto cleanup;
     904              : 
     905            3 : syntax:
     906            3 :   gfc_error ("Syntax error in OpenACC %<DEVICE_TYPE%> argument at %C.  Expected "
     907              :              "host, radeon, nvidia or * as argument.");
     908              : 
     909            6 : cleanup:
     910            6 :   gfc_current_locus = old_loc;
     911            6 :   return MATCH_ERROR;
     912              : }
     913              : 
     914              : static match
     915         1960 : match_omp_oacc_expr_list (const char *str, gfc_expr_list **list,
     916              :                           bool allow_asterisk, bool is_omp)
     917              : {
     918         1960 :   gfc_expr_list *head, *tail, *p;
     919         1960 :   locus old_loc;
     920         1960 :   gfc_expr *expr;
     921         1960 :   match m;
     922              : 
     923         1960 :   head = tail = NULL;
     924              : 
     925         1960 :   old_loc = gfc_current_locus;
     926              : 
     927         1960 :   if (str && (m = gfc_match (str)) != MATCH_YES)
     928              :     return m;
     929              : 
     930         2237 :   for (;;)
     931              :     {
     932         2237 :       m = gfc_match_expr (&expr);
     933         2237 :       if (m == MATCH_YES || allow_asterisk)
     934              :         {
     935         2220 :           p = gfc_get_expr_list ();
     936         2220 :           if (head == NULL)
     937              :             head = tail = p;
     938              :           else
     939              :             {
     940          400 :               tail->next = p;
     941          400 :               tail = tail->next;
     942              :             }
     943         2220 :           if (m == MATCH_YES)
     944         2087 :             tail->expr = expr;
     945          133 :           else if (gfc_match (" *") != MATCH_YES)
     946           18 :             goto syntax;
     947         2202 :           goto next_item;
     948              :         }
     949           17 :       if (m == MATCH_ERROR)
     950            0 :         goto cleanup;
     951           17 :       goto syntax;
     952              : 
     953         2202 :     next_item:
     954         2202 :       if (gfc_match_char (')') == MATCH_YES)
     955              :         break;
     956          422 :       if (gfc_match_char (',') != MATCH_YES)
     957           17 :         goto syntax;
     958              :     }
     959              : 
     960         1786 :   while (*list)
     961            6 :     list = &(*list)->next;
     962              : 
     963         1780 :   *list = head;
     964         1780 :   return MATCH_YES;
     965              : 
     966           52 : syntax:
     967           52 :   if (is_omp)
     968           23 :     gfc_error ("Syntax error in OpenMP expression list at %C");
     969              :   else
     970           29 :     gfc_error ("Syntax error in OpenACC expression list at %C");
     971              : 
     972           52 : cleanup:
     973           52 :   gfc_free_expr_list (head);
     974           52 :   gfc_current_locus = old_loc;
     975           52 :   return MATCH_ERROR;
     976              : }
     977              : 
     978              : static match
     979         3056 : match_oacc_clause_gwv (gfc_omp_clauses *cp, unsigned gwv)
     980              : {
     981         3056 :   match ret = MATCH_YES;
     982              : 
     983         3056 :   if (gfc_match (" ( ") != MATCH_YES)
     984              :     return MATCH_NO;
     985              : 
     986          470 :   if (gwv == GOMP_DIM_GANG)
     987              :     {
     988              :         /* The gang clause accepts two optional arguments, num and static.
     989              :          The num argument may either be explicit (num: <val>) or
     990              :          implicit without (<val> without num:).  */
     991              : 
     992          457 :       while (ret == MATCH_YES)
     993              :         {
     994          236 :           if (gfc_match (" static :") == MATCH_YES)
     995              :             {
     996          114 :               if (cp->gang_static)
     997              :                 return MATCH_ERROR;
     998              :               else
     999          113 :                 cp->gang_static = true;
    1000          113 :               if (gfc_match_char ('*') == MATCH_YES)
    1001           18 :                 cp->gang_static_expr = NULL;
    1002           95 :               else if (gfc_match (" %e ", &cp->gang_static_expr) != MATCH_YES)
    1003              :                 return MATCH_ERROR;
    1004              :             }
    1005              :           else
    1006              :             {
    1007          122 :               if (cp->gang_num_expr)
    1008              :                 return MATCH_ERROR;
    1009              : 
    1010              :               /* The 'num' argument is optional.  */
    1011          121 :               gfc_match (" num :");
    1012              : 
    1013          121 :               if (gfc_match (" %e ", &cp->gang_num_expr) != MATCH_YES)
    1014              :                 return MATCH_ERROR;
    1015              :             }
    1016              : 
    1017          231 :           ret = gfc_match (" , ");
    1018              :         }
    1019              :     }
    1020          244 :   else if (gwv == GOMP_DIM_WORKER)
    1021              :     {
    1022              :       /* The 'num' argument is optional.  */
    1023          107 :       gfc_match (" num :");
    1024              : 
    1025          107 :       if (gfc_match (" %e ", &cp->worker_expr) != MATCH_YES)
    1026              :         return MATCH_ERROR;
    1027              :     }
    1028          137 :   else if (gwv == GOMP_DIM_VECTOR)
    1029              :     {
    1030              :       /* The 'length' argument is optional.  */
    1031          137 :       gfc_match (" length :");
    1032              : 
    1033          137 :       if (gfc_match (" %e ", &cp->vector_expr) != MATCH_YES)
    1034              :         return MATCH_ERROR;
    1035              :     }
    1036              :   else
    1037            0 :     gfc_fatal_error ("Unexpected OpenACC parallelism.");
    1038              : 
    1039          459 :   return gfc_match (" )");
    1040              : }
    1041              : 
    1042              : static match
    1043            8 : gfc_match_oacc_clause_link (const char *str, gfc_omp_namelist **list)
    1044              : {
    1045            8 :   gfc_omp_namelist *head = NULL;
    1046            8 :   gfc_omp_namelist *tail, *p;
    1047            8 :   locus old_loc;
    1048            8 :   char n[GFC_MAX_SYMBOL_LEN+1];
    1049            8 :   gfc_symbol *sym;
    1050            8 :   match m;
    1051            8 :   gfc_symtree *st;
    1052              : 
    1053            8 :   old_loc = gfc_current_locus;
    1054              : 
    1055            8 :   m = gfc_match (str);
    1056            8 :   if (m != MATCH_YES)
    1057              :     return m;
    1058              : 
    1059            8 :   m = gfc_match (" (");
    1060              : 
    1061           14 :   for (;;)
    1062              :     {
    1063           14 :       m = gfc_match_symbol (&sym, 0);
    1064           14 :       switch (m)
    1065              :         {
    1066            8 :         case MATCH_YES:
    1067            8 :           if (sym->attr.in_common)
    1068              :             {
    1069            2 :               gfc_error_now ("Variable at %C is an element of a COMMON block");
    1070            2 :               goto cleanup;
    1071              :             }
    1072            6 :           gfc_set_sym_referenced (sym);
    1073            6 :           p = gfc_get_omp_namelist ();
    1074            6 :           if (head == NULL)
    1075              :             head = tail = p;
    1076              :           else
    1077              :             {
    1078            4 :               tail->next = p;
    1079            4 :               tail = tail->next;
    1080              :             }
    1081            6 :           tail->sym = sym;
    1082            6 :           tail->expr = NULL;
    1083            6 :           tail->where = gfc_current_locus;
    1084            6 :           goto next_item;
    1085              :         case MATCH_NO:
    1086              :           break;
    1087              : 
    1088            0 :         case MATCH_ERROR:
    1089            0 :           goto cleanup;
    1090              :         }
    1091              : 
    1092            6 :       m = gfc_match (" / %n /", n);
    1093            6 :       if (m == MATCH_ERROR)
    1094            0 :         goto cleanup;
    1095            6 :       if (m == MATCH_NO || n[0] == '\0')
    1096            0 :         goto syntax;
    1097              : 
    1098            6 :       st = gfc_find_symtree (gfc_current_ns->common_root, n);
    1099            6 :       if (st == NULL)
    1100              :         {
    1101            1 :           gfc_error ("COMMON block /%s/ not found at %C", n);
    1102            1 :           goto cleanup;
    1103              :         }
    1104              : 
    1105           20 :       for (sym = st->n.common->head; sym; sym = sym->common_next)
    1106              :         {
    1107           15 :           gfc_set_sym_referenced (sym);
    1108           15 :           p = gfc_get_omp_namelist ();
    1109           15 :           if (head == NULL)
    1110              :             head = tail = p;
    1111              :           else
    1112              :             {
    1113           12 :               tail->next = p;
    1114           12 :               tail = tail->next;
    1115              :             }
    1116           15 :           tail->sym = sym;
    1117           15 :           tail->where = gfc_current_locus;
    1118              :         }
    1119              : 
    1120            5 :     next_item:
    1121           11 :       if (gfc_match_char (')') == MATCH_YES)
    1122              :         break;
    1123            6 :       if (gfc_match_char (',') != MATCH_YES)
    1124            0 :         goto syntax;
    1125              :     }
    1126              : 
    1127            5 :   if (gfc_match_omp_eos () != MATCH_YES)
    1128              :     {
    1129            1 :       gfc_error ("Unexpected junk after !$ACC DECLARE at %C");
    1130            1 :       goto cleanup;
    1131              :     }
    1132              : 
    1133            4 :   while (*list)
    1134            0 :     list = &(*list)->next;
    1135            4 :   *list = head;
    1136            4 :   return MATCH_YES;
    1137              : 
    1138            0 : syntax:
    1139            0 :   gfc_error ("Syntax error in !$ACC DECLARE list at %C");
    1140              : 
    1141            4 : cleanup:
    1142            4 :   gfc_current_locus = old_loc;
    1143            4 :   return MATCH_ERROR;
    1144              : }
    1145              : 
    1146              : /* OpenMP clauses.  */
    1147              : enum omp_mask1
    1148              : {
    1149              :   OMP_CLAUSE_PRIVATE,
    1150              :   OMP_CLAUSE_FIRSTPRIVATE,
    1151              :   OMP_CLAUSE_LASTPRIVATE,
    1152              :   OMP_CLAUSE_COPYPRIVATE,
    1153              :   OMP_CLAUSE_SHARED,
    1154              :   OMP_CLAUSE_COPYIN,
    1155              :   OMP_CLAUSE_REDUCTION,
    1156              :   OMP_CLAUSE_IN_REDUCTION,
    1157              :   OMP_CLAUSE_TASK_REDUCTION,
    1158              :   OMP_CLAUSE_IF,
    1159              :   OMP_CLAUSE_NUM_THREADS,
    1160              :   OMP_CLAUSE_SCHEDULE,
    1161              :   OMP_CLAUSE_DEFAULT,
    1162              :   OMP_CLAUSE_ORDER,
    1163              :   OMP_CLAUSE_ORDERED,
    1164              :   OMP_CLAUSE_COLLAPSE,
    1165              :   OMP_CLAUSE_UNTIED,
    1166              :   OMP_CLAUSE_FINAL,
    1167              :   OMP_CLAUSE_MERGEABLE,
    1168              :   OMP_CLAUSE_ALIGNED,
    1169              :   OMP_CLAUSE_DEPEND,
    1170              :   OMP_CLAUSE_INBRANCH,
    1171              :   OMP_CLAUSE_LINEAR,
    1172              :   OMP_CLAUSE_NOTINBRANCH,
    1173              :   OMP_CLAUSE_PROC_BIND,
    1174              :   OMP_CLAUSE_SAFELEN,
    1175              :   OMP_CLAUSE_SIMDLEN,
    1176              :   OMP_CLAUSE_UNIFORM,
    1177              :   OMP_CLAUSE_DEVICE,
    1178              :   OMP_CLAUSE_MAP,
    1179              :   OMP_CLAUSE_TO,
    1180              :   OMP_CLAUSE_FROM,
    1181              :   OMP_CLAUSE_NUM_TEAMS,
    1182              :   OMP_CLAUSE_THREAD_LIMIT,
    1183              :   OMP_CLAUSE_DIST_SCHEDULE,
    1184              :   OMP_CLAUSE_DEFAULTMAP,
    1185              :   OMP_CLAUSE_GRAINSIZE,
    1186              :   OMP_CLAUSE_HINT,
    1187              :   OMP_CLAUSE_IS_DEVICE_PTR,
    1188              :   OMP_CLAUSE_LINK,
    1189              :   OMP_CLAUSE_NOGROUP,
    1190              :   OMP_CLAUSE_NOTEMPORAL,
    1191              :   OMP_CLAUSE_NUM_TASKS,
    1192              :   OMP_CLAUSE_PRIORITY,
    1193              :   OMP_CLAUSE_SIMD,
    1194              :   OMP_CLAUSE_THREADS,
    1195              :   OMP_CLAUSE_USE_DEVICE_PTR,
    1196              :   OMP_CLAUSE_USE_DEVICE_ADDR,  /* OpenMP 5.0.  */
    1197              :   OMP_CLAUSE_DEVICE_TYPE,  /* OpenMP 5.0.  */
    1198              :   OMP_CLAUSE_ATOMIC,  /* OpenMP 5.0.  */
    1199              :   OMP_CLAUSE_CAPTURE,  /* OpenMP 5.0.  */
    1200              :   OMP_CLAUSE_MEMORDER,  /* OpenMP 5.0.  */
    1201              :   OMP_CLAUSE_DETACH,  /* OpenMP 5.0.  */
    1202              :   OMP_CLAUSE_AFFINITY,  /* OpenMP 5.0.  */
    1203              :   OMP_CLAUSE_ALLOCATE,  /* OpenMP 5.0.  */
    1204              :   OMP_CLAUSE_BIND,  /* OpenMP 5.0.  */
    1205              :   OMP_CLAUSE_FILTER,  /* OpenMP 5.1.  */
    1206              :   OMP_CLAUSE_AT,  /* OpenMP 5.1.  */
    1207              :   OMP_CLAUSE_MESSAGE,  /* OpenMP 5.1.  */
    1208              :   OMP_CLAUSE_SEVERITY,  /* OpenMP 5.1.  */
    1209              :   OMP_CLAUSE_COMPARE,  /* OpenMP 5.1.  */
    1210              :   OMP_CLAUSE_FAIL,  /* OpenMP 5.1.  */
    1211              :   OMP_CLAUSE_WEAK,  /* OpenMP 5.1.  */
    1212              :   OMP_CLAUSE_NOWAIT,
    1213              :   /* This must come last.  */
    1214              :   OMP_MASK1_LAST
    1215              : };
    1216              : 
    1217              : /* More OpenMP clauses and OpenACC 2.0+ specific clauses. */
    1218              : enum omp_mask2
    1219              : {
    1220              :   OMP_CLAUSE_ASYNC,
    1221              :   OMP_CLAUSE_NUM_GANGS,
    1222              :   OMP_CLAUSE_NUM_WORKERS,
    1223              :   OMP_CLAUSE_VECTOR_LENGTH,
    1224              :   OMP_CLAUSE_COPY,
    1225              :   OMP_CLAUSE_COPYOUT,
    1226              :   OMP_CLAUSE_CREATE,
    1227              :   OMP_CLAUSE_NO_CREATE,
    1228              :   OMP_CLAUSE_PRESENT,
    1229              :   OMP_CLAUSE_DEVICEPTR,
    1230              :   OMP_CLAUSE_GANG,
    1231              :   OMP_CLAUSE_WORKER,
    1232              :   OMP_CLAUSE_VECTOR,
    1233              :   OMP_CLAUSE_SEQ,
    1234              :   OMP_CLAUSE_INDEPENDENT,
    1235              :   OMP_CLAUSE_USE_DEVICE,
    1236              :   OMP_CLAUSE_DEVICE_RESIDENT,
    1237              :   OMP_CLAUSE_SELF,
    1238              :   OMP_CLAUSE_HOST,
    1239              :   OMP_CLAUSE_WAIT,
    1240              :   OMP_CLAUSE_DELETE,
    1241              :   OMP_CLAUSE_AUTO,
    1242              :   OMP_CLAUSE_TILE,
    1243              :   OMP_CLAUSE_IF_PRESENT,
    1244              :   OMP_CLAUSE_FINALIZE,
    1245              :   OMP_CLAUSE_ATTACH,
    1246              :   OMP_CLAUSE_NOHOST,
    1247              :   OMP_CLAUSE_HAS_DEVICE_ADDR,  /* OpenMP 5.1  */
    1248              :   OMP_CLAUSE_ENTER, /* OpenMP 5.2 */
    1249              :   OMP_CLAUSE_DOACROSS, /* OpenMP 5.2 */
    1250              :   OMP_CLAUSE_ASSUMPTIONS, /* OpenMP 5.1. */
    1251              :   OMP_CLAUSE_USES_ALLOCATORS, /* OpenMP 5.0  */
    1252              :   OMP_CLAUSE_INDIRECT, /* OpenMP 5.1  */
    1253              :   OMP_CLAUSE_FULL,  /* OpenMP 5.1.  */
    1254              :   OMP_CLAUSE_PARTIAL,  /* OpenMP 5.1.  */
    1255              :   OMP_CLAUSE_SIZES,  /* OpenMP 5.1.  */
    1256              :   OMP_CLAUSE_INIT,  /* OpenMP 5.1.  */
    1257              :   OMP_CLAUSE_DESTROY,  /* OpenMP 5.1.  */
    1258              :   OMP_CLAUSE_USE,  /* OpenMP 5.1.  */
    1259              :   OMP_CLAUSE_NOVARIANTS, /* OpenMP 5.1  */
    1260              :   OMP_CLAUSE_NOCONTEXT, /* OpenMP 5.1  */
    1261              :   OMP_CLAUSE_INTEROP, /* OpenMP 5.1  */
    1262              :   OMP_CLAUSE_LOCAL, /* OpenMP 6.0 */
    1263              :   OMP_CLAUSE_DYN_GROUPPRIVATE, /* OpenMP 6.1 */
    1264              :   OMP_CLAUSE_DEVICE_NUM,
    1265              :   /* This must come last.  */
    1266              :   OMP_MASK2_LAST
    1267              : };
    1268              : 
    1269              : struct omp_inv_mask;
    1270              : 
    1271              : /* Customized bitset for up to 128-bits.
    1272              :    The two enums above provide bit numbers to use, and which of the
    1273              :    two enums it is determines which of the two mask fields is used.
    1274              :    Supported operations are defining a mask, like:
    1275              :    #define XXX_CLAUSES \
    1276              :      (omp_mask (OMP_CLAUSE_XXX) | OMP_CLAUSE_YYY | OMP_CLAUSE_ZZZ)
    1277              :    oring such bitsets together or removing selected bits:
    1278              :    (XXX_CLAUSES | YYY_CLAUSES) & ~(omp_mask (OMP_CLAUSE_VVV))
    1279              :    and testing individual bits:
    1280              :    if (mask & OMP_CLAUSE_UUU)  */
    1281              : 
    1282              : struct omp_mask {
    1283              :   const uint64_t mask1;
    1284              :   const uint64_t mask2;
    1285              :   inline omp_mask ();
    1286              :   inline omp_mask (omp_mask1);
    1287              :   inline omp_mask (omp_mask2);
    1288              :   inline omp_mask (uint64_t, uint64_t);
    1289              :   inline omp_mask operator| (omp_mask1) const;
    1290              :   inline omp_mask operator| (omp_mask2) const;
    1291              :   inline omp_mask operator| (omp_mask) const;
    1292              :   inline omp_mask operator& (const omp_inv_mask &) const;
    1293              :   inline bool operator& (omp_mask1) const;
    1294              :   inline bool operator& (omp_mask2) const;
    1295              :   inline omp_inv_mask operator~ () const;
    1296              : };
    1297              : 
    1298              : struct omp_inv_mask : public omp_mask {
    1299              :   inline omp_inv_mask (const omp_mask &);
    1300              : };
    1301              : 
    1302              : omp_mask::omp_mask () : mask1 (0), mask2 (0)
    1303              : {
    1304              : }
    1305              : 
    1306        32972 : omp_mask::omp_mask (omp_mask1 m) : mask1 (((uint64_t) 1) << m), mask2 (0)
    1307              : {
    1308              : }
    1309              : 
    1310         2244 : omp_mask::omp_mask (omp_mask2 m) : mask1 (0), mask2 (((uint64_t) 1) << m)
    1311              : {
    1312              : }
    1313              : 
    1314        33859 : omp_mask::omp_mask (uint64_t m1, uint64_t m2) : mask1 (m1), mask2 (m2)
    1315              : {
    1316              : }
    1317              : 
    1318              : omp_mask
    1319        32899 : omp_mask::operator| (omp_mask1 m) const
    1320              : {
    1321        32899 :   return omp_mask (mask1 | (((uint64_t) 1) << m), mask2);
    1322              : }
    1323              : 
    1324              : omp_mask
    1325        17296 : omp_mask::operator| (omp_mask2 m) const
    1326              : {
    1327        17296 :   return omp_mask (mask1, mask2 | (((uint64_t) 1) << m));
    1328              : }
    1329              : 
    1330              : omp_mask
    1331         4378 : omp_mask::operator| (omp_mask m) const
    1332              : {
    1333         4378 :   return omp_mask (mask1 | m.mask1, mask2 | m.mask2);
    1334              : }
    1335              : 
    1336              : omp_mask
    1337         2033 : omp_mask::operator& (const omp_inv_mask &m) const
    1338              : {
    1339         2033 :   return omp_mask (mask1 & ~m.mask1, mask2 & ~m.mask2);
    1340              : }
    1341              : 
    1342              : bool
    1343       130134 : omp_mask::operator& (omp_mask1 m) const
    1344              : {
    1345       130134 :   return (mask1 & (((uint64_t) 1) << m)) != 0;
    1346              : }
    1347              : 
    1348              : bool
    1349        92603 : omp_mask::operator& (omp_mask2 m) const
    1350              : {
    1351        92603 :   return (mask2 & (((uint64_t) 1) << m)) != 0;
    1352              : }
    1353              : 
    1354              : omp_inv_mask
    1355         2033 : omp_mask::operator~ () const
    1356              : {
    1357         2033 :   return omp_inv_mask (*this);
    1358              : }
    1359              : 
    1360         2033 : omp_inv_mask::omp_inv_mask (const omp_mask &m) : omp_mask (m)
    1361              : {
    1362              : }
    1363              : 
    1364              : /* Helper function for OpenACC and OpenMP clauses involving memory
    1365              :    mapping.  */
    1366              : 
    1367              : static bool
    1368         5544 : gfc_match_omp_map_clause (gfc_omp_namelist **list, gfc_omp_map_op map_op,
    1369              :                           bool allow_common, bool allow_derived)
    1370              : {
    1371         5544 :   gfc_omp_namelist **head = NULL;
    1372         5544 :   if (gfc_match_omp_variable_list ("", list, allow_common, NULL, &head, true,
    1373              :                                    allow_derived)
    1374              :       == MATCH_YES)
    1375              :     {
    1376         5535 :       gfc_omp_namelist *n;
    1377        13409 :       for (n = *head; n; n = n->next)
    1378         7874 :         n->u.map.op = map_op;
    1379              :       return true;
    1380              :     }
    1381              : 
    1382              :   return false;
    1383              : }
    1384              : 
    1385              : static match
    1386         8749 : gfc_match_iterator (gfc_namespace **ns, bool permit_var)
    1387              : {
    1388         8749 :   locus old_loc = gfc_current_locus;
    1389              : 
    1390         8749 :   if (gfc_match ("iterator ( ") != MATCH_YES)
    1391              :     return MATCH_NO;
    1392              : 
    1393          142 :   gfc_typespec ts;
    1394          142 :   gfc_symbol *last = NULL;
    1395          142 :   gfc_expr *begin, *end, *step;
    1396          142 :   *ns = gfc_build_block_ns (gfc_current_ns);
    1397          161 :   char name[GFC_MAX_SYMBOL_LEN + 1];
    1398          180 :   while (true)
    1399              :     {
    1400          161 :       locus prev_loc = gfc_current_locus;
    1401          161 :       if (gfc_match_type_spec (&ts) == MATCH_YES
    1402          161 :           && gfc_match (" :: ") == MATCH_YES)
    1403              :         {
    1404            5 :           if (ts.type != BT_INTEGER)
    1405              :             {
    1406            2 :               gfc_error ("Expected INTEGER type at %L", &prev_loc);
    1407            5 :               return MATCH_ERROR;
    1408              :             }
    1409              :           permit_var = false;
    1410              :         }
    1411              :       else
    1412              :         {
    1413          156 :           ts.type = BT_INTEGER;
    1414          156 :           ts.kind = gfc_default_integer_kind;
    1415          156 :           gfc_current_locus = prev_loc;
    1416              :         }
    1417          159 :       prev_loc = gfc_current_locus;
    1418          159 :       if (gfc_match_name (name) != MATCH_YES)
    1419              :         {
    1420            4 :           gfc_error ("Expected identifier at %C");
    1421            4 :           goto failed;
    1422              :         }
    1423          155 :       if (gfc_find_symtree ((*ns)->sym_root, name))
    1424              :         {
    1425            2 :           gfc_error ("Same identifier %qs specified again at %C", name);
    1426            2 :           goto failed;
    1427              :         }
    1428              : 
    1429          153 :       gfc_symbol *sym = gfc_new_symbol (name, *ns);
    1430          153 :       if (last)
    1431           17 :         last->tlink = sym;
    1432              :       else
    1433          136 :         (*ns)->omp_affinity_iterators = sym;
    1434          153 :       last = sym;
    1435          153 :       sym->declared_at = prev_loc;
    1436          153 :       sym->ts = ts;
    1437          153 :       sym->attr.flavor = FL_VARIABLE;
    1438          153 :       sym->attr.artificial = 1;
    1439          153 :       sym->attr.referenced = 1;
    1440          153 :       sym->refs++;
    1441          153 :       gfc_symtree *st = gfc_new_symtree (&(*ns)->sym_root, name);
    1442          153 :       st->n.sym = sym;
    1443              : 
    1444          153 :       prev_loc = gfc_current_locus;
    1445          153 :       if (gfc_match (" = ") != MATCH_YES)
    1446            3 :         goto failed;
    1447          150 :       permit_var = false;
    1448          150 :       begin = end = step = NULL;
    1449          150 :       if (gfc_match ("%e : ", &begin) != MATCH_YES
    1450          150 :           || gfc_match ("%e ", &end) != MATCH_YES)
    1451              :         {
    1452            3 :           gfc_error ("Expected range-specification at %C");
    1453            3 :           gfc_free_expr (begin);
    1454            3 :           gfc_free_expr (end);
    1455            3 :           return MATCH_ERROR;
    1456              :         }
    1457          147 :       if (':' == gfc_peek_ascii_char ())
    1458              :         {
    1459           23 :           if (gfc_match (": %e ", &step) != MATCH_YES)
    1460              :             {
    1461            5 :               gfc_free_expr (begin);
    1462            5 :               gfc_free_expr (end);
    1463            5 :               gfc_free_expr (step);
    1464            5 :               goto failed;
    1465              :             }
    1466              :         }
    1467              : 
    1468          142 :       gfc_expr *e = gfc_get_expr ();
    1469          142 :       e->where = prev_loc;
    1470          142 :       e->expr_type = EXPR_ARRAY;
    1471          142 :       e->ts = ts;
    1472          142 :       e->rank = 1;
    1473          142 :       e->shape = gfc_get_shape (1);
    1474          266 :       mpz_init_set_ui (e->shape[0], step ? 3 : 2);
    1475          142 :       gfc_constructor_append_expr (&e->value.constructor, begin, &begin->where);
    1476          142 :       gfc_constructor_append_expr (&e->value.constructor, end, &end->where);
    1477          142 :       if (step)
    1478           18 :         gfc_constructor_append_expr (&e->value.constructor, step, &step->where);
    1479          142 :       sym->value = e;
    1480              : 
    1481          142 :       if (gfc_match (") ") == MATCH_YES)
    1482              :         break;
    1483           19 :       if (gfc_match (", ") != MATCH_YES)
    1484            0 :         goto failed;
    1485           19 :     }
    1486          123 :   return MATCH_YES;
    1487              : 
    1488           14 : failed:
    1489           14 :   gfc_namespace *prev_ns = NULL;
    1490           14 :   for (gfc_namespace *it = gfc_current_ns->contained; it; it = it->sibling)
    1491              :     {
    1492            0 :       if (it == *ns)
    1493              :         {
    1494            0 :           if (prev_ns)
    1495            0 :             prev_ns->sibling = it->sibling;
    1496              :           else
    1497            0 :             gfc_current_ns->contained = it->sibling;
    1498            0 :           gfc_free_namespace (it);
    1499            0 :           break;
    1500              :         }
    1501            0 :       prev_ns = it;
    1502              :     }
    1503           14 :   *ns = NULL;
    1504           14 :   if (!permit_var)
    1505              :     return MATCH_ERROR;
    1506            4 :   gfc_current_locus = old_loc;
    1507            4 :   return MATCH_NO;
    1508              : }
    1509              : 
    1510              : /* Match target update's to/from( [present:] var-list).  */
    1511              : 
    1512              : static match
    1513         1738 : gfc_match_motion_var_list (const char *str, gfc_omp_namelist **list,
    1514              :                            gfc_omp_namelist ***headp)
    1515              : {
    1516         1738 :   match m = gfc_match (str);
    1517         1738 :   if (m != MATCH_YES)
    1518              :     return m;
    1519              : 
    1520         1738 :   gfc_namespace *ns_iter = NULL, *ns_curr = gfc_current_ns;
    1521         1738 :   locus old_loc = gfc_current_locus;
    1522         1738 :   int present_modifier = 0;
    1523         1738 :   int iterator_modifier = 0;
    1524         1738 :   locus second_present_locus = old_loc;
    1525         1738 :   locus second_iterator_locus = old_loc;
    1526         1738 :   bool saw_modifier = false;
    1527              : 
    1528         1750 :   for (;;)
    1529              :     {
    1530         1744 :       locus current_locus = gfc_current_locus;
    1531         1744 :       if (gfc_match ("present ") == MATCH_YES)
    1532              :         {
    1533            8 :           if (present_modifier++ == 1)
    1534            0 :             second_present_locus = current_locus;
    1535              :         }
    1536         1736 :       else if (gfc_match_iterator (&ns_iter, true) == MATCH_YES)
    1537              :         {
    1538           20 :           if (iterator_modifier++ == 1)
    1539            1 :             second_iterator_locus = current_locus;
    1540              :         }
    1541         1716 :       else if (!saw_modifier)
    1542              :         break;
    1543              :       else
    1544              :         {
    1545            2 :           gfc_error ("Expected clause modifier at %C");
    1546            4 :           return MATCH_ERROR;
    1547              :         }
    1548              : 
    1549              :       /* OpenMP 5.1 syntax mistakenly allowed commas to be optional
    1550              :          between and after modifiers in a clause.  This was corrected
    1551              :          in 5.2 and later specifications: they're now required between
    1552              :          modifiers and a trailing comma is not permitted.  We implement
    1553              :          the 5.2 syntax here.  */
    1554           28 :       saw_modifier = true;
    1555           28 :       if (gfc_match (" : ") == MATCH_YES)
    1556              :         break;
    1557            8 :       else if (gfc_match (", ") == MATCH_YES)
    1558            6 :         continue;
    1559              :       else
    1560              :         {
    1561            2 :           gfc_error ("Expected %<,%> or %<:%> after clause modifier at %C");
    1562            2 :           return MATCH_ERROR;
    1563              :         }
    1564            6 :     }
    1565              : 
    1566         1734 :   if (!saw_modifier)
    1567              :     {
    1568         1714 :       gfc_current_locus = old_loc;
    1569         1714 :       present_modifier = 0;
    1570         1714 :       iterator_modifier = 0;
    1571              :     }
    1572              : 
    1573         1734 :   if (present_modifier > 1)
    1574              :     {
    1575            0 :       gfc_error ("Too many %<present%> modifiers at %L", &second_present_locus);
    1576            0 :       return MATCH_ERROR;
    1577              :     }
    1578         1734 :   if (iterator_modifier > 1)
    1579              :     {
    1580            1 :       gfc_error ("Too many %<iterator%> modifiers at %L",
    1581              :                  &second_iterator_locus);
    1582            1 :       return MATCH_ERROR;
    1583              :     }
    1584              : 
    1585         1733 :   if (ns_iter)
    1586           14 :     gfc_current_ns = ns_iter;
    1587              : 
    1588         1733 :   m = gfc_match_omp_variable_list ("", list, false, NULL, headp, true, true);
    1589         1733 :   gfc_current_ns = ns_curr;
    1590         1733 :   if (m != MATCH_YES)
    1591              :     return m;
    1592         1731 :   gfc_omp_namelist *n;
    1593         3536 :   for (n = **headp; n; n = n->next)
    1594              :     {
    1595         1805 :       if (present_modifier)
    1596            6 :         n->u.present_modifier = true;
    1597         1805 :       if (iterator_modifier)
    1598              :         {
    1599           18 :           n->u2.ns = ns_iter;
    1600           18 :           ns_iter->refs++;
    1601              :         }
    1602              :     }
    1603              :   return MATCH_YES;
    1604              : }
    1605              : 
    1606              : /* reduction ( reduction-modifier, reduction-operator : variable-list )
    1607              :    in_reduction ( reduction-operator : variable-list )
    1608              :    task_reduction ( reduction-operator : variable-list )  */
    1609              : 
    1610              : static match
    1611         4361 : gfc_match_omp_clause_reduction (char pc, gfc_omp_clauses *c, bool openacc,
    1612              :                                 bool allow_derived, bool openmp_target = false)
    1613              : {
    1614         4361 :   if (pc == 'r' && gfc_match ("reduction ( ") != MATCH_YES)
    1615              :     return MATCH_NO;
    1616         4361 :   else if (pc == 'i' && gfc_match ("in_reduction ( ") != MATCH_YES)
    1617              :     return MATCH_NO;
    1618         4249 :   else if (pc == 't' && gfc_match ("task_reduction ( ") != MATCH_YES)
    1619              :     return MATCH_NO;
    1620              : 
    1621         4249 :   locus old_loc = gfc_current_locus;
    1622         4249 :   enum gfc_omp_list_type list_idx = OMP_LIST_NONE;
    1623              : 
    1624         4249 :   if (pc == 'r' && !openacc)
    1625              :     {
    1626         2122 :       if (gfc_match ("inscan") == MATCH_YES)
    1627              :         list_idx = OMP_LIST_REDUCTION_INSCAN;
    1628         2052 :       else if (gfc_match ("task") == MATCH_YES)
    1629              :         list_idx = OMP_LIST_REDUCTION_TASK;
    1630         1947 :       else if (gfc_match ("default") == MATCH_YES)
    1631              :         list_idx = OMP_LIST_REDUCTION;
    1632          231 :       if (list_idx != OMP_LIST_NONE && gfc_match (", ") != MATCH_YES)
    1633              :         {
    1634            1 :           gfc_error ("Comma expected at %C");
    1635            1 :           gfc_current_locus = old_loc;
    1636            1 :           return MATCH_NO;
    1637              :         }
    1638         2121 :       if (list_idx == OMP_LIST_NONE)
    1639         3835 :         list_idx = OMP_LIST_REDUCTION;
    1640              :     }
    1641         2127 :   else if (pc == 'i')
    1642              :     list_idx = OMP_LIST_IN_REDUCTION;
    1643         2009 :   else if (pc == 't')
    1644              :     list_idx = OMP_LIST_TASK_REDUCTION;
    1645              :   else
    1646         3835 :     list_idx = OMP_LIST_REDUCTION;
    1647              : 
    1648         4248 :   gfc_omp_reduction_op rop = OMP_REDUCTION_NONE;
    1649         4248 :   char buffer[GFC_MAX_SYMBOL_LEN + 3];
    1650         4248 :   if (gfc_match_char ('+') == MATCH_YES)
    1651              :     rop = OMP_REDUCTION_PLUS;
    1652         2224 :   else if (gfc_match_char ('*') == MATCH_YES)
    1653              :     rop = OMP_REDUCTION_TIMES;
    1654         1992 :   else if (gfc_match_char ('-') == MATCH_YES)
    1655              :     {
    1656          171 :       if (!openacc)
    1657           16 :         gfc_warning (OPT_Wdeprecated_openmp,
    1658              :                      "%<-%> operator at %C for reductions deprecated in "
    1659              :                      "OpenMP 5.2");
    1660              :       rop = OMP_REDUCTION_MINUS;
    1661              :     }
    1662         1821 :   else if (gfc_match (".and.") == MATCH_YES)
    1663              :     rop = OMP_REDUCTION_AND;
    1664         1715 :   else if (gfc_match (".or.") == MATCH_YES)
    1665              :     rop = OMP_REDUCTION_OR;
    1666          930 :   else if (gfc_match (".eqv.") == MATCH_YES)
    1667              :     rop = OMP_REDUCTION_EQV;
    1668          832 :   else if (gfc_match (".neqv.") == MATCH_YES)
    1669              :     rop = OMP_REDUCTION_NEQV;
    1670           16 :   if (rop != OMP_REDUCTION_NONE)
    1671         3511 :     snprintf (buffer, sizeof buffer, "operator %s",
    1672              :               gfc_op2string ((gfc_intrinsic_op) rop));
    1673          737 :   else if (gfc_match_defined_op_name (buffer + 1, 1) == MATCH_YES)
    1674              :     {
    1675           38 :       buffer[0] = '.';
    1676           38 :       strcat (buffer, ".");
    1677              :     }
    1678          699 :   else if (gfc_match_name (buffer) == MATCH_YES)
    1679              :     {
    1680          698 :       gfc_symbol *sym;
    1681          698 :       const char *n = buffer;
    1682              : 
    1683          698 :       gfc_find_symbol (buffer, NULL, 1, &sym);
    1684          698 :       if (sym != NULL)
    1685              :         {
    1686          217 :           if (sym->attr.intrinsic)
    1687          139 :             n = sym->name;
    1688           78 :           else if ((sym->attr.flavor != FL_UNKNOWN
    1689           76 :                     && sym->attr.flavor != FL_PROCEDURE)
    1690           76 :                    || sym->attr.external
    1691           65 :                    || sym->attr.generic
    1692           65 :                    || sym->attr.entry
    1693           65 :                    || sym->attr.result
    1694           65 :                    || sym->attr.dummy
    1695           65 :                    || sym->attr.subroutine
    1696           64 :                    || sym->attr.pointer
    1697           64 :                    || sym->attr.target
    1698           64 :                    || sym->attr.cray_pointer
    1699           64 :                    || sym->attr.cray_pointee
    1700           64 :                    || (sym->attr.proc != PROC_UNKNOWN
    1701            2 :                        && sym->attr.proc != PROC_INTRINSIC)
    1702           62 :                    || sym->attr.if_source != IFSRC_UNKNOWN
    1703           62 :                    || sym == sym->ns->proc_name)
    1704              :                 {
    1705              :                   sym = NULL;
    1706              :                   n = NULL;
    1707              :                 }
    1708              :               else
    1709           62 :                 n = sym->name;
    1710              :             }
    1711          201 :           if (n == NULL)
    1712              :             rop = OMP_REDUCTION_NONE;
    1713          682 :           else if (strcmp (n, "max") == 0)
    1714              :             rop = OMP_REDUCTION_MAX;
    1715          517 :           else if (strcmp (n, "min") == 0)
    1716              :             rop = OMP_REDUCTION_MIN;
    1717          376 :           else if (strcmp (n, "iand") == 0)
    1718              :             rop = OMP_REDUCTION_IAND;
    1719          321 :           else if (strcmp (n, "ior") == 0)
    1720              :             rop = OMP_REDUCTION_IOR;
    1721          255 :           else if (strcmp (n, "ieor") == 0)
    1722              :             rop = OMP_REDUCTION_IEOR;
    1723              :           if (rop != OMP_REDUCTION_NONE
    1724          477 :               && sym != NULL
    1725          200 :               && ! sym->attr.intrinsic
    1726           61 :               && ! sym->attr.use_assoc
    1727           61 :               && ((sym->attr.flavor == FL_UNKNOWN
    1728            2 :                    && !gfc_add_flavor (&sym->attr, FL_PROCEDURE,
    1729              :                                               sym->name, NULL))
    1730           61 :                   || !gfc_add_intrinsic (&sym->attr, NULL)))
    1731              :             rop = OMP_REDUCTION_NONE;
    1732              :     }
    1733              :   else
    1734            1 :     buffer[0] = '\0';
    1735         4248 :   gfc_omp_udr *udr = (buffer[0] ? gfc_find_omp_udr (gfc_current_ns, buffer, NULL)
    1736              :                                 : NULL);
    1737         4248 :   gfc_omp_namelist **head = NULL;
    1738         4248 :   if (rop == OMP_REDUCTION_NONE && udr)
    1739          251 :     rop = OMP_REDUCTION_USER;
    1740              : 
    1741         4248 :   if (gfc_match_omp_variable_list (" :", &c->lists[list_idx], false, NULL,
    1742              :                                    &head, openacc, allow_derived) != MATCH_YES)
    1743              :     {
    1744            9 :       gfc_current_locus = old_loc;
    1745            9 :       return MATCH_NO;
    1746              :     }
    1747         4239 :   gfc_omp_namelist *n;
    1748         4239 :   if (rop == OMP_REDUCTION_NONE)
    1749              :     {
    1750            6 :       n = *head;
    1751            6 :       *head = NULL;
    1752            6 :       gfc_error_now ("!$OMP DECLARE REDUCTION %s not found at %L",
    1753              :                      buffer, &old_loc);
    1754            6 :       gfc_free_omp_namelist (n, OMP_LIST_NONE);
    1755              :     }
    1756              :   else
    1757         9118 :     for (n = *head; n; n = n->next)
    1758              :       {
    1759         4885 :         n->u.reduction_op = rop;
    1760         4885 :         if (udr)
    1761              :           {
    1762          477 :             n->u2.udr = gfc_get_omp_namelist_udr ();
    1763          477 :             n->u2.udr->udr = udr;
    1764              :           }
    1765         4885 :         if (openmp_target && list_idx == OMP_LIST_IN_REDUCTION)
    1766              :           {
    1767           40 :             gfc_omp_namelist *p = gfc_get_omp_namelist (), **tl;
    1768           40 :             p->sym = n->sym;
    1769           40 :             p->where = n->where;
    1770           40 :             p->u.map.op = OMP_MAP_ALWAYS_TOFROM;
    1771              : 
    1772           40 :             tl = &c->lists[OMP_LIST_MAP];
    1773           52 :             while (*tl)
    1774           12 :               tl = &((*tl)->next);
    1775           40 :             *tl = p;
    1776           40 :             p->next = NULL;
    1777              :           }
    1778              :      }
    1779              :   return MATCH_YES;
    1780              : }
    1781              : 
    1782              : static match
    1783           47 : gfc_omp_absent_contains_clause (gfc_omp_assumptions **assume, bool is_absent)
    1784              : {
    1785           47 :   if (*assume == NULL)
    1786           22 :     *assume = gfc_get_omp_assumptions ();
    1787           77 :   do
    1788              :     {
    1789           62 :       gfc_statement st = ST_NONE;
    1790           62 :       gfc_gobble_whitespace ();
    1791           62 :       locus old_loc = gfc_current_locus;
    1792           62 :       char c = gfc_peek_ascii_char ();
    1793           62 :       enum gfc_omp_directive_kind kind
    1794              :         = GFC_OMP_DIR_DECLARATIVE; /* Silence warning. */
    1795         2369 :       for (size_t i = 0; i < ARRAY_SIZE (gfc_omp_directives); i++)
    1796              :         {
    1797         2307 :           if (gfc_omp_directives[i].name[0] > c)
    1798              :             break;
    1799         2245 :           if (gfc_omp_directives[i].name[0] != c)
    1800         1668 :             continue;
    1801          577 :           if (gfc_match (gfc_omp_directives[i].name) == MATCH_YES)
    1802              :             {
    1803           62 :               st = gfc_omp_directives[i].st;
    1804           62 :               kind = gfc_omp_directives[i].kind;
    1805              :             }
    1806              :         }
    1807           62 :       gfc_gobble_whitespace ();
    1808           62 :       c = gfc_peek_ascii_char ();
    1809           62 :       if (st == ST_NONE || (c != ',' && c != ')'))
    1810              :         {
    1811            0 :           if (st == ST_NONE)
    1812            0 :             gfc_error ("Unknown directive at %L", &old_loc);
    1813              :           else
    1814            0 :             gfc_error ("Invalid combined or composite directive at %L",
    1815              :                        &old_loc);
    1816            9 :           return MATCH_ERROR;
    1817              :         }
    1818           62 :       if (kind == GFC_OMP_DIR_DECLARATIVE
    1819           62 :           || kind == GFC_OMP_DIR_INFORMATIONAL
    1820              :           || kind == GFC_OMP_DIR_META)
    1821              :         {
    1822           15 :           gfc_error ("Invalid %qs directive at %L in %s clause: declarative, "
    1823              :                      "informational, and meta directives not permitted",
    1824              :                      gfc_ascii_statement (st, true), &old_loc,
    1825              :                      is_absent ? "ABSENT" : "CONTAINS");
    1826            9 :           return MATCH_ERROR;
    1827              :         }
    1828           53 :       if (is_absent)
    1829              :         {
    1830              :           /* Use exponential allocation; equivalent to pow2p(x). */
    1831           38 :           int i = (*assume)->n_absent;
    1832           38 :           int size = ((i == 0) ? 4
    1833           14 :                       : pow2p_hwi (i) == 1 ? i*2 : 0);
    1834           11 :           if (size != 0)
    1835           35 :             (*assume)->absent = XRESIZEVEC (gfc_statement,
    1836              :                                             (*assume)->absent, size);
    1837           38 :           (*assume)->absent[(*assume)->n_absent++] = st;
    1838              :         }
    1839              :       else
    1840              :         {
    1841           15 :           int i = (*assume)->n_contains;
    1842           15 :           int size = ((i == 0) ? 4
    1843            4 :                       : pow2p_hwi (i) == 1 ? i*2 : 0);
    1844            4 :           if (size != 0)
    1845           15 :             (*assume)->contains = XRESIZEVEC (gfc_statement,
    1846              :                                               (*assume)->contains, size);
    1847           15 :           (*assume)->contains[(*assume)->n_contains++] = st;
    1848              :         }
    1849           53 :       gfc_gobble_whitespace ();
    1850           53 :       if (gfc_match(",") == MATCH_YES)
    1851           15 :         continue;
    1852           38 :       if (gfc_match(")") == MATCH_YES)
    1853              :         break;
    1854            0 :       gfc_error ("Expected %<,%> or %<)%> at %C");
    1855            0 :       return MATCH_ERROR;
    1856           15 :     }
    1857              :   while (true);
    1858              : 
    1859           38 :   return MATCH_YES;
    1860              : }
    1861              : 
    1862              : /* Check 'check' argument for duplicated statements in absent and/or contains
    1863              :    clauses. If 'merge', merge them from check to 'merge'.  */
    1864              : 
    1865              : static match
    1866           50 : omp_verify_merge_absent_contains (gfc_statement st, gfc_omp_assumptions *check,
    1867              :                                   gfc_omp_assumptions *merge, locus *loc)
    1868              : {
    1869           50 :   if (check == NULL)
    1870              :     return MATCH_YES;
    1871           49 :   bitmap_head absent_head, contains_head;
    1872           49 :   bitmap_obstack_initialize (NULL);
    1873           49 :   bitmap_initialize (&absent_head, &bitmap_default_obstack);
    1874           49 :   bitmap_initialize (&contains_head, &bitmap_default_obstack);
    1875              : 
    1876           49 :   match m = MATCH_YES;
    1877           87 :   for (int i = 0; i < check->n_absent; i++)
    1878           38 :     if (!bitmap_set_bit (&absent_head, check->absent[i]))
    1879              :       {
    1880            2 :         gfc_error ("%qs directive mentioned multiple times in %s clause in %s "
    1881              :                    "directive at %L",
    1882            2 :                    gfc_ascii_statement (check->absent[i], true),
    1883              :                    "ABSENT", gfc_ascii_statement (st), loc);
    1884            2 :         m = MATCH_ERROR;
    1885              :       }
    1886           64 :   for (int i = 0; i < check->n_contains; i++)
    1887              :     {
    1888           15 :       if (!bitmap_set_bit (&contains_head, check->contains[i]))
    1889              :         {
    1890            2 :           gfc_error ("%qs directive mentioned multiple times in %s clause in %s "
    1891              :                      "directive at %L",
    1892            2 :                      gfc_ascii_statement (check->contains[i], true),
    1893              :                      "CONTAINS", gfc_ascii_statement (st), loc);
    1894            2 :           m = MATCH_ERROR;
    1895              :         }
    1896           15 :       if (bitmap_bit_p (&absent_head, check->contains[i]))
    1897              :         {
    1898            2 :           gfc_error ("%qs directive mentioned both times in ABSENT and CONTAINS "
    1899              :                      "clauses in %s directive at %L",
    1900            2 :                      gfc_ascii_statement (check->absent[i], true),
    1901              :                      gfc_ascii_statement (st), loc);
    1902            2 :           m = MATCH_ERROR;
    1903              :         }
    1904              :     }
    1905              : 
    1906           49 :   if (m == MATCH_ERROR)
    1907              :     return MATCH_ERROR;
    1908           43 :   if (merge == NULL)
    1909              :     return MATCH_YES;
    1910            3 :   if (merge->absent == NULL && check->absent)
    1911              :     {
    1912            1 :       merge->n_absent = check->n_absent;
    1913            1 :       merge->absent = check->absent;
    1914            1 :       check->absent = NULL;
    1915              :     }
    1916            2 :   else if (merge->absent && check->absent)
    1917              :     {
    1918            0 :       check->absent = XRESIZEVEC (gfc_statement, check->absent,
    1919              :                                   merge->n_absent + check->n_absent);
    1920            0 :       for (int i = 0; i < merge->n_absent; i++)
    1921            0 :         if (!bitmap_bit_p (&absent_head, merge->absent[i]))
    1922            0 :           check->absent[check->n_absent++] = merge->absent[i];
    1923            0 :       free (merge->absent);
    1924            0 :       merge->absent = check->absent;
    1925            0 :       merge->n_absent = check->n_absent;
    1926            0 :       check->absent = NULL;
    1927              :     }
    1928            3 :   if (merge->contains == NULL && check->contains)
    1929              :     {
    1930            0 :       merge->n_contains = check->n_contains;
    1931            0 :       merge->contains = check->contains;
    1932            0 :       check->contains = NULL;
    1933              :     }
    1934            3 :   else if (merge->contains && check->contains)
    1935              :     {
    1936            0 :       check->contains = XRESIZEVEC (gfc_statement, check->contains,
    1937              :                                     merge->n_contains + check->n_contains);
    1938            0 :       for (int i = 0; i < merge->n_contains; i++)
    1939            0 :         if (!bitmap_bit_p (&contains_head, merge->contains[i]))
    1940            0 :           check->contains[check->n_contains++] = merge->contains[i];
    1941            0 :       free (merge->contains);
    1942            0 :       merge->contains = check->contains;
    1943            0 :       merge->n_contains = check->n_contains;
    1944            0 :       check->contains = NULL;
    1945              :     }
    1946              :   return MATCH_YES;
    1947              : }
    1948              : 
    1949              : /* OpenMP 5.0
    1950              :    uses_allocators ( allocator-list )
    1951              : 
    1952              :    allocator:
    1953              :      predefined-allocator
    1954              :      variable ( traits-array )
    1955              : 
    1956              :    OpenMP 5.2 deprecated, 6.0 deleted: 'variable ( traits-array )'
    1957              : 
    1958              :    OpenMP 5.2:
    1959              :    uses_allocators ( [modifier-list :] allocator-list )
    1960              : 
    1961              :    OpenMP 6.0:
    1962              :    uses_allocators ( [modifier-list :] allocator-list [; ...])
    1963              : 
    1964              :    allocator:
    1965              :      variable or predefined-allocator
    1966              :    modifier:
    1967              :      traits ( traits-array )
    1968              :      memspace ( mem-space-handle )  */
    1969              : 
    1970              : static match
    1971           78 : gfc_match_omp_clause_uses_allocators (gfc_omp_clauses *c)
    1972              : {
    1973           82 : parse_next:
    1974           82 :   gfc_symbol *memspace_sym = NULL;
    1975           82 :   gfc_symbol *traits_sym = NULL;
    1976           82 :   gfc_omp_namelist *head = NULL;
    1977           82 :   gfc_omp_namelist *p, *tail, **list;
    1978           82 :   int ntraits, nmemspace;
    1979           82 :   bool has_modifiers;
    1980           82 :   locus old_loc, cur_loc;
    1981              : 
    1982           82 :   gfc_gobble_whitespace ();
    1983           82 :   old_loc = gfc_current_locus;
    1984           82 :   ntraits = nmemspace = 0;
    1985          126 :   do
    1986              :     {
    1987          104 :       cur_loc = gfc_current_locus;
    1988          104 :       if (gfc_match ("traits ( %S ) ", &traits_sym) == MATCH_YES)
    1989           34 :         ntraits++;
    1990           70 :       else if (gfc_match ("memspace ( %S ) ", &memspace_sym) == MATCH_YES)
    1991           33 :         nmemspace++;
    1992          104 :       if (ntraits > 1 || nmemspace > 1)
    1993              :         {
    1994            5 :           gfc_error ("Duplicate %s modifier at %L in USES_ALLOCATORS clause",
    1995              :                      ntraits > 1 ? "TRAITS" : "MEMSPACE", &cur_loc);
    1996            5 :           return MATCH_ERROR;
    1997              :         }
    1998           99 :       if (gfc_match (", ") == MATCH_YES)
    1999           22 :         continue;
    2000           77 :       if (gfc_match (": ") != MATCH_YES)
    2001              :         {
    2002              :           /* Assume no modifier. */
    2003           39 :           memspace_sym = traits_sym = NULL;
    2004           39 :           gfc_current_locus = old_loc;
    2005           39 :           break;
    2006              :         }
    2007              :       break;
    2008              :     } while (true);
    2009              : 
    2010          115 :   has_modifiers = traits_sym != NULL || memspace_sym != NULL;
    2011          179 :   do
    2012              :     {
    2013          128 :       p = gfc_get_omp_namelist ();
    2014          128 :       p->where = gfc_current_locus;
    2015          128 :       if (head == NULL)
    2016              :         head = tail = p;
    2017              :       else
    2018              :         {
    2019           51 :           tail->next = p;
    2020           51 :           tail = tail->next;
    2021              :         }
    2022          128 :       if (gfc_match ("%S ", &p->sym) != MATCH_YES)
    2023            1 :         goto error;
    2024          127 :       if (!has_modifiers)
    2025              :         {
    2026           83 :           if (gfc_match ("( %S ) ", &p->u2.traits_sym) == MATCH_YES)
    2027           22 :             gfc_warning (OPT_Wdeprecated_openmp,
    2028              :                          "The specification of arguments to "
    2029              :                          "%<uses_allocators%> at %L where each item is of "
    2030              :                          "the form %<allocator(traits)%> is deprecated since "
    2031              :                          "OpenMP 5.2; instead use %<uses_allocators(traits(%s"
    2032           22 :                          "): %s)%>", &p->where, p->u2.traits_sym->name,
    2033           22 :                          p->sym->name);
    2034              :         }
    2035           44 :       else if (gfc_peek_ascii_char () == '(')
    2036              :         {
    2037            1 :           gfc_error ("Unexpected %<(%> at %C");
    2038            1 :           goto error;
    2039              :         }
    2040              :       else
    2041              :         {
    2042           43 :           p->u.memspace_sym = memspace_sym;
    2043           43 :           p->u2.traits_sym = traits_sym;
    2044              :         }
    2045          126 :       gfc_gobble_whitespace ();
    2046          126 :       const char c = gfc_peek_ascii_char ();
    2047          126 :       if (c == ';' || c == ')')
    2048              :         break;
    2049           53 :       if (c != ',')
    2050              :         {
    2051            2 :           gfc_error ("Expected %<,%>, %<)%> or %<;%> at %C");
    2052            2 :           goto error;
    2053              :         }
    2054           51 :       gfc_match_char (',');
    2055           51 :       gfc_gobble_whitespace ();
    2056           51 :     } while (true);
    2057              : 
    2058           73 :   list = &c->lists[OMP_LIST_USES_ALLOCATORS];
    2059           91 :   while (*list)
    2060           18 :     list = &(*list)->next;
    2061           73 :   *list = head;
    2062              : 
    2063           73 :   if (gfc_match_char (';') == MATCH_YES)
    2064            4 :     goto parse_next;
    2065              : 
    2066           69 :   gfc_match_char (')');
    2067           69 :   return MATCH_YES;
    2068              : 
    2069            4 : error:
    2070            4 :   gfc_free_omp_namelist (head, OMP_LIST_USES_ALLOCATORS);
    2071            4 :   return MATCH_ERROR;
    2072              : }
    2073              : 
    2074              : 
    2075              : /* Match the 'prefer_type' modifier of the interop 'init' clause:
    2076              :    with either OpenMP 5.1's
    2077              :      prefer_type ( <const-int-expr|string literal> [, ...]
    2078              :    or
    2079              :      prefer_type ( '{' <fr(...) | attr (...)>, ...] '}' [, '{' ... '}' ] )
    2080              :    where 'fr' takes a constant expression or a string literal
    2081              :    and 'attr takes a list of string literals, starting with 'ompx_')
    2082              : 
    2083              :    For the foreign runtime identifiers, string values are converted to
    2084              :    their integer value; unknown string or integer values are set to
    2085              :    GOMP_INTEROP_IFR_KNOWN.
    2086              : 
    2087              :    Data format:
    2088              :     For the foreign runtime identifiers, string values are converted to
    2089              :     their integer value; unknown string or integer values are set to 0.
    2090              : 
    2091              :     Each item (a) GOMP_INTEROP_IFR_SEPARATOR
    2092              :               (b) for any 'fr', its integer value.
    2093              :                   Note: Spec only permits 1 'fr' entry (6.0; changed after TR13)
    2094              :               (c) GOMP_INTEROP_IFR_SEPARATOR
    2095              :               (d) list of \0-terminated non-empty strings for 'attr'
    2096              :               (e) '\0'
    2097              :     Tailing '\0'.  */
    2098              : 
    2099              : static match
    2100           82 : gfc_match_omp_prefer_type (char **type_str, int *type_str_len)
    2101              : {
    2102           82 :   gfc_expr *e;
    2103           82 :   std::string type_string, attr_string;
    2104              :   /* New syntax.  */
    2105           82 :   if (gfc_peek_ascii_char () == '{')
    2106          115 :     do
    2107              :       {
    2108           85 :         attr_string.clear ();
    2109           85 :         type_string += (char) GOMP_INTEROP_IFR_SEPARATOR;
    2110           85 :         if (gfc_match ("{ ") != MATCH_YES)
    2111              :           {
    2112            1 :             gfc_error ("Expected %<{%> at %C");
    2113            1 :             return MATCH_ERROR;
    2114              :           }
    2115              :         bool fr_found = false;
    2116          148 :         do
    2117              :           {
    2118          116 :             if (gfc_match ("fr ( ") == MATCH_YES)
    2119              :               {
    2120           62 :                 if (fr_found)
    2121              :                   {
    2122            1 :                     gfc_error ("Duplicated %<fr%> preference-selector-name "
    2123              :                                "at %C");
    2124            1 :                     return MATCH_ERROR;
    2125              :                   }
    2126           61 :                 fr_found = true;
    2127           61 :                 do
    2128              :                   {
    2129           61 :                     bool found_literal = false;
    2130           61 :                     match m = MATCH_YES;
    2131           61 :                     if (gfc_match_literal_constant (&e, false) == MATCH_YES)
    2132              :                       found_literal = true;
    2133              :                     else
    2134           12 :                       m = gfc_match_expr (&e);
    2135           12 :                     if (m != MATCH_YES
    2136           61 :                         || !gfc_resolve_expr (e)
    2137           61 :                         || e->rank != 0
    2138           60 :                         || e->expr_type != EXPR_CONSTANT
    2139           59 :                         || (e->ts.type != BT_INTEGER
    2140           43 :                             && (!found_literal || e->ts.type != BT_CHARACTER))
    2141           58 :                         || (e->ts.type == BT_INTEGER
    2142           16 :                             && !mpz_fits_sint_p (e->value.integer))
    2143           70 :                         || (e->ts.type == BT_CHARACTER
    2144           42 :                             && (e->ts.kind != gfc_default_character_kind
    2145           41 :                         || e->value.character.length == 0)))
    2146              :                       {
    2147            5 :                         gfc_error ("Expected constant scalar integer expression"
    2148              :                                    " or non-empty default-kind character "
    2149            5 :                                    "literal at %L", &e->where);
    2150            5 :                         gfc_free_expr (e);
    2151            5 :                         return MATCH_ERROR;
    2152              :                       }
    2153           56 :                     gfc_gobble_whitespace ();
    2154           56 :                     int val;
    2155           56 :                     if (e->ts.type == BT_INTEGER)
    2156              :                       {
    2157           16 :                         val = mpz_get_si (e->value.integer);
    2158           16 :                         if (val < 1 || val > GOMP_INTEROP_IFR_LAST)
    2159              :                           {
    2160            0 :                             gfc_warning_now (OPT_Wopenmp,
    2161              :                                              "Unknown foreign runtime "
    2162              :                                              "identifier %qd at %L",
    2163              :                                              val, &e->where);
    2164            0 :                             val = GOMP_INTEROP_IFR_UNKNOWN;
    2165              :                           }
    2166              :                       }
    2167              :                     else
    2168              :                       {
    2169           40 :                         char *str = XALLOCAVEC (char,
    2170              :                                                 e->value.character.length+1);
    2171          229 :                         for (int i = 0; i < e->value.character.length + 1; i++)
    2172          189 :                           str[i] = e->value.character.string[i];
    2173           40 :                         if (memchr (str, '\0', e->value.character.length) != 0)
    2174              :                           {
    2175            0 :                             gfc_error ("Unexpected null character in character "
    2176              :                                        "literal at %L", &e->where);
    2177            0 :                             return MATCH_ERROR;
    2178              :                           }
    2179           40 :                         val = omp_get_fr_id_from_name (str);
    2180           40 :                         if (val == GOMP_INTEROP_IFR_UNKNOWN)
    2181            2 :                           gfc_warning_now (OPT_Wopenmp,
    2182              :                                            "Unknown foreign runtime identifier "
    2183            2 :                                            "%qs at %L", str, &e->where);
    2184              :                       }
    2185              : 
    2186           56 :                     type_string += (char) val;
    2187           56 :                     if (gfc_match (") ") == MATCH_YES)
    2188              :                       break;
    2189            4 :                     gfc_error ("Expected %<)%> at %C");
    2190            4 :                     return MATCH_ERROR;
    2191              :                   }
    2192              :                 while (true);
    2193              :               }
    2194           54 :             else if (gfc_match ("attr ( ") == MATCH_YES)
    2195              :               {
    2196           60 :                 do
    2197              :                   {
    2198           57 :                     if (gfc_match_literal_constant (&e, false) != MATCH_YES
    2199           56 :                         || !gfc_resolve_expr (e)
    2200           56 :                         || e->expr_type != EXPR_CONSTANT
    2201           56 :                         || e->rank != 0
    2202           56 :                         || e->ts.type != BT_CHARACTER
    2203          113 :                         || e->ts.kind != gfc_default_character_kind)
    2204              :                       {
    2205            1 :                         gfc_error ("Expected default-kind character literal "
    2206            1 :                                    "at %L", &e->where);
    2207            1 :                         gfc_free_expr (e);
    2208            1 :                         return MATCH_ERROR;
    2209              :                       }
    2210           56 :                     gfc_gobble_whitespace ();
    2211           56 :                     char *str = XALLOCAVEC (char, e->value.character.length+1);
    2212          564 :                     for (int i = 0; i < e->value.character.length + 1; i++)
    2213          508 :                       str[i] = e->value.character.string[i];
    2214           56 :                     if (!startswith (str, "ompx_"))
    2215              :                       {
    2216            1 :                         gfc_error ("Character literal at %L must start with "
    2217              :                                    "%<ompx_%>", &e->where);
    2218            1 :                         gfc_free_expr (e);
    2219            1 :                         return MATCH_ERROR;
    2220              :                       }
    2221           55 :                     if (memchr (str, '\0', e->value.character.length) != 0
    2222           55 :                         || memchr (str, ',', e->value.character.length) != 0)
    2223              :                       {
    2224            1 :                         gfc_error ("Unexpected null or %<,%> character in "
    2225              :                                    "character literal at %L", &e->where);
    2226            1 :                         return MATCH_ERROR;
    2227              :                       }
    2228           54 :                     attr_string += str;
    2229           54 :                     attr_string += '\0';
    2230           54 :                     if (gfc_match (", ") == MATCH_YES)
    2231            3 :                       continue;
    2232           51 :                     if (gfc_match (") ") == MATCH_YES)
    2233              :                       break;
    2234            0 :                     gfc_error ("Expected %<,%> or %<)%> at %C");
    2235            0 :                     return MATCH_ERROR;
    2236            3 :                   }
    2237              :                 while (true);
    2238              :               }
    2239              :             else
    2240              :               {
    2241            0 :                 gfc_error ("Expected %<fr(%> or %<attr(%> at %C");
    2242            0 :                 return MATCH_ERROR;
    2243              :               }
    2244          103 :             if (gfc_match (", ") == MATCH_YES)
    2245           32 :               continue;
    2246           71 :             if (gfc_match ("} ") == MATCH_YES)
    2247              :               break;
    2248            2 :             gfc_error ("Expected %<,%> or %<}%> at %C");
    2249            2 :             return MATCH_ERROR;
    2250           32 :           }
    2251              :         while (true);
    2252           69 :         type_string += (char) GOMP_INTEROP_IFR_SEPARATOR;
    2253           69 :         type_string += attr_string;
    2254           69 :         type_string += '\0';
    2255           69 :         if (gfc_match (", ") == MATCH_YES)
    2256           30 :           continue;
    2257           39 :         if (gfc_match (") ") == MATCH_YES)
    2258              :           break;
    2259            1 :         gfc_error ("Expected %<,%> or %<)%> at %C");
    2260            1 :         return MATCH_ERROR;
    2261           30 :       }
    2262              :     while (true);
    2263              :   else
    2264           75 :     do
    2265              :       {
    2266           51 :         type_string += (char) GOMP_INTEROP_IFR_SEPARATOR;
    2267           51 :         bool found_literal = false;
    2268           51 :         match m = MATCH_YES;
    2269           51 :         if (gfc_match_literal_constant (&e, false) == MATCH_YES)
    2270              :           found_literal = true;
    2271              :         else
    2272           19 :           m = gfc_match_expr (&e);
    2273           19 :         if (m != MATCH_YES
    2274           51 :             || !gfc_resolve_expr (e)
    2275           51 :             || e->rank != 0
    2276           50 :             || e->expr_type != EXPR_CONSTANT
    2277           49 :             || (e->ts.type != BT_INTEGER
    2278           28 :                 && (!found_literal || e->ts.type != BT_CHARACTER))
    2279           48 :             || (e->ts.type == BT_INTEGER
    2280           21 :                 && !mpz_fits_sint_p (e->value.integer))
    2281           67 :             || (e->ts.type == BT_CHARACTER
    2282           27 :                 && (e->ts.kind != gfc_default_character_kind
    2283           27 :                     || e->value.character.length == 0)))
    2284              :           {
    2285            3 :             gfc_error ("Expected constant scalar integer expression or "
    2286            3 :                        "non-empty default-kind character literal at %L", &e->where);
    2287            3 :             gfc_free_expr (e);
    2288            3 :             return MATCH_ERROR;
    2289              :           }
    2290           48 :         gfc_gobble_whitespace ();
    2291           48 :         int val;
    2292           48 :         if (e->ts.type == BT_INTEGER)
    2293              :           {
    2294           21 :             val = mpz_get_si (e->value.integer);
    2295           21 :             if (val < 1 || val > GOMP_INTEROP_IFR_LAST)
    2296              :               {
    2297            3 :                 gfc_warning_now (OPT_Wopenmp,
    2298              :                                  "Unknown foreign runtime identifier %qd at %L",
    2299              :                                  val, &e->where);
    2300            3 :                 val = 0;
    2301              :               }
    2302              :           }
    2303              :         else
    2304              :           {
    2305           27 :             char *str = XALLOCAVEC (char, e->value.character.length+1);
    2306          169 :             for (int i = 0; i < e->value.character.length + 1; i++)
    2307          142 :               str[i] = e->value.character.string[i];
    2308           27 :             if (memchr (str, '\0', e->value.character.length) != 0)
    2309              :               {
    2310            0 :                 gfc_error ("Unexpected null character in character "
    2311              :                            "literal at %L", &e->where);
    2312            0 :                 return MATCH_ERROR;
    2313              :               }
    2314           27 :             val = omp_get_fr_id_from_name (str);
    2315           27 :             if (val == GOMP_INTEROP_IFR_UNKNOWN)
    2316            5 :               gfc_warning_now (OPT_Wopenmp,
    2317              :                                "Unknown foreign runtime identifier %qs at %L",
    2318            5 :                                str, &e->where);
    2319              :           }
    2320           48 :         type_string += (char) val;
    2321           48 :         type_string += (char) GOMP_INTEROP_IFR_SEPARATOR;
    2322           48 :         type_string += '\0';
    2323           48 :         gfc_free_expr (e);
    2324           48 :         if (gfc_match (", ") == MATCH_YES)
    2325           24 :           continue;
    2326           24 :         if (gfc_match (") ") == MATCH_YES)
    2327              :           break;
    2328            2 :         gfc_error ("Expected %<,%> or %<)%> at %C");
    2329            2 :         return MATCH_ERROR;
    2330           24 :       }
    2331              :     while (true);
    2332           60 :   type_string += '\0';
    2333           60 :   *type_str_len = type_string.length();
    2334           60 :   *type_str = XNEWVEC (char, type_string.length ());
    2335           60 :   memcpy (*type_str, type_string.data (), type_string.length ());
    2336           60 :   return MATCH_YES;
    2337           82 : }
    2338              : 
    2339              : 
    2340              : /* Match OpenMP 5.1's 'init'-clause modifiers, used by the 'init' clause of
    2341              :    the 'interop' directive and the 'append_args' directive of 'declare variant'.
    2342              :      [prefer_type(...)][,][<target|targetsync>, ...])
    2343              : 
    2344              :    If is_init_clause, the modifier parsing ends with a ':'.
    2345              :    If not is_init_clause (i.e. append_args), the parsing ends with ')'.  */
    2346              : 
    2347              : static match
    2348          164 : gfc_parser_omp_clause_init_modifiers (bool &target, bool &targetsync,
    2349              :                                       char **type_str, int &type_str_len,
    2350              :                                       bool is_init_clause)
    2351              : {
    2352          164 :   target = false;
    2353          164 :   targetsync = false;
    2354          164 :   *type_str = NULL;
    2355          164 :   type_str_len = 0;
    2356          286 :   match m;
    2357              : 
    2358          286 :   do
    2359              :     {
    2360          286 :       if (gfc_match ("prefer_type ( ") == MATCH_YES)
    2361              :         {
    2362           83 :           if (*type_str)
    2363              :             {
    2364            1 :               gfc_error ("Duplicate %<prefer_type%> modifier at %C");
    2365            1 :               return MATCH_ERROR;
    2366              :             }
    2367           82 :           m = gfc_match_omp_prefer_type (type_str, &type_str_len);
    2368           82 :           if (m != MATCH_YES)
    2369              :             return m;
    2370           60 :           if (gfc_match (", ") == MATCH_YES)
    2371           14 :             continue;
    2372           46 :           if (is_init_clause)
    2373              :             {
    2374           24 :               if (gfc_match (": ") == MATCH_YES)
    2375              :                 break;
    2376            0 :               gfc_error ("Expected %<,%> or %<:%> at %C");
    2377              :             }
    2378              :           else
    2379              :             {
    2380           22 :               if (gfc_match (") ") == MATCH_YES)
    2381              :                 break;
    2382            0 :               gfc_error ("Expected %<,%> or %<)%> at %C");
    2383              :             }
    2384              :           return MATCH_ERROR;
    2385              :         }
    2386              : 
    2387          203 :       if (gfc_match ("prefer_type ") == MATCH_YES)
    2388              :         {
    2389            2 :           gfc_error ("Expected %<(%> after %<prefer_type%> at %C");
    2390            2 :           return MATCH_ERROR;
    2391              :         }
    2392              : 
    2393          201 :       if (gfc_match ("targetsync ") == MATCH_YES)
    2394              :         {
    2395           57 :           if (targetsync)
    2396              :             {
    2397            3 :               gfc_error ("Duplicate %<targetsync%> at %C");
    2398            3 :               return MATCH_ERROR;
    2399              :             }
    2400           54 :           targetsync = true;
    2401           54 :           if (gfc_match (", ") == MATCH_YES)
    2402           13 :             continue;
    2403           41 :           if (!is_init_clause)
    2404              :             {
    2405           23 :               if (gfc_match (") ") == MATCH_YES)
    2406              :                 break;
    2407            0 :               gfc_error ("Expected %<,%> or %<)%> at %C");
    2408            0 :               return MATCH_ERROR;
    2409              :             }
    2410           18 :           if (gfc_match (": ") == MATCH_YES)
    2411              :             break;
    2412            1 :           gfc_error ("Expected %<,%> or %<:%> at %C");
    2413            1 :           return MATCH_ERROR;
    2414              :         }
    2415          144 :       if (gfc_match ("target ") == MATCH_YES)
    2416              :         {
    2417          135 :           if (target)
    2418              :             {
    2419            3 :               gfc_error ("Duplicate %<target%> at %C");
    2420            3 :               return MATCH_ERROR;
    2421              :             }
    2422          132 :           target = true;
    2423          132 :           if (gfc_match (", ") == MATCH_YES)
    2424           95 :             continue;
    2425           37 :           if (!is_init_clause)
    2426              :             {
    2427           11 :               if (gfc_match (") ") == MATCH_YES)
    2428              :                 break;
    2429            0 :               gfc_error ("Expected %<,%> or %<)%> at %C");
    2430            0 :               return MATCH_ERROR;
    2431              :             }
    2432           26 :           if (gfc_match (": ") == MATCH_YES)
    2433              :             break;
    2434            1 :           gfc_error ("Expected %<,%> or %<:%> at %C");
    2435            1 :           return MATCH_ERROR;
    2436              :         }
    2437            9 :       gfc_error ("Expected %<prefer_type%>, %<target%>, or %<targetsync%> "
    2438              :                  "at %C");
    2439            9 :       return MATCH_ERROR;
    2440              :     }
    2441              :   while (true);
    2442              : 
    2443          122 :   if (!target && !targetsync)
    2444              :     {
    2445            4 :       gfc_error ("Missing required %<target%> and/or %<targetsync%> "
    2446              :                  "modifier at %C");
    2447            4 :       return MATCH_ERROR;
    2448              :     }
    2449              :   return MATCH_YES;
    2450              : }
    2451              : 
    2452              : /* Match OpenMP 5.1's 'init' clause for 'interop' objects:
    2453              :    init([prefer_type(...)][,][<target|targetsync>, ...] :] interop-obj-list)  */
    2454              : 
    2455              : static match
    2456          108 : gfc_match_omp_init (gfc_omp_namelist **list)
    2457              : {
    2458          108 :   bool target, targetsync;
    2459          108 :   char *type_str = NULL;
    2460          108 :   int type_str_len;
    2461          108 :   if (gfc_parser_omp_clause_init_modifiers (target, targetsync, &type_str,
    2462              :                                             type_str_len, true) == MATCH_ERROR)
    2463              :     return MATCH_ERROR;
    2464              : 
    2465           64 :   gfc_omp_namelist **head = NULL;
    2466           64 :   if (gfc_match_omp_variable_list ("", list, false, NULL, &head) != MATCH_YES)
    2467              :     return MATCH_ERROR;
    2468          147 :   for (gfc_omp_namelist *n = *head; n; n = n->next)
    2469              :     {
    2470           84 :       n->u.init.target = target;
    2471           84 :       n->u.init.targetsync = targetsync;
    2472           84 :       n->u.init.len = type_str_len;
    2473           84 :       n->u2.init_interop = type_str;
    2474              :     }
    2475              :   return MATCH_YES;
    2476              : }
    2477              : 
    2478              : /* Match boolean-type clause with duplicate check. Matches 'name' then matches
    2479              :    an optional '(const-logical-expr)'; already_set is used for the duplicate
    2480              :    check.  If the clause is not matched NO is returned, if an error occurs ERROR
    2481              :    and otherwise YES.  In the no-error case RES contains the value of the
    2482              :    expression or true if no expression exists.
    2483              :    If FALSE_OK, 'false' implies an absent clause, which can be repeated without
    2484              :    printing an error; that is the case for clause groups.
    2485              :    If DUPL_MSG is nonnull, the string is used as error message and must contain
    2486              :    %qs and %L in that order.  */
    2487              : 
    2488              : static match
    2489         3748 : gfc_match_boolean_clause (bool *res, const char *name, bool already_set,
    2490              :                           bool false_ok = false, const char *dupl_msg = NULL)
    2491              : {
    2492         3748 :   gfc_expr *expr = NULL;
    2493         3748 :   match m;
    2494         3748 :   char c;
    2495         3748 :   locus old_loc = gfc_current_locus;
    2496         3748 :   locus old_loc2;
    2497         3748 :   if ((m = gfc_match (name)) != MATCH_YES)
    2498              :     return m;
    2499              :   /* Ensure that no partial string is matched.  */
    2500         2506 :   if (gfc_current_form == FORM_FREE
    2501         2506 :       && gfc_match_eos () != MATCH_YES
    2502         3254 :       && ((c = gfc_peek_ascii_char ()) == '_' || ISALNUM (c)))
    2503              :     {
    2504            1 :       gfc_current_locus = old_loc;
    2505            1 :       return MATCH_NO;
    2506              :     }
    2507         2505 :   if (already_set && !false_ok)
    2508           22 :     goto dupl;
    2509         2483 :   if (gfc_match (" (") == MATCH_NO)
    2510              :     {
    2511         2289 :       if (already_set)
    2512            3 :         goto dupl;
    2513         2286 :       *res = true;  /* Implicit boolean true.  */
    2514         2286 :       return MATCH_YES;
    2515              :     }
    2516          194 :   old_loc2 = gfc_current_locus;
    2517          194 :   m = gfc_match_expr (&expr);
    2518          194 :   if (m != MATCH_YES
    2519          193 :       || gfc_match (" )") != MATCH_YES
    2520          188 :       || !gfc_resolve_expr (expr)
    2521          188 :       || expr->rank != 0
    2522          187 :       || expr->expr_type != EXPR_CONSTANT
    2523          379 :       || expr->ts.type != BT_LOGICAL)
    2524              :     {
    2525           13 :       gfc_free_expr (expr);
    2526           13 :       gfc_error ("Expected %<( const-logical-expr )%> at %L", &old_loc2);
    2527           13 :       return MATCH_ERROR;
    2528              :     }
    2529          181 :   if (already_set && expr->value.logical)
    2530            4 :     goto dupl;
    2531          177 :   *res = expr->value.logical;
    2532          177 :   gfc_free_expr (expr);
    2533          177 :   return MATCH_YES;
    2534              : 
    2535           29 : dupl:
    2536           29 :   if (dupl_msg)
    2537           12 :     gfc_error (dupl_msg, name, &old_loc);
    2538              :   else
    2539           17 :     gfc_error ("Duplicated %qs clause at %L", name, &old_loc);
    2540              :   return MATCH_ERROR;
    2541              : }
    2542              : 
    2543              : 
    2544              : /* Match a clause from the atomic clauses set.  */
    2545              : 
    2546              : static match
    2547         1231 : gfc_match_dupl_atomic (bool *res, const char *name, bool already_set)
    2548              : {
    2549         1231 :   const char *msg = G_("Duplicated atomic clause: unexpected %qs clause at %L");
    2550            0 :   return gfc_match_boolean_clause (res, name, already_set, true, msg);
    2551              : }
    2552              : 
    2553              : 
    2554              : /* Match a clause from the memory-order clauses set.  */
    2555              : 
    2556              : static match
    2557          451 : gfc_match_dupl_memorder (bool *res, const char *name, bool already_set)
    2558              : {
    2559          451 :   const char *msg = G_("Duplicated memory-order clause: unexpected %qs clause "
    2560              :                        "at %L");
    2561            0 :   return gfc_match_boolean_clause (res, name, already_set, true, msg);
    2562              : }
    2563              : 
    2564              : 
    2565              : /* Match a clause from the branch clauses set; interestingly, here
    2566              :    inbranch(false) branch(false/true) is not permitted!  */
    2567              : 
    2568              : static match
    2569           62 : gfc_match_dupl_branch_clause (bool *res, const char *name, bool already_set)
    2570              : {
    2571           62 :   const char *msg = G_("Duplicated branch clause: unexpected %qs clause "
    2572              :                        "at %L");
    2573           62 :   return gfc_match_boolean_clause (res, name, already_set, false, msg);
    2574              : }
    2575              : 
    2576              : 
    2577              : /* Match with duplicate check. Matches 'name'. If expr != NULL, it
    2578              :    then matches '(expr)', otherwise, if open_parens is true,
    2579              :    it matches a ' ( ' after 'name'.  */
    2580              : 
    2581              : static match
    2582        20373 : gfc_match_dupl_check (bool not_dupl, const char *name, bool open_parens = false,
    2583              :                       gfc_expr **expr = NULL)
    2584              : {
    2585        20373 :   match m;
    2586        20373 :   char c;
    2587        20373 :   locus old_loc = gfc_current_locus;
    2588        20373 :   if ((m = gfc_match (name)) != MATCH_YES)
    2589              :     return m;
    2590              :   /* Ensure that no partial string is matched.  */
    2591        16010 :   if (gfc_current_form == FORM_FREE
    2592        15512 :       && gfc_match_eos () != MATCH_YES
    2593        29058 :       && ((c = gfc_peek_ascii_char ()) == '_' || ISALNUM (c)))
    2594              :     {
    2595           12 :       gfc_current_locus = old_loc;
    2596           12 :       return MATCH_NO;
    2597              :     }
    2598        15998 :   if (!not_dupl)
    2599              :     {
    2600           46 :       gfc_error ("Duplicated %qs clause at %L", name, &old_loc);
    2601           46 :       return MATCH_ERROR;
    2602              :     }
    2603        15952 :   if (open_parens || expr)
    2604              :     {
    2605        10156 :       if (gfc_match (" ( ") != MATCH_YES)
    2606              :         {
    2607           25 :           gfc_error ("Expected %<(%> after %qs at %C", name);
    2608           25 :           return MATCH_ERROR;
    2609              :         }
    2610        10131 :       if (expr)
    2611              :         {
    2612         3404 :           if (gfc_match ("%e )", expr) != MATCH_YES)
    2613              :             {
    2614            9 :               gfc_error ("Invalid expression after %<%s(%> at %C", name);
    2615            9 :               return MATCH_ERROR;
    2616              :             }
    2617              :         }
    2618              :     }
    2619              :   return MATCH_YES;
    2620              : }
    2621              : 
    2622              : /* Search upwards though namespace NS and its parents to find an
    2623              :    !$omp declare mapper named MAPPER_ID, for typespec TS.  The default
    2624              :    mapper has mapper_id == "".  */
    2625              : 
    2626              : gfc_omp_udm *
    2627         1002 : gfc_find_omp_udm (gfc_namespace *ns, const char *mapper_id, gfc_typespec *ts)
    2628              : {
    2629         1002 :   gfc_symtree *st;
    2630              : 
    2631         1002 :   if (ns == NULL)
    2632            0 :     ns = gfc_current_ns;
    2633              : 
    2634         1181 :   do
    2635              :     {
    2636         1181 :       gfc_omp_udm *omp_udm;
    2637              : 
    2638         1181 :       st = gfc_find_symtree (ns->omp_udm_root, mapper_id);
    2639              : 
    2640         1181 :       if (st != NULL)
    2641              :         {
    2642           29 :           for (omp_udm = st->n.omp_udm; omp_udm; omp_udm = omp_udm->next)
    2643           29 :             if (gfc_compare_types (&omp_udm->ts, ts))
    2644              :               return omp_udm;
    2645              :         }
    2646              : 
    2647              :       /* Don't escape an interface block.  */
    2648         1154 :       if (ns && !ns->has_import_set
    2649         1154 :           && ns->proc_name && ns->proc_name->attr.if_source == IFSRC_IFBODY)
    2650              :         break;
    2651              : 
    2652         1154 :       ns = ns->parent;
    2653              :     }
    2654         1154 :   while (ns != NULL);
    2655              : 
    2656              :   return NULL;
    2657              : }
    2658              : 
    2659              : 
    2660              : /* Match OpenMP and OpenACC directive clauses. MASK is a bitmask of
    2661              :    clauses that are allowed for a particular directive.  */
    2662              : 
    2663              : static match
    2664        35216 : gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
    2665              :                        bool first_no_comma = true, bool needs_space = true,
    2666              :                        bool openacc = false, bool openmp_target = false,
    2667              :                        gfc_omp_map_op default_map_op = OMP_MAP_TOFROM)
    2668              : {
    2669        35216 :   bool error = false;
    2670        35216 :   bool bval;
    2671        35216 :   gfc_omp_clauses *c = gfc_get_omp_clauses ();
    2672        35216 :   gfc_omp_clauses *cfalse = openacc ? NULL : gfc_get_omp_clauses ();
    2673        21348 :   locus old_loc;
    2674              :   /* Determine whether we're dealing with an OpenACC directive that permits
    2675              :      derived type member accesses.  This in particular disallows
    2676              :      "!$acc declare" from using such accesses, because it's not clear if/how
    2677              :      that should work.  */
    2678        21348 :   bool allow_derived = (openacc
    2679        13868 :                         && ((mask & OMP_CLAUSE_ATTACH)
    2680         6326 :                             || (mask & OMP_CLAUSE_DETACH)));
    2681              : 
    2682        35216 :   gcc_checking_assert (OMP_MASK1_LAST <= 64 && OMP_MASK2_LAST <= 64);
    2683        35216 :   *cp = NULL;
    2684       129422 :   while (1)
    2685              :     {
    2686        82319 :       match m = MATCH_NO;
    2687        82234 :       if ((first_no_comma || (m = gfc_match_char (',')) != MATCH_YES)
    2688       164108 :           && (needs_space && gfc_match_space () != MATCH_YES))
    2689              :         break;
    2690        77785 :       needs_space = false;
    2691        77785 :       first_no_comma = false;
    2692        77785 :       gfc_gobble_whitespace ();
    2693        77785 :       bool end_colon;
    2694        77785 :       gfc_omp_namelist **head;
    2695        77785 :       old_loc = gfc_current_locus;
    2696        77785 :       char pc = gfc_peek_ascii_char ();
    2697        77785 :       if (pc == '\n' && m == MATCH_YES)
    2698              :         {
    2699            1 :           gfc_error ("Clause expected at %C after trailing comma");
    2700            1 :           goto error;
    2701              :         }
    2702        77784 :       switch (pc)
    2703              :         {
    2704         1339 :         case 'a':
    2705         1339 :           end_colon = false;
    2706         1339 :           head = NULL;
    2707         1364 :           if ((mask & OMP_CLAUSE_ASSUMPTIONS)
    2708         1339 :               && gfc_match ("absent ( ") == MATCH_YES)
    2709              :             {
    2710           28 :               if (gfc_omp_absent_contains_clause (&c->assume, true)
    2711              :                   != MATCH_YES)
    2712            3 :                 goto error;
    2713           25 :               continue;
    2714              :             }
    2715         1311 :           if ((mask & OMP_CLAUSE_ALIGNED)
    2716         1311 :               && gfc_match_omp_variable_list ("aligned (",
    2717              :                                               &c->lists[OMP_LIST_ALIGNED],
    2718              :                                               false, &end_colon,
    2719              :                                               &head) == MATCH_YES)
    2720              :             {
    2721          112 :               gfc_expr *alignment = NULL;
    2722          112 :               gfc_omp_namelist *n;
    2723              : 
    2724          112 :               if (end_colon && gfc_match (" %e )", &alignment) != MATCH_YES)
    2725              :                 {
    2726            0 :                   gfc_free_omp_namelist (*head, OMP_LIST_ALIGNED);
    2727            0 :                   gfc_current_locus = old_loc;
    2728            0 :                   *head = NULL;
    2729            0 :                   break;
    2730              :                 }
    2731          268 :               for (n = *head; n; n = n->next)
    2732          156 :                 if (n->next && alignment)
    2733           42 :                   n->expr = gfc_copy_expr (alignment);
    2734              :                 else
    2735          114 :                   n->expr = alignment;
    2736          112 :               continue;
    2737          112 :             }
    2738         1218 :           if ((mask & OMP_CLAUSE_MEMORDER)
    2739         1234 :               && (m = gfc_match_dupl_memorder (&bval, "acq_rel",
    2740           35 :                         c->memorder != OMP_MEMORDER_UNSET)) != MATCH_NO)
    2741              :             {
    2742           19 :               if (m == MATCH_ERROR)
    2743            0 :                 goto error;
    2744           19 :               if (bval)
    2745           12 :                 c->memorder = OMP_MEMORDER_ACQ_REL;
    2746           19 :               continue;
    2747              :             }
    2748         1196 :           if ((mask & OMP_CLAUSE_MEMORDER)
    2749         1196 :               && (m = gfc_match_dupl_memorder (&bval, "acquire",
    2750           16 :                         c->memorder != OMP_MEMORDER_UNSET)) != MATCH_NO)
    2751              :             {
    2752           16 :               if (m == MATCH_ERROR)
    2753            0 :                 goto error;
    2754           16 :               if (bval)
    2755            9 :                 c->memorder = OMP_MEMORDER_ACQUIRE;
    2756           16 :               continue;
    2757              :             }
    2758         1164 :           if ((mask & OMP_CLAUSE_AFFINITY)
    2759         1164 :               && gfc_match ("affinity ( ") == MATCH_YES)
    2760              :             {
    2761           41 :               gfc_namespace *ns_iter = NULL, *ns_curr = gfc_current_ns;
    2762           41 :               m = gfc_match_iterator (&ns_iter, true);
    2763           41 :               if (m == MATCH_ERROR)
    2764              :                 break;
    2765           31 :               if (m == MATCH_YES && gfc_match (" : ") != MATCH_YES)
    2766              :                 {
    2767            1 :                   gfc_error ("Expected %<:%> at %C");
    2768            1 :                   break;
    2769              :                 }
    2770           30 :               if (ns_iter)
    2771           18 :                 gfc_current_ns = ns_iter;
    2772           30 :               head = NULL;
    2773           30 :               m = gfc_match_omp_variable_list ("", &c->lists[OMP_LIST_AFFINITY],
    2774              :                                                false, NULL, &head, true);
    2775           30 :               gfc_current_ns = ns_curr;
    2776           30 :               if (m == MATCH_ERROR)
    2777              :                 break;
    2778           27 :               if (ns_iter)
    2779              :                 {
    2780           45 :                   for (gfc_omp_namelist *n = *head; n; n = n->next)
    2781              :                     {
    2782           27 :                       n->u2.ns = ns_iter;
    2783           27 :                       ns_iter->refs++;
    2784              :                     }
    2785              :                 }
    2786           27 :               continue;
    2787           27 :             }
    2788         1123 :           if ((mask & OMP_CLAUSE_ALLOCATE)
    2789         1123 :               && gfc_match ("allocate ( ") == MATCH_YES)
    2790              :             {
    2791          281 :               gfc_expr *allocator = NULL;
    2792          281 :               gfc_expr *align = NULL;
    2793          281 :               old_loc = gfc_current_locus;
    2794          281 :               if ((m = gfc_match ("allocator ( %e )", &allocator)) == MATCH_YES)
    2795           50 :                 gfc_match (" , align ( %e )", &align);
    2796          231 :               else if ((m = gfc_match ("align ( %e )", &align)) == MATCH_YES)
    2797           29 :                 gfc_match (" , allocator ( %e )", &allocator);
    2798              : 
    2799           79 :               if (m == MATCH_YES)
    2800              :                 {
    2801           79 :                   if (gfc_match (" : ") != MATCH_YES)
    2802              :                     {
    2803            5 :                       gfc_error ("Expected %<:%> at %C");
    2804            8 :                       goto error;
    2805              :                     }
    2806              :                 }
    2807              :               else
    2808              :                 {
    2809          202 :                   m = gfc_match_expr (&allocator);
    2810          202 :                   if (m == MATCH_YES && gfc_match (" : ") != MATCH_YES)
    2811              :                     {
    2812              :                        /* If no ":" then there is no allocator, we backtrack
    2813              :                           and read the variable list.  */
    2814          101 :                       gfc_free_expr (allocator);
    2815          101 :                       allocator = NULL;
    2816          101 :                       gfc_current_locus = old_loc;
    2817              :                     }
    2818              :                 }
    2819          276 :               gfc_omp_namelist **head = NULL;
    2820          276 :               m = gfc_match_omp_variable_list ("", &c->lists[OMP_LIST_ALLOCATE],
    2821              :                                                true, NULL, &head);
    2822              : 
    2823          276 :               if (m != MATCH_YES)
    2824              :                 {
    2825            3 :                   gfc_free_expr (allocator);
    2826            3 :                   gfc_free_expr (align);
    2827            3 :                   gfc_error ("Expected variable list at %C");
    2828            3 :                   goto error;
    2829              :                 }
    2830              : 
    2831          729 :               for (gfc_omp_namelist *n = *head; n; n = n->next)
    2832              :                 {
    2833          456 :                   n->u2.allocator = allocator;
    2834          456 :                   n->u.align = (align) ? gfc_copy_expr (align) : NULL;
    2835              :                 }
    2836          273 :               gfc_free_expr (align);
    2837          273 :               continue;
    2838          273 :             }
    2839          905 :           if ((mask & OMP_CLAUSE_AT)
    2840          842 :               && (m = gfc_match_dupl_check (c->at == OMP_AT_UNSET, "at", true))
    2841              :                  != MATCH_NO)
    2842              :             {
    2843           69 :               if (m == MATCH_ERROR)
    2844            2 :                 goto error;
    2845           67 :               if (gfc_match ("compilation )") == MATCH_YES)
    2846           15 :                 c->at = OMP_AT_COMPILATION;
    2847           52 :               else if (gfc_match ("execution )") == MATCH_YES)
    2848           48 :                 c->at = OMP_AT_EXECUTION;
    2849              :               else
    2850              :                 {
    2851            4 :                   gfc_error ("Expected COMPILATION or EXECUTION in AT clause "
    2852              :                              "at %C");
    2853            4 :                   goto error;
    2854              :                 }
    2855           63 :               continue;
    2856              :             }
    2857         1416 :           if ((mask & OMP_CLAUSE_ASYNC)
    2858          773 :               && (m = gfc_match_dupl_check (!c->async, "async")) != MATCH_NO)
    2859              :             {
    2860          643 :               if (m == MATCH_ERROR)
    2861            0 :                 goto error;
    2862          643 :               c->async = true;
    2863          643 :               m = gfc_match (" ( %e )", &c->async_expr);
    2864          643 :               if (m == MATCH_ERROR)
    2865              :                 {
    2866            0 :                   gfc_current_locus = old_loc;
    2867            0 :                   break;
    2868              :                 }
    2869          643 :               else if (m == MATCH_NO)
    2870              :                 {
    2871          133 :                   c->async_expr
    2872          133 :                     = gfc_get_constant_expr (BT_INTEGER,
    2873              :                                              gfc_default_integer_kind,
    2874              :                                              &gfc_current_locus);
    2875          133 :                   mpz_set_si (c->async_expr->value.integer, GOMP_ASYNC_NOVAL);
    2876              :                 }
    2877          643 :               continue;
    2878              :             }
    2879          193 :           if ((mask & OMP_CLAUSE_AUTO)
    2880          130 :               && (m = gfc_match_dupl_check (!c->par_auto, "auto"))
    2881              :                  != MATCH_NO)
    2882              :             {
    2883           63 :               if (m == MATCH_ERROR)
    2884            0 :                 goto error;
    2885           63 :               c->par_auto = true;
    2886           63 :               continue;
    2887              :             }
    2888          128 :           if ((mask & OMP_CLAUSE_ATTACH)
    2889           62 :               && gfc_match ("attach ( ") == MATCH_YES
    2890          128 :               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
    2891              :                                            OMP_MAP_ATTACH, false,
    2892              :                                            allow_derived))
    2893           61 :             continue;
    2894              :           break;
    2895           36 :         case 'b':
    2896           70 :           if ((mask & OMP_CLAUSE_BIND)
    2897           36 :               && (m = gfc_match_dupl_check (c->bind == OMP_BIND_UNSET, "bind",
    2898              :                                             true)) != MATCH_NO)
    2899              :             {
    2900           36 :               if (m == MATCH_ERROR)
    2901            1 :                 goto error;
    2902           35 :               if (gfc_match ("teams )") == MATCH_YES)
    2903           11 :                 c->bind = OMP_BIND_TEAMS;
    2904           24 :               else if (gfc_match ("parallel )") == MATCH_YES)
    2905           15 :                 c->bind = OMP_BIND_PARALLEL;
    2906            9 :               else if (gfc_match ("thread )") == MATCH_YES)
    2907            8 :                 c->bind = OMP_BIND_THREAD;
    2908              :               else
    2909              :                 {
    2910            1 :                   gfc_error ("Expected TEAMS, PARALLEL or THREAD as binding in "
    2911              :                              "BIND at %C");
    2912            1 :                   break;
    2913              :                 }
    2914           34 :               continue;
    2915              :             }
    2916              :           break;
    2917         7123 :         case 'c':
    2918         7399 :           if ((mask & OMP_CLAUSE_CAPTURE)
    2919         7571 :               && (m = gfc_match_boolean_clause (&bval, "capture",
    2920          448 :                          c->capture || cfalse->capture)) != MATCH_NO)
    2921              :             {
    2922          277 :               if (m == MATCH_ERROR)
    2923            1 :                 goto error;
    2924          276 :               if (bval)
    2925          273 :                 c->capture = true;
    2926              :               else
    2927            3 :                 cfalse->capture = true;
    2928          276 :               continue;
    2929              :             }
    2930         6846 :           if (mask & OMP_CLAUSE_COLLAPSE)
    2931              :             {
    2932         1996 :               gfc_expr *cexpr = NULL;
    2933         1996 :               if ((m = gfc_match_dupl_check (!c->collapse, "collapse", true,
    2934              :                                              &cexpr)) != MATCH_NO)
    2935              :               {
    2936         1506 :                 int collapse;
    2937         1506 :                 if (m == MATCH_ERROR)
    2938            0 :                   goto error;
    2939         1506 :                 if (gfc_extract_int (cexpr, &collapse, -1))
    2940            4 :                   collapse = 1;
    2941         1502 :                 else if (collapse <= 0)
    2942              :                   {
    2943            8 :                     gfc_error_now ("COLLAPSE clause argument not constant "
    2944              :                                    "positive integer at %C");
    2945            8 :                     collapse = 1;
    2946              :                   }
    2947         1506 :                 gfc_free_expr (cexpr);
    2948         1506 :                 c->collapse = collapse;
    2949         1506 :                 continue;
    2950         1506 :               }
    2951              :             }
    2952         5510 :           if ((mask & OMP_CLAUSE_COMPARE)
    2953         5511 :               && (m = gfc_match_boolean_clause (&bval, "compare",
    2954          171 :                          c->compare || cfalse->compare)) != MATCH_NO)
    2955              :             {
    2956          171 :               if (m == MATCH_ERROR)
    2957            1 :                 goto error;
    2958          170 :               if (bval)
    2959          167 :                 c->compare = true;
    2960              :               else
    2961            3 :                 cfalse->compare = true;
    2962          170 :               continue;
    2963              :             }
    2964         5182 :           if ((mask & OMP_CLAUSE_ASSUMPTIONS)
    2965         5169 :               && gfc_match ("contains ( ") == MATCH_YES)
    2966              :             {
    2967           19 :               if (gfc_omp_absent_contains_clause (&c->assume, false)
    2968              :                   != MATCH_YES)
    2969            6 :                 goto error;
    2970           13 :               continue;
    2971              :             }
    2972         7266 :           if ((mask & OMP_CLAUSE_COPY)
    2973         3723 :               && gfc_match ("copy ( ") == MATCH_YES
    2974         7267 :               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
    2975              :                                            OMP_MAP_TOFROM, true,
    2976              :                                            allow_derived))
    2977         2116 :             continue;
    2978         3034 :           if (mask & OMP_CLAUSE_COPYIN)
    2979              :             {
    2980         2628 :               if (openacc)
    2981              :                 {
    2982         2529 :                   if (gfc_match ("copyin ( ") == MATCH_YES)
    2983              :                     {
    2984         1458 :                       bool readonly = gfc_match ("readonly : ") == MATCH_YES;
    2985         1458 :                       head = NULL;
    2986         1458 :                       if (gfc_match_omp_variable_list ("",
    2987              :                                                        &c->lists[OMP_LIST_MAP],
    2988              :                                                        true, NULL, &head, true,
    2989              :                                                        allow_derived)
    2990              :                           == MATCH_YES)
    2991              :                         {
    2992         1452 :                           gfc_omp_namelist *n;
    2993         3349 :                           for (n = *head; n; n = n->next)
    2994              :                             {
    2995         1897 :                               n->u.map.op = OMP_MAP_TO;
    2996         1897 :                               n->u.map.readonly = readonly;
    2997              :                             }
    2998         1452 :                           continue;
    2999         1452 :                         }
    3000              :                     }
    3001              :                 }
    3002           99 :               else if (gfc_match_omp_variable_list ("copyin (",
    3003              :                                                     &c->lists[OMP_LIST_COPYIN],
    3004              :                                                     true) == MATCH_YES)
    3005           97 :                 continue;
    3006              :             }
    3007         2556 :           if ((mask & OMP_CLAUSE_COPYOUT)
    3008         1216 :               && gfc_match ("copyout ( ") == MATCH_YES
    3009         2556 :               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
    3010              :                                            OMP_MAP_FROM, true, allow_derived))
    3011         1071 :             continue;
    3012          498 :           if ((mask & OMP_CLAUSE_COPYPRIVATE)
    3013          414 :               && gfc_match_omp_variable_list ("copyprivate (",
    3014              :                                               &c->lists[OMP_LIST_COPYPRIVATE],
    3015              :                                               true) == MATCH_YES)
    3016           84 :             continue;
    3017          651 :           if ((mask & OMP_CLAUSE_CREATE)
    3018          328 :               && gfc_match ("create ( ") == MATCH_YES
    3019          651 :               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
    3020              :                                            OMP_MAP_ALLOC, true, allow_derived))
    3021          321 :             continue;
    3022              :           break;
    3023         4190 :         case 'd':
    3024         4190 :           if ((mask & OMP_CLAUSE_DEFAULTMAP)
    3025         4190 :               && gfc_match ("defaultmap ( ") == MATCH_YES)
    3026              :             {
    3027          181 :               enum gfc_omp_defaultmap behavior;
    3028          181 :               gfc_omp_defaultmap_category category
    3029              :                 = OMP_DEFAULTMAP_CAT_UNCATEGORIZED;
    3030          181 :               if (gfc_match ("alloc ") == MATCH_YES)
    3031              :                 behavior = OMP_DEFAULTMAP_ALLOC;
    3032          175 :               else if (gfc_match ("tofrom ") == MATCH_YES)
    3033              :                 behavior = OMP_DEFAULTMAP_TOFROM;
    3034          143 :               else if (gfc_match ("to ") == MATCH_YES)
    3035              :                 behavior = OMP_DEFAULTMAP_TO;
    3036          133 :               else if (gfc_match ("from ") == MATCH_YES)
    3037              :                 behavior = OMP_DEFAULTMAP_FROM;
    3038          130 :               else if (gfc_match ("firstprivate ") == MATCH_YES)
    3039              :                 behavior = OMP_DEFAULTMAP_FIRSTPRIVATE;
    3040           95 :               else if (gfc_match ("present ") == MATCH_YES)
    3041              :                 behavior = OMP_DEFAULTMAP_PRESENT;
    3042           91 :               else if (gfc_match ("none ") == MATCH_YES)
    3043              :                 behavior = OMP_DEFAULTMAP_NONE;
    3044           10 :               else if (gfc_match ("default ") == MATCH_YES)
    3045              :                 behavior = OMP_DEFAULTMAP_DEFAULT;
    3046              :               else
    3047              :                 {
    3048            1 :                   gfc_error ("Expected ALLOC, TO, FROM, TOFROM, FIRSTPRIVATE, "
    3049              :                              "PRESENT, NONE or DEFAULT at %C");
    3050            1 :                   break;
    3051              :                 }
    3052          180 :               if (')' == gfc_peek_ascii_char ())
    3053              :                 ;
    3054          102 :               else if (gfc_match (": ") != MATCH_YES)
    3055              :                 break;
    3056              :               else
    3057              :                 {
    3058          102 :                   if (gfc_match ("scalar ") == MATCH_YES)
    3059              :                     category = OMP_DEFAULTMAP_CAT_SCALAR;
    3060           67 :                   else if (gfc_match ("aggregate ") == MATCH_YES)
    3061              :                     category = OMP_DEFAULTMAP_CAT_AGGREGATE;
    3062           43 :                   else if (gfc_match ("allocatable ") == MATCH_YES)
    3063              :                     category = OMP_DEFAULTMAP_CAT_ALLOCATABLE;
    3064           31 :                   else if (gfc_match ("pointer ") == MATCH_YES)
    3065              :                     category = OMP_DEFAULTMAP_CAT_POINTER;
    3066           14 :                   else if (gfc_match ("all ") == MATCH_YES)
    3067              :                     category = OMP_DEFAULTMAP_CAT_ALL;
    3068              :                   else
    3069              :                     {
    3070            1 :                       gfc_error ("Expected SCALAR, AGGREGATE, ALLOCATABLE, "
    3071              :                                  "POINTER or ALL at %C");
    3072            1 :                       break;
    3073              :                     }
    3074              :                 }
    3075         1200 :               for (int i = 0; i < OMP_DEFAULTMAP_CAT_NUM; ++i)
    3076              :                 {
    3077         1034 :                   if (i != category
    3078         1034 :                       && category != OMP_DEFAULTMAP_CAT_UNCATEGORIZED
    3079          486 :                       && category != OMP_DEFAULTMAP_CAT_ALL
    3080          486 :                       && i != OMP_DEFAULTMAP_CAT_UNCATEGORIZED
    3081          341 :                       && i != OMP_DEFAULTMAP_CAT_ALL)
    3082          254 :                     continue;
    3083          780 :                   if (c->defaultmap[i] != OMP_DEFAULTMAP_UNSET)
    3084              :                     {
    3085           13 :                       const char *pcategory = NULL;
    3086           13 :                       switch (i)
    3087              :                         {
    3088              :                         case OMP_DEFAULTMAP_CAT_UNCATEGORIZED: break;
    3089            3 :                         case OMP_DEFAULTMAP_CAT_ALL: pcategory = "ALL"; break;
    3090            1 :                         case OMP_DEFAULTMAP_CAT_SCALAR: pcategory = "SCALAR"; break;
    3091            2 :                         case OMP_DEFAULTMAP_CAT_AGGREGATE:
    3092            2 :                           pcategory = "AGGREGATE";
    3093            2 :                           break;
    3094            1 :                         case OMP_DEFAULTMAP_CAT_ALLOCATABLE:
    3095            1 :                           pcategory = "ALLOCATABLE";
    3096            1 :                           break;
    3097              :                         case OMP_DEFAULTMAP_CAT_POINTER:
    3098              :                           pcategory = "POINTER";
    3099              :                           break;
    3100            0 :                         default: gcc_unreachable ();
    3101              :                         }
    3102            7 :                      if (i == OMP_DEFAULTMAP_CAT_UNCATEGORIZED)
    3103            4 :                       gfc_error ("DEFAULTMAP at %C but prior DEFAULTMAP with "
    3104              :                                  "unspecified category");
    3105              :                      else
    3106            9 :                       gfc_error ("DEFAULTMAP at %C but prior DEFAULTMAP for "
    3107              :                                  "category %s", pcategory);
    3108           13 :                      goto error;
    3109              :                     }
    3110              :                 }
    3111          166 :               c->defaultmap[category] = behavior;
    3112          166 :               if (gfc_match (")") != MATCH_YES)
    3113              :                 break;
    3114          166 :               continue;
    3115          166 :             }
    3116         4976 :           if ((mask & OMP_CLAUSE_DEFAULT)
    3117         4009 :               && (m = gfc_match_dupl_check (c->default_sharing
    3118              :                                             == OMP_DEFAULT_UNKNOWN, "default",
    3119              :                                             true)) != MATCH_NO)
    3120              :             {
    3121         1012 :               if (m == MATCH_ERROR)
    3122            6 :                 goto error;
    3123         1006 :               if (gfc_match ("none") == MATCH_YES)
    3124          596 :                 c->default_sharing = OMP_DEFAULT_NONE;
    3125          410 :               else if (openacc)
    3126              :                 {
    3127          225 :                   if (gfc_match ("present") == MATCH_YES)
    3128          195 :                     c->default_sharing = OMP_DEFAULT_PRESENT;
    3129              :                 }
    3130              :               else
    3131              :                 {
    3132          185 :                   if (gfc_match ("firstprivate") == MATCH_YES)
    3133            8 :                     c->default_sharing = OMP_DEFAULT_FIRSTPRIVATE;
    3134          177 :                   else if (gfc_match ("private") == MATCH_YES)
    3135           24 :                     c->default_sharing = OMP_DEFAULT_PRIVATE;
    3136          153 :                   else if (gfc_match ("shared") == MATCH_YES)
    3137          153 :                     c->default_sharing = OMP_DEFAULT_SHARED;
    3138              :                 }
    3139         1006 :               if (c->default_sharing == OMP_DEFAULT_UNKNOWN)
    3140              :                 {
    3141           30 :                   if (openacc)
    3142           30 :                     gfc_error ("Expected NONE or PRESENT in DEFAULT clause "
    3143              :                                "at %C");
    3144              :                   else
    3145            0 :                     gfc_error ("Expected NONE, FIRSTPRIVATE, PRIVATE or SHARED "
    3146              :                                "in DEFAULT clause at %C");
    3147           30 :                   goto error;
    3148              :                 }
    3149          976 :               if (gfc_match (" )") != MATCH_YES)
    3150            9 :                 goto error;
    3151          967 :               continue;
    3152              :             }
    3153         3305 :           if ((mask & OMP_CLAUSE_DELETE)
    3154          345 :               && gfc_match ("delete ( ") == MATCH_YES
    3155         3305 :               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
    3156              :                                            OMP_MAP_RELEASE, true,
    3157              :                                            allow_derived))
    3158          308 :             continue;
    3159              :           /* DOACROSS: match 'doacross' and 'depend' with sink/source.
    3160              :              DEPEND: match 'depend' but not sink/source.  */
    3161         2689 :           m = MATCH_NO;
    3162         2689 :           if (((mask & OMP_CLAUSE_DOACROSS)
    3163          383 :                && gfc_match ("doacross ( ") == MATCH_YES)
    3164         3045 :               || (((mask & OMP_CLAUSE_DEPEND) || (mask & OMP_CLAUSE_DOACROSS))
    3165         1601 :                   && (m = gfc_match ("depend ( ")) == MATCH_YES))
    3166              :             {
    3167         1101 :               bool has_omp_all_memory;
    3168         1101 :               bool is_depend = m == MATCH_YES;
    3169         1101 :               gfc_namespace *ns_iter = NULL, *ns_curr = gfc_current_ns;
    3170         1101 :               match m_it = MATCH_NO;
    3171         1101 :               if (is_depend)
    3172         1074 :                 m_it = gfc_match_iterator (&ns_iter, false);
    3173         1074 :               if (m_it == MATCH_ERROR)
    3174              :                 break;
    3175         1096 :               if (m_it == MATCH_YES && gfc_match (" , ") != MATCH_YES)
    3176              :                 break;
    3177         1096 :               m = MATCH_YES;
    3178         1096 :               gfc_omp_depend_doacross_op depend_op = OMP_DEPEND_OUT;
    3179         1096 :               if (gfc_match ("inoutset") == MATCH_YES)
    3180              :                 depend_op = OMP_DEPEND_INOUTSET;
    3181         1084 :               else if (gfc_match ("inout") == MATCH_YES)
    3182              :                 depend_op = OMP_DEPEND_INOUT;
    3183          992 :               else if (gfc_match ("in") == MATCH_YES)
    3184              :                 depend_op = OMP_DEPEND_IN;
    3185          704 :               else if (gfc_match ("out") == MATCH_YES)
    3186              :                 depend_op = OMP_DEPEND_OUT;
    3187          442 :               else if (gfc_match ("mutexinoutset") == MATCH_YES)
    3188              :                 depend_op = OMP_DEPEND_MUTEXINOUTSET;
    3189          424 :               else if (gfc_match ("depobj") == MATCH_YES)
    3190              :                 depend_op = OMP_DEPEND_DEPOBJ;
    3191          387 :               else if (gfc_match ("source") == MATCH_YES)
    3192              :                 {
    3193          143 :                   if (m_it == MATCH_YES)
    3194              :                     {
    3195            1 :                       gfc_error ("ITERATOR may not be combined with SOURCE "
    3196              :                                  "at %C");
    3197           17 :                       goto error;
    3198              :                     }
    3199          142 :                   if (!(mask & OMP_CLAUSE_DOACROSS))
    3200              :                     {
    3201            1 :                       gfc_error ("SOURCE at %C not permitted as dependence-type"
    3202              :                                  " for this directive");
    3203            1 :                       goto error;
    3204              :                     }
    3205          141 :                   if (c->doacross_source)
    3206              :                     {
    3207            0 :                       gfc_error ("Duplicated clause with SOURCE dependence-type"
    3208              :                                  " at %C");
    3209            0 :                       goto error;
    3210              :                     }
    3211          141 :                   gfc_gobble_whitespace ();
    3212          141 :                   m = gfc_match (": ");
    3213          141 :                   if (m != MATCH_YES && !is_depend)
    3214              :                     {
    3215            1 :                       gfc_error ("Expected %<:%> at %C");
    3216            1 :                       goto error;
    3217              :                     }
    3218          140 :                   if (gfc_match (")") != MATCH_YES
    3219          146 :                       && !(m == MATCH_YES
    3220            6 :                            && gfc_match ("omp_cur_iteration )") == MATCH_YES))
    3221              :                     {
    3222            2 :                       gfc_error ("Expected %<)%> or %<omp_cur_iteration)%> "
    3223              :                                  "at %C");
    3224            2 :                       goto error;
    3225              :                     }
    3226          138 :                   if (is_depend)
    3227          130 :                     gfc_warning (OPT_Wdeprecated_openmp,
    3228              :                                  "%<source%> modifier with %<depend%> clause "
    3229              :                                  "at %L deprecated since OpenMP 5.2, use with "
    3230              :                                  "%<doacross%>", &old_loc);
    3231          138 :                   c->doacross_source = true;
    3232          138 :                   c->depend_source = is_depend;
    3233         1079 :                   continue;
    3234              :                 }
    3235          244 :               else if (gfc_match ("sink ") == MATCH_YES)
    3236              :                 {
    3237          244 :                   if (!(mask & OMP_CLAUSE_DOACROSS))
    3238              :                     {
    3239            2 :                       gfc_error ("SINK at %C not permitted as dependence-type "
    3240              :                                  "for this directive");
    3241            2 :                       goto error;
    3242              :                     }
    3243          242 :                   if (gfc_match (": ") != MATCH_YES)
    3244              :                     {
    3245            1 :                       gfc_error ("Expected %<:%> at %C");
    3246            1 :                       goto error;
    3247              :                     }
    3248          241 :                   if (m_it == MATCH_YES)
    3249              :                     {
    3250            0 :                       gfc_error ("ITERATOR may not be combined with SINK "
    3251              :                                  "at %C");
    3252            0 :                       goto error;
    3253              :                     }
    3254          241 :                   if (is_depend)
    3255          226 :                     gfc_warning (OPT_Wdeprecated_openmp,
    3256              :                                  "%<sink%> modifier with %<depend%> clause at "
    3257              :                                  "%L deprecated since OpenMP 5.2, use with "
    3258              :                                  "%<doacross%>", &old_loc);
    3259          241 :                   m = gfc_match_omp_doacross_sink (&c->lists[OMP_LIST_DEPEND],
    3260              :                                                    is_depend);
    3261          241 :                   if (m == MATCH_YES)
    3262          238 :                     continue;
    3263            3 :                   goto error;
    3264              :                 }
    3265              :               else
    3266              :                 m = MATCH_NO;
    3267          709 :               if (!(mask & OMP_CLAUSE_DEPEND))
    3268              :                 {
    3269            0 :                   gfc_error ("Expected dependence-type SINK or SOURCE at %C");
    3270            0 :                   goto error;
    3271              :                 }
    3272          709 :               head = NULL;
    3273          709 :               if (ns_iter)
    3274           40 :                 gfc_current_ns = ns_iter;
    3275          709 :               if (m == MATCH_YES)
    3276          709 :                 m = gfc_match_omp_variable_list (" : ",
    3277              :                                                  &c->lists[OMP_LIST_DEPEND],
    3278              :                                                  false, NULL, &head, true,
    3279              :                                                  false, &has_omp_all_memory);
    3280          709 :               if (m != MATCH_YES)
    3281            2 :                 goto error;
    3282          707 :               gfc_current_ns = ns_curr;
    3283          707 :               if (has_omp_all_memory && depend_op != OMP_DEPEND_INOUT
    3284           21 :                   && depend_op != OMP_DEPEND_OUT)
    3285              :                 {
    3286            4 :                   gfc_error ("%<omp_all_memory%> used with DEPEND kind "
    3287              :                              "other than OUT or INOUT at %C");
    3288            4 :                   goto error;
    3289              :                 }
    3290          703 :               gfc_omp_namelist *n;
    3291         1437 :               for (n = *head; n; n = n->next)
    3292              :                 {
    3293          734 :                   n->u.depend_doacross_op = depend_op;
    3294          734 :                   n->u2.ns = ns_iter;
    3295          734 :                   if (ns_iter)
    3296           39 :                     ns_iter->refs++;
    3297              :                 }
    3298          703 :               continue;
    3299          703 :             }
    3300         1609 :           if ((mask & OMP_CLAUSE_DESTROY)
    3301         1588 :               && gfc_match_omp_variable_list ("destroy (",
    3302              :                                               &c->lists[OMP_LIST_DESTROY],
    3303              :                                               true) == MATCH_YES)
    3304           21 :             continue;
    3305         1693 :           if ((mask & OMP_CLAUSE_DETACH)
    3306          164 :               && !openacc
    3307          127 :               && !c->detach
    3308         1693 :               && gfc_match_omp_detach (&c->detach) == MATCH_YES)
    3309          126 :             continue;
    3310         1478 :           if ((mask & OMP_CLAUSE_DETACH)
    3311           38 :               && openacc
    3312           37 :               && gfc_match ("detach ( ") == MATCH_YES
    3313         1478 :               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
    3314              :                                            OMP_MAP_DETACH, false,
    3315              :                                            allow_derived))
    3316           37 :             continue;
    3317         1440 :           if ((mask & OMP_CLAUSE_DEVICEPTR)
    3318           87 :               && gfc_match ("deviceptr ( ") == MATCH_YES
    3319         1442 :               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
    3320              :                                            OMP_MAP_FORCE_DEVICEPTR, false,
    3321              :                                            allow_derived))
    3322           36 :             continue;
    3323          823 :           if ((mask & OMP_CLAUSE_DEVICE_TYPE) && openacc
    3324          444 :               && gfc_match_dupl_check (!c->oacc_device_type_present,
    3325              :                                        "device_type", true) == MATCH_YES
    3326         1700 :               && match_oacc_device_type (c) == MATCH_YES)
    3327          326 :             continue;
    3328          497 :           if ((mask & OMP_CLAUSE_DEVICE_TYPE) && !openacc
    3329         1421 :               && gfc_match_dupl_check (c->device_type == OMP_DEVICE_TYPE_UNSET,
    3330              :                                        "device_type", true) == MATCH_YES)
    3331              :             {
    3332           95 :               if (gfc_match ("host") == MATCH_YES)
    3333           32 :                 c->device_type = OMP_DEVICE_TYPE_HOST;
    3334           63 :               else if (gfc_match ("nohost") == MATCH_YES)
    3335           24 :                 c->device_type = OMP_DEVICE_TYPE_NOHOST;
    3336           39 :               else if (gfc_match ("any") == MATCH_YES)
    3337           38 :                 c->device_type = OMP_DEVICE_TYPE_ANY;
    3338              :               else
    3339              :                 {
    3340            1 :                   gfc_error ("Expected HOST, NOHOST or ANY at %C");
    3341            1 :                   break;
    3342              :                 }
    3343           94 :               if (gfc_match (" )") != MATCH_YES)
    3344              :                 break;
    3345           94 :               continue;
    3346              :             }
    3347         1054 :           if ((mask & OMP_CLAUSE_DEVICE_NUM)
    3348          947 :               && (m = gfc_match_dupl_check (!c->device_num_expr,
    3349              :                                             "device_num")) != MATCH_NO)
    3350              :             {
    3351          109 :               if (m == MATCH_ERROR)
    3352            2 :                 goto error;
    3353          107 :               if (gfc_match ("( %e )", &c->device_num_expr) != MATCH_YES)
    3354            0 :                 goto error;
    3355          107 :               continue;
    3356              :             }
    3357          886 :           if ((mask & OMP_CLAUSE_DEVICE_RESIDENT)
    3358          887 :               && gfc_match_omp_variable_list
    3359           49 :                    ("device_resident (",
    3360              :                     &c->lists[OMP_LIST_DEVICE_RESIDENT], true) == MATCH_YES)
    3361           48 :             continue;
    3362         1102 :           if ((mask & OMP_CLAUSE_DEVICE)
    3363          705 :               && openacc
    3364          314 :               && gfc_match ("device ( ") == MATCH_YES
    3365         1103 :               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
    3366              :                                            OMP_MAP_FORCE_TO, true,
    3367              :                                            /* allow_derived = */ true))
    3368          312 :             continue;
    3369          478 :           if ((mask & OMP_CLAUSE_DEVICE)
    3370          393 :               && !openacc
    3371          869 :               && ((m = gfc_match_dupl_check (!c->device, "device", true))
    3372              :                   != MATCH_NO))
    3373              :             {
    3374          351 :               if (m == MATCH_ERROR)
    3375            0 :                 goto error;
    3376          351 :               c->ancestor = false;
    3377          351 :               if (gfc_match ("device_num : ") == MATCH_YES)
    3378              :                 {
    3379           18 :                   if (gfc_match ("%e )", &c->device) != MATCH_YES)
    3380              :                     {
    3381            1 :                       gfc_error ("Expected integer expression at %C");
    3382            1 :                       break;
    3383              :                     }
    3384              :                 }
    3385          333 :               else if (gfc_match ("ancestor : ") == MATCH_YES)
    3386              :                 {
    3387           45 :                   bool has_requires = false;
    3388           45 :                   c->ancestor = true;
    3389           82 :                   for (gfc_namespace *ns = gfc_current_ns; ns; ns = ns->parent)
    3390           80 :                     if (ns->omp_requires & OMP_REQ_REVERSE_OFFLOAD)
    3391              :                       {
    3392              :                         has_requires = true;
    3393              :                         break;
    3394              :                       }
    3395           45 :                   if (!has_requires)
    3396              :                     {
    3397            2 :                       gfc_error ("%<ancestor%> device modifier not "
    3398              :                                  "preceded by %<requires%> directive "
    3399              :                                  "with %<reverse_offload%> clause at %C");
    3400            5 :                       break;
    3401              :                     }
    3402           43 :                   locus old_loc2 = gfc_current_locus;
    3403           43 :                   if (gfc_match ("%e )", &c->device) == MATCH_YES)
    3404              :                     {
    3405           43 :                       int device = 0;
    3406           43 :                       if (!gfc_extract_int (c->device, &device) && device != 1)
    3407              :                       {
    3408            1 :                         gfc_current_locus = old_loc2;
    3409            1 :                         gfc_error ("the %<device%> clause expression must "
    3410              :                                    "evaluate to %<1%> at %C");
    3411            1 :                         break;
    3412              :                       }
    3413              :                     }
    3414              :                   else
    3415              :                     {
    3416            0 :                       gfc_error ("Expected integer expression at %C");
    3417            0 :                       break;
    3418              :                     }
    3419              :                 }
    3420          288 :               else if (gfc_match ("%e )", &c->device) != MATCH_YES)
    3421              :                 {
    3422           13 :                   gfc_error ("Expected integer expression or a single device-"
    3423              :                               "modifier %<device_num%> or %<ancestor%> at %C");
    3424           13 :                   break;
    3425              :                 }
    3426          334 :               continue;
    3427          334 :             }
    3428          127 :           if ((mask & OMP_CLAUSE_DIST_SCHEDULE)
    3429           97 :               && c->dist_sched_kind == OMP_SCHED_NONE
    3430          224 :               && gfc_match ("dist_schedule ( static") == MATCH_YES)
    3431              :             {
    3432           97 :               m = MATCH_NO;
    3433           97 :               c->dist_sched_kind = OMP_SCHED_STATIC;
    3434           97 :               m = gfc_match (" , %e )", &c->dist_chunk_size);
    3435           97 :               if (m != MATCH_YES)
    3436           14 :                 m = gfc_match_char (')');
    3437           14 :               if (m != MATCH_YES)
    3438              :                 {
    3439            0 :                   c->dist_sched_kind = OMP_SCHED_NONE;
    3440            0 :                   gfc_current_locus = old_loc;
    3441              :                 }
    3442              :               else
    3443           97 :                 continue;
    3444              :             }
    3445           41 :           if ((mask & OMP_CLAUSE_DYN_GROUPPRIVATE)
    3446           30 :               && gfc_match_dupl_check (!c->dyn_groupprivate,
    3447              :                                        "dyn_groupprivate", true) == MATCH_YES)
    3448              :             {
    3449           12 :               if (gfc_match ("fallback ( abort ) : ") == MATCH_YES)
    3450            1 :                 c->fallback = OMP_FALLBACK_ABORT;
    3451           11 :               else if (gfc_match ("fallback ( default_mem ) : ") == MATCH_YES)
    3452            1 :                 c->fallback = OMP_FALLBACK_DEFAULT_MEM;
    3453           10 :               else if (gfc_match ("fallback ( null ) : ") == MATCH_YES)
    3454            1 :                 c->fallback = OMP_FALLBACK_NULL;
    3455           12 :               if (gfc_match_expr (&c->dyn_groupprivate) != MATCH_YES)
    3456            0 :                 return MATCH_ERROR;
    3457           12 :               if (gfc_match (" )") != MATCH_YES)
    3458            1 :                 goto error;
    3459           11 :               continue;
    3460              :             }
    3461              :           break;
    3462           98 :         case 'e':
    3463           98 :           if ((mask & OMP_CLAUSE_ENTER))
    3464              :             {
    3465           98 :               m = gfc_match_omp_to_link ("enter (", &c->lists[OMP_LIST_ENTER]);
    3466           98 :               if (m == MATCH_ERROR)
    3467            0 :                 goto error;
    3468           98 :               if (m == MATCH_YES)
    3469           98 :                 continue;
    3470              :             }
    3471              :           break;
    3472         2326 :         case 'f':
    3473         2375 :           if ((mask & OMP_CLAUSE_FAIL)
    3474         2326 :               && (m = gfc_match_dupl_check (c->fail == OMP_MEMORDER_UNSET,
    3475              :                                             "fail", true)) != MATCH_NO)
    3476              :             {
    3477           58 :               if (m == MATCH_ERROR)
    3478            3 :                 goto error;
    3479           55 :               if (gfc_match ("seq_cst") == MATCH_YES)
    3480            6 :                 c->fail = OMP_MEMORDER_SEQ_CST;
    3481           49 :               else if (gfc_match ("acquire") == MATCH_YES)
    3482           14 :                 c->fail = OMP_MEMORDER_ACQUIRE;
    3483           35 :               else if (gfc_match ("relaxed") == MATCH_YES)
    3484           30 :                 c->fail = OMP_MEMORDER_RELAXED;
    3485              :               else
    3486              :                 {
    3487            5 :                   gfc_error ("Expected SEQ_CST, ACQUIRE or RELAXED at %C");
    3488            5 :                   break;
    3489              :                 }
    3490           50 :               if (gfc_match (" )") != MATCH_YES)
    3491            1 :                 goto error;
    3492           49 :               continue;
    3493              :             }
    3494         2311 :           if ((mask & OMP_CLAUSE_FILTER)
    3495         2268 :               && (m = gfc_match_dupl_check (!c->filter, "filter", true,
    3496              :                                             &c->filter)) != MATCH_NO)
    3497              :             {
    3498           44 :               if (m == MATCH_ERROR)
    3499            1 :                 goto error;
    3500           43 :               continue;
    3501              :             }
    3502         2288 :           if ((mask & OMP_CLAUSE_FINAL)
    3503         2224 :               && (m = gfc_match_dupl_check (!c->final_expr, "final", true,
    3504              :                                             &c->final_expr)) != MATCH_NO)
    3505              :             {
    3506           64 :               if (m == MATCH_ERROR)
    3507            0 :                 goto error;
    3508           64 :               continue;
    3509              :             }
    3510         2186 :           if ((mask & OMP_CLAUSE_FINALIZE)
    3511         2160 :               && (m = gfc_match_dupl_check (!c->finalize, "finalize"))
    3512              :                  != MATCH_NO)
    3513              :             {
    3514           26 :               if (m == MATCH_ERROR)
    3515            0 :                 goto error;
    3516           26 :               c->finalize = true;
    3517           26 :               continue;
    3518              :             }
    3519         3176 :           if ((mask & OMP_CLAUSE_FIRSTPRIVATE)
    3520         2134 :               && gfc_match_omp_variable_list ("firstprivate (",
    3521              :                                               &c->lists[OMP_LIST_FIRSTPRIVATE],
    3522              :                                               true) == MATCH_YES)
    3523         1042 :             continue;
    3524         2095 :           if ((mask & OMP_CLAUSE_FROM)
    3525         1092 :               && gfc_match_motion_var_list ("from (", &c->lists[OMP_LIST_FROM],
    3526              :                                              &head) == MATCH_YES)
    3527         1003 :             continue;
    3528          158 :           if ((mask & OMP_CLAUSE_FULL)
    3529          165 :               && (m = gfc_match_boolean_clause (&bval, "full",
    3530           76 :                          c->full || cfalse->full)) != MATCH_NO)
    3531              :             {
    3532           76 :               if (m == MATCH_ERROR)
    3533            7 :                 goto error;
    3534           69 :               if (bval)
    3535           68 :                 c->full = true;
    3536              :               else
    3537            1 :                 cfalse->full = true;
    3538           69 :               continue;
    3539              :             }
    3540              :           break;
    3541         1231 :         case 'g':
    3542         2423 :           if ((mask & OMP_CLAUSE_GANG)
    3543         1231 :               && (m = gfc_match_dupl_check (!c->gang, "gang")) != MATCH_NO)
    3544              :             {
    3545         1197 :               if (m == MATCH_ERROR)
    3546            0 :                 goto error;
    3547         1197 :               c->gang = true;
    3548         1197 :               m = match_oacc_clause_gwv (c, GOMP_DIM_GANG);
    3549         1197 :               if (m == MATCH_ERROR)
    3550              :                 {
    3551            5 :                   gfc_current_locus = old_loc;
    3552            5 :                   break;
    3553              :                 }
    3554         1192 :               continue;
    3555              :             }
    3556           68 :           if ((mask & OMP_CLAUSE_GRAINSIZE)
    3557           34 :               && (m = gfc_match_dupl_check (!c->grainsize, "grainsize", true))
    3558              :                  != MATCH_NO)
    3559              :             {
    3560           34 :               if (m == MATCH_ERROR)
    3561            0 :                 goto error;
    3562           34 :               if (gfc_match ("strict : ") == MATCH_YES)
    3563            1 :                 c->grainsize_strict = true;
    3564           34 :               if (gfc_match (" %e )", &c->grainsize) != MATCH_YES)
    3565            0 :                 goto error;
    3566           34 :               continue;
    3567              :             }
    3568              :           break;
    3569          474 :         case 'h':
    3570          523 :           if ((mask & OMP_CLAUSE_HAS_DEVICE_ADDR)
    3571          523 :               && gfc_match_omp_variable_list
    3572           49 :                    ("has_device_addr (", &c->lists[OMP_LIST_HAS_DEVICE_ADDR],
    3573              :                     false, NULL, NULL, true) == MATCH_YES)
    3574           49 :             continue;
    3575          473 :           if ((mask & OMP_CLAUSE_HINT)
    3576          425 :               && (m = gfc_match_dupl_check (!c->hint, "hint", true, &c->hint))
    3577              :                  != MATCH_NO)
    3578              :             {
    3579           48 :               if (m == MATCH_ERROR)
    3580            0 :                 goto error;
    3581           48 :               continue;
    3582              :             }
    3583          377 :           if ((mask & OMP_CLAUSE_ASSUMPTIONS)
    3584          377 :               && gfc_match ("holds ( ") == MATCH_YES)
    3585              :             {
    3586           22 :               gfc_expr *e;
    3587           22 :               if (gfc_match ("%e )", &e) != MATCH_YES)
    3588            0 :                 goto error;
    3589           22 :               if (c->assume == NULL)
    3590           15 :                 c->assume = gfc_get_omp_assumptions ();
    3591           22 :               gfc_expr_list *el = XCNEW (gfc_expr_list);
    3592           22 :               el->expr = e;
    3593           22 :               el->next = c->assume->holds;
    3594           22 :               c->assume->holds = el;
    3595           22 :               continue;
    3596           22 :             }
    3597          709 :           if ((mask & OMP_CLAUSE_HOST)
    3598          355 :               && gfc_match ("host ( ") == MATCH_YES
    3599          710 :               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
    3600              :                                            OMP_MAP_FORCE_FROM, true,
    3601              :                                            /* allow_derived = */ true))
    3602          354 :             continue;
    3603              :           break;
    3604         2251 :         case 'i':
    3605         2274 :           if ((mask & OMP_CLAUSE_IF_PRESENT)
    3606         2251 :               && (m = gfc_match_dupl_check (!c->if_present, "if_present"))
    3607              :                  != MATCH_NO)
    3608              :             {
    3609           23 :               if (m == MATCH_ERROR)
    3610            0 :                 goto error;
    3611           23 :               c->if_present = true;
    3612           23 :               continue;
    3613              :             }
    3614         2228 :           if ((mask & OMP_CLAUSE_IF)
    3615         2228 :               && (m = gfc_match_dupl_check (!c->if_expr, "if", true))
    3616              :                  != MATCH_NO)
    3617              :             {
    3618         1470 :               if (m == MATCH_ERROR)
    3619           14 :                 goto error;
    3620         1456 :               if (!openacc)
    3621              :                 {
    3622              :                   /* This should match the enum gfc_omp_if_kind order.  */
    3623              :                   static const char *ifs[OMP_IF_LAST] = {
    3624              :                     "cancel : %e )",
    3625              :                     "parallel : %e )",
    3626              :                     "simd : %e )",
    3627              :                     "task : %e )",
    3628              :                     "taskloop : %e )",
    3629              :                     "target : %e )",
    3630              :                     "target data : %e )",
    3631              :                     "target update : %e )",
    3632              :                     "target enter data : %e )",
    3633              :                     "target exit data : %e )" };
    3634              :                   static const char *ifs2[] = {
    3635              :                     "target_data : %e )",
    3636              :                     "target_update : %e )",
    3637              :                     "target_enter_data : %e )",
    3638              :                     "target_exit_data : %e )" };
    3639              :                   int i;
    3640         4951 :                   for (i = 0; i < OMP_IF_LAST; i++)
    3641         4543 :                     if (c->if_exprs[i] == NULL
    3642         4543 :                         && gfc_match (ifs[i], &c->if_exprs[i]) == MATCH_YES)
    3643              :                       break;
    3644          546 :                   if (i < OMP_IF_LAST)
    3645          138 :                     continue;
    3646         2030 :                   for (i = 0; i < (int) ARRAY_SIZE (ifs2); i++)
    3647         1626 :                     if (c->if_exprs[OMP_IF_TARGET_DATA + i] == NULL
    3648         1626 :                         && (gfc_match (ifs2[i],
    3649              :                                       &c->if_exprs[OMP_IF_TARGET_DATA + i])
    3650              :                             == MATCH_YES))
    3651              :                       break;
    3652          408 :                   if (i < (int) ARRAY_SIZE (ifs2))
    3653            4 :                     continue;
    3654              :                 }
    3655         1314 :               if (gfc_match (" %e )", &c->if_expr) == MATCH_YES)
    3656         1309 :                 continue;
    3657            5 :               goto error;
    3658              :             }
    3659          875 :           if ((mask & OMP_CLAUSE_IN_REDUCTION)
    3660          758 :               && gfc_match_omp_clause_reduction (pc, c, openacc, allow_derived,
    3661              :                                                  openmp_target) == MATCH_YES)
    3662          117 :             continue;
    3663          668 :           if ((mask & OMP_CLAUSE_INBRANCH)
    3664          670 :               && (m = gfc_match_dupl_branch_clause (&bval, "inbranch",
    3665           29 :                         c->notinbranch || cfalse->notinbranch
    3666           27 :                         || c->inbranch || cfalse->inbranch)) != MATCH_NO)
    3667              :             {
    3668           29 :               if (m == MATCH_ERROR)
    3669            2 :                 goto error;
    3670           27 :               if (bval)
    3671           25 :                 c->inbranch = true;
    3672              :               else
    3673            2 :                 cfalse->inbranch = true;
    3674           27 :               continue;
    3675              :             }
    3676          854 :           if ((mask & OMP_CLAUSE_INDEPENDENT)
    3677          612 :               && (m = gfc_match_dupl_check (!c->independent, "independent"))
    3678              :                  != MATCH_NO)
    3679              :             {
    3680          242 :               if (m == MATCH_ERROR)
    3681            0 :                 goto error;
    3682          242 :               c->independent = true;
    3683          242 :               continue;
    3684              :             }
    3685          426 :           if ((mask & OMP_CLAUSE_INDIRECT)
    3686          431 :               && (m = gfc_match_boolean_clause (&bval, "indirect",
    3687           61 :                          c->indirect || cfalse->indirect)) != MATCH_NO)
    3688              :             {
    3689           61 :               if (m == MATCH_ERROR)
    3690            5 :                 goto error;
    3691           56 :               if (bval)
    3692           51 :                 c->indirect = true;
    3693              :               else
    3694            5 :                 cfalse->indirect = true;
    3695           56 :               continue;
    3696              :             }
    3697          309 :           if ((mask & OMP_CLAUSE_INIT)
    3698          309 :               && gfc_match ("init ( ") == MATCH_YES)
    3699              :             {
    3700          108 :               m = gfc_match_omp_init (&c->lists[OMP_LIST_INIT]);
    3701          108 :               if (m == MATCH_YES)
    3702           63 :                 continue;
    3703           45 :               goto error;
    3704              :             }
    3705          201 :           if ((mask & OMP_CLAUSE_INTEROP)
    3706          201 :               && (m = gfc_match_dupl_check (!c->lists[OMP_LIST_INTEROP],
    3707              :                                             "interop", true)) != MATCH_NO)
    3708              :             {
    3709              :               /* Note: the interop objects are saved in reverse order to match
    3710              :                  the order in C/C++.  */
    3711          125 :               if (m == MATCH_YES
    3712           63 :                   && (gfc_match_omp_variable_list ("",
    3713              :                                                    &c->lists[OMP_LIST_INTEROP],
    3714              :                                                    false, NULL, NULL, false,
    3715              :                                                    false, NULL, false, true)
    3716              :                       == MATCH_YES))
    3717           62 :                 continue;
    3718            1 :               goto error;
    3719              :             }
    3720          258 :           if ((mask & OMP_CLAUSE_IS_DEVICE_PTR)
    3721          258 :               && gfc_match_omp_variable_list
    3722          120 :                    ("is_device_ptr (",
    3723              :                     &c->lists[OMP_LIST_IS_DEVICE_PTR], false) == MATCH_YES)
    3724          120 :             continue;
    3725              :           break;
    3726         2360 :         case 'l':
    3727         2360 :           if ((mask & OMP_CLAUSE_LASTPRIVATE)
    3728         2360 :               && gfc_match ("lastprivate ( ") == MATCH_YES)
    3729              :             {
    3730         1433 :               bool conditional = gfc_match ("conditional : ") == MATCH_YES;
    3731         1433 :               head = NULL;
    3732         1433 :               if (gfc_match_omp_variable_list ("",
    3733              :                                                &c->lists[OMP_LIST_LASTPRIVATE],
    3734              :                                                false, NULL, &head) == MATCH_YES)
    3735              :                 {
    3736         1433 :                   gfc_omp_namelist *n;
    3737         3741 :                   for (n = *head; n; n = n->next)
    3738         2308 :                     n->u.lastprivate_conditional = conditional;
    3739         1433 :                   continue;
    3740         1433 :                 }
    3741            0 :               gfc_current_locus = old_loc;
    3742            0 :               break;
    3743              :             }
    3744          927 :           end_colon = false;
    3745          927 :           head = NULL;
    3746          927 :           if ((mask & OMP_CLAUSE_LINEAR)
    3747          927 :               && gfc_match ("linear (") == MATCH_YES)
    3748              :             {
    3749          849 :               bool old_linear_modifier = false;
    3750          849 :               gfc_omp_linear_op linear_op = OMP_LINEAR_DEFAULT;
    3751          849 :               gfc_expr *step = NULL;
    3752          849 :               locus saved_loc = gfc_current_locus;
    3753              : 
    3754          849 :               if (gfc_match_omp_variable_list (" ref (",
    3755              :                                                &c->lists[OMP_LIST_LINEAR],
    3756              :                                                false, NULL, &head)
    3757              :                   == MATCH_YES)
    3758              :                 {
    3759              :                   linear_op = OMP_LINEAR_REF;
    3760              :                   old_linear_modifier = true;
    3761              :                 }
    3762          821 :               else if (gfc_match_omp_variable_list (" val (",
    3763              :                                                     &c->lists[OMP_LIST_LINEAR],
    3764              :                                                     false, NULL, &head)
    3765              :                        == MATCH_YES)
    3766              :                 {
    3767              :                   linear_op = OMP_LINEAR_VAL;
    3768              :                   old_linear_modifier = true;
    3769              :                 }
    3770          810 :               else if (gfc_match_omp_variable_list (" uval (",
    3771              :                                                     &c->lists[OMP_LIST_LINEAR],
    3772              :                                                     false, NULL, &head)
    3773              :                        == MATCH_YES)
    3774              :                 {
    3775              :                   linear_op = OMP_LINEAR_UVAL;
    3776              :                   old_linear_modifier = true;
    3777              :                 }
    3778          801 :               else if (gfc_match_omp_variable_list ("",
    3779              :                                                     &c->lists[OMP_LIST_LINEAR],
    3780              :                                                     false, &end_colon, &head)
    3781              :                        == MATCH_YES)
    3782              :                 linear_op = OMP_LINEAR_DEFAULT;
    3783              :               else
    3784              :                 {
    3785            2 :                   gfc_current_locus = old_loc;
    3786            2 :                   break;
    3787              :                 }
    3788              :               if (linear_op != OMP_LINEAR_DEFAULT)
    3789              :                 {
    3790           48 :                   if (gfc_match (" :") == MATCH_YES)
    3791           31 :                     end_colon = true;
    3792           17 :                   else if (gfc_match (" )") != MATCH_YES)
    3793              :                     {
    3794            0 :                       gfc_free_omp_namelist (*head, OMP_LIST_LINEAR);
    3795            0 :                       gfc_current_locus = old_loc;
    3796            0 :                       *head = NULL;
    3797            0 :                       break;
    3798              :                     }
    3799              :                 }
    3800          847 :               gfc_gobble_whitespace ();
    3801          847 :               if (old_linear_modifier && end_colon)
    3802              :                 {
    3803           31 :                   if (gfc_match (" %e )", &step) != MATCH_YES)
    3804              :                     {
    3805            1 :                       gfc_free_omp_namelist (*head, OMP_LIST_LINEAR);
    3806            1 :                       gfc_current_locus = old_loc;
    3807            1 :                       *head = NULL;
    3808            5 :                       goto error;
    3809              :                     }
    3810              :                 }
    3811           47 :               if (old_linear_modifier)
    3812              :                 {
    3813           47 :                   char var_names[512]{};
    3814           47 :                   int count, offset = 0;
    3815          106 :                   for (gfc_omp_namelist *n = *head; n; n = n->next)
    3816              :                     {
    3817           59 :                       if (!n->next)
    3818           47 :                         count = snprintf (var_names + offset,
    3819           47 :                                           sizeof (var_names) - offset,
    3820           47 :                                           "%s", n->sym->name);
    3821              :                       else
    3822           12 :                         count = snprintf (var_names + offset,
    3823           12 :                                           sizeof (var_names) - offset,
    3824           12 :                                           "%s, ", n->sym->name);
    3825           59 :                       if (count < 0 || count >= ((int)sizeof (var_names))
    3826           59 :                                                 - offset)
    3827              :                         {
    3828            0 :                           snprintf (var_names, 512, "%s, ..., ",
    3829            0 :                                     (*head)->sym->name);
    3830            0 :                           while (n->next)
    3831              :                             n = n->next;
    3832            0 :                           offset = strlen (var_names);
    3833            0 :                           snprintf (var_names + offset,
    3834            0 :                                     sizeof (var_names) - offset,
    3835            0 :                                     "%s", n->sym->name);
    3836            0 :                           break;
    3837              :                         }
    3838           59 :                       offset += count;
    3839              :                     }
    3840           47 :                   char *var_names_for_warn = var_names;
    3841           47 :                   const char *op_name;
    3842           47 :                   switch (linear_op)
    3843              :                     {
    3844              :                       case OMP_LINEAR_REF: op_name = "ref"; break;
    3845           10 :                       case OMP_LINEAR_VAL: op_name = "val"; break;
    3846            9 :                       case OMP_LINEAR_UVAL: op_name = "uval"; break;
    3847            0 :                       default: gcc_unreachable ();
    3848              :                     }
    3849           47 :                   gfc_warning (OPT_Wdeprecated_openmp,
    3850              :                                "Specification of the list items as "
    3851              :                                "arguments to the modifiers at %L is "
    3852              :                                "deprecated; since OpenMP 5.2, use "
    3853              :                                "%<linear(%s : %s%s)%>", &saved_loc,
    3854              :                                var_names_for_warn, op_name,
    3855           47 :                                step == nullptr ? "" : ", step(...)");
    3856              :                 }
    3857          799 :               else if (end_colon)
    3858              :                 {
    3859          732 :                   bool has_error = false;
    3860              :                   bool has_modifiers = false;
    3861              :                   bool has_step = false;
    3862          732 :                   bool duplicate_step = false;
    3863          732 :                   bool duplicate_mod = false;
    3864          732 :                   while (true)
    3865              :                     {
    3866          732 :                       old_loc = gfc_current_locus;
    3867          732 :                       bool close_paren = gfc_match ("val )") == MATCH_YES;
    3868          732 :                       if (close_paren || gfc_match ("val , ") == MATCH_YES)
    3869              :                         {
    3870           23 :                           if (linear_op != OMP_LINEAR_DEFAULT)
    3871              :                             {
    3872              :                               duplicate_mod = true;
    3873              :                               break;
    3874              :                             }
    3875           22 :                           linear_op = OMP_LINEAR_VAL;
    3876           22 :                           has_modifiers = true;
    3877           22 :                           if (close_paren)
    3878              :                             break;
    3879           16 :                           continue;
    3880              :                         }
    3881          709 :                       close_paren = gfc_match ("uval )") == MATCH_YES;
    3882          709 :                       if (close_paren || gfc_match ("uval , ") == MATCH_YES)
    3883              :                         {
    3884            7 :                           if (linear_op != OMP_LINEAR_DEFAULT)
    3885              :                             {
    3886              :                               duplicate_mod = true;
    3887              :                               break;
    3888              :                             }
    3889            7 :                           linear_op = OMP_LINEAR_UVAL;
    3890            7 :                           has_modifiers = true;
    3891            7 :                           if (close_paren)
    3892              :                             break;
    3893            2 :                           continue;
    3894              :                         }
    3895          702 :                       close_paren = gfc_match ("ref )") == MATCH_YES;
    3896          702 :                       if (close_paren || gfc_match ("ref , ") == MATCH_YES)
    3897              :                         {
    3898           16 :                           if (linear_op != OMP_LINEAR_DEFAULT)
    3899              :                             {
    3900              :                               duplicate_mod = true;
    3901              :                               break;
    3902              :                             }
    3903           15 :                           linear_op = OMP_LINEAR_REF;
    3904           15 :                           has_modifiers = true;
    3905           15 :                           if (close_paren)
    3906              :                             break;
    3907            7 :                           continue;
    3908              :                         }
    3909          686 :                       close_paren = (gfc_match ("step ( %e ) )", &step)
    3910              :                                      == MATCH_YES);
    3911          697 :                       if (close_paren
    3912          686 :                           || gfc_match ("step ( %e ) , ", &step) == MATCH_YES)
    3913              :                         {
    3914           50 :                           if (has_step)
    3915              :                             {
    3916              :                               duplicate_step = true;
    3917              :                               break;
    3918              :                             }
    3919           49 :                           has_modifiers = has_step = true;
    3920           49 :                           if (close_paren)
    3921              :                             break;
    3922           11 :                           continue;
    3923              :                         }
    3924          636 :                       if (!has_modifiers
    3925          636 :                           && gfc_match ("%e )", &step) == MATCH_YES)
    3926              :                         {
    3927          636 :                           if ((step->expr_type == EXPR_FUNCTION
    3928          635 :                                 || step->expr_type == EXPR_VARIABLE)
    3929           31 :                               && strcmp (step->symtree->name, "step") == 0)
    3930              :                             {
    3931            1 :                               gfc_current_locus = old_loc;
    3932            1 :                               gfc_match ("step (");
    3933            1 :                               has_error = true;
    3934              :                             }
    3935              :                           break;
    3936              :                         }
    3937              :                       has_error = true;
    3938              :                       break;
    3939              :                     }
    3940           61 :                   if (duplicate_mod || duplicate_step)
    3941              :                     {
    3942            3 :                       gfc_error ("Multiple %qs modifiers specified at %C",
    3943              :                                  duplicate_mod ? "linear" : "step");
    3944            3 :                       has_error = true;
    3945              :                     }
    3946          696 :                   if (has_error)
    3947              :                     {
    3948            4 :                       gfc_free_omp_namelist (*head, OMP_LIST_LINEAR);
    3949            4 :                       *head = NULL;
    3950            4 :                       goto error;
    3951              :                     }
    3952              :                 }
    3953          842 :               if (step == NULL)
    3954              :                 {
    3955          130 :                   step = gfc_get_constant_expr (BT_INTEGER,
    3956              :                                                 gfc_default_integer_kind,
    3957              :                                                 &old_loc);
    3958          130 :                   mpz_set_si (step->value.integer, 1);
    3959              :                 }
    3960          842 :               (*head)->expr = step;
    3961          842 :               if (linear_op != OMP_LINEAR_DEFAULT || old_linear_modifier)
    3962          188 :                 for (gfc_omp_namelist *n = *head; n; n = n->next)
    3963              :                   {
    3964          100 :                     n->u.linear.op = linear_op;
    3965          100 :                     n->u.linear.old_modifier = old_linear_modifier;
    3966              :                   }
    3967          842 :               continue;
    3968          842 :             }
    3969           82 :           if ((mask & OMP_CLAUSE_LINK)
    3970           78 :               && openacc
    3971           86 :               && (gfc_match_oacc_clause_link ("link (",
    3972              :                                               &c->lists[OMP_LIST_LINK])
    3973              :                   == MATCH_YES))
    3974            4 :             continue;
    3975          123 :           else if ((mask & OMP_CLAUSE_LINK)
    3976           74 :                    && !openacc
    3977          144 :                    && (gfc_match_omp_to_link ("link (",
    3978              :                                               &c->lists[OMP_LIST_LINK])
    3979              :                        == MATCH_YES))
    3980           49 :             continue;
    3981           46 :           if ((mask & OMP_CLAUSE_LOCAL)
    3982           25 :               && (gfc_match_omp_to_link ("local (", &c->lists[OMP_LIST_LOCAL])
    3983              :                   == MATCH_YES))
    3984           21 :             continue;
    3985              :           break;
    3986         5962 :         case 'm':
    3987         5962 :           if ((mask & OMP_CLAUSE_MAP)
    3988         5962 :               && gfc_match ("map ( ") == MATCH_YES)
    3989              :             {
    3990         5856 :               locus old_loc2 = gfc_current_locus;
    3991         5856 :               int always_modifier = 0;
    3992         5856 :               int close_modifier = 0;
    3993         5856 :               int present_modifier = 0;
    3994         5856 :               int mapper_modifier = 0;
    3995         5856 :               int iterator_modifier = 0;
    3996         5856 :               gfc_namespace *ns_iter = NULL, *ns_curr = gfc_current_ns;
    3997         5856 :               locus second_always_locus = old_loc2;
    3998         5856 :               locus second_close_locus = old_loc2;
    3999         5856 :               locus second_mapper_locus = old_loc2;
    4000         5856 :               locus second_present_locus = old_loc2;
    4001         5856 :               char mapper_id[GFC_MAX_SYMBOL_LEN + 1] = { '\0' };
    4002         5856 :               locus second_iterator_locus = old_loc2;
    4003              : 
    4004         6524 :               for (;;)
    4005              :                 {
    4006         6190 :                   locus current_locus = gfc_current_locus;
    4007         6190 :                   if (gfc_match ("always ") == MATCH_YES)
    4008              :                     {
    4009          148 :                       if (always_modifier++ == 1)
    4010            5 :                         second_always_locus = current_locus;
    4011              :                     }
    4012         6042 :                   else if (gfc_match ("close ") == MATCH_YES)
    4013              :                     {
    4014           69 :                       if (close_modifier++ == 1)
    4015            5 :                         second_close_locus = current_locus;
    4016              :                     }
    4017         5973 :                   else if (gfc_match ("present ") == MATCH_YES)
    4018              :                     {
    4019           67 :                       if (present_modifier++ == 1)
    4020            4 :                         second_present_locus = current_locus;
    4021              :                     }
    4022         5906 :                   else if (gfc_match ("mapper ( ") == MATCH_YES)
    4023              :                     {
    4024            8 :                       if (mapper_modifier++ == 1)
    4025            0 :                         second_mapper_locus = current_locus;
    4026            8 :                       m = gfc_match (" %n ) ", mapper_id);
    4027            8 :                       if (m != MATCH_YES)
    4028            0 :                         goto error;
    4029            8 :                       if (strcmp (mapper_id, "default") == 0)
    4030            3 :                         mapper_id[0] = '\0';
    4031              :                     }
    4032         5898 :                   else if (gfc_match_iterator (&ns_iter, true) == MATCH_YES)
    4033              :                     {
    4034           42 :                       if (iterator_modifier++ == 1)
    4035            1 :                       second_iterator_locus = current_locus;
    4036              :                     }
    4037              :                   else
    4038              :                     break;
    4039          334 :                   if (gfc_match (", ") != MATCH_YES)
    4040           62 :                     gfc_warning (OPT_Wdeprecated_openmp,
    4041              :                                  "The specification of modifiers without "
    4042              :                                  "comma separators for the %<map%> clause "
    4043              :                                  "at %C has been deprecated since "
    4044              :                                  "OpenMP 5.2");
    4045          334 :                 }
    4046              : 
    4047         5856 :               gfc_omp_map_op map_op = default_map_op;
    4048         5856 :               int always_present_modifier
    4049         5856 :                 = always_modifier && present_modifier;
    4050              : 
    4051         5856 :               if (gfc_match ("alloc : ") == MATCH_YES)
    4052          799 :                 map_op = (present_modifier ? OMP_MAP_PRESENT_ALLOC
    4053              :                           : OMP_MAP_ALLOC);
    4054         5057 :               else if (gfc_match ("tofrom : ") == MATCH_YES)
    4055          954 :                 map_op = (always_present_modifier ? OMP_MAP_ALWAYS_PRESENT_TOFROM
    4056          950 :                           : present_modifier ? OMP_MAP_PRESENT_TOFROM
    4057          945 :                           : always_modifier ? OMP_MAP_ALWAYS_TOFROM
    4058              :                           : OMP_MAP_TOFROM);
    4059         4103 :               else if (gfc_match ("to : ") == MATCH_YES)
    4060         1815 :                 map_op = (always_present_modifier ? OMP_MAP_ALWAYS_PRESENT_TO
    4061         1809 :                           : present_modifier ? OMP_MAP_PRESENT_TO
    4062         1797 :                           : always_modifier ? OMP_MAP_ALWAYS_TO
    4063              :                           : OMP_MAP_TO);
    4064         2288 :               else if (gfc_match ("from : ") == MATCH_YES)
    4065         1656 :                 map_op = (always_present_modifier ? OMP_MAP_ALWAYS_PRESENT_FROM
    4066         1652 :                           : present_modifier ? OMP_MAP_PRESENT_FROM
    4067         1647 :                           : always_modifier ? OMP_MAP_ALWAYS_FROM
    4068              :                           : OMP_MAP_FROM);
    4069          632 :               else if (gfc_match ("release : ") == MATCH_YES)
    4070              :                 map_op = OMP_MAP_RELEASE;
    4071          578 :               else if (gfc_match ("delete : ") == MATCH_YES)
    4072              :                 map_op = OMP_MAP_DELETE;
    4073              :               else
    4074              :                 {
    4075          501 :                   gfc_current_locus = old_loc2;
    4076          501 :                   always_modifier = 0;
    4077          501 :                   close_modifier = 0;
    4078          501 :                   mapper_modifier = 0;
    4079              :                 }
    4080              : 
    4081         1579 :               if (always_modifier > 1)
    4082              :                 {
    4083            5 :                   gfc_error ("too many %<always%> modifiers at %L",
    4084              :                              &second_always_locus);
    4085           24 :                   break;
    4086              :                 }
    4087         5851 :               if (close_modifier > 1)
    4088              :                 {
    4089            4 :                   gfc_error ("too many %<close%> modifiers at %L",
    4090              :                              &second_close_locus);
    4091            4 :                   break;
    4092              :                 }
    4093         5847 :               if (present_modifier > 1)
    4094              :                 {
    4095            4 :                   gfc_error ("too many %<present%> modifiers at %L",
    4096              :                              &second_present_locus);
    4097            4 :                   break;
    4098              :                 }
    4099         5843 :               if (mapper_modifier > 1)
    4100              :                 {
    4101            0 :                   gfc_error ("too many %<mapper%> modifiers at %L",
    4102              :                              &second_mapper_locus);
    4103            0 :                   break;
    4104              :                 }
    4105         5843 :               if (iterator_modifier > 1)
    4106              :                 {
    4107            1 :                   gfc_error ("too many %<iterator%> modifiers at %L",
    4108              :                              &second_iterator_locus);
    4109            1 :                   break;
    4110              :                 }
    4111              : 
    4112         5842 :               head = NULL;
    4113         5842 :               if (ns_iter)
    4114           40 :                 gfc_current_ns = ns_iter;
    4115         5842 :               m = gfc_match_omp_variable_list ("", &c->lists[OMP_LIST_MAP],
    4116              :                                                false, NULL, &head, true, true);
    4117         5842 :               gfc_current_ns = ns_curr;
    4118         5842 :               if (m == MATCH_YES)
    4119              :                 {
    4120         5837 :                   gfc_omp_namelist *n;
    4121        13257 :                   for (n = *head; n; n = n->next)
    4122              :                     {
    4123         7420 :                       n->u.map.op = map_op;
    4124         7420 :                       if (mapper_id[0] != '\0')
    4125              :                         {
    4126            5 :                           n->u3.udm = gfc_get_omp_namelist_udm ();
    4127            5 :                           n->u3.udm->requested_mapper_id
    4128            5 :                             = gfc_get_string ("%s", mapper_id);
    4129              :                         }
    4130         7420 :                       n->u2.ns = ns_iter;
    4131         7420 :                       if (ns_iter)
    4132           42 :                         ns_iter->refs++;
    4133              :                     }
    4134         5837 :                   continue;
    4135         5837 :                 }
    4136            5 :               gfc_current_locus = old_loc;
    4137            5 :               break;
    4138              :             }
    4139          140 :           if ((mask & OMP_CLAUSE_MERGEABLE)
    4140          140 :               && (m = gfc_match_boolean_clause (&bval, "mergeable",
    4141           34 :                          c->mergeable || cfalse->mergeable)) != MATCH_NO)
    4142              :             {
    4143           34 :               if (m == MATCH_ERROR)
    4144            0 :                 goto error;
    4145           34 :               if (bval)
    4146           34 :                 c->mergeable = true;
    4147              :               else
    4148            0 :                 cfalse->mergeable = true;
    4149           34 :               continue;
    4150              :             }
    4151          139 :           if ((mask & OMP_CLAUSE_MESSAGE)
    4152           72 :               && (m = gfc_match_dupl_check (!c->message, "message", true,
    4153              :                  &c->message)) != MATCH_NO)
    4154              :             {
    4155           72 :               if (m == MATCH_ERROR)
    4156            5 :                 goto error;
    4157           67 :               continue;
    4158              :             }
    4159              :           break;
    4160         3033 :         case 'n':
    4161         3085 :           if ((mask & OMP_CLAUSE_NO_CREATE)
    4162         1343 :               && gfc_match ("no_create ( ") == MATCH_YES
    4163         3085 :               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
    4164              :                                            OMP_MAP_IF_PRESENT, true,
    4165              :                                            allow_derived))
    4166           52 :             continue;
    4167         2984 :           if ((mask & OMP_CLAUSE_ASSUMPTIONS)
    4168         3015 :               && ((m = gfc_match_boolean_clause (&bval, "no_openmp_constructs",
    4169           34 :                          (c->assume && c->assume->no_openmp_constructs)
    4170           31 :                          || (cfalse->assume && cfalse->assume->no_openmp_constructs)))
    4171              :                   != MATCH_NO))
    4172              :             {
    4173            4 :               if (m == MATCH_ERROR)
    4174            1 :                 goto error;
    4175            3 :               if (bval)
    4176              :                 {
    4177            2 :                   if (c->assume == NULL)
    4178            0 :                     c->assume = gfc_get_omp_assumptions ();
    4179            2 :                   c->assume->no_openmp_constructs = true;
    4180              :                 }
    4181              :               else
    4182              :                 {
    4183            1 :                   if (cfalse->assume == NULL)
    4184            0 :                     cfalse->assume = gfc_get_omp_assumptions ();
    4185            1 :                   cfalse->assume->no_openmp_constructs = true;
    4186              :                 }
    4187            3 :               continue;
    4188              :             }
    4189         2992 :           if ((mask & OMP_CLAUSE_ASSUMPTIONS)
    4190         3007 :               && ((m = gfc_match_boolean_clause (&bval, "no_openmp_routines",
    4191           30 :                          (c->assume && c->assume->no_openmp_routines)
    4192           29 :                          || (cfalse->assume && cfalse->assume->no_openmp_routines)))
    4193              :                   != MATCH_NO))
    4194              :             {
    4195           15 :               if (m == MATCH_ERROR)
    4196            0 :                 goto error;
    4197           15 :               if (bval)
    4198              :                 {
    4199           14 :                   if (c->assume == NULL)
    4200           12 :                     c->assume = gfc_get_omp_assumptions ();
    4201           14 :                   c->assume->no_openmp_routines = true;
    4202              :                 }
    4203              :               else
    4204              :                 {
    4205            1 :                   if (cfalse->assume == NULL)
    4206            0 :                     cfalse->assume = gfc_get_omp_assumptions ();
    4207            1 :                   cfalse->assume->no_openmp_routines = true;
    4208              :                 }
    4209           15 :               continue;
    4210              :             }
    4211         2968 :           if ((mask & OMP_CLAUSE_ASSUMPTIONS)
    4212         2977 :               && ((m = gfc_match_boolean_clause (&bval, "no_openmp",
    4213           15 :                          (c->assume && c->assume->no_openmp)
    4214           13 :                          || (cfalse->assume && cfalse->assume->no_openmp)))
    4215              :                   != MATCH_NO))
    4216              :             {
    4217            6 :               if (m == MATCH_ERROR)
    4218            0 :                 goto error;
    4219            6 :               if (bval)
    4220              :                 {
    4221            5 :                   if (c->assume == NULL)
    4222            5 :                     c->assume = gfc_get_omp_assumptions ();
    4223            5 :                   c->assume->no_openmp = true;
    4224              :                 }
    4225              :               else
    4226              :                 {
    4227            1 :                   if (cfalse->assume == NULL)
    4228            1 :                     cfalse->assume = gfc_get_omp_assumptions ();
    4229            1 :                   cfalse->assume->no_openmp = true;
    4230              :                 }
    4231            6 :               continue;
    4232              :             }
    4233         2964 :           if ((mask & OMP_CLAUSE_ASSUMPTIONS)
    4234         2965 :               && ((m = gfc_match_boolean_clause (&bval, "no_parallelism",
    4235            9 :                          (c->assume && c->assume->no_parallelism)
    4236            9 :                          || (cfalse->assume && cfalse->assume->no_parallelism)))
    4237              :                   != MATCH_NO))
    4238              :             {
    4239            8 :               if (m == MATCH_ERROR)
    4240            0 :                 goto error;
    4241            8 :               if (bval)
    4242              :                 {
    4243            7 :                   if (c->assume == NULL)
    4244            6 :                     c->assume = gfc_get_omp_assumptions ();
    4245            7 :                   c->assume->no_parallelism = true;
    4246              :                 }
    4247              :               else
    4248              :                 {
    4249            1 :                   if (cfalse->assume == NULL)
    4250            0 :                     cfalse->assume = gfc_get_omp_assumptions ();
    4251            1 :                   cfalse->assume->no_parallelism = true;
    4252              :                 }
    4253            8 :               continue;
    4254              :             }
    4255              : 
    4256         2958 :           if ((mask & OMP_CLAUSE_NOVARIANTS)
    4257         2948 :               && (m = gfc_match_dupl_check (!c->novariants, "novariants", true,
    4258              :                                             &c->novariants))
    4259              :                    != MATCH_NO)
    4260              :             {
    4261           12 :               if (m == MATCH_ERROR)
    4262            2 :                 goto error;
    4263           10 :               continue;
    4264              :             }
    4265         2949 :           if ((mask & OMP_CLAUSE_NOCONTEXT)
    4266         2936 :               && (m = gfc_match_dupl_check (!c->nocontext, "nocontext", true,
    4267              :                                             &c->nocontext))
    4268              :                    != MATCH_NO)
    4269              :             {
    4270           15 :               if (m == MATCH_ERROR)
    4271            2 :                 goto error;
    4272           13 :               continue;
    4273              :             }
    4274         2935 :           if ((mask & OMP_CLAUSE_NOGROUP)
    4275         3005 :               && ((m = gfc_match_boolean_clause (&bval, "nogroup",
    4276           84 :                                                  c->nogroup || cfalse->nogroup))
    4277              :                   != MATCH_NO))
    4278              :             {
    4279           14 :               if (m == MATCH_ERROR)
    4280            0 :                 goto error;
    4281           14 :               if (bval)
    4282           14 :                 c->nogroup = true;
    4283              :               else
    4284            0 :                 cfalse->nogroup = true;
    4285           14 :               continue;
    4286              :             }
    4287         3057 :           if ((mask & OMP_CLAUSE_NOHOST)
    4288         2907 :               && (m = gfc_match_dupl_check (!c->nohost, "nohost")) != MATCH_NO)
    4289              :             {
    4290          151 :               if (m == MATCH_ERROR)
    4291            1 :                 goto error;
    4292          150 :               c->nohost = true;
    4293          150 :               continue;
    4294              :             }
    4295         2798 :           if ((mask & OMP_CLAUSE_NOTEMPORAL)
    4296         2756 :               && gfc_match_omp_variable_list ("nontemporal (",
    4297              :                                               &c->lists[OMP_LIST_NONTEMPORAL],
    4298              :                                               true) == MATCH_YES)
    4299           42 :             continue;
    4300         2744 :           if ((mask & OMP_CLAUSE_NOTINBRANCH)
    4301         2747 :               && (m = gfc_match_dupl_branch_clause (&bval, "notinbranch",
    4302           33 :                         c->notinbranch || cfalse->notinbranch
    4303           33 :                         || c->inbranch || cfalse->inbranch)) != MATCH_NO)
    4304              :             {
    4305           33 :               if (m == MATCH_ERROR)
    4306            3 :                 goto error;
    4307           30 :               if (bval)
    4308           27 :                 c->notinbranch = true;
    4309              :               else
    4310            3 :                 cfalse->notinbranch = true;
    4311           30 :               continue;
    4312              :             }
    4313         2814 :           if ((mask & OMP_CLAUSE_NOWAIT)
    4314         2681 :               && (m = gfc_match_dupl_check (!c->nowait, "nowait")) != MATCH_NO)
    4315              :             {
    4316          136 :               if (m == MATCH_ERROR)
    4317            3 :                 goto error;
    4318          133 :               c->nowait = true;
    4319          133 :               continue;
    4320              :             }
    4321         3227 :           if ((mask & OMP_CLAUSE_NUM_GANGS)
    4322         2545 :               && (m = gfc_match_dupl_check (!c->num_gangs_expr, "num_gangs",
    4323              :                                             true)) != MATCH_NO)
    4324              :             {
    4325          686 :               if (m == MATCH_ERROR)
    4326            2 :                 goto error;
    4327          684 :               if (gfc_match (" %e )", &c->num_gangs_expr) != MATCH_YES)
    4328            2 :                 goto error;
    4329          682 :               continue;
    4330              :             }
    4331         1885 :           if ((mask & OMP_CLAUSE_NUM_TASKS)
    4332         1859 :               && (m = gfc_match_dupl_check (!c->num_tasks, "num_tasks", true))
    4333              :                  != MATCH_NO)
    4334              :             {
    4335           26 :               if (m == MATCH_ERROR)
    4336            0 :                 goto error;
    4337           26 :               if (gfc_match ("strict : ") == MATCH_YES)
    4338            1 :                 c->num_tasks_strict = true;
    4339           26 :               if (gfc_match (" %e )", &c->num_tasks) != MATCH_YES)
    4340            0 :                 goto error;
    4341           26 :               continue;
    4342              :             }
    4343         1833 :           if ((mask & OMP_CLAUSE_NUM_TEAMS)
    4344         1833 :               && (m = gfc_match_dupl_check (!c->num_teams_list,
    4345              :                                             "num_teams", true)) != MATCH_NO)
    4346              :             {
    4347          174 :               if (m == MATCH_ERROR)
    4348           20 :                 goto error;
    4349          172 :               gfc_expr *expr;
    4350          172 :               if (gfc_match ("dims ( %e ) : ", &expr) == MATCH_YES
    4351          172 :                   && match_omp_oacc_expr_list (NULL, &c->num_teams_list,
    4352              :                                                false, true) == MATCH_YES)
    4353              :                 {
    4354           19 :                   int num = 0;
    4355           19 :                   gfc_expr_list *el;
    4356           55 :                   for (el = c->num_teams_list; el; el = el->next)
    4357           36 :                     ++num;
    4358           19 :                   if (!gfc_resolve_expr (expr)
    4359           19 :                       || expr->ts.type != BT_INTEGER
    4360           18 :                       || expr->rank != 0
    4361           17 :                       || expr->expr_type != EXPR_CONSTANT
    4362           34 :                       || mpz_sgn (expr->value.integer) <= 0)
    4363              :                     {
    4364            5 :                       gfc_error ("DIMS must be a constant positive integer "
    4365            5 :                                  "at %L", &expr->where);
    4366            5 :                       goto error;
    4367              :                     }
    4368           14 :                   if (mpz_cmp_si (expr->value.integer, num) != 0)
    4369              :                     {
    4370            1 :                       gfc_error ("The number of arguments (%d) must be the same"
    4371              :                                  " as specified for DIMS at %L", num,
    4372              :                                  &expr->where);
    4373            1 :                       goto error;
    4374              :                     }
    4375           13 :                   c->num_teams_dims = true;
    4376          154 :                   continue;
    4377           13 :                 }
    4378          153 :               else if (gfc_match ("%e ", &expr) == MATCH_YES)
    4379              :                 {
    4380          150 :                   c->num_teams_list = gfc_get_expr_list();
    4381          150 :                   c->num_teams_list->expr = expr;
    4382          150 :                   if (gfc_peek_ascii_char () == ':')
    4383              :                     {
    4384           30 :                       expr = NULL;
    4385           30 :                       if (gfc_match (": %e ", &expr) == MATCH_YES)
    4386              :                         {
    4387           29 :                           c->num_teams_list->next = gfc_get_expr_list();
    4388           29 :                           c->num_teams_list->next->expr = expr;
    4389           29 :                           if (gfc_match (") ") == MATCH_YES)
    4390           27 :                             continue;
    4391              :                         }
    4392              :                     }
    4393          120 :                   else if (gfc_match (") ") == MATCH_YES)
    4394          114 :                     continue;
    4395              :                 }
    4396           12 :               gfc_error ("Expected either %<[lower-expr : ] upper-expr%> or "
    4397              :                              "%<dims(N): expr-list%> at %C");
    4398           12 :               goto error;
    4399              :             }
    4400         1659 :           if ((mask & OMP_CLAUSE_NUM_THREADS)
    4401         1659 :               && (m = gfc_match_dupl_check (!c->num_threads_list,
    4402              :                                             "num_threads", true, NULL))
    4403              :                   != MATCH_NO)
    4404              :             {
    4405         1018 :               int nstrict = 0, nrelaxed = 0, ndims = 0;
    4406         1018 :               bool fail = false;
    4407         1018 :               gfc_expr *dims = NULL;
    4408         1018 :               locus old_loc = gfc_current_locus;
    4409              : 
    4410         1018 :               if (m == MATCH_ERROR)
    4411           27 :                 goto error;
    4412         1068 :               while (true)
    4413              :                 {
    4414         1042 :                   if (gfc_match ("strict ") == MATCH_YES)
    4415           16 :                     nstrict++;
    4416         1026 :                   else if (gfc_match ("relaxed ") == MATCH_YES)
    4417           21 :                     nrelaxed++;
    4418         1005 :                   else if (gfc_match ("dims ") == MATCH_YES)
    4419              :                     {
    4420           32 :                       ndims++;
    4421           32 :                       if (dims)
    4422            3 :                         gfc_free_expr (dims);
    4423           32 :                       if (gfc_match ("( %e ) ", &dims) != MATCH_YES)
    4424              :                         break;
    4425              :                     }
    4426              :                   else
    4427              :                     {
    4428              :                       fail = true;
    4429              :                       break;
    4430              :                     }
    4431           68 :                   if (gfc_match (", ") == MATCH_YES)
    4432           26 :                     continue;
    4433              :                   break;
    4434              :                 }
    4435         1016 :               if (gfc_match (" : ") == MATCH_YES)
    4436              :                 {
    4437           40 :                   if (nstrict + nrelaxed + ndims == 0 || fail)
    4438              :                     {
    4439            1 :                       gfc_error ("Expected STRICT, RELAXED or DIMS modifier at "
    4440              :                                  "%C");
    4441            1 :                       goto error;
    4442              :                     }
    4443           39 :                   else if (nstrict + nrelaxed > 1)
    4444              :                     {
    4445            8 :                       gfc_error ("Only one STRICT or RELAXED modifier permitted"
    4446              :                                  " at %L", &old_loc);
    4447            8 :                       goto error;
    4448              :                     }
    4449           31 :                   if (ndims > 1)
    4450              :                     {
    4451            3 :                       gfc_error ("Duplicated DIMS expression at %L",
    4452            3 :                                  &dims->where);
    4453            3 :                       goto error;
    4454              :                     }
    4455           28 :                   if (nstrict || (dims && !nrelaxed))
    4456           17 :                     c->num_threads_strict = true;
    4457              :                 }
    4458              :               else
    4459              :                 {
    4460          976 :                   gfc_free_expr (dims);
    4461          976 :                   dims = NULL;
    4462          976 :                   gfc_current_locus = old_loc;
    4463              :                 }
    4464              : 
    4465         1004 :               m = match_omp_oacc_expr_list (NULL, &c->num_threads_list, false,
    4466              :                                             true);
    4467         1004 :               if (m != MATCH_YES)
    4468              :                 {
    4469            7 :                   gfc_error ("Expected a list of integer expressions followed "
    4470              :                              "by a %<)%> and optionally preceded by the STRICT,"
    4471              :                              " RELAXED, or DIMS as modifiers and a colon at %C");
    4472            7 :                   goto error;
    4473              :                 }
    4474          997 :               if (dims)
    4475              :                 {
    4476           17 :                   int num = 0;
    4477           17 :                   gfc_expr_list *el;
    4478           46 :                   for (el = c->num_threads_list; el; el = el->next)
    4479           29 :                     ++num;
    4480           17 :                   if (!gfc_resolve_expr (dims)
    4481           17 :                       || dims->ts.type != BT_INTEGER
    4482           16 :                       || dims->rank != 0
    4483           15 :                       || dims->expr_type != EXPR_CONSTANT
    4484           30 :                       || mpz_sgn (dims->value.integer) <= 0)
    4485              :                     {
    4486            5 :                       gfc_error ("DIMS must be a constant positive integer "
    4487            5 :                                  "at %L", &dims->where);
    4488            5 :                       goto error;
    4489              :                     }
    4490           12 :                   if (mpz_cmp_si (dims->value.integer, num) != 0)
    4491              :                     {
    4492            1 :                       gfc_error ("The number of arguments (%d) must be the same"
    4493              :                                  " as specified for DIMS at %L", num,
    4494              :                                  &dims->where);
    4495            1 :                       goto error;
    4496              :                     }
    4497           11 :                   c->num_threads_dims = true;
    4498              :                 }
    4499          991 :               continue;
    4500          991 :             }
    4501         1240 :           if ((mask & OMP_CLAUSE_NUM_WORKERS)
    4502          641 :               && (m = gfc_match_dupl_check (!c->num_workers_expr, "num_workers",
    4503              :                                             true, &c->num_workers_expr))
    4504              :                  != MATCH_NO)
    4505              :             {
    4506          603 :               if (m == MATCH_ERROR)
    4507            4 :                 goto error;
    4508          599 :               continue;
    4509              :             }
    4510              :           break;
    4511          591 :         case 'o':
    4512          591 :           if ((mask & OMP_CLAUSE_ORDERED)
    4513          591 :               && (m = gfc_match_dupl_check (!c->ordered, "ordered"))
    4514              :                  != MATCH_NO)
    4515              :             {
    4516          343 :               if (m == MATCH_ERROR)
    4517            0 :                 goto error;
    4518          343 :               gfc_expr *cexpr = NULL;
    4519          343 :               m = gfc_match (" ( %e )", &cexpr);
    4520              : 
    4521          343 :               c->ordered = true;
    4522          343 :               if (m == MATCH_YES)
    4523              :                 {
    4524          144 :                   int ordered = 0;
    4525          144 :                   if (gfc_extract_int (cexpr, &ordered, -1))
    4526            0 :                     ordered = 0;
    4527          144 :                   else if (ordered <= 0)
    4528              :                     {
    4529            0 :                       gfc_error_now ("ORDERED clause argument not"
    4530              :                                      " constant positive integer at %C");
    4531            0 :                       ordered = 0;
    4532              :                     }
    4533          144 :                   c->orderedc = ordered;
    4534          144 :                   gfc_free_expr (cexpr);
    4535          144 :                   continue;
    4536          144 :                 }
    4537              : 
    4538          199 :               continue;
    4539          199 :             }
    4540          482 :           if ((mask & OMP_CLAUSE_ORDER)
    4541          248 :               && (m = gfc_match_dupl_check (!c->order_concurrent, "order", true))
    4542              :                  != MATCH_NO)
    4543              :             {
    4544          247 :               if (m == MATCH_ERROR)
    4545           10 :                 goto error;
    4546          237 :               if (gfc_match (" reproducible : concurrent )") == MATCH_YES)
    4547           55 :                 c->order_reproducible = true;
    4548          182 :               else if (gfc_match (" concurrent )") == MATCH_YES)
    4549              :                 ;
    4550           50 :               else if (gfc_match (" unconstrained : concurrent )") == MATCH_YES)
    4551           47 :                 c->order_unconstrained = true;
    4552              :               else
    4553              :                 {
    4554            3 :                   gfc_error ("Expected ORDER(CONCURRENT) at %C "
    4555              :                              "with optional %<reproducible%> or "
    4556              :                              "%<unconstrained%> modifier");
    4557            3 :                   goto error;
    4558              :                 }
    4559          234 :               c->order_concurrent = true;
    4560          234 :               continue;
    4561              :             }
    4562              :           break;
    4563         3107 :         case 'p':
    4564         3107 :           if (mask & OMP_CLAUSE_PARTIAL)
    4565              :             {
    4566          276 :               if ((m = gfc_match_dupl_check (!c->partial, "partial"))
    4567              :                   != MATCH_NO)
    4568              :                 {
    4569          276 :                   int expr;
    4570          276 :                   if (m == MATCH_ERROR)
    4571            0 :                     goto error;
    4572              : 
    4573          276 :                   c->partial = -1;
    4574              : 
    4575          276 :                   gfc_expr *cexpr = NULL;
    4576          276 :                   m = gfc_match (" ( %e )", &cexpr);
    4577          276 :                   if (m == MATCH_NO)
    4578              :                     ;
    4579          251 :                   else if (m == MATCH_YES
    4580          251 :                            && !gfc_extract_int (cexpr, &expr, -1)
    4581          502 :                            && expr > 0)
    4582          247 :                     c->partial = expr;
    4583              :                   else
    4584            4 :                     gfc_error_now ("PARTIAL clause argument not constant "
    4585              :                                    "positive integer at %C");
    4586          276 :                   gfc_free_expr (cexpr);
    4587          276 :                   continue;
    4588          276 :                 }
    4589              :             }
    4590         2900 :           if ((mask & OMP_CLAUSE_COPY)
    4591          877 :               && gfc_match ("pcopy ( ") == MATCH_YES
    4592         2901 :               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
    4593              :                                            OMP_MAP_TOFROM, true, allow_derived))
    4594           69 :             continue;
    4595         2836 :           if ((mask & OMP_CLAUSE_COPYIN)
    4596         1910 :               && gfc_match ("pcopyin ( ") == MATCH_YES
    4597         2836 :               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
    4598              :                                            OMP_MAP_TO, true, allow_derived))
    4599           74 :             continue;
    4600         2761 :           if ((mask & OMP_CLAUSE_COPYOUT)
    4601          735 :               && gfc_match ("pcopyout ( ") == MATCH_YES
    4602         2761 :               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
    4603              :                                            OMP_MAP_FROM, true, allow_derived))
    4604           73 :             continue;
    4605         2630 :           if ((mask & OMP_CLAUSE_CREATE)
    4606          672 :               && gfc_match ("pcreate ( ") == MATCH_YES
    4607         2630 :               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
    4608              :                                            OMP_MAP_ALLOC, true, allow_derived))
    4609           15 :             continue;
    4610         3016 :           if ((mask & OMP_CLAUSE_PRESENT)
    4611          647 :               && gfc_match ("present ( ") == MATCH_YES
    4612         3018 :               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
    4613              :                                            OMP_MAP_FORCE_PRESENT, false,
    4614              :                                            allow_derived))
    4615          416 :             continue;
    4616         2207 :           if ((mask & OMP_CLAUSE_COPY)
    4617          231 :               && gfc_match ("present_or_copy ( ") == MATCH_YES
    4618         2207 :               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
    4619              :                                            OMP_MAP_TOFROM, true,
    4620              :                                            allow_derived))
    4621           23 :             continue;
    4622         2201 :           if ((mask & OMP_CLAUSE_COPYIN)
    4623         1309 :               && gfc_match ("present_or_copyin ( ") == MATCH_YES
    4624         2201 :               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
    4625              :                                            OMP_MAP_TO, true, allow_derived))
    4626           40 :             continue;
    4627         2156 :           if ((mask & OMP_CLAUSE_COPYOUT)
    4628          173 :               && gfc_match ("present_or_copyout ( ") == MATCH_YES
    4629         2156 :               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
    4630              :                                            OMP_MAP_FROM, true, allow_derived))
    4631           35 :             continue;
    4632         2114 :           if ((mask & OMP_CLAUSE_CREATE)
    4633          143 :               && gfc_match ("present_or_create ( ") == MATCH_YES
    4634         2114 :               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
    4635              :                                            OMP_MAP_ALLOC, true, allow_derived))
    4636           28 :             continue;
    4637         2092 :           if ((mask & OMP_CLAUSE_PRIORITY)
    4638         2058 :               && (m = gfc_match_dupl_check (!c->priority, "priority", true,
    4639              :                                             &c->priority)) != MATCH_NO)
    4640              :             {
    4641           34 :               if (m == MATCH_ERROR)
    4642            0 :                 goto error;
    4643           34 :               continue;
    4644              :             }
    4645         3971 :           if ((mask & OMP_CLAUSE_PRIVATE)
    4646         2024 :               && gfc_match_omp_variable_list ("private (",
    4647              :                                               &c->lists[OMP_LIST_PRIVATE],
    4648              :                                               true) == MATCH_YES)
    4649         1947 :             continue;
    4650          141 :           if ((mask & OMP_CLAUSE_PROC_BIND)
    4651          141 :               && (m = gfc_match_dupl_check ((c->proc_bind
    4652           64 :                                              == OMP_PROC_BIND_UNKNOWN),
    4653              :                                             "proc_bind", true)) != MATCH_NO)
    4654              :             {
    4655           64 :               if (m == MATCH_ERROR)
    4656            0 :                 goto error;
    4657           64 :               if (gfc_match ("primary )") == MATCH_YES)
    4658            1 :                 c->proc_bind = OMP_PROC_BIND_PRIMARY;
    4659           63 :               else if (gfc_match ("master )") == MATCH_YES)
    4660              :                 {
    4661            9 :                   gfc_warning (OPT_Wdeprecated_openmp,
    4662              :                                "%<master%> affinity policy at %C deprecated "
    4663              :                                "since OpenMP 5.1, use %<primary%>");
    4664            9 :                   c->proc_bind = OMP_PROC_BIND_MASTER;
    4665              :                 }
    4666           54 :               else if (gfc_match ("spread )") == MATCH_YES)
    4667           53 :                 c->proc_bind = OMP_PROC_BIND_SPREAD;
    4668            1 :               else if (gfc_match ("close )") == MATCH_YES)
    4669            1 :                 c->proc_bind = OMP_PROC_BIND_CLOSE;
    4670              :               else
    4671            0 :                 goto error;
    4672           64 :               continue;
    4673              :             }
    4674              :           break;
    4675         4613 :         case 'r':
    4676         5114 :           if ((mask & OMP_CLAUSE_ATOMIC)
    4677         5160 :               && (m = gfc_match_dupl_atomic (&bval, "read",
    4678          547 :                         c->atomic_op != GFC_OMP_ATOMIC_UNSET)) != MATCH_NO)
    4679              :             {
    4680          501 :               if (m == MATCH_ERROR)
    4681            0 :                 goto error;
    4682          501 :               if (bval)
    4683          493 :                 c->atomic_op = GFC_OMP_ATOMIC_READ;
    4684          501 :               continue;
    4685              :             }
    4686         8169 :           if ((mask & OMP_CLAUSE_REDUCTION)
    4687         4112 :               && gfc_match_omp_clause_reduction (pc, c, openacc,
    4688              :                                                  allow_derived) == MATCH_YES)
    4689         4057 :             continue;
    4690           74 :           if ((mask & OMP_CLAUSE_MEMORDER)
    4691          101 :               && (m = gfc_match_dupl_memorder (&bval, "relaxed",
    4692           46 :                         c->memorder != OMP_MEMORDER_UNSET)) != MATCH_NO)
    4693              :             {
    4694           19 :               if (m == MATCH_ERROR)
    4695            0 :                 goto error;
    4696           19 :               if (bval)
    4697           12 :                 c->memorder = OMP_MEMORDER_RELAXED;
    4698           19 :               continue;
    4699              :             }
    4700           61 :           if ((mask & OMP_CLAUSE_MEMORDER)
    4701           63 :               && (m = gfc_match_dupl_memorder (&bval, "release",
    4702           27 :                         c->memorder != OMP_MEMORDER_UNSET)) != MATCH_NO)
    4703              :             {
    4704           27 :               if (m == MATCH_ERROR)
    4705            2 :                 goto error;
    4706           25 :               if (bval)
    4707           17 :                 c->memorder = OMP_MEMORDER_RELEASE;
    4708           25 :               continue;
    4709              :             }
    4710              :           break;
    4711         3060 :         case 's':
    4712         3153 :           if ((mask & OMP_CLAUSE_SAFELEN)
    4713         3060 :               && (m = gfc_match_dupl_check (!c->safelen_expr, "safelen",
    4714              :                                             true, &c->safelen_expr))
    4715              :                  != MATCH_NO)
    4716              :             {
    4717           93 :               if (m == MATCH_ERROR)
    4718            0 :                 goto error;
    4719           93 :               continue;
    4720              :             }
    4721         2967 :           if ((mask & OMP_CLAUSE_SCHEDULE)
    4722         2967 :               && (m = gfc_match_dupl_check (c->sched_kind == OMP_SCHED_NONE,
    4723              :                                             "schedule", true)) != MATCH_NO)
    4724              :             {
    4725          809 :               if (m == MATCH_ERROR)
    4726            0 :                 goto error;
    4727          809 :               int nmodifiers = 0;
    4728          809 :               locus old_loc2 = gfc_current_locus;
    4729          827 :               do
    4730              :                 {
    4731          818 :                   if (gfc_match ("simd") == MATCH_YES)
    4732              :                     {
    4733           18 :                       c->sched_simd = true;
    4734           18 :                       nmodifiers++;
    4735              :                     }
    4736          800 :                   else if (gfc_match ("monotonic") == MATCH_YES)
    4737              :                     {
    4738           30 :                       c->sched_monotonic = true;
    4739           30 :                       nmodifiers++;
    4740              :                     }
    4741          770 :                   else if (gfc_match ("nonmonotonic") == MATCH_YES)
    4742              :                     {
    4743           35 :                       c->sched_nonmonotonic = true;
    4744           35 :                       nmodifiers++;
    4745              :                     }
    4746              :                   else
    4747              :                     {
    4748          735 :                       if (nmodifiers)
    4749            0 :                         gfc_current_locus = old_loc2;
    4750              :                       break;
    4751              :                     }
    4752           92 :                   if (nmodifiers == 1
    4753           83 :                       && gfc_match (" , ") == MATCH_YES)
    4754            9 :                     continue;
    4755           74 :                   else if (gfc_match (" : ") == MATCH_YES)
    4756              :                     break;
    4757            0 :                   gfc_current_locus = old_loc2;
    4758            0 :                   break;
    4759              :                 }
    4760              :               while (1);
    4761          809 :               if (gfc_match ("static") == MATCH_YES)
    4762          425 :                 c->sched_kind = OMP_SCHED_STATIC;
    4763          384 :               else if (gfc_match ("dynamic") == MATCH_YES)
    4764          164 :                 c->sched_kind = OMP_SCHED_DYNAMIC;
    4765          220 :               else if (gfc_match ("guided") == MATCH_YES)
    4766          127 :                 c->sched_kind = OMP_SCHED_GUIDED;
    4767           93 :               else if (gfc_match ("runtime") == MATCH_YES)
    4768           85 :                 c->sched_kind = OMP_SCHED_RUNTIME;
    4769            8 :               else if (gfc_match ("auto") == MATCH_YES)
    4770            8 :                 c->sched_kind = OMP_SCHED_AUTO;
    4771          809 :               if (c->sched_kind != OMP_SCHED_NONE)
    4772              :                 {
    4773          809 :                   m = MATCH_NO;
    4774          809 :                   if (c->sched_kind != OMP_SCHED_RUNTIME
    4775          724 :                       && c->sched_kind != OMP_SCHED_AUTO)
    4776          716 :                     m = gfc_match (" , %e )", &c->chunk_size);
    4777          716 :                   if (m != MATCH_YES)
    4778          299 :                     m = gfc_match_char (')');
    4779          299 :                   if (m != MATCH_YES)
    4780            0 :                     c->sched_kind = OMP_SCHED_NONE;
    4781              :                 }
    4782          809 :               if (c->sched_kind != OMP_SCHED_NONE)
    4783          809 :                 continue;
    4784              :               else
    4785            0 :                 gfc_current_locus = old_loc;
    4786              :             }
    4787         2341 :           if ((mask & OMP_CLAUSE_SELF)
    4788          335 :               && !(mask & OMP_CLAUSE_HOST) /* OpenACC compute construct */
    4789         2398 :               && (m = gfc_match_dupl_check (!c->self_expr, "self"))
    4790              :                   != MATCH_NO)
    4791              :             {
    4792          186 :               if (m == MATCH_ERROR)
    4793            3 :                 goto error;
    4794          183 :               m = gfc_match (" ( %e )", &c->self_expr);
    4795          183 :               if (m == MATCH_ERROR)
    4796              :                 {
    4797            0 :                   gfc_current_locus = old_loc;
    4798            0 :                   break;
    4799              :                 }
    4800          183 :               else if (m == MATCH_NO)
    4801            9 :                 c->self_expr = gfc_get_logical_expr (gfc_default_logical_kind,
    4802              :                                                      NULL, true);
    4803          183 :               continue;
    4804              :             }
    4805         2066 :           if ((mask & OMP_CLAUSE_SELF)
    4806          149 :               && (mask & OMP_CLAUSE_HOST) /* OpenACC 'update' directive */
    4807           95 :               && gfc_match ("self ( ") == MATCH_YES
    4808         2067 :               && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP],
    4809              :                                            OMP_MAP_FORCE_FROM, true,
    4810              :                                            /* allow_derived = */ true))
    4811           94 :             continue;
    4812         2226 :           if ((mask & OMP_CLAUSE_SEQ)
    4813         1878 :               && (m = gfc_match_dupl_check (!c->seq, "seq")) != MATCH_NO)
    4814              :             {
    4815          348 :               if (m == MATCH_ERROR)
    4816            0 :                 goto error;
    4817          348 :               c->seq = true;
    4818          348 :               continue;
    4819              :             }
    4820         1679 :           if ((mask & OMP_CLAUSE_MEMORDER)
    4821         1679 :               && (m = gfc_match_dupl_memorder (&bval, "seq_cst",
    4822          149 :                         c->memorder != OMP_MEMORDER_UNSET)) != MATCH_NO)
    4823              :             {
    4824          149 :               if (m == MATCH_ERROR)
    4825            0 :                 goto error;
    4826          149 :               if (bval)
    4827          143 :                 c->memorder = OMP_MEMORDER_SEQ_CST;
    4828          149 :               continue;
    4829              :             }
    4830         2356 :           if ((mask & OMP_CLAUSE_SHARED)
    4831         1381 :               && gfc_match_omp_variable_list ("shared (",
    4832              :                                               &c->lists[OMP_LIST_SHARED],
    4833              :                                               true) == MATCH_YES)
    4834          975 :             continue;
    4835          524 :           if ((mask & OMP_CLAUSE_SIMDLEN)
    4836          406 :               && (m = gfc_match_dupl_check (!c->simdlen_expr, "simdlen", true,
    4837              :                                             &c->simdlen_expr)) != MATCH_NO)
    4838              :             {
    4839          118 :               if (m == MATCH_ERROR)
    4840            0 :                 goto error;
    4841          118 :               continue;
    4842              :             }
    4843          314 :           if ((mask & OMP_CLAUSE_SIMD)
    4844          314 :               && ((m = gfc_match_boolean_clause (&bval, "simd",
    4845           26 :                                                  c->simd || cfalse->simd))
    4846              :                   != MATCH_NO))
    4847              :             {
    4848           26 :               if (m == MATCH_ERROR)
    4849            0 :                 goto error;
    4850           26 :               if (bval)
    4851           24 :                 c->simd = true;
    4852              :               else
    4853            2 :                 cfalse->simd = false;
    4854           26 :               continue;
    4855              :             }
    4856          313 :           if ((mask & OMP_CLAUSE_SEVERITY)
    4857          262 :               && (m = gfc_match_dupl_check (!c->severity, "severity", true))
    4858              :                  != MATCH_NO)
    4859              :             {
    4860           57 :               if (m == MATCH_ERROR)
    4861            2 :                 goto error;
    4862           55 :               if (gfc_match ("fatal )") == MATCH_YES)
    4863           15 :                 c->severity = OMP_SEVERITY_FATAL;
    4864           40 :               else if (gfc_match ("warning )") == MATCH_YES)
    4865           36 :                 c->severity = OMP_SEVERITY_WARNING;
    4866              :               else
    4867              :                 {
    4868            4 :                   gfc_error ("Expected FATAL or WARNING in SEVERITY clause "
    4869              :                              "at %C");
    4870            4 :                   goto error;
    4871              :                 }
    4872           51 :               continue;
    4873              :             }
    4874          205 :           if ((mask & OMP_CLAUSE_SIZES)
    4875          205 :               && ((m = gfc_match_dupl_check (!c->sizes_list, "sizes"))
    4876              :                   != MATCH_NO))
    4877              :             {
    4878          203 :               if (m == MATCH_ERROR)
    4879            0 :                 goto error;
    4880          203 :               m = match_omp_oacc_expr_list (" (", &c->sizes_list, false, true);
    4881          203 :               if (m == MATCH_ERROR)
    4882            7 :                 goto error;
    4883          196 :               if (m == MATCH_YES)
    4884          195 :                 continue;
    4885            1 :               gfc_error ("Expected %<(%> after %qs at %C", "sizes");
    4886            1 :               goto error;
    4887              :             }
    4888              :           break;
    4889         1286 :         case 't':
    4890         1351 :           if ((mask & OMP_CLAUSE_TASK_REDUCTION)
    4891         1286 :               && gfc_match_omp_clause_reduction (pc, c, openacc,
    4892              :                                                  allow_derived) == MATCH_YES)
    4893           65 :             continue;
    4894         1221 :           if ((mask & OMP_CLAUSE_THREAD_LIMIT)
    4895         1221 :               && (m = gfc_match_dupl_check (!c->thread_limit_list, "thread_limit",
    4896              :                                             true, NULL)) != MATCH_NO)
    4897              :             {
    4898          131 :               int nstrict = 0, nrelaxed = 0, ndims = 0;
    4899          131 :               bool fail = false;
    4900          131 :               gfc_expr *dims = NULL;
    4901          131 :               locus old_loc = gfc_current_locus;
    4902              : 
    4903          131 :               if (m == MATCH_ERROR)
    4904           28 :                 goto error;
    4905          177 :               while (true)
    4906              :                 {
    4907          153 :                   if (gfc_match ("strict ") == MATCH_YES)
    4908           15 :                     nstrict++;
    4909          138 :                   else if (gfc_match ("relaxed ") == MATCH_YES)
    4910           25 :                     nrelaxed++;
    4911          113 :                   else if (gfc_match ("dims ") == MATCH_YES)
    4912              :                     {
    4913           31 :                       ndims++;
    4914           31 :                       if (dims)
    4915            3 :                         gfc_free_expr (dims);
    4916           31 :                       if (gfc_match ("( %e ) ", &dims) != MATCH_YES)
    4917              :                         break;
    4918              :                     }
    4919              :                   else
    4920              :                     {
    4921              :                       fail = true;
    4922              :                       break;
    4923              :                     }
    4924           70 :                   if (gfc_match (", ") == MATCH_YES)
    4925           24 :                     continue;
    4926              :                   break;
    4927              :                 }
    4928          129 :               if (gfc_match (" : ") == MATCH_YES)
    4929              :                 {
    4930           44 :                   if (nstrict + nrelaxed + ndims == 0 || fail)
    4931              :                     {
    4932            1 :                       gfc_error ("Expected STRICT, RELAXED or DIMS modifier at "
    4933              :                                  "%C");
    4934            1 :                       goto error;
    4935              :                     }
    4936           43 :                   else if (nstrict + nrelaxed > 1)
    4937              :                     {
    4938            8 :                       gfc_error ("Only one STRICT or RELAXED modifier permitted"
    4939              :                                  " at %L", &old_loc);
    4940            8 :                       goto error;
    4941              :                     }
    4942           35 :                   if (ndims > 1)
    4943              :                     {
    4944            3 :                       gfc_error ("Duplicated DIMS expression at %L",
    4945            3 :                                  &dims->where);
    4946            3 :                       goto error;
    4947              :                     }
    4948              :                 }
    4949              :               else
    4950              :                 {
    4951           85 :                   gfc_free_expr (dims);
    4952           85 :                   dims = NULL;
    4953           85 :                   gfc_current_locus = old_loc;
    4954              :                 }
    4955              : 
    4956          117 :               m = match_omp_oacc_expr_list (NULL, &c->thread_limit_list,
    4957              :                                             false, true);
    4958          117 :               if (m != MATCH_YES)
    4959              :                 {
    4960            7 :                   gfc_error ("Expected a list of integer expressions followed "
    4961              :                              "by a %<)%> and optionally preceded by the STRICT,"
    4962              :                              " RELAXED, or DIMS as modifiers and a colon at %C");
    4963            7 :                   goto error;
    4964              :                 }
    4965          110 :               c->thread_limit_strict = (nstrict != 0) || (dims && !nrelaxed);
    4966              : 
    4967          110 :               if (!dims && c->thread_limit_list->next)
    4968              :                 {
    4969            1 :                   gfc_error ("Without the DIM modifier, only a single integer "
    4970              :                              "expression may be specified at %L",
    4971            1 :                              &c->thread_limit_list->next->expr->where);
    4972            1 :                   goto error;
    4973              :                 }
    4974          109 :               else if (dims)
    4975              :                 {
    4976           16 :                   int num = 0;
    4977           16 :                   gfc_expr_list *el;
    4978           53 :                   for (el = c->thread_limit_list; el; el = el->next)
    4979           37 :                     ++num;
    4980           16 :                   if (!gfc_resolve_expr (dims)
    4981           16 :                       || dims->ts.type != BT_INTEGER
    4982           15 :                       || dims->rank != 0
    4983           14 :                       || dims->expr_type != EXPR_CONSTANT
    4984           28 :                       || mpz_sgn (dims->value.integer) <= 0)
    4985              :                     {
    4986            5 :                       gfc_error ("DIMS must be a constant positive integer "
    4987            5 :                                  "at %L", &dims->where);
    4988            5 :                       goto error;
    4989              :                     }
    4990           11 :                   if (mpz_cmp_si (dims->value.integer, num) != 0)
    4991              :                     {
    4992            1 :                       gfc_error ("The number of arguments (%d) must be the same"
    4993              :                                  " as specified for DIMS at %L", num,
    4994              :                                  &dims->where);
    4995            1 :                       goto error;
    4996              :                     }
    4997           10 :                   c->thread_limit_dims = true;
    4998              :                 }
    4999          103 :               continue;
    5000          103 :             }
    5001         1107 :           if ((mask & OMP_CLAUSE_THREADS)
    5002         1107 :               && ((m = gfc_match_boolean_clause (&bval, "threads",
    5003           17 :                                                  c->threads || cfalse->threads))
    5004              :                   != MATCH_NO))
    5005              :             {
    5006           17 :               if (m == MATCH_ERROR)
    5007            0 :                 goto error;
    5008           17 :               if (bval)
    5009           15 :                 c->threads = true;
    5010              :               else
    5011            2 :                 cfalse->threads = false;
    5012           17 :               continue;
    5013              :             }
    5014         1270 :           if ((mask & OMP_CLAUSE_TILE)
    5015          221 :               && !c->tile_list
    5016         1294 :               && match_omp_oacc_expr_list ("tile (", &c->tile_list,
    5017              :                                            true, false) == MATCH_YES)
    5018          197 :             continue;
    5019          876 :           if ((mask & OMP_CLAUSE_TO) && (mask & OMP_CLAUSE_LINK))
    5020              :             {
    5021              :               /* Declare target: 'to' is an alias for 'enter';
    5022              :                  'to' is deprecated since 5.2.  */
    5023          117 :               m = gfc_match_omp_to_link ("to (", &c->lists[OMP_LIST_TO]);
    5024          117 :               if (m == MATCH_ERROR)
    5025            0 :                 goto error;
    5026          117 :               if (m == MATCH_YES)
    5027              :                 {
    5028          117 :                   gfc_warning (OPT_Wdeprecated_openmp,
    5029              :                                "%<to%> clause with %<declare target%> at %L "
    5030              :                                "deprecated since OpenMP 5.2, use %<enter%>",
    5031              :                                &old_loc);
    5032          117 :                   continue;
    5033              :                 }
    5034              :             }
    5035         1487 :           else if ((mask & OMP_CLAUSE_TO)
    5036          759 :                    && gfc_match_motion_var_list ("to (", &c->lists[OMP_LIST_TO],
    5037              :                                                  &head) == MATCH_YES)
    5038          728 :             continue;
    5039              :           break;
    5040         1551 :         case 'u':
    5041         1609 :           if ((mask & OMP_CLAUSE_UNIFORM)
    5042         1551 :               && gfc_match_omp_variable_list ("uniform (",
    5043              :                                               &c->lists[OMP_LIST_UNIFORM],
    5044              :                                               false) == MATCH_YES)
    5045           58 :             continue;
    5046         1636 :           if ((mask & OMP_CLAUSE_UNTIED)
    5047         1636 :               && ((m = gfc_match_boolean_clause (&bval, "untied",
    5048          143 :                                                  c->untied || cfalse->untied))
    5049              :                   != MATCH_NO))
    5050              :             {
    5051          143 :               if (m == MATCH_ERROR)
    5052            0 :                 goto error;
    5053          143 :               if (bval)
    5054          142 :                 c->untied = true;
    5055              :               else
    5056            1 :                 cfalse->untied = true;
    5057          143 :               continue;
    5058              :             }
    5059         1605 :           if ((mask & OMP_CLAUSE_ATOMIC)
    5060         1606 :               && (m = gfc_match_dupl_atomic (&bval, "update",
    5061          256 :                         c->atomic_op != GFC_OMP_ATOMIC_UNSET)) != MATCH_NO)
    5062              :             {
    5063          256 :               if (m == MATCH_ERROR)
    5064            1 :                 goto error;
    5065          255 :               if (bval)
    5066          249 :                 c->atomic_op = GFC_OMP_ATOMIC_UPDATE;
    5067          255 :               continue;
    5068              :             }
    5069         1116 :           if ((mask & OMP_CLAUSE_USE)
    5070         1094 :               && gfc_match_omp_variable_list ("use (",
    5071              :                                               &c->lists[OMP_LIST_USE],
    5072              :                                               true) == MATCH_YES)
    5073           22 :             continue;
    5074         1132 :           if ((mask & OMP_CLAUSE_USE_DEVICE)
    5075         1072 :               && gfc_match_omp_variable_list ("use_device (",
    5076              :                                               &c->lists[OMP_LIST_USE_DEVICE],
    5077              :                                               true) == MATCH_YES)
    5078           60 :             continue;
    5079         1175 :           if ((mask & OMP_CLAUSE_USE_DEVICE_PTR)
    5080         1940 :               && gfc_match_omp_variable_list
    5081          928 :                    ("use_device_ptr (",
    5082              :                     &c->lists[OMP_LIST_USE_DEVICE_PTR], false) == MATCH_YES)
    5083          163 :             continue;
    5084         1614 :           if ((mask & OMP_CLAUSE_USE_DEVICE_ADDR)
    5085         1614 :               && gfc_match_omp_variable_list
    5086          765 :                    ("use_device_addr (", &c->lists[OMP_LIST_USE_DEVICE_ADDR],
    5087              :                     false, NULL, NULL, true) == MATCH_YES)
    5088          765 :             continue;
    5089          153 :           if ((mask & OMP_CLAUSE_USES_ALLOCATORS)
    5090           84 :               && (gfc_match ("uses_allocators ( ") == MATCH_YES))
    5091              :             {
    5092           78 :               if (gfc_match_omp_clause_uses_allocators (c) != MATCH_YES)
    5093            9 :                 goto error;
    5094           69 :               continue;
    5095              :             }
    5096              :           break;
    5097         1570 :         case 'v':
    5098              :           /* VECTOR_LENGTH must be matched before VECTOR, because the latter
    5099              :              doesn't unconditionally match '('.  */
    5100         2139 :           if ((mask & OMP_CLAUSE_VECTOR_LENGTH)
    5101         1570 :               && (m = gfc_match_dupl_check (!c->vector_length_expr,
    5102              :                                             "vector_length", true,
    5103              :                                             &c->vector_length_expr))
    5104              :                  != MATCH_NO)
    5105              :             {
    5106          573 :               if (m == MATCH_ERROR)
    5107            4 :                 goto error;
    5108          569 :               continue;
    5109              :             }
    5110         1989 :           if ((mask & OMP_CLAUSE_VECTOR)
    5111          997 :               && (m = gfc_match_dupl_check (!c->vector, "vector")) != MATCH_NO)
    5112              :             {
    5113          995 :               if (m == MATCH_ERROR)
    5114            0 :                 goto error;
    5115          995 :               c->vector = true;
    5116          995 :               m = match_oacc_clause_gwv (c, GOMP_DIM_VECTOR);
    5117          995 :               if (m == MATCH_ERROR)
    5118            3 :                 goto error;
    5119          992 :               continue;
    5120              :             }
    5121              :           break;
    5122         1505 :         case 'w':
    5123         1505 :           if ((mask & OMP_CLAUSE_WAIT)
    5124         1505 :               && gfc_match ("wait") == MATCH_YES)
    5125              :             {
    5126          192 :               m = match_omp_oacc_expr_list (" (", &c->wait_list, false, false);
    5127          192 :               if (m == MATCH_ERROR)
    5128            9 :                 goto error;
    5129          183 :               else if (m == MATCH_NO)
    5130              :                 {
    5131           47 :                   gfc_expr *expr
    5132           47 :                     = gfc_get_constant_expr (BT_INTEGER,
    5133              :                                              gfc_default_integer_kind,
    5134              :                                              &gfc_current_locus);
    5135           47 :                   mpz_set_si (expr->value.integer, GOMP_ASYNC_NOVAL);
    5136           47 :                   gfc_expr_list **expr_list = &c->wait_list;
    5137           56 :                   while (*expr_list)
    5138            9 :                     expr_list = &(*expr_list)->next;
    5139           47 :                   *expr_list = gfc_get_expr_list ();
    5140           47 :                   (*expr_list)->expr = expr;
    5141           47 :                   needs_space = true;
    5142              :                 }
    5143          183 :               continue;
    5144          183 :             }
    5145         1330 :           if ((mask & OMP_CLAUSE_WEAK)
    5146         1759 :               && ((m = gfc_match_boolean_clause (&bval, "weak",
    5147          446 :                                                 c->weak || cfalse->weak))
    5148              :                   != MATCH_NO))
    5149              :             {
    5150           18 :               if (m == MATCH_ERROR)
    5151            1 :                 goto error;
    5152           17 :               if (bval)
    5153           14 :                 c->weak = true;
    5154              :               else
    5155            3 :                 cfalse->weak = true;
    5156           17 :               continue;
    5157              :             }
    5158         2156 :           if ((mask & OMP_CLAUSE_WORKER)
    5159         1295 :               && (m = gfc_match_dupl_check (!c->worker, "worker")) != MATCH_NO)
    5160              :             {
    5161          864 :               if (m == MATCH_ERROR)
    5162            0 :                 goto error;
    5163          864 :               c->worker = true;
    5164          864 :               m = match_oacc_clause_gwv (c, GOMP_DIM_WORKER);
    5165          864 :               if (m == MATCH_ERROR)
    5166            3 :                 goto error;
    5167          861 :               continue;
    5168              :             }
    5169          856 :           if ((mask & OMP_CLAUSE_ATOMIC)
    5170          859 :               && (m = gfc_match_dupl_atomic (&bval, "write",
    5171          428 :                         c->atomic_op != GFC_OMP_ATOMIC_UNSET)) != MATCH_NO)
    5172              :             {
    5173          428 :               if (m == MATCH_ERROR)
    5174            3 :                 goto error;
    5175          425 :               if (bval)
    5176          418 :                 c->atomic_op = GFC_OMP_ATOMIC_WRITE;
    5177          425 :               continue;
    5178              :             }
    5179              :           break;
    5180              :         }
    5181              :       break;
    5182        47103 :     }
    5183              : 
    5184        35216 : end:
    5185        35216 :   if (cfalse)
    5186        21348 :     gfc_free_omp_clauses (cfalse);
    5187        35216 :   if (error || gfc_match_omp_eos () != MATCH_YES)
    5188              :     {
    5189          656 :       if (!gfc_error_flag_test ())
    5190          149 :         gfc_error ("Failed to match clause at %C");
    5191          656 :       gfc_free_omp_clauses (c);
    5192          656 :       return MATCH_ERROR;
    5193              :     }
    5194              : 
    5195        34560 :   *cp = c;
    5196        34560 :   return MATCH_YES;
    5197              : 
    5198          359 : error:
    5199          359 :   error = true;
    5200          359 :   goto end;
    5201              : }
    5202              : 
    5203              : 
    5204              : #define OACC_PARALLEL_CLAUSES \
    5205              :   (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_NUM_GANGS         \
    5206              :    | OMP_CLAUSE_NUM_WORKERS | OMP_CLAUSE_VECTOR_LENGTH | OMP_CLAUSE_REDUCTION \
    5207              :    | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT                 \
    5208              :    | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT            \
    5209              :    | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE      \
    5210              :    | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH                 \
    5211              :    | OMP_CLAUSE_SELF)
    5212              : #define OACC_KERNELS_CLAUSES \
    5213              :   (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_NUM_GANGS         \
    5214              :    | OMP_CLAUSE_NUM_WORKERS | OMP_CLAUSE_VECTOR_LENGTH | OMP_CLAUSE_DEVICEPTR \
    5215              :    | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT                 \
    5216              :    | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT            \
    5217              :    | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH                 \
    5218              :    | OMP_CLAUSE_SELF)
    5219              : #define OACC_SERIAL_CLAUSES \
    5220              :   (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_REDUCTION         \
    5221              :    | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT                 \
    5222              :    | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT            \
    5223              :    | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE      \
    5224              :    | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH                 \
    5225              :    | OMP_CLAUSE_SELF)
    5226              : #define OACC_DATA_CLAUSES \
    5227              :   (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_DEVICEPTR  | OMP_CLAUSE_COPY         \
    5228              :    | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_CREATE               \
    5229              :    | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT | OMP_CLAUSE_ATTACH            \
    5230              :    | OMP_CLAUSE_DEFAULT)
    5231              : #define OACC_LOOP_CLAUSES \
    5232              :   (omp_mask (OMP_CLAUSE_COLLAPSE) | OMP_CLAUSE_GANG | OMP_CLAUSE_WORKER       \
    5233              :    | OMP_CLAUSE_VECTOR | OMP_CLAUSE_SEQ | OMP_CLAUSE_INDEPENDENT              \
    5234              :    | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_AUTO              \
    5235              :    | OMP_CLAUSE_TILE)
    5236              : #define OACC_PARALLEL_LOOP_CLAUSES \
    5237              :   (OACC_LOOP_CLAUSES | OACC_PARALLEL_CLAUSES)
    5238              : #define OACC_KERNELS_LOOP_CLAUSES \
    5239              :   (OACC_LOOP_CLAUSES | OACC_KERNELS_CLAUSES)
    5240              : #define OACC_SERIAL_LOOP_CLAUSES \
    5241              :   (OACC_LOOP_CLAUSES | OACC_SERIAL_CLAUSES)
    5242              : #define OACC_HOST_DATA_CLAUSES \
    5243              :   (omp_mask (OMP_CLAUSE_USE_DEVICE)                                           \
    5244              :    | OMP_CLAUSE_IF                                                            \
    5245              :    | OMP_CLAUSE_IF_PRESENT)
    5246              : #define OACC_DECLARE_CLAUSES \
    5247              :   (omp_mask (OMP_CLAUSE_COPY) | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT        \
    5248              :    | OMP_CLAUSE_CREATE | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_DEVICE_RESIDENT    \
    5249              :    | OMP_CLAUSE_PRESENT                       \
    5250              :    | OMP_CLAUSE_LINK)
    5251              : #define OACC_UPDATE_CLAUSES                                             \
    5252              :   (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_HOST              \
    5253              :    | OMP_CLAUSE_DEVICE | OMP_CLAUSE_WAIT | OMP_CLAUSE_IF_PRESENT              \
    5254              :    | OMP_CLAUSE_SELF)
    5255              : #define OACC_ENTER_DATA_CLAUSES \
    5256              :   (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_WAIT              \
    5257              :    | OMP_CLAUSE_COPYIN | OMP_CLAUSE_CREATE | OMP_CLAUSE_ATTACH)
    5258              : #define OACC_EXIT_DATA_CLAUSES \
    5259              :   (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_WAIT              \
    5260              :    | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_DELETE | OMP_CLAUSE_FINALIZE             \
    5261              :    | OMP_CLAUSE_DETACH)
    5262              : #define OACC_WAIT_CLAUSES \
    5263              :   omp_mask (OMP_CLAUSE_ASYNC) | OMP_CLAUSE_IF
    5264              : #define OACC_ROUTINE_CLAUSES \
    5265              :   (omp_mask (OMP_CLAUSE_GANG) | OMP_CLAUSE_WORKER | OMP_CLAUSE_VECTOR         \
    5266              :    | OMP_CLAUSE_SEQ                                                           \
    5267              :    | OMP_CLAUSE_NOHOST)
    5268              : #define OACC_INIT_CLAUSES                                                      \
    5269              :   (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_DEVICE_NUM | OMP_CLAUSE_DEVICE_TYPE)
    5270              : #define OACC_SHUTDOWN_CLAUSES                                                  \
    5271              :   (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_DEVICE_NUM | OMP_CLAUSE_DEVICE_TYPE)
    5272              : #define OACC_SET_CLAUSES                                                       \
    5273              :   (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_DEVICE_NUM | OMP_CLAUSE_DEVICE_TYPE)
    5274              : 
    5275              : 
    5276              : static match
    5277        12198 : match_acc (gfc_exec_op op, const omp_mask mask)
    5278              : {
    5279        12198 :   gfc_omp_clauses *c;
    5280        12198 :   if (gfc_match_omp_clauses (&c, mask, false, false, true) != MATCH_YES)
    5281              :     return MATCH_ERROR;
    5282        11969 :   new_st.op = op;
    5283        11969 :   new_st.ext.omp_clauses = c;
    5284        11969 :   return MATCH_YES;
    5285              : }
    5286              : 
    5287              : match
    5288         1378 : gfc_match_oacc_parallel_loop (void)
    5289              : {
    5290         1378 :   return match_acc (EXEC_OACC_PARALLEL_LOOP, OACC_PARALLEL_LOOP_CLAUSES);
    5291              : }
    5292              : 
    5293              : 
    5294              : match
    5295         2974 : gfc_match_oacc_parallel (void)
    5296              : {
    5297         2974 :   return match_acc (EXEC_OACC_PARALLEL, OACC_PARALLEL_CLAUSES);
    5298              : }
    5299              : 
    5300              : 
    5301              : match
    5302          129 : gfc_match_oacc_kernels_loop (void)
    5303              : {
    5304          129 :   return match_acc (EXEC_OACC_KERNELS_LOOP, OACC_KERNELS_LOOP_CLAUSES);
    5305              : }
    5306              : 
    5307              : 
    5308              : match
    5309          906 : gfc_match_oacc_kernels (void)
    5310              : {
    5311          906 :   return match_acc (EXEC_OACC_KERNELS, OACC_KERNELS_CLAUSES);
    5312              : }
    5313              : 
    5314              : 
    5315              : match
    5316          230 : gfc_match_oacc_serial_loop (void)
    5317              : {
    5318          230 :   return match_acc (EXEC_OACC_SERIAL_LOOP, OACC_SERIAL_LOOP_CLAUSES);
    5319              : }
    5320              : 
    5321              : 
    5322              : match
    5323          359 : gfc_match_oacc_serial (void)
    5324              : {
    5325          359 :   return match_acc (EXEC_OACC_SERIAL, OACC_SERIAL_CLAUSES);
    5326              : }
    5327              : 
    5328              : 
    5329              : match
    5330          689 : gfc_match_oacc_data (void)
    5331              : {
    5332          689 :   return match_acc (EXEC_OACC_DATA, OACC_DATA_CLAUSES);
    5333              : }
    5334              : 
    5335              : 
    5336              : match
    5337           65 : gfc_match_oacc_host_data (void)
    5338              : {
    5339           65 :   return match_acc (EXEC_OACC_HOST_DATA, OACC_HOST_DATA_CLAUSES);
    5340              : }
    5341              : 
    5342              : 
    5343              : match
    5344         3585 : gfc_match_oacc_loop (void)
    5345              : {
    5346         3585 :   return match_acc (EXEC_OACC_LOOP, OACC_LOOP_CLAUSES);
    5347              : }
    5348              : 
    5349              : 
    5350              : match
    5351          178 : gfc_match_oacc_declare (void)
    5352              : {
    5353          178 :   gfc_omp_clauses *c;
    5354          178 :   gfc_omp_namelist *n;
    5355          178 :   gfc_namespace *ns = gfc_current_ns;
    5356          178 :   gfc_oacc_declare *new_oc;
    5357          178 :   bool module_var = false;
    5358          178 :   locus where = gfc_current_locus;
    5359              : 
    5360          178 :   if (gfc_match_omp_clauses (&c, OACC_DECLARE_CLAUSES, false, false, true)
    5361              :       != MATCH_YES)
    5362              :     return MATCH_ERROR;
    5363              : 
    5364          262 :   for (n = c->lists[OMP_LIST_DEVICE_RESIDENT]; n != NULL; n = n->next)
    5365           90 :     n->sym->attr.oacc_declare_device_resident = 1;
    5366              : 
    5367          192 :   for (n = c->lists[OMP_LIST_LINK]; n != NULL; n = n->next)
    5368           20 :     n->sym->attr.oacc_declare_link = 1;
    5369              : 
    5370          318 :   for (n = c->lists[OMP_LIST_MAP]; n != NULL; n = n->next)
    5371              :     {
    5372          156 :       gfc_symbol *s = n->sym;
    5373              : 
    5374          156 :       if (gfc_current_ns->proc_name
    5375          156 :           && gfc_current_ns->proc_name->attr.flavor == FL_MODULE)
    5376              :         {
    5377           52 :           if (n->u.map.op != OMP_MAP_ALLOC && n->u.map.op != OMP_MAP_TO)
    5378              :             {
    5379            6 :               gfc_error ("Invalid clause in module with !$ACC DECLARE at %L",
    5380              :                          &where);
    5381            6 :               return MATCH_ERROR;
    5382              :             }
    5383              : 
    5384              :           module_var = true;
    5385              :         }
    5386              : 
    5387          150 :       if (s->attr.use_assoc)
    5388              :         {
    5389            0 :           gfc_error ("Variable is USE-associated with !$ACC DECLARE at %L",
    5390              :                      &where);
    5391            0 :           return MATCH_ERROR;
    5392              :         }
    5393              : 
    5394          150 :       if ((s->result == s && s->ns->contained != gfc_current_ns)
    5395          150 :           || ((s->attr.flavor == FL_UNKNOWN || s->attr.flavor == FL_VARIABLE)
    5396          135 :               && s->ns != gfc_current_ns))
    5397              :         {
    5398            2 :           gfc_error ("Variable %qs shall be declared in the same scoping unit "
    5399              :                      "as !$ACC DECLARE at %L", s->name, &where);
    5400            2 :           return MATCH_ERROR;
    5401              :         }
    5402              : 
    5403          148 :       if ((s->attr.dimension || s->attr.codimension)
    5404           76 :           && s->attr.dummy && s->as->type != AS_EXPLICIT)
    5405              :         {
    5406            2 :           gfc_error ("Assumed-size dummy array with !$ACC DECLARE at %L",
    5407              :                      &where);
    5408            2 :           return MATCH_ERROR;
    5409              :         }
    5410              : 
    5411          146 :       switch (n->u.map.op)
    5412              :         {
    5413           49 :           case OMP_MAP_FORCE_ALLOC:
    5414           49 :           case OMP_MAP_ALLOC:
    5415           49 :             s->attr.oacc_declare_create = 1;
    5416           49 :             break;
    5417              : 
    5418           63 :           case OMP_MAP_FORCE_TO:
    5419           63 :           case OMP_MAP_TO:
    5420           63 :             s->attr.oacc_declare_copyin = 1;
    5421           63 :             break;
    5422              : 
    5423            1 :           case OMP_MAP_FORCE_DEVICEPTR:
    5424            1 :             s->attr.oacc_declare_deviceptr = 1;
    5425            1 :             break;
    5426              : 
    5427              :           default:
    5428              :             break;
    5429              :         }
    5430              :     }
    5431              : 
    5432          162 :   new_oc = gfc_get_oacc_declare ();
    5433          162 :   new_oc->next = ns->oacc_declare;
    5434          162 :   new_oc->module_var = module_var;
    5435          162 :   new_oc->clauses = c;
    5436          162 :   new_oc->loc = gfc_current_locus;
    5437          162 :   ns->oacc_declare = new_oc;
    5438              : 
    5439          162 :   return MATCH_YES;
    5440              : }
    5441              : 
    5442              : 
    5443              : match
    5444          760 : gfc_match_oacc_update (void)
    5445              : {
    5446          760 :   gfc_omp_clauses *c;
    5447          760 :   locus here = gfc_current_locus;
    5448              : 
    5449          760 :   if (gfc_match_omp_clauses (&c, OACC_UPDATE_CLAUSES, false, false, true)
    5450              :       != MATCH_YES)
    5451              :     return MATCH_ERROR;
    5452              : 
    5453          756 :   if (!c->lists[OMP_LIST_MAP])
    5454              :     {
    5455            1 :       gfc_error ("%<acc update%> must contain at least one "
    5456              :                  "%<device%> or %<host%> or %<self%> clause at %L", &here);
    5457            1 :       return MATCH_ERROR;
    5458              :     }
    5459              : 
    5460          755 :   new_st.op = EXEC_OACC_UPDATE;
    5461          755 :   new_st.ext.omp_clauses = c;
    5462          755 :   return MATCH_YES;
    5463              : }
    5464              : 
    5465              : 
    5466              : match
    5467          877 : gfc_match_oacc_enter_data (void)
    5468              : {
    5469          877 :   return match_acc (EXEC_OACC_ENTER_DATA, OACC_ENTER_DATA_CLAUSES);
    5470              : }
    5471              : 
    5472              : 
    5473              : match
    5474          612 : gfc_match_oacc_exit_data (void)
    5475              : {
    5476          612 :   return match_acc (EXEC_OACC_EXIT_DATA, OACC_EXIT_DATA_CLAUSES);
    5477              : }
    5478              : 
    5479              : 
    5480              : match
    5481          202 : gfc_match_oacc_wait (void)
    5482              : {
    5483          202 :   gfc_omp_clauses *c = gfc_get_omp_clauses ();
    5484          202 :   gfc_expr_list *wait_list = NULL, *el;
    5485          202 :   bool space = true;
    5486          202 :   match m;
    5487              : 
    5488          202 :   m = match_omp_oacc_expr_list (" (", &wait_list, true, false);
    5489          202 :   if (m == MATCH_ERROR)
    5490              :     return m;
    5491          196 :   else if (m == MATCH_YES)
    5492          126 :     space = false;
    5493              : 
    5494          196 :   if (gfc_match_omp_clauses (&c, OACC_WAIT_CLAUSES, space, space, true)
    5495              :       == MATCH_ERROR)
    5496              :     return MATCH_ERROR;
    5497              : 
    5498          184 :   if (wait_list)
    5499          261 :     for (el = wait_list; el; el = el->next)
    5500              :       {
    5501          140 :         if (el->expr == NULL)
    5502              :           {
    5503            2 :             gfc_error ("Invalid argument to !$ACC WAIT at %C");
    5504            2 :             return MATCH_ERROR;
    5505              :           }
    5506              : 
    5507          138 :         if (!gfc_resolve_expr (el->expr)
    5508          138 :             || el->expr->ts.type != BT_INTEGER || el->expr->rank != 0)
    5509              :           {
    5510            3 :             gfc_error ("WAIT clause at %L requires a scalar INTEGER expression",
    5511            3 :                        &el->expr->where);
    5512              : 
    5513            3 :             return MATCH_ERROR;
    5514              :           }
    5515              :       }
    5516          179 :   c->wait_list = wait_list;
    5517          179 :   new_st.op = EXEC_OACC_WAIT;
    5518          179 :   new_st.ext.omp_clauses = c;
    5519          179 :   return MATCH_YES;
    5520              : }
    5521              : 
    5522              : 
    5523              : match
    5524           97 : gfc_match_oacc_cache (void)
    5525              : {
    5526           97 :   bool readonly = false;
    5527           97 :   gfc_omp_clauses *c = gfc_get_omp_clauses ();
    5528              :   /* The OpenACC cache directive explicitly only allows "array elements or
    5529              :      subarrays", which we're currently not checking here.  Either check this
    5530              :      after the call of gfc_match_omp_variable_list, or add something like a
    5531              :      only_sections variant next to its allow_sections parameter.  */
    5532           97 :   match m = gfc_match (" ( ");
    5533           97 :   if (m != MATCH_YES)
    5534              :     {
    5535            0 :       gfc_free_omp_clauses(c);
    5536            0 :       return m;
    5537              :     }
    5538              : 
    5539           97 :   if (gfc_match ("readonly : ") == MATCH_YES)
    5540            8 :     readonly = true;
    5541              : 
    5542           97 :   gfc_omp_namelist **head = NULL;
    5543           97 :   m = gfc_match_omp_variable_list ("", &c->lists[OMP_LIST_CACHE], true,
    5544              :                                    NULL, &head, true);
    5545           97 :   if (m != MATCH_YES)
    5546              :     {
    5547            2 :       gfc_free_omp_clauses(c);
    5548            2 :       return m;
    5549              :     }
    5550              : 
    5551           95 :   if (readonly)
    5552           24 :     for (gfc_omp_namelist *n = *head; n; n = n->next)
    5553           16 :       n->u.map.readonly = true;
    5554              : 
    5555           95 :   if (gfc_current_state() != COMP_DO
    5556           56 :       && gfc_current_state() != COMP_DO_CONCURRENT)
    5557              :     {
    5558            2 :       gfc_error ("ACC CACHE directive must be inside of loop %C");
    5559            2 :       gfc_free_omp_clauses(c);
    5560            2 :       return MATCH_ERROR;
    5561              :     }
    5562              : 
    5563           93 :   new_st.op = EXEC_OACC_CACHE;
    5564           93 :   new_st.ext.omp_clauses = c;
    5565           93 :   return MATCH_YES;
    5566              : }
    5567              : 
    5568              : match
    5569          134 : gfc_match_oacc_init (void)
    5570              : {
    5571          134 :   return match_acc (EXEC_OACC_INIT, OACC_INIT_CLAUSES);
    5572              : }
    5573              : 
    5574              : match
    5575          130 : gfc_match_oacc_shutdown (void)
    5576              : {
    5577          130 :   return match_acc (EXEC_OACC_SHUTDOWN, OACC_SHUTDOWN_CLAUSES);
    5578              : }
    5579              : 
    5580              : match
    5581          130 : gfc_match_oacc_set (void)
    5582              : {
    5583          130 :   return match_acc (EXEC_OACC_SET, OACC_SET_CLAUSES);
    5584              : }
    5585              : 
    5586              : /* Determine the OpenACC 'routine' directive's level of parallelism.  */
    5587              : 
    5588              : static oacc_routine_lop
    5589          734 : gfc_oacc_routine_lop (gfc_omp_clauses *clauses)
    5590              : {
    5591          734 :   oacc_routine_lop ret = OACC_ROUTINE_LOP_SEQ;
    5592              : 
    5593          734 :   if (clauses)
    5594              :     {
    5595          584 :       unsigned n_lop_clauses = 0;
    5596              : 
    5597          584 :       if (clauses->gang)
    5598              :         {
    5599          164 :           ++n_lop_clauses;
    5600          164 :           ret = OACC_ROUTINE_LOP_GANG;
    5601              :         }
    5602          584 :       if (clauses->worker)
    5603              :         {
    5604          114 :           ++n_lop_clauses;
    5605          114 :           ret = OACC_ROUTINE_LOP_WORKER;
    5606              :         }
    5607          584 :       if (clauses->vector)
    5608              :         {
    5609          116 :           ++n_lop_clauses;
    5610          116 :           ret = OACC_ROUTINE_LOP_VECTOR;
    5611              :         }
    5612          584 :       if (clauses->seq)
    5613              :         {
    5614          206 :           ++n_lop_clauses;
    5615          206 :           ret = OACC_ROUTINE_LOP_SEQ;
    5616              :         }
    5617              : 
    5618          584 :       if (n_lop_clauses > 1)
    5619           47 :         ret = OACC_ROUTINE_LOP_ERROR;
    5620              :     }
    5621              : 
    5622          734 :   return ret;
    5623              : }
    5624              : 
    5625              : match
    5626          698 : gfc_match_oacc_routine (void)
    5627              : {
    5628          698 :   locus old_loc;
    5629          698 :   match m;
    5630          698 :   gfc_intrinsic_sym *isym = NULL;
    5631          698 :   gfc_symbol *sym = NULL;
    5632          698 :   gfc_omp_clauses *c = NULL;
    5633          698 :   gfc_oacc_routine_name *n = NULL;
    5634          698 :   oacc_routine_lop lop = OACC_ROUTINE_LOP_NONE;
    5635          698 :   bool nohost;
    5636              : 
    5637          698 :   old_loc = gfc_current_locus;
    5638              : 
    5639          698 :   m = gfc_match (" (");
    5640              : 
    5641          698 :   if (gfc_current_ns->proc_name
    5642          696 :       && gfc_current_ns->proc_name->attr.if_source == IFSRC_IFBODY
    5643           90 :       && m == MATCH_YES)
    5644              :     {
    5645            3 :       gfc_error ("Only the !$ACC ROUTINE form without "
    5646              :                  "list is allowed in interface block at %C");
    5647            3 :       goto cleanup;
    5648              :     }
    5649              : 
    5650          608 :   if (m == MATCH_YES)
    5651              :     {
    5652          295 :       char buffer[GFC_MAX_SYMBOL_LEN + 1];
    5653              : 
    5654          295 :       m = gfc_match_name (buffer);
    5655          295 :       if (m == MATCH_YES)
    5656              :         {
    5657          294 :           gfc_symtree *st = NULL;
    5658              : 
    5659              :           /* First look for an intrinsic symbol.  */
    5660          294 :           isym = gfc_find_function (buffer);
    5661          294 :           if (!isym)
    5662          294 :             isym = gfc_find_subroutine (buffer);
    5663              :           /* If no intrinsic symbol found, search the current namespace.  */
    5664          294 :           if (!isym)
    5665          276 :             st = gfc_find_symtree (gfc_current_ns->sym_root, buffer);
    5666          276 :           if (st)
    5667              :             {
    5668          270 :               sym = st->n.sym;
    5669              :               /* If the name in a 'routine' directive refers to the containing
    5670              :                  subroutine or function, then make sure that we'll later handle
    5671              :                  this accordingly.  */
    5672          270 :               if (gfc_current_ns->proc_name != NULL
    5673          270 :                   && strcmp (sym->name, gfc_current_ns->proc_name->name) == 0)
    5674          294 :                 sym = NULL;
    5675              :             }
    5676              : 
    5677          294 :           if (isym == NULL && st == NULL)
    5678              :             {
    5679            6 :               gfc_error ("Invalid NAME %qs in !$ACC ROUTINE ( NAME ) at %C",
    5680              :                          buffer);
    5681            6 :               gfc_current_locus = old_loc;
    5682            9 :               return MATCH_ERROR;
    5683              :             }
    5684              :         }
    5685              :       else
    5686              :         {
    5687            1 :           gfc_error ("Syntax error in !$ACC ROUTINE ( NAME ) at %C");
    5688            1 :           gfc_current_locus = old_loc;
    5689            1 :           return MATCH_ERROR;
    5690              :         }
    5691              : 
    5692          288 :       if (gfc_match_char (')') != MATCH_YES)
    5693              :         {
    5694            2 :           gfc_error ("Syntax error in !$ACC ROUTINE ( NAME ) at %C, expecting"
    5695              :                      " %<)%> after NAME");
    5696            2 :           gfc_current_locus = old_loc;
    5697            2 :           return MATCH_ERROR;
    5698              :         }
    5699              :     }
    5700              : 
    5701          686 :   if (gfc_match_omp_eos () != MATCH_YES
    5702          686 :       && (gfc_match_omp_clauses (&c, OACC_ROUTINE_CLAUSES, false, false, true)
    5703              :           != MATCH_YES))
    5704              :     return MATCH_ERROR;
    5705              : 
    5706          683 :   lop = gfc_oacc_routine_lop (c);
    5707          683 :   if (lop == OACC_ROUTINE_LOP_ERROR)
    5708              :     {
    5709           47 :       gfc_error ("Multiple loop axes specified for routine at %C");
    5710           47 :       goto cleanup;
    5711              :     }
    5712          636 :   nohost = c ? c->nohost : false;
    5713              : 
    5714          636 :   if (isym != NULL)
    5715              :     {
    5716              :       /* Diagnose any OpenACC 'routine' directive that doesn't match the
    5717              :          (implicit) one with a 'seq' clause.  */
    5718           16 :       if (c && (c->gang || c->worker || c->vector))
    5719              :         {
    5720           10 :           gfc_error ("Intrinsic symbol specified in !$ACC ROUTINE ( NAME )"
    5721              :                      " at %C marked with incompatible GANG, WORKER, or VECTOR"
    5722              :                      " clause");
    5723           10 :           goto cleanup;
    5724              :         }
    5725              :       /* ..., and no 'nohost' clause.  */
    5726            6 :       if (nohost)
    5727              :         {
    5728            2 :           gfc_error ("Intrinsic symbol specified in !$ACC ROUTINE ( NAME )"
    5729              :                      " at %C marked with incompatible NOHOST clause");
    5730            2 :           goto cleanup;
    5731              :         }
    5732              :     }
    5733          620 :   else if (sym != NULL)
    5734              :     {
    5735          151 :       bool add = true;
    5736              : 
    5737              :       /* For a repeated OpenACC 'routine' directive, diagnose if it doesn't
    5738              :          match the first one.  */
    5739          151 :       for (gfc_oacc_routine_name *n_p = gfc_current_ns->oacc_routine_names;
    5740          346 :            n_p;
    5741          195 :            n_p = n_p->next)
    5742          235 :         if (n_p->sym == sym)
    5743              :           {
    5744           51 :             add = false;
    5745           51 :             bool nohost_p = n_p->clauses ? n_p->clauses->nohost : false;
    5746           51 :             if (lop != gfc_oacc_routine_lop (n_p->clauses)
    5747           51 :                 || nohost != nohost_p)
    5748              :               {
    5749           40 :                 gfc_error ("!$ACC ROUTINE already applied at %C");
    5750           40 :                 goto cleanup;
    5751              :               }
    5752              :           }
    5753              : 
    5754          111 :       if (add)
    5755              :         {
    5756          100 :           sym->attr.oacc_routine_lop = lop;
    5757          100 :           sym->attr.oacc_routine_nohost = nohost;
    5758              : 
    5759          100 :           n = gfc_get_oacc_routine_name ();
    5760          100 :           n->sym = sym;
    5761          100 :           n->clauses = c;
    5762          100 :           n->next = gfc_current_ns->oacc_routine_names;
    5763          100 :           n->loc = old_loc;
    5764          100 :           gfc_current_ns->oacc_routine_names = n;
    5765              :         }
    5766              :     }
    5767          469 :   else if (gfc_current_ns->proc_name)
    5768              :     {
    5769              :       /* For a repeated OpenACC 'routine' directive, diagnose if it doesn't
    5770              :          match the first one.  */
    5771          468 :       oacc_routine_lop lop_p = gfc_current_ns->proc_name->attr.oacc_routine_lop;
    5772          468 :       bool nohost_p = gfc_current_ns->proc_name->attr.oacc_routine_nohost;
    5773          468 :       if (lop_p != OACC_ROUTINE_LOP_NONE
    5774           86 :           && (lop != lop_p
    5775           86 :               || nohost != nohost_p))
    5776              :         {
    5777           56 :           gfc_error ("!$ACC ROUTINE already applied at %C");
    5778           56 :           goto cleanup;
    5779              :         }
    5780              : 
    5781          412 :       if (!gfc_add_omp_declare_target (&gfc_current_ns->proc_name->attr,
    5782              :                                        gfc_current_ns->proc_name->name,
    5783              :                                        &old_loc))
    5784            1 :         goto cleanup;
    5785          411 :       gfc_current_ns->proc_name->attr.oacc_routine_lop = lop;
    5786          411 :       gfc_current_ns->proc_name->attr.oacc_routine_nohost = nohost;
    5787              :     }
    5788              :   else
    5789              :     /* Something has gone wrong, possibly a syntax error.  */
    5790            1 :     goto cleanup;
    5791              : 
    5792          526 :   if (gfc_pure (NULL) && c && (c->gang || c->worker || c->vector))
    5793              :     {
    5794            6 :       gfc_error ("!$ACC ROUTINE with GANG, WORKER, or VECTOR clause is not "
    5795              :                  "permitted in PURE procedure at %C");
    5796            6 :       goto cleanup;
    5797              :     }
    5798              : 
    5799              : 
    5800          520 :   if (n)
    5801          100 :     n->clauses = c;
    5802          420 :   else if (gfc_current_ns->oacc_routine)
    5803            0 :     gfc_current_ns->oacc_routine_clauses = c;
    5804              : 
    5805          520 :   new_st.op = EXEC_OACC_ROUTINE;
    5806          520 :   new_st.ext.omp_clauses = c;
    5807          520 :   return MATCH_YES;
    5808              : 
    5809          166 : cleanup:
    5810          166 :   gfc_current_locus = old_loc;
    5811          166 :   return MATCH_ERROR;
    5812              : }
    5813              : 
    5814              : 
    5815              : #define OMP_PARALLEL_CLAUSES \
    5816              :   (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE              \
    5817              :    | OMP_CLAUSE_SHARED | OMP_CLAUSE_COPYIN | OMP_CLAUSE_REDUCTION       \
    5818              :    | OMP_CLAUSE_IF | OMP_CLAUSE_NUM_THREADS | OMP_CLAUSE_DEFAULT        \
    5819              :    | OMP_CLAUSE_PROC_BIND | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_MESSAGE    \
    5820              :    | OMP_CLAUSE_SEVERITY)
    5821              : #define OMP_DECLARE_SIMD_CLAUSES \
    5822              :   (omp_mask (OMP_CLAUSE_SIMDLEN) | OMP_CLAUSE_LINEAR                    \
    5823              :    | OMP_CLAUSE_UNIFORM | OMP_CLAUSE_ALIGNED | OMP_CLAUSE_INBRANCH      \
    5824              :    | OMP_CLAUSE_NOTINBRANCH)
    5825              : #define OMP_DO_CLAUSES \
    5826              :   (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE              \
    5827              :    | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION                      \
    5828              :    | OMP_CLAUSE_SCHEDULE | OMP_CLAUSE_ORDERED | OMP_CLAUSE_COLLAPSE     \
    5829              :    | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ORDER | OMP_CLAUSE_ALLOCATE         \
    5830              :    | OMP_CLAUSE_NOWAIT)
    5831              : #define OMP_LOOP_CLAUSES \
    5832              :   (omp_mask (OMP_CLAUSE_BIND) | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_ORDER  \
    5833              :    | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION)
    5834              : 
    5835              : #define OMP_SCOPE_CLAUSES \
    5836              :   (omp_mask (OMP_CLAUSE_PRIVATE) |OMP_CLAUSE_FIRSTPRIVATE               \
    5837              :    | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT)
    5838              : #define OMP_SECTIONS_CLAUSES \
    5839              :   (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE              \
    5840              :    | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION                      \
    5841              :    | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT)
    5842              : #define OMP_SIMD_CLAUSES \
    5843              :   (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_LASTPRIVATE               \
    5844              :    | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_SAFELEN    \
    5845              :    | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ALIGNED | OMP_CLAUSE_SIMDLEN        \
    5846              :    | OMP_CLAUSE_IF | OMP_CLAUSE_ORDER | OMP_CLAUSE_NOTEMPORAL)
    5847              : #define OMP_TASK_CLAUSES \
    5848              :   (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE              \
    5849              :    | OMP_CLAUSE_SHARED | OMP_CLAUSE_IF | OMP_CLAUSE_DEFAULT             \
    5850              :    | OMP_CLAUSE_UNTIED | OMP_CLAUSE_FINAL | OMP_CLAUSE_MERGEABLE        \
    5851              :    | OMP_CLAUSE_DEPEND | OMP_CLAUSE_PRIORITY | OMP_CLAUSE_IN_REDUCTION  \
    5852              :    | OMP_CLAUSE_DETACH | OMP_CLAUSE_AFFINITY | OMP_CLAUSE_ALLOCATE)
    5853              : #define OMP_TASKLOOP_CLAUSES \
    5854              :   (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE              \
    5855              :    | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_IF         \
    5856              :    | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_UNTIED | OMP_CLAUSE_FINAL          \
    5857              :    | OMP_CLAUSE_MERGEABLE | OMP_CLAUSE_PRIORITY | OMP_CLAUSE_GRAINSIZE  \
    5858              :    | OMP_CLAUSE_NUM_TASKS | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_NOGROUP    \
    5859              :    | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_IN_REDUCTION | OMP_CLAUSE_ALLOCATE)
    5860              : #define OMP_TASKGROUP_CLAUSES \
    5861              :   (omp_mask (OMP_CLAUSE_TASK_REDUCTION) | OMP_CLAUSE_ALLOCATE)
    5862              : #define OMP_TARGET_CLAUSES \
    5863              :   (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF        \
    5864              :    | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_PRIVATE         \
    5865              :    | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_DEFAULTMAP                    \
    5866              :    | OMP_CLAUSE_IS_DEVICE_PTR | OMP_CLAUSE_IN_REDUCTION                 \
    5867              :    | OMP_CLAUSE_THREAD_LIMIT | OMP_CLAUSE_ALLOCATE                      \
    5868              :    | OMP_CLAUSE_HAS_DEVICE_ADDR | OMP_CLAUSE_USES_ALLOCATORS            \
    5869              :    | OMP_CLAUSE_DYN_GROUPPRIVATE | OMP_CLAUSE_DEVICE_TYPE               \
    5870              :    | OMP_CLAUSE_MESSAGE | OMP_CLAUSE_SEVERITY)
    5871              : #define OMP_TARGET_DATA_CLAUSES \
    5872              :   (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF        \
    5873              :    | OMP_CLAUSE_USE_DEVICE_PTR | OMP_CLAUSE_USE_DEVICE_ADDR)
    5874              : #define OMP_TARGET_ENTER_DATA_CLAUSES \
    5875              :   (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF        \
    5876              :    | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT)
    5877              : #define OMP_TARGET_EXIT_DATA_CLAUSES \
    5878              :   (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF        \
    5879              :    | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT)
    5880              : #define OMP_TARGET_UPDATE_CLAUSES \
    5881              :   (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_IF | OMP_CLAUSE_TO         \
    5882              :    | OMP_CLAUSE_FROM | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT)
    5883              : #define OMP_TEAMS_CLAUSES \
    5884              :   (omp_mask (OMP_CLAUSE_NUM_TEAMS) | OMP_CLAUSE_THREAD_LIMIT            \
    5885              :    | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE  \
    5886              :    | OMP_CLAUSE_SHARED | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_ALLOCATE     \
    5887              :    | OMP_CLAUSE_MESSAGE | OMP_CLAUSE_SEVERITY)
    5888              : #define OMP_DISTRIBUTE_CLAUSES \
    5889              :   (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE              \
    5890              :    | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_DIST_SCHEDULE \
    5891              :    | OMP_CLAUSE_ORDER | OMP_CLAUSE_ALLOCATE)
    5892              : #define OMP_SINGLE_CLAUSES \
    5893              :   (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE              \
    5894              :    | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_COPYPRIVATE)
    5895              : #define OMP_ORDERED_CLAUSES \
    5896              :   (omp_mask (OMP_CLAUSE_THREADS) | OMP_CLAUSE_SIMD)
    5897              : #define OMP_DECLARE_TARGET_CLAUSES \
    5898              :   (omp_mask (OMP_CLAUSE_ENTER) | OMP_CLAUSE_LINK | OMP_CLAUSE_DEVICE_TYPE \
    5899              :    | OMP_CLAUSE_TO | OMP_CLAUSE_INDIRECT | OMP_CLAUSE_LOCAL)
    5900              : #define OMP_ATOMIC_CLAUSES \
    5901              :   (omp_mask (OMP_CLAUSE_ATOMIC) | OMP_CLAUSE_CAPTURE | OMP_CLAUSE_HINT  \
    5902              :    | OMP_CLAUSE_MEMORDER | OMP_CLAUSE_COMPARE | OMP_CLAUSE_FAIL         \
    5903              :    | OMP_CLAUSE_WEAK)
    5904              : #define OMP_MASKED_CLAUSES \
    5905              :   (omp_mask (OMP_CLAUSE_FILTER))
    5906              : #define OMP_ERROR_CLAUSES \
    5907              :   (omp_mask (OMP_CLAUSE_AT) | OMP_CLAUSE_MESSAGE | OMP_CLAUSE_SEVERITY)
    5908              : #define OMP_WORKSHARE_CLAUSES \
    5909              :   omp_mask (OMP_CLAUSE_NOWAIT)
    5910              : #define OMP_UNROLL_CLAUSES \
    5911              :   (omp_mask (OMP_CLAUSE_FULL) | OMP_CLAUSE_PARTIAL)
    5912              : #define OMP_TILE_CLAUSES \
    5913              :   (omp_mask (OMP_CLAUSE_SIZES))
    5914              : #define OMP_ALLOCATORS_CLAUSES \
    5915              :   omp_mask (OMP_CLAUSE_ALLOCATE)
    5916              : #define OMP_INTEROP_CLAUSES \
    5917              :   (omp_mask (OMP_CLAUSE_DEPEND) | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_DEVICE \
    5918              :    | OMP_CLAUSE_INIT | OMP_CLAUSE_DESTROY | OMP_CLAUSE_USE)
    5919              : #define OMP_DISPATCH_CLAUSES                                                   \
    5920              :   (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOVARIANTS    \
    5921              :    | OMP_CLAUSE_NOCONTEXT | OMP_CLAUSE_IS_DEVICE_PTR | OMP_CLAUSE_NOWAIT       \
    5922              :    | OMP_CLAUSE_HAS_DEVICE_ADDR | OMP_CLAUSE_INTEROP)
    5923              : 
    5924              : 
    5925              : static match
    5926        17391 : match_omp (gfc_exec_op op, const omp_mask mask)
    5927              : {
    5928        17391 :   gfc_omp_clauses *c;
    5929        17391 :   if (gfc_match_omp_clauses (&c, mask, false, true, false,
    5930              :                              op == EXEC_OMP_TARGET) != MATCH_YES)
    5931              :     return MATCH_ERROR;
    5932        17046 :   new_st.op = op;
    5933        17046 :   new_st.ext.omp_clauses = c;
    5934        17046 :   return MATCH_YES;
    5935              : }
    5936              : 
    5937              : /* Handles both declarative and (deprecated) executable ALLOCATE directive;
    5938              :    accepts optional list (for executable) and common blocks.
    5939              :    If no variables have been provided, the single omp namelist has sym == NULL.
    5940              : 
    5941              :    Note that the executable ALLOCATE directive permits structure elements only
    5942              :    in OpenMP 5.0 and 5.1 but not longer in 5.2.  See also the comment on the
    5943              :    'omp allocators' directive below. The accidental change was reverted for
    5944              :    OpenMP TR12, permitting them again. See also gfc_match_omp_allocators.
    5945              : 
    5946              :    Hence, structure elements are rejected for now, also to make resolving
    5947              :    OMP_LIST_ALLOCATE simpler (check for duplicates, same symbol in
    5948              :    Fortran allocate stmt).  TODO: Permit structure elements.  */
    5949              : 
    5950              : match
    5951          274 : gfc_match_omp_allocate (void)
    5952              : {
    5953          274 :   match m;
    5954          274 :   gfc_omp_namelist *vars = NULL;
    5955          274 :   gfc_expr *align = NULL;
    5956          274 :   gfc_expr *allocator = NULL;
    5957          274 :   locus loc = gfc_current_locus;
    5958              : 
    5959          274 :   m = gfc_match_omp_variable_list (" (", &vars, true, NULL, NULL, true, true,
    5960              :                                    NULL, true);
    5961              : 
    5962          274 :   if (m == MATCH_ERROR)
    5963              :     return m;
    5964              : 
    5965          502 :   while (true)
    5966              :     {
    5967          502 :       gfc_gobble_whitespace ();
    5968          502 :       if (gfc_match_omp_eos () == MATCH_YES)
    5969              :         break;
    5970          234 :       gfc_match (", ");  /* optionally  */
    5971          234 :       if ((m = gfc_match_dupl_check (!align, "align", true, &align))
    5972              :           != MATCH_NO)
    5973              :         {
    5974           62 :           if (m == MATCH_ERROR)
    5975            1 :             goto error;
    5976           61 :           continue;
    5977              :         }
    5978          172 :       if ((m = gfc_match_dupl_check (!allocator, "allocator",
    5979              :                                      true, &allocator)) != MATCH_NO)
    5980              :         {
    5981          171 :           if (m == MATCH_ERROR)
    5982            1 :             goto error;
    5983          170 :           continue;
    5984              :         }
    5985            1 :       gfc_error ("Expected ALIGN or ALLOCATOR clause at %C");
    5986            1 :       return MATCH_ERROR;
    5987              :     }
    5988          541 :   for (gfc_omp_namelist *n = vars; n; n = n->next)
    5989          276 :     if (n->expr)
    5990              :       {
    5991            3 :         if ((n->expr->ref && n->expr->ref->type == REF_COMPONENT)
    5992            3 :             || (n->expr->ref->next && n->expr->ref->type == REF_COMPONENT))
    5993            1 :           gfc_error ("Sorry, structure-element list item at %L in ALLOCATE "
    5994              :                      "directive is not yet supported", &n->expr->where);
    5995              :         else
    5996            2 :           gfc_error ("Unexpected expression as list item at %L in ALLOCATE "
    5997              :                      "directive", &n->expr->where);
    5998              : 
    5999            3 :         gfc_free_omp_namelist (vars, OMP_LIST_ALLOCATE);
    6000            3 :         goto error;
    6001              :       }
    6002              : 
    6003          265 :   new_st.op = EXEC_OMP_ALLOCATE;
    6004          265 :   new_st.ext.omp_clauses = gfc_get_omp_clauses ();
    6005          265 :   if (vars == NULL)
    6006              :     {
    6007           27 :       vars = gfc_get_omp_namelist ();
    6008           27 :       vars->where = loc;
    6009           27 :       vars->u.align = align;
    6010           27 :       vars->u2.allocator = allocator;
    6011           27 :       new_st.ext.omp_clauses->lists[OMP_LIST_ALLOCATE] = vars;
    6012              :     }
    6013              :   else
    6014              :     {
    6015          238 :       new_st.ext.omp_clauses->lists[OMP_LIST_ALLOCATE] = vars;
    6016          511 :       for (; vars; vars = vars->next)
    6017              :         {
    6018          273 :           vars->u.align = (align) ? gfc_copy_expr (align) : NULL;
    6019          273 :           vars->u2.allocator = allocator;
    6020              :         }
    6021          238 :       gfc_free_expr (align);
    6022              :     }
    6023              :   return MATCH_YES;
    6024              : 
    6025            5 : error:
    6026            5 :   gfc_free_expr (align);
    6027            5 :   gfc_free_expr (allocator);
    6028            5 :   return MATCH_ERROR;
    6029              : }
    6030              : 
    6031              : /* In line with OpenMP 5.2 derived-type components are rejected.
    6032              :    See also comment before gfc_match_omp_allocate.  */
    6033              : 
    6034              : match
    6035           26 : gfc_match_omp_allocators (void)
    6036              : {
    6037           26 :   return match_omp (EXEC_OMP_ALLOCATORS, OMP_ALLOCATORS_CLAUSES);
    6038              : }
    6039              : 
    6040              : 
    6041              : match
    6042           25 : gfc_match_omp_assume (void)
    6043              : {
    6044           25 :   gfc_omp_clauses *c;
    6045           25 :   locus loc = gfc_current_locus;
    6046           32 :   if ((gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_ASSUMPTIONS), false)
    6047              :        != MATCH_YES)
    6048           25 :       || (omp_verify_merge_absent_contains (ST_OMP_ASSUME, c->assume, NULL,
    6049              :                                             &loc) != MATCH_YES))
    6050              :     return MATCH_ERROR;
    6051           18 :   new_st.op = EXEC_OMP_ASSUME;
    6052           18 :   new_st.ext.omp_clauses = c;
    6053           18 :   return MATCH_YES;
    6054              : }
    6055              : 
    6056              : 
    6057              : match
    6058           38 : gfc_match_omp_assumes (void)
    6059              : {
    6060           38 :   gfc_omp_clauses *c;
    6061           38 :   locus loc = gfc_current_locus;
    6062           38 :   if (!gfc_current_ns->proc_name
    6063           37 :       || (gfc_current_ns->proc_name->attr.flavor != FL_MODULE
    6064           23 :           && !gfc_current_ns->proc_name->attr.subroutine
    6065           10 :           && !gfc_current_ns->proc_name->attr.function))
    6066              :     {
    6067            2 :       gfc_error ("!$OMP ASSUMES at %C must be in the specification part of a "
    6068              :                  "subprogram or module");
    6069            2 :       return MATCH_ERROR;
    6070              :     }
    6071           46 :   if ((gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_ASSUMPTIONS), false)
    6072              :        != MATCH_YES)
    6073           65 :       || (omp_verify_merge_absent_contains (ST_OMP_ASSUMES, c->assume,
    6074           29 :                                             gfc_current_ns->omp_assumes, &loc)
    6075              :           != MATCH_YES))
    6076              :     return MATCH_ERROR;
    6077           26 :   if (gfc_current_ns->omp_assumes == NULL)
    6078              :     {
    6079           23 :       gfc_current_ns->omp_assumes = c->assume;
    6080           23 :       c->assume = NULL;
    6081              :     }
    6082            3 :   else if (gfc_current_ns->omp_assumes && c->assume)
    6083              :     {
    6084            3 :       gfc_current_ns->omp_assumes->no_openmp |= c->assume->no_openmp;
    6085            3 :       gfc_current_ns->omp_assumes->no_openmp_routines
    6086            3 :         |= c->assume->no_openmp_routines;
    6087            3 :       gfc_current_ns->omp_assumes->no_openmp_constructs
    6088            3 :         |= c->assume->no_openmp_constructs;
    6089            3 :       gfc_current_ns->omp_assumes->no_parallelism |= c->assume->no_parallelism;
    6090            3 :       if (gfc_current_ns->omp_assumes->holds && c->assume->holds)
    6091              :         {
    6092              :           gfc_expr_list *el = gfc_current_ns->omp_assumes->holds;
    6093            1 :           for ( ; el->next ; el = el->next)
    6094              :             ;
    6095            1 :           el->next = c->assume->holds;
    6096            1 :         }
    6097            2 :       else if (c->assume->holds)
    6098            1 :         gfc_current_ns->omp_assumes->holds = c->assume->holds;
    6099            3 :       c->assume->holds = NULL;
    6100              :     }
    6101           26 :   gfc_free_omp_clauses (c);
    6102           26 :   return MATCH_YES;
    6103              : }
    6104              : 
    6105              : 
    6106              : match
    6107          168 : gfc_match_omp_critical (void)
    6108              : {
    6109          168 :   char n[GFC_MAX_SYMBOL_LEN+1];
    6110          168 :   gfc_omp_clauses *c = NULL;
    6111              : 
    6112          168 :   if (gfc_match (" ( %n )", n) != MATCH_YES)
    6113          117 :     n[0] = '\0';
    6114              : 
    6115          168 :   if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_HINT), false,
    6116          168 :                              /* needs_space = */ n[0] == '\0') != MATCH_YES)
    6117              :     return MATCH_ERROR;
    6118              : 
    6119          166 :   new_st.op = EXEC_OMP_CRITICAL;
    6120          166 :   new_st.ext.omp_clauses = c;
    6121          166 :   if (n[0])
    6122           51 :     c->critical_name = xstrdup (n);
    6123              :   return MATCH_YES;
    6124              : }
    6125              : 
    6126              : 
    6127              : match
    6128          166 : gfc_match_omp_end_critical (void)
    6129              : {
    6130          166 :   char n[GFC_MAX_SYMBOL_LEN+1];
    6131              : 
    6132          166 :   if (gfc_match (" ( %n )", n) != MATCH_YES)
    6133          115 :     n[0] = '\0';
    6134          166 :   if (gfc_match_omp_eos () != MATCH_YES)
    6135              :     {
    6136            1 :       gfc_error ("Unexpected junk after $OMP CRITICAL statement at %C");
    6137            1 :       return MATCH_ERROR;
    6138              :     }
    6139              : 
    6140          165 :   new_st.op = EXEC_OMP_END_CRITICAL;
    6141          165 :   new_st.ext.omp_name = n[0] ? xstrdup (n) : NULL;
    6142          165 :   return MATCH_YES;
    6143              : }
    6144              : 
    6145              : /* depobj(depobj) depend(dep-type:loc)|destroy|update(dep-type)
    6146              :    dep-type = in/out/inout/mutexinoutset/depobj/source/sink
    6147              :    depend: !source, !sink
    6148              :    update: !source, !sink, !depobj
    6149              :    locator = exactly one list item  .*/
    6150              : match
    6151          128 : gfc_match_omp_depobj (void)
    6152              : {
    6153          128 :   gfc_omp_clauses *c = NULL;
    6154          128 :   gfc_expr *depobj;
    6155              : 
    6156          128 :   if (gfc_match (" ( %v ) ", &depobj) != MATCH_YES)
    6157              :     {
    6158            2 :       gfc_error ("Expected %<( depobj )%> at %C");
    6159            2 :       return MATCH_ERROR;
    6160              :     }
    6161          126 :   gfc_match (", ");  /* optionally */
    6162          126 :   if (gfc_match ("update ( ") == MATCH_YES)
    6163              :     {
    6164           12 :       c = gfc_get_omp_clauses ();
    6165           12 :       if (gfc_match ("inoutset )") == MATCH_YES)
    6166            2 :         c->depobj_update = OMP_DEPEND_INOUTSET;
    6167           10 :       else if (gfc_match ("inout )") == MATCH_YES)
    6168            1 :         c->depobj_update = OMP_DEPEND_INOUT;
    6169            9 :       else if (gfc_match ("in )") == MATCH_YES)
    6170            2 :         c->depobj_update = OMP_DEPEND_IN;
    6171            7 :       else if (gfc_match ("out )") == MATCH_YES)
    6172            2 :         c->depobj_update = OMP_DEPEND_OUT;
    6173            5 :       else if (gfc_match ("mutexinoutset )") == MATCH_YES)
    6174            2 :         c->depobj_update = OMP_DEPEND_MUTEXINOUTSET;
    6175              :       else
    6176              :         {
    6177            3 :           gfc_error ("Expected IN, OUT, INOUT, INOUTSET or MUTEXINOUTSET "
    6178              :                      "followed by %<)%> at %C");
    6179            3 :           goto error;
    6180              :         }
    6181              :     }
    6182          114 :   else if (gfc_match ("destroy ") == MATCH_YES)
    6183              :     {
    6184           18 :       gfc_expr *destroyobj = NULL;
    6185           18 :       c = gfc_get_omp_clauses ();
    6186           18 :       c->destroy = true;
    6187              : 
    6188           18 :       if (gfc_match (" ( %v ) ", &destroyobj) == MATCH_YES)
    6189              :         {
    6190            3 :           if (destroyobj->symtree != depobj->symtree)
    6191            2 :             gfc_warning (OPT_Wopenmp, "The same depend object should be used as"
    6192              :                          " DEPOBJ argument at %L and as DESTROY argument at %L",
    6193              :                          &depobj->where, &destroyobj->where);
    6194            3 :           gfc_free_expr (destroyobj);
    6195              :         }
    6196              :     }
    6197           96 :   else if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_DEPEND), false, false)
    6198              :            != MATCH_YES)
    6199            2 :     goto error;
    6200              : 
    6201          121 :   if (c->depobj_update == OMP_DEPEND_UNSET && !c->destroy)
    6202              :     {
    6203           94 :       if (!c->doacross_source && !c->lists[OMP_LIST_DEPEND])
    6204              :         {
    6205            1 :           gfc_error ("Expected DEPEND, UPDATE, or DESTROY clause at %C");
    6206            1 :           goto error;
    6207              :         }
    6208           93 :       if (c->lists[OMP_LIST_DEPEND]->u.depend_doacross_op == OMP_DEPEND_DEPOBJ)
    6209              :         {
    6210            1 :           gfc_error ("DEPEND clause at %L of OMP DEPOBJ construct shall not "
    6211              :                      "have dependence-type DEPOBJ",
    6212              :                      c->lists[OMP_LIST_DEPEND]
    6213              :                      ? &c->lists[OMP_LIST_DEPEND]->where : &gfc_current_locus);
    6214            1 :           goto error;
    6215              :         }
    6216           92 :       if (c->lists[OMP_LIST_DEPEND]->next)
    6217              :         {
    6218            1 :           gfc_error ("DEPEND clause at %L of OMP DEPOBJ construct shall have "
    6219              :                      "only a single locator",
    6220              :                      &c->lists[OMP_LIST_DEPEND]->next->where);
    6221            1 :           goto error;
    6222              :         }
    6223              :     }
    6224              : 
    6225          118 :   c->depobj = depobj;
    6226          118 :   new_st.op = EXEC_OMP_DEPOBJ;
    6227          118 :   new_st.ext.omp_clauses = c;
    6228          118 :   return MATCH_YES;
    6229              : 
    6230            8 : error:
    6231            8 :   gfc_free_expr (depobj);
    6232            8 :   gfc_free_omp_clauses (c);
    6233            8 :   return MATCH_ERROR;
    6234              : }
    6235              : 
    6236              : match
    6237          160 : gfc_match_omp_dispatch (void)
    6238              : {
    6239          160 :   return match_omp (EXEC_OMP_DISPATCH, OMP_DISPATCH_CLAUSES);
    6240              : }
    6241              : 
    6242              : match
    6243           57 : gfc_match_omp_distribute (void)
    6244              : {
    6245           57 :   return match_omp (EXEC_OMP_DISTRIBUTE, OMP_DISTRIBUTE_CLAUSES);
    6246              : }
    6247              : 
    6248              : 
    6249              : match
    6250           44 : gfc_match_omp_distribute_parallel_do (void)
    6251              : {
    6252           44 :   return match_omp (EXEC_OMP_DISTRIBUTE_PARALLEL_DO,
    6253           44 :                     (OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
    6254           44 :                      | OMP_DO_CLAUSES)
    6255           44 :                     & ~(omp_mask (OMP_CLAUSE_ORDERED)
    6256           44 :                         | OMP_CLAUSE_LINEAR | OMP_CLAUSE_NOWAIT));
    6257              : }
    6258              : 
    6259              : 
    6260              : match
    6261           34 : gfc_match_omp_distribute_parallel_do_simd (void)
    6262              : {
    6263           34 :   return match_omp (EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD,
    6264           34 :                     (OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
    6265           34 :                      | OMP_DO_CLAUSES | OMP_SIMD_CLAUSES)
    6266           34 :                     & ~(omp_mask (OMP_CLAUSE_ORDERED) | OMP_CLAUSE_NOWAIT));
    6267              : }
    6268              : 
    6269              : 
    6270              : match
    6271           52 : gfc_match_omp_distribute_simd (void)
    6272              : {
    6273           52 :   return match_omp (EXEC_OMP_DISTRIBUTE_SIMD,
    6274           52 :                     OMP_DISTRIBUTE_CLAUSES | OMP_SIMD_CLAUSES);
    6275              : }
    6276              : 
    6277              : 
    6278              : match
    6279         1255 : gfc_match_omp_do (void)
    6280              : {
    6281         1255 :   return match_omp (EXEC_OMP_DO, OMP_DO_CLAUSES);
    6282              : }
    6283              : 
    6284              : 
    6285              : match
    6286          139 : gfc_match_omp_do_simd (void)
    6287              : {
    6288          139 :   return match_omp (EXEC_OMP_DO_SIMD, OMP_DO_CLAUSES | OMP_SIMD_CLAUSES);
    6289              : }
    6290              : 
    6291              : 
    6292              : match
    6293           70 : gfc_match_omp_loop (void)
    6294              : {
    6295           70 :   return match_omp (EXEC_OMP_LOOP, OMP_LOOP_CLAUSES);
    6296              : }
    6297              : 
    6298              : 
    6299              : match
    6300           35 : gfc_match_omp_teams_loop (void)
    6301              : {
    6302           35 :   return match_omp (EXEC_OMP_TEAMS_LOOP, OMP_TEAMS_CLAUSES | OMP_LOOP_CLAUSES);
    6303              : }
    6304              : 
    6305              : 
    6306              : match
    6307           18 : gfc_match_omp_target_teams_loop (void)
    6308              : {
    6309           18 :   return match_omp (EXEC_OMP_TARGET_TEAMS_LOOP,
    6310           18 :                     OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES | OMP_LOOP_CLAUSES);
    6311              : }
    6312              : 
    6313              : 
    6314              : match
    6315           31 : gfc_match_omp_parallel_loop (void)
    6316              : {
    6317           31 :   return match_omp (EXEC_OMP_PARALLEL_LOOP,
    6318           31 :                     OMP_PARALLEL_CLAUSES | OMP_LOOP_CLAUSES);
    6319              : }
    6320              : 
    6321              : 
    6322              : match
    6323           16 : gfc_match_omp_target_parallel_loop (void)
    6324              : {
    6325           16 :   return match_omp (EXEC_OMP_TARGET_PARALLEL_LOOP,
    6326           16 :                     (OMP_TARGET_CLAUSES | OMP_PARALLEL_CLAUSES
    6327           16 :                      | OMP_LOOP_CLAUSES));
    6328              : }
    6329              : 
    6330              : 
    6331              : match
    6332          104 : gfc_match_omp_error (void)
    6333              : {
    6334          104 :   locus loc = gfc_current_locus;
    6335          104 :   match m = match_omp (EXEC_OMP_ERROR, OMP_ERROR_CLAUSES);
    6336          104 :   if (m != MATCH_YES)
    6337              :     return m;
    6338              : 
    6339           85 :   gfc_omp_clauses *c = new_st.ext.omp_clauses;
    6340           85 :   if (c->severity == OMP_SEVERITY_UNSET)
    6341           48 :     c->severity = OMP_SEVERITY_FATAL;
    6342           85 :   if (new_st.ext.omp_clauses->at == OMP_AT_EXECUTION)
    6343              :     return MATCH_YES;
    6344           37 :   if (c->message
    6345           37 :       && (!gfc_resolve_expr (c->message)
    6346           16 :           || c->message->ts.type != BT_CHARACTER
    6347           14 :           || c->message->ts.kind != gfc_default_character_kind
    6348           13 :           || c->message->rank != 0))
    6349              :     {
    6350            4 :       gfc_error ("MESSAGE clause at %L requires a scalar default-kind "
    6351              :                    "CHARACTER expression",
    6352            4 :                  &new_st.ext.omp_clauses->message->where);
    6353            4 :       return MATCH_ERROR;
    6354              :     }
    6355           33 :   if (c->message && !gfc_is_constant_expr (c->message))
    6356              :     {
    6357            2 :       gfc_error ("Constant character expression required in MESSAGE clause "
    6358            2 :                  "at %L", &new_st.ext.omp_clauses->message->where);
    6359            2 :       return MATCH_ERROR;
    6360              :     }
    6361           31 :   if (c->message)
    6362              :     {
    6363           10 :       const char *msg = G_("$OMP ERROR encountered at %L: %s");
    6364           10 :       gcc_assert (c->message->expr_type == EXPR_CONSTANT);
    6365           10 :       gfc_charlen_t slen = c->message->value.character.length;
    6366           10 :       int i = gfc_validate_kind (BT_CHARACTER, gfc_default_character_kind,
    6367              :                                  false);
    6368           10 :       size_t size = slen * gfc_character_kinds[i].bit_size / 8;
    6369           10 :       unsigned char *s = XCNEWVAR (unsigned char, size + 1);
    6370           10 :       gfc_encode_character (gfc_default_character_kind, slen,
    6371           10 :                             c->message->value.character.string,
    6372              :                             (unsigned char *) s, size);
    6373           10 :       s[size] = '\0';
    6374           10 :       if (c->severity == OMP_SEVERITY_WARNING)
    6375            6 :         gfc_warning_now (0, msg, &loc, s);
    6376              :       else
    6377            4 :         gfc_error_now (msg, &loc, s);
    6378           10 :       free (s);
    6379              :     }
    6380              :   else
    6381              :     {
    6382           21 :       const char *msg = G_("$OMP ERROR encountered at %L");
    6383           21 :       if (c->severity == OMP_SEVERITY_WARNING)
    6384            7 :         gfc_warning_now (0, msg, &loc);
    6385              :       else
    6386           14 :         gfc_error_now (msg, &loc);
    6387              :     }
    6388              :   return MATCH_YES;
    6389              : }
    6390              : 
    6391              : match
    6392          100 : gfc_match_omp_flush (void)
    6393              : {
    6394          100 :   gfc_omp_namelist *list = NULL;
    6395          100 :   gfc_omp_clauses *c = NULL;
    6396          100 :   gfc_gobble_whitespace ();
    6397          100 :   enum gfc_omp_memorder mo = OMP_MEMORDER_UNSET;
    6398          100 :   if (gfc_match_omp_variable_list (" (", &list, true) == MATCH_ERROR)
    6399              :     return MATCH_ERROR;
    6400              :   match m = MATCH_YES;
    6401          150 :   while (gfc_match_omp_eos () != MATCH_YES)
    6402              :     {
    6403           59 :       gfc_gobble_whitespace ();
    6404           59 :       gfc_match (", ");  /* optionally  */
    6405           59 :       enum gfc_omp_memorder mo2 = OMP_MEMORDER_UNSET;
    6406           59 :       bool bval = false;
    6407           59 :       locus loc = gfc_current_locus;
    6408           59 :       if ((m = gfc_match_dupl_memorder (&bval, "seq_cst",
    6409              :                                         mo != OMP_MEMORDER_UNSET)) != MATCH_NO)
    6410              :         mo2 = OMP_MEMORDER_SEQ_CST;
    6411           48 :       else if ((m = gfc_match_dupl_memorder (&bval, "acq_rel",
    6412              :                                              mo != OMP_MEMORDER_UNSET))
    6413              :               != MATCH_NO)
    6414              :         mo2 = OMP_MEMORDER_ACQ_REL;
    6415           35 :       else if ((m = gfc_match_dupl_memorder (&bval, "release",
    6416              :                                              mo != OMP_MEMORDER_UNSET))
    6417              :               != MATCH_NO)
    6418              :         mo2 = OMP_MEMORDER_RELEASE;
    6419           24 :       else if ((m = gfc_match_dupl_memorder (&bval, "acquire",
    6420              :                                              mo != OMP_MEMORDER_UNSET))
    6421              :               != MATCH_NO)
    6422              :         mo2 = OMP_MEMORDER_ACQUIRE;
    6423           12 :       else if ((m = gfc_match_dupl_memorder (&bval, "relaxed",
    6424              :                                              mo != OMP_MEMORDER_UNSET))
    6425              :               != MATCH_NO)
    6426              :         {
    6427           10 :           if (m == MATCH_YES && bval)
    6428              :             {
    6429              :               /* relaxed only permitted with 'false'.  */
    6430            2 :               gfc_current_locus = loc;
    6431            2 :               m = MATCH_NO;
    6432            2 :               break;
    6433              :             }
    6434              :         }
    6435              :       else
    6436              :         break;
    6437           55 :       if (m == MATCH_ERROR)
    6438            5 :         return MATCH_ERROR;
    6439           50 :       if (bval)
    6440           18 :         mo = mo2;
    6441              :     }
    6442           95 :   if (m == MATCH_NO)
    6443              :     {
    6444            4 :       gfc_error ("Expected SEQ_CST, AQC_REL, RELEASE, or ACQUIRE at %C");
    6445            4 :       gfc_free_omp_namelist (list, OMP_LIST_NONE);
    6446            4 :       return MATCH_ERROR;
    6447              :     }
    6448           91 :   if (list && mo != OMP_MEMORDER_UNSET)
    6449              :     {
    6450            1 :       gfc_error ("List specified together with memory order clause in FLUSH "
    6451              :                  "directive at %C");
    6452            1 :       gfc_free_omp_namelist (list, OMP_LIST_NONE);
    6453            1 :       return MATCH_ERROR;
    6454              :     }
    6455           90 :   if (gfc_match_omp_eos () != MATCH_YES)
    6456              :     {
    6457            0 :       gfc_error ("Unexpected junk after $OMP FLUSH statement at %C");
    6458            0 :       gfc_free_omp_namelist (list, OMP_LIST_NONE);
    6459            0 :       return MATCH_ERROR;
    6460              :     }
    6461           90 :   if (mo != OMP_MEMORDER_UNSET)
    6462              :     {
    6463           16 :       c = gfc_get_omp_clauses ();
    6464           16 :       c->memorder = mo;
    6465              :     }
    6466           90 :   new_st.op = EXEC_OMP_FLUSH;
    6467           90 :   new_st.ext.omp_namelist = list;
    6468           90 :   new_st.ext.omp_clauses = c;
    6469           90 :   return MATCH_YES;
    6470              : }
    6471              : 
    6472              : 
    6473              : match
    6474          203 : gfc_match_omp_declare_simd (void)
    6475              : {
    6476          203 :   locus where = gfc_current_locus;
    6477          203 :   gfc_symbol *proc_name;
    6478          203 :   gfc_omp_clauses *c;
    6479          203 :   gfc_omp_declare_simd *ods;
    6480          203 :   bool needs_space = false;
    6481              : 
    6482          203 :   switch (gfc_match (" ( "))
    6483              :     {
    6484          145 :     case MATCH_YES:
    6485          145 :       if (gfc_match_symbol (&proc_name, /* host assoc = */ true) != MATCH_YES
    6486          145 :           || gfc_match (" ) ") != MATCH_YES)
    6487              :         return MATCH_ERROR;
    6488              :       break;
    6489           58 :     case MATCH_NO: proc_name = NULL; needs_space = true; break;
    6490              :     case MATCH_ERROR: return MATCH_ERROR;
    6491              :     }
    6492              : 
    6493          203 :   if (gfc_match_omp_clauses (&c, OMP_DECLARE_SIMD_CLAUSES, false,
    6494              :                              needs_space) != MATCH_YES)
    6495              :     return MATCH_ERROR;
    6496              : 
    6497          194 :   if (gfc_current_ns->is_block_data)
    6498              :     {
    6499            1 :       gfc_free_omp_clauses (c);
    6500            1 :       return MATCH_YES;
    6501              :     }
    6502              : 
    6503          193 :   ods = gfc_get_omp_declare_simd ();
    6504          193 :   ods->where = where;
    6505          193 :   ods->proc_name = proc_name;
    6506          193 :   ods->clauses = c;
    6507          193 :   ods->next = gfc_current_ns->omp_declare_simd;
    6508          193 :   gfc_current_ns->omp_declare_simd = ods;
    6509          193 :   return MATCH_YES;
    6510              : }
    6511              : 
    6512              : 
    6513              : /* Find a matching "!$omp declare mapper" for typespec TS in symtree ST.  */
    6514              : 
    6515              : gfc_omp_udm *
    6516           37 : gfc_omp_udm_find (gfc_symtree *st, gfc_typespec *ts)
    6517              : {
    6518           37 :   gfc_omp_udm *omp_udm;
    6519              : 
    6520           37 :   if (st == NULL)
    6521              :     return NULL;
    6522              : 
    6523           14 :   gfc_symbol *dt = (ts->type == BT_CLASS
    6524            0 :                     ? CLASS_DATA (ts->u.derived)->ts.u.derived
    6525              :                     : ts->u.derived);
    6526           15 :   for (omp_udm = st->n.omp_udm; omp_udm; omp_udm = omp_udm->next)
    6527              :     {
    6528            5 :       if (dt == omp_udm->ts.u.derived)
    6529              :         return omp_udm;
    6530              :       /* Special case for comparing derived types across namespaces.  If the
    6531              :          true names and module names are the same and the module name is
    6532              :          nonnull, then they are equal.  */
    6533            1 :       if (dt->module && omp_udm->ts.u.derived->module
    6534            1 :           && strcmp (dt->name, omp_udm->ts.u.derived->name) == 0
    6535            1 :           && strcmp (dt->module, omp_udm->ts.u.derived->module) == 0)
    6536              :         return omp_udm;
    6537              :     }
    6538              : 
    6539              :   return NULL;
    6540              : }
    6541              : 
    6542              : 
    6543              : /* Match !$omp declare mapper([ mapper-identifier : ] type :: var) clauses-list  */
    6544              : 
    6545              : match
    6546           35 : gfc_match_omp_declare_mapper (void)
    6547              : {
    6548           35 :   match m;
    6549           35 :   gfc_typespec ts;
    6550           35 :   char mapper_id[GFC_MAX_SYMBOL_LEN + 1];
    6551           35 :   char var[GFC_MAX_SYMBOL_LEN + 1];
    6552           35 :   gfc_namespace *mapper_ns = NULL;
    6553           35 :   gfc_symtree *var_st;
    6554           35 :   gfc_symtree *st;
    6555           35 :   gfc_omp_udm *omp_udm = NULL, *prev_udm = NULL;
    6556           35 :   locus where = gfc_current_locus;
    6557              : 
    6558           35 :   if (gfc_match_char ('(') != MATCH_YES)
    6559              :     {
    6560            1 :       gfc_error ("Expected %<(%> at %C");
    6561            1 :       return MATCH_ERROR;
    6562              :     }
    6563              : 
    6564           34 :   locus old_locus = gfc_current_locus;
    6565              : 
    6566           34 :   m = gfc_match (" %n : ", mapper_id);
    6567              : 
    6568           34 :   if (m == MATCH_ERROR)
    6569              :     return MATCH_ERROR;
    6570              : 
    6571              :   /* As a special case, a mapper named "default" and an unnamed mapper are
    6572              :      both the default mapper for a given type.  */
    6573           34 :   if (strcmp (mapper_id, "default") == 0)
    6574            0 :     mapper_id[0] = '\0';
    6575              : 
    6576           34 :   if (gfc_peek_ascii_char () == ':')
    6577              :    {
    6578              :      /* If we see '::', the user did not name the mapper, and instead we just
    6579              :         saw the type.  So backtrack and try parsing as a type instead.  */
    6580           15 :      mapper_id[0] = '\0';
    6581           15 :      gfc_current_locus = old_locus;
    6582              :    }
    6583           34 :   old_locus = gfc_current_locus;
    6584              : 
    6585           34 :   m = gfc_match_type_spec (&ts);
    6586           34 :   if (m != MATCH_YES)
    6587              :     {
    6588            4 :       gfc_error ("Expected either a type name at %L or a map-type "
    6589              :                  "identifier, a colon, or a type name", &old_locus);
    6590            4 :       return MATCH_ERROR;
    6591              :     }
    6592              : 
    6593           30 :   if (ts.type != BT_DERIVED)
    6594              :     {
    6595            1 :       gfc_error ("!$OMP DECLARE MAPPER with non-derived type at %L", &old_locus);
    6596            1 :       return MATCH_ERROR;
    6597              :     }
    6598              : 
    6599           29 :   if (gfc_match (" :: ") != MATCH_YES)
    6600              :     {
    6601            0 :       gfc_error ("Expected %<::%> at %C");
    6602            0 :       return MATCH_ERROR;
    6603              :     }
    6604              : 
    6605           29 :   if (gfc_match_name (var) != MATCH_YES)
    6606              :     {
    6607            1 :       gfc_error ("Expected variable name at %C");
    6608            1 :       return MATCH_ERROR;
    6609              :     }
    6610              : 
    6611           28 :   if (gfc_match_char (')') != MATCH_YES)
    6612              :     {
    6613            2 :       gfc_error ("Expected %<)%> at %C");
    6614            2 :       return MATCH_ERROR;
    6615              :     }
    6616              : 
    6617           26 :   st = gfc_find_symtree (gfc_current_ns->omp_udm_root, mapper_id);
    6618              : 
    6619              :   /* Now we need to set up a new namespace, and create a new sym_tree for our
    6620              :      dummy variable so we can use it in the following list of mapping
    6621              :      clauses.  */
    6622              : 
    6623           26 :   gfc_current_ns = mapper_ns = gfc_get_namespace (gfc_current_ns, 1);
    6624           26 :   mapper_ns->proc_name = mapper_ns->parent->proc_name;
    6625           26 :   mapper_ns->omp_udm_ns = 1;
    6626              : 
    6627           26 :   gfc_get_sym_tree (var, mapper_ns, &var_st, false);
    6628           26 :   var_st->n.sym->ts = ts;
    6629           26 :   var_st->n.sym->attr.omp_udm_artificial_var = 1;
    6630           26 :   var_st->n.sym->attr.flavor = FL_VARIABLE;
    6631           26 :   gfc_commit_symbols ();
    6632              : 
    6633           26 :   gfc_omp_clauses *clauses = NULL;
    6634              : 
    6635           26 :   m = gfc_match_omp_clauses (&clauses, omp_mask (OMP_CLAUSE_MAP), false, false,
    6636              :                              false, false, OMP_MAP_UNSET);
    6637           26 :   if (m != MATCH_YES)
    6638            1 :     goto failure;
    6639              : 
    6640           25 :   omp_udm = gfc_get_omp_udm ();
    6641           25 :   omp_udm->next = NULL;
    6642           25 :   omp_udm->where = where;
    6643           25 :   omp_udm->mapper_id = gfc_get_string ("%s", mapper_id);
    6644           25 :   omp_udm->ts = ts;
    6645           25 :   omp_udm->var_sym = var_st->n.sym;
    6646           25 :   omp_udm->mapper_ns = mapper_ns;
    6647           25 :   omp_udm->clauses = clauses;
    6648              : 
    6649           25 :   gfc_current_ns = mapper_ns->parent;
    6650              : 
    6651           25 :   prev_udm = gfc_omp_udm_find (st, &ts);
    6652           25 :   if (prev_udm)
    6653              :     {
    6654            2 :       if (mapper_id[0])
    6655            1 :         gfc_error ("Redefinition of !$OMP DECLARE MAPPER at %L for type %qs with id %qs",
    6656              :                    &where, gfc_typename (&ts), mapper_id);
    6657              :       else
    6658            1 :         gfc_error ("Redefinition of !$OMP DECLARE MAPPER at %L for type %qs",
    6659              :                    &where, gfc_typename (&ts));
    6660            2 :       inform (gfc_get_location (&prev_udm->where),
    6661              :               "Previous !$OMP DECLARE MAPPER here");
    6662            2 :       return MATCH_ERROR;
    6663              :     }
    6664           23 :   else if (st)
    6665              :     {
    6666            0 :       omp_udm->next = st->n.omp_udm;
    6667            0 :       st->n.omp_udm = omp_udm;
    6668              :     }
    6669              :   else
    6670              :     {
    6671           23 :       st = gfc_new_symtree (&gfc_current_ns->omp_udm_root, mapper_id);
    6672           23 :       st->n.omp_udm = omp_udm;
    6673              :     }
    6674              : 
    6675              :   return MATCH_YES;
    6676              : 
    6677            1 : failure:
    6678            1 :   if (mapper_ns)
    6679            1 :     gfc_current_ns = mapper_ns->parent;
    6680            1 :   gfc_free_omp_udm (omp_udm);
    6681              : 
    6682            1 :   return MATCH_ERROR;
    6683              : }
    6684              : 
    6685              : /* For 'declare reduction', matches either the combiner or initializer
    6686              :    expression, either can be an assignment of 'omp_sym1 = ...'
    6687              :    or a subroutine call, i.e. 'subroutine-name(argument-list)'.  */
    6688              : 
    6689              : static bool
    6690          935 : match_udr_expr (gfc_symtree *omp_sym1, gfc_symtree *omp_sym2)
    6691              : {
    6692          935 :   match m;
    6693          935 :   locus old_loc = gfc_current_locus;
    6694          935 :   char sname[GFC_MAX_SYMBOL_LEN + 1];
    6695          935 :   gfc_symbol *sym;
    6696          935 :   gfc_namespace *ns = gfc_current_ns;
    6697          935 :   gfc_expr *lvalue = NULL, *rvalue = NULL;
    6698          935 :   gfc_symtree *st;
    6699          935 :   gfc_actual_arglist *arglist;
    6700              : 
    6701          935 :   m = gfc_match (" %v =", &lvalue);
    6702          935 :   if (m != MATCH_YES)
    6703          210 :     gfc_current_locus = old_loc;
    6704              :   else
    6705              :     {
    6706          725 :       m = gfc_match (" %e )", &rvalue);
    6707          725 :       if (m == MATCH_YES)
    6708              :         {
    6709          715 :           ns->code = gfc_get_code (EXEC_ASSIGN);
    6710          715 :           ns->code->expr1 = lvalue;
    6711          715 :           ns->code->expr2 = rvalue;
    6712          715 :           ns->code->loc = old_loc;
    6713          715 :           return true;
    6714              :         }
    6715              : 
    6716           10 :       gfc_current_locus = old_loc;
    6717           10 :       gfc_free_expr (lvalue);
    6718              :     }
    6719              : 
    6720          220 :   m = gfc_match (" %n", sname);
    6721          220 :   if (m != MATCH_YES)
    6722            4 :     goto syntax;
    6723              : 
    6724          216 :   if (strcmp (sname, omp_sym1->name) == 0
    6725          203 :       || strcmp (sname, omp_sym2->name) == 0)
    6726           14 :     goto syntax;
    6727              : 
    6728          202 :   gfc_current_ns = ns->parent;
    6729          202 :   if (gfc_get_ha_sym_tree (sname, &st))
    6730            0 :     goto syntax;
    6731              : 
    6732          202 :   sym = st->n.sym;
    6733          202 :   if (sym->attr.flavor != FL_PROCEDURE
    6734           74 :       && sym->attr.flavor != FL_UNKNOWN)
    6735            1 :     goto syntax;
    6736              : 
    6737          201 :   if (!sym->attr.generic
    6738          191 :       && !sym->attr.subroutine
    6739           73 :       && !sym->attr.function)
    6740              :     {
    6741           73 :       if (!(sym->attr.external && !sym->attr.referenced))
    6742              :         {
    6743              :           /* ...create a symbol in this scope...  */
    6744           73 :           if (sym->ns != gfc_current_ns
    6745           73 :               && gfc_get_sym_tree (sname, NULL, &st, false) == 1)
    6746            0 :             goto syntax;
    6747              : 
    6748           73 :           if (sym != st->n.sym)
    6749           73 :             sym = st->n.sym;
    6750              :         }
    6751              : 
    6752              :       /* ...and then to try to make the symbol into a subroutine.  */
    6753           73 :       if (!gfc_add_subroutine (&sym->attr, sym->name, NULL))
    6754            0 :         goto syntax;
    6755              :     }
    6756              : 
    6757          201 :   gfc_set_sym_referenced (sym);
    6758          201 :   gfc_gobble_whitespace ();
    6759          201 :   if (gfc_peek_ascii_char () != '(')
    6760            6 :     goto syntax;
    6761              : 
    6762          195 :   gfc_current_ns = ns;
    6763          195 :   m = gfc_match_actual_arglist (1, &arglist);
    6764          195 :   if (m != MATCH_YES)
    6765            0 :     goto syntax;
    6766              : 
    6767          195 :   if (gfc_match_char (')') != MATCH_YES)
    6768            0 :     goto syntax;
    6769              : 
    6770          195 :   gfc_clear_error ();
    6771          195 :   ns->code = gfc_get_code (EXEC_CALL);
    6772          195 :   ns->code->symtree = st;
    6773          195 :   ns->code->ext.actual = arglist;
    6774          195 :   ns->code->loc = old_loc;
    6775          195 :   return true;
    6776           25 : syntax:
    6777           25 :   gfc_clear_error ();
    6778           25 :   gfc_error ("Expected either %<%s = expr%> or %<subroutine-name(argument-list)"
    6779              :              "%> followed by %<)%> at %L", omp_sym1->name, &old_loc);
    6780           25 :   return false;
    6781              : }
    6782              : 
    6783              : static bool
    6784         1217 : gfc_omp_udr_predef (gfc_omp_reduction_op rop, const char *name,
    6785              :                     gfc_typespec *ts, const char **n)
    6786              : {
    6787         1217 :   if (!gfc_numeric_ts (ts) && ts->type != BT_LOGICAL)
    6788              :     return false;
    6789              : 
    6790          675 :   switch (rop)
    6791              :     {
    6792           19 :     case OMP_REDUCTION_PLUS:
    6793           19 :     case OMP_REDUCTION_MINUS:
    6794           19 :     case OMP_REDUCTION_TIMES:
    6795           19 :       return ts->type != BT_LOGICAL;
    6796           12 :     case OMP_REDUCTION_AND:
    6797           12 :     case OMP_REDUCTION_OR:
    6798           12 :     case OMP_REDUCTION_EQV:
    6799           12 :     case OMP_REDUCTION_NEQV:
    6800           12 :       return ts->type == BT_LOGICAL;
    6801          643 :     case OMP_REDUCTION_USER:
    6802          643 :       if (name[0] != '.' && (ts->type == BT_INTEGER || ts->type == BT_REAL))
    6803              :         {
    6804          571 :           gfc_symbol *sym;
    6805              : 
    6806          571 :           gfc_find_symbol (name, NULL, 1, &sym);
    6807          571 :           if (sym != NULL)
    6808              :             {
    6809           94 :               if (sym->attr.intrinsic)
    6810            0 :                 *n = sym->name;
    6811           94 :               else if ((sym->attr.flavor != FL_UNKNOWN
    6812           82 :                         && sym->attr.flavor != FL_PROCEDURE)
    6813           70 :                        || sym->attr.external
    6814           55 :                        || sym->attr.generic
    6815           55 :                        || sym->attr.entry
    6816           55 :                        || sym->attr.result
    6817           55 :                        || sym->attr.dummy
    6818           55 :                        || sym->attr.subroutine
    6819           51 :                        || sym->attr.pointer
    6820           51 :                        || sym->attr.target
    6821           51 :                        || sym->attr.cray_pointer
    6822           51 :                        || sym->attr.cray_pointee
    6823           51 :                        || (sym->attr.proc != PROC_UNKNOWN
    6824            1 :                            && sym->attr.proc != PROC_INTRINSIC)
    6825           50 :                        || sym->attr.if_source != IFSRC_UNKNOWN
    6826           50 :                        || sym == sym->ns->proc_name)
    6827           44 :                 *n = NULL;
    6828              :               else
    6829           50 :                 *n = sym->name;
    6830              :             }
    6831              :           else
    6832          477 :             *n = name;
    6833          571 :           if (*n
    6834          527 :               && (strcmp (*n, "max") == 0 || strcmp (*n, "min") == 0))
    6835           56 :             return true;
    6836          533 :           else if (*n
    6837          489 :                    && ts->type == BT_INTEGER
    6838          403 :                    && (strcmp (*n, "iand") == 0
    6839          397 :                        || strcmp (*n, "ior") == 0
    6840          391 :                        || strcmp (*n, "ieor") == 0))
    6841              :             return true;
    6842              :         }
    6843              :       break;
    6844              :     default:
    6845              :       break;
    6846              :     }
    6847              :   return false;
    6848              : }
    6849              : 
    6850              : gfc_omp_udr *
    6851          673 : gfc_omp_udr_find (gfc_symtree *st, gfc_typespec *ts)
    6852              : {
    6853          673 :   gfc_omp_udr *omp_udr;
    6854              : 
    6855          673 :   if (st == NULL)
    6856              :     return NULL;
    6857              : 
    6858          112 :   gfc_symbol *dt = NULL;
    6859          112 :   if (ts->type == BT_DERIVED || ts->type == BT_CLASS)
    6860           25 :     dt = (ts->type == BT_CLASS
    6861            0 :           ? CLASS_DATA (ts->u.derived)->ts.u.derived : ts->u.derived);
    6862          260 :   for (omp_udr = st->n.omp_udr; omp_udr; omp_udr = omp_udr->next)
    6863          161 :     if (omp_udr->ts.type == ts->type
    6864           91 :         || (dt && omp_udr->ts.type == BT_DERIVED))
    6865              :       {
    6866           70 :         if (dt && omp_udr->ts.type == BT_DERIVED)
    6867              :           {
    6868           15 :             gfc_symbol *dtu = omp_udr->ts.u.derived;
    6869           15 :             if (dt == dtu)
    6870              :               return omp_udr;
    6871              :             /* Special case for comparing derived types across namespaces.  If
    6872              :                the true names and module names are the same and the module name
    6873              :                is nonnull, then they are equal.  */
    6874            7 :             if (dt->module && dtu->module
    6875            1 :                 && strcmp (dt->name, dtu->name) == 0
    6876            1 :                 && strcmp (dt->module, dtu->module) == 0)
    6877              :               return omp_udr;
    6878              :           }
    6879           55 :         else if (omp_udr->ts.kind == ts->kind)
    6880              :           {
    6881           20 :             if (omp_udr->ts.type == BT_CHARACTER)
    6882              :               {
    6883           17 :                 if (omp_udr->ts.u.cl->length == NULL
    6884           15 :                     || ts->u.cl->length == NULL)
    6885              :                   return omp_udr;
    6886           15 :                 if (omp_udr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
    6887              :                   return omp_udr;
    6888           15 :                 if (ts->u.cl->length->expr_type != EXPR_CONSTANT)
    6889              :                   return omp_udr;
    6890           15 :                 if (omp_udr->ts.u.cl->length->ts.type != BT_INTEGER)
    6891              :                   return omp_udr;
    6892           15 :                 if (ts->u.cl->length->ts.type != BT_INTEGER)
    6893              :                   return omp_udr;
    6894           15 :                 if (gfc_compare_expr (omp_udr->ts.u.cl->length,
    6895              :                                       ts->u.cl->length, INTRINSIC_EQ) != 0)
    6896           15 :                   continue;
    6897              :               }
    6898              :             return omp_udr;
    6899              :           }
    6900              :       }
    6901              :   return NULL;
    6902              : }
    6903              : 
    6904              : match
    6905          594 : gfc_match_omp_declare_reduction (void)
    6906              : {
    6907          594 :   match m;
    6908          594 :   gfc_intrinsic_op op;
    6909          594 :   char name[GFC_MAX_SYMBOL_LEN + 3];
    6910          594 :   auto_vec<gfc_typespec, 5> tss;
    6911          594 :   gfc_typespec ts;
    6912          594 :   unsigned int i;
    6913          594 :   gfc_symtree *st;
    6914          594 :   locus where = gfc_current_locus;
    6915          594 :   locus end_loc = gfc_current_locus;
    6916          594 :   bool end_loc_set = false;
    6917          594 :   gfc_omp_reduction_op rop = OMP_REDUCTION_NONE;
    6918              : 
    6919          594 :   if (gfc_match_char ('(') != MATCH_YES)
    6920              :     {
    6921            4 :       gfc_error ("Expected %<(%> at %C");
    6922            4 :       return MATCH_ERROR;
    6923              :     }
    6924              : 
    6925          590 :   m = gfc_match (" %o : ", &op);
    6926          590 :   if (m == MATCH_ERROR)
    6927              :     return MATCH_ERROR;
    6928          590 :   if (m == MATCH_YES)
    6929              :     {
    6930          142 :       snprintf (name, sizeof name, "operator %s", gfc_op2string (op));
    6931          142 :       rop = (gfc_omp_reduction_op) op;
    6932              :     }
    6933              :   else
    6934              :     {
    6935          448 :       m = gfc_match_defined_op_name (name + 1, 1);
    6936          448 :       if (m == MATCH_ERROR)
    6937              :         return MATCH_ERROR;
    6938          447 :       if (m == MATCH_YES)
    6939              :         {
    6940           41 :           name[0] = '.';
    6941           41 :           strcat (name, ".");
    6942           41 :           if (gfc_match (" : ") != MATCH_YES)
    6943              :             {
    6944            0 :               gfc_error ("Expected %<:%> at %C");
    6945            0 :               return MATCH_ERROR;
    6946              :             }
    6947              :         }
    6948              :       else
    6949              :         {
    6950          406 :           if (gfc_match (" %n : ", name) != MATCH_YES)
    6951              :             {
    6952            4 :               gfc_error ("Expected an identfifier or operator as reduction "
    6953              :                          "identifier followed by a colon at %C");
    6954            4 :               return MATCH_ERROR;
    6955              :             }
    6956              :         }
    6957              :       rop = OMP_REDUCTION_USER;
    6958              :     }
    6959              : 
    6960          585 :   m = gfc_match_type_spec (&ts);
    6961          585 :   if (m != MATCH_YES)
    6962              :     {
    6963            4 :       gfc_error ("Expected type spec at %C");
    6964            4 :       return MATCH_ERROR;
    6965              :     }
    6966              :   /* Treat len=: the same as len=*.  */
    6967          581 :   if (ts.type == BT_CHARACTER)
    6968           61 :     ts.deferred = false;
    6969          581 :   tss.safe_push (ts);
    6970              : 
    6971         1203 :   while (gfc_match_char (',') == MATCH_YES)
    6972              :     {
    6973           42 :       m = gfc_match_type_spec (&ts);
    6974           42 :       if (m != MATCH_YES)
    6975              :         {
    6976            1 :           gfc_error ("Expected type spec at %C");
    6977            1 :           return MATCH_ERROR;
    6978              :         }
    6979           41 :       tss.safe_push (ts);
    6980              :     }
    6981          580 :   if (gfc_match_char (':') != MATCH_YES)
    6982              :     {
    6983            6 :       gfc_error ("Expected %<:%> or %<,%> at %C");
    6984            6 :       return MATCH_ERROR;
    6985              :     }
    6986              : 
    6987          574 :   st = gfc_find_symtree (gfc_current_ns->omp_udr_root, name);
    6988         1699 :   for (i = 0; i < tss.length (); i++)
    6989              :     {
    6990          610 :       gfc_symtree *omp_out, *omp_in;
    6991          610 :       gfc_symtree *omp_priv = NULL, *omp_orig = NULL;
    6992          610 :       gfc_namespace *combiner_ns, *initializer_ns = NULL;
    6993          610 :       gfc_omp_udr *prev_udr, *omp_udr;
    6994          610 :       const char *predef_name = NULL;
    6995              : 
    6996          610 :       omp_udr = gfc_get_omp_udr ();
    6997          610 :       omp_udr->name = gfc_get_string ("%s", name);
    6998          610 :       omp_udr->rop = rop;
    6999          610 :       omp_udr->ts = tss[i];
    7000          610 :       omp_udr->where = where;
    7001              : 
    7002          610 :       gfc_current_ns = combiner_ns = gfc_get_namespace (gfc_current_ns, 1);
    7003          610 :       combiner_ns->proc_name = combiner_ns->parent->proc_name;
    7004              : 
    7005          610 :       gfc_get_sym_tree ("omp_out", combiner_ns, &omp_out, false);
    7006          610 :       gfc_get_sym_tree ("omp_in", combiner_ns, &omp_in, false);
    7007          610 :       combiner_ns->omp_udr_ns = 1;
    7008          610 :       omp_out->n.sym->ts = tss[i];
    7009          610 :       omp_in->n.sym->ts = tss[i];
    7010          610 :       omp_out->n.sym->attr.omp_udr_artificial_var = 1;
    7011          610 :       omp_in->n.sym->attr.omp_udr_artificial_var = 1;
    7012          610 :       omp_out->n.sym->attr.flavor = FL_VARIABLE;
    7013          610 :       omp_in->n.sym->attr.flavor = FL_VARIABLE;
    7014          610 :       gfc_commit_symbols ();
    7015          610 :       omp_udr->combiner_ns = combiner_ns;
    7016          610 :       omp_udr->omp_out = omp_out->n.sym;
    7017          610 :       omp_udr->omp_in = omp_in->n.sym;
    7018              : 
    7019          610 :       locus old_loc = gfc_current_locus;
    7020              : 
    7021          610 :       if (!match_udr_expr (omp_out, omp_in))
    7022              :         {
    7023           19 :          syntax:
    7024           59 :           gfc_current_ns = combiner_ns->parent;
    7025           59 :           gfc_undo_symbols ();
    7026           59 :           gfc_free_omp_udr (omp_udr);
    7027           59 :           return MATCH_ERROR;
    7028              :         }
    7029          591 :       gfc_match_char (',');  /* optionally  */
    7030          591 :       if (gfc_match (" initializer ( ") == MATCH_YES)
    7031              :         {
    7032          325 :           gfc_current_ns = combiner_ns->parent;
    7033          325 :           initializer_ns = gfc_get_namespace (gfc_current_ns, 1);
    7034          325 :           gfc_current_ns = initializer_ns;
    7035          325 :           initializer_ns->proc_name = initializer_ns->parent->proc_name;
    7036              : 
    7037          325 :           gfc_get_sym_tree ("omp_priv", initializer_ns, &omp_priv, false);
    7038          325 :           gfc_get_sym_tree ("omp_orig", initializer_ns, &omp_orig, false);
    7039          325 :           initializer_ns->omp_udr_ns = 1;
    7040          325 :           omp_priv->n.sym->ts = tss[i];
    7041          325 :           omp_orig->n.sym->ts = tss[i];
    7042          325 :           omp_priv->n.sym->attr.omp_udr_artificial_var = 1;
    7043          325 :           omp_orig->n.sym->attr.omp_udr_artificial_var = 1;
    7044          325 :           omp_priv->n.sym->attr.flavor = FL_VARIABLE;
    7045          325 :           omp_orig->n.sym->attr.flavor = FL_VARIABLE;
    7046          325 :           gfc_commit_symbols ();
    7047          325 :           omp_udr->initializer_ns = initializer_ns;
    7048          325 :           omp_udr->omp_priv = omp_priv->n.sym;
    7049          325 :           omp_udr->omp_orig = omp_orig->n.sym;
    7050              : 
    7051          325 :           if (!match_udr_expr (omp_priv, omp_orig))
    7052            6 :             goto syntax;
    7053              :         }
    7054              : 
    7055          585 :       gfc_current_ns = combiner_ns->parent;
    7056          585 :       if (!end_loc_set)
    7057              :         {
    7058          549 :           end_loc_set = true;
    7059          549 :           end_loc = gfc_current_locus;
    7060              :         }
    7061          585 :       gfc_current_locus = old_loc;
    7062              : 
    7063          585 :       prev_udr = gfc_omp_udr_find (st, &tss[i]);
    7064          585 :       if (gfc_omp_udr_predef (rop, name, &tss[i], &predef_name)
    7065              :           /* Don't error on !$omp declare reduction (min : integer : ...)
    7066              :              just yet, there could be integer :: min afterwards,
    7067              :              making it valid.  When the UDR is resolved, we'll get
    7068              :              to it again.  */
    7069          585 :           && (rop != OMP_REDUCTION_USER || name[0] == '.'))
    7070              :         {
    7071           27 :           if (predef_name)
    7072            0 :             gfc_error_now ("Redefinition of predefined %qs in "
    7073              :                            "!$OMP DECLARE REDUCTION at %L",
    7074              :                            predef_name, &where);
    7075              :           else
    7076           27 :             gfc_error_now ("Redefinition of predefined %qs in "
    7077              :                            "!$OMP DECLARE REDUCTION at %L", name, &where);
    7078           27 :           goto syntax;
    7079              :         }
    7080          558 :       else if (prev_udr)
    7081              :         {
    7082            7 :           gfc_error_now ("Redefinition of %qs in !$OMP DECLARE REDUCTION at %L",
    7083              :                          name, &where);
    7084            7 :           inform (gfc_get_location (&prev_udr->where),
    7085              :                   "Previous !$OMP DECLARE REDUCTION");
    7086            7 :           goto syntax;
    7087              :         }
    7088          551 :       else if (st)
    7089              :         {
    7090           98 :           omp_udr->next = st->n.omp_udr;
    7091           98 :           st->n.omp_udr = omp_udr;
    7092              :         }
    7093              :       else
    7094              :         {
    7095          453 :           st = gfc_new_symtree (&gfc_current_ns->omp_udr_root, name);
    7096          453 :           st->n.omp_udr = omp_udr;
    7097              :         }
    7098              :     }
    7099              : 
    7100          515 :   if (end_loc_set)
    7101              :     {
    7102          515 :       gfc_current_locus = end_loc;
    7103          515 :       if (gfc_match_omp_eos () != MATCH_YES)
    7104              :         {
    7105            4 :           gfc_error ("Unexpected junk at %C");
    7106            4 :           return MATCH_ERROR;
    7107              :         }
    7108              :       return MATCH_YES;
    7109              :     }
    7110              :   return MATCH_ERROR;
    7111          594 : }
    7112              : 
    7113              : 
    7114              : match
    7115          490 : gfc_match_omp_declare_target (void)
    7116              : {
    7117          490 :   locus old_loc;
    7118          490 :   match m;
    7119          490 :   gfc_omp_clauses *c = NULL;
    7120          490 :   enum gfc_omp_list_type list;
    7121          490 :   gfc_omp_namelist *n;
    7122          490 :   gfc_symbol *s;
    7123              : 
    7124          490 :   old_loc = gfc_current_locus;
    7125              : 
    7126          490 :   if (gfc_current_ns->proc_name
    7127          490 :       && gfc_match_omp_eos () == MATCH_YES)
    7128              :     {
    7129          138 :       if (!gfc_add_omp_declare_target (&gfc_current_ns->proc_name->attr,
    7130          138 :                                        gfc_current_ns->proc_name->name,
    7131              :                                        &old_loc))
    7132            0 :         goto cleanup;
    7133              :       return MATCH_YES;
    7134              :     }
    7135              : 
    7136          352 :   if (gfc_current_ns->proc_name
    7137          352 :       && gfc_current_ns->proc_name->attr.if_source == IFSRC_IFBODY)
    7138              :     {
    7139            2 :       gfc_error ("Only the !$OMP DECLARE TARGET form without "
    7140              :                  "clauses is allowed in interface block at %C");
    7141            2 :       goto cleanup;
    7142              :     }
    7143              : 
    7144          350 :   m = gfc_match (" (");
    7145          350 :   if (m == MATCH_YES)
    7146              :     {
    7147           86 :       c = gfc_get_omp_clauses ();
    7148           86 :       gfc_current_locus = old_loc;
    7149           86 :       m = gfc_match_omp_to_link (" (", &c->lists[OMP_LIST_ENTER]);
    7150           86 :       if (m != MATCH_YES)
    7151            0 :         goto syntax;
    7152           86 :       if (gfc_match_omp_eos () != MATCH_YES)
    7153              :         {
    7154            0 :           gfc_error ("Unexpected junk after !$OMP DECLARE TARGET at %C");
    7155            0 :           goto cleanup;
    7156              :         }
    7157              :     }
    7158          264 :   else if (gfc_match_omp_clauses (&c, OMP_DECLARE_TARGET_CLAUSES, false)
    7159              :            != MATCH_YES)
    7160              :     return MATCH_ERROR;
    7161              : 
    7162          344 :   gfc_buffer_error (false);
    7163              : 
    7164          344 :   static const enum gfc_omp_list_type to_enter_link_lists[]
    7165              :     = { OMP_LIST_TO, OMP_LIST_ENTER, OMP_LIST_LINK, OMP_LIST_LOCAL };
    7166         1720 :   for (size_t listn = 0; listn < ARRAY_SIZE (to_enter_link_lists)
    7167         1720 :                          && (list = to_enter_link_lists[listn], true); ++listn)
    7168         1941 :     for (n = c->lists[list]; n; n = n->next)
    7169          565 :       if (n->sym)
    7170          523 :         n->sym->mark = 0;
    7171           42 :       else if (n->u.common->head)
    7172           42 :         n->u.common->head->mark = 0;
    7173              : 
    7174          344 :   if (c->device_type == OMP_DEVICE_TYPE_UNSET)
    7175          276 :     c->device_type = OMP_DEVICE_TYPE_ANY;
    7176         1720 :   for (size_t listn = 0; listn < ARRAY_SIZE (to_enter_link_lists)
    7177         1720 :                          && (list = to_enter_link_lists[listn], true); ++listn)
    7178         1941 :     for (n = c->lists[list]; n; n = n->next)
    7179          565 :       if (n->sym)
    7180              :         {
    7181          523 :           if (n->sym->attr.in_common)
    7182            1 :             gfc_error_now ("OMP DECLARE TARGET variable at %L is an "
    7183              :                            "element of a COMMON block", &n->where);
    7184          522 :           else if (n->sym->attr.omp_groupprivate && list != OMP_LIST_LOCAL)
    7185           12 :             gfc_error_now ("List item %qs at %L should not appear in the %qs "
    7186              :                            "clause, as it was previously specified in a "
    7187              :                            "GROUPPRIVATE directive", n->sym->name, &n->where,
    7188              :                            list == OMP_LIST_LINK
    7189            5 :                            ? "link" : list == OMP_LIST_TO ? "to" : "enter");
    7190          515 :           else if (n->sym->mark)
    7191           11 :             gfc_error_now ("Variable at %L mentioned multiple times in "
    7192              :                            "clauses of the same OMP DECLARE TARGET directive",
    7193              :                            &n->where);
    7194          504 :           else if ((list != OMP_LIST_LINK
    7195          471 :                     && n->sym->attr.omp_declare_target_link)
    7196          469 :                    || (list != OMP_LIST_LOCAL
    7197          488 :                        && n->sym->attr.omp_declare_target_local))
    7198           10 :             gfc_error_now ("OMP DECLARE TARGET variable at %L previously "
    7199              :                            "mentioned in %s clause and later in %s clause",
    7200              :                            &n->where,
    7201            5 :                            n->sym->attr.omp_declare_target_link ? "LINK"
    7202              :                                                                 : "LOCAL",
    7203              :                            (list == OMP_LIST_LOCAL ? "LOCAL"
    7204              :                             : list == OMP_LIST_LINK ? "LINK"
    7205              :                             : list == OMP_LIST_TO ? "TO" : "ENTER"));
    7206          499 :           else if (n->sym->attr.omp_declare_target
    7207           15 :                    && (list == OMP_LIST_LINK || list == OMP_LIST_LOCAL))
    7208            3 :             gfc_error_now ("OMP DECLARE TARGET variable at %L previously "
    7209              :                            "mentioned in TO or ENTER clause and later in "
    7210              :                            "%s clause", &n->where,
    7211              :                            list == OMP_LIST_LINK ? "LINK" : "LOCAL");
    7212              :           else
    7213              :             {
    7214          497 :               if (list == OMP_LIST_TO || list == OMP_LIST_ENTER)
    7215          453 :                 gfc_add_omp_declare_target (&n->sym->attr, n->sym->name,
    7216              :                                             &n->sym->declared_at);
    7217          497 :               if (list == OMP_LIST_LINK)
    7218           31 :                 gfc_add_omp_declare_target_link (&n->sym->attr, n->sym->name,
    7219           31 :                                                  &n->sym->declared_at);
    7220          497 :               if (list == OMP_LIST_LOCAL)
    7221           13 :                 gfc_add_omp_declare_target_local (&n->sym->attr, n->sym->name,
    7222           13 :                                                   &n->sym->declared_at);
    7223              :             }
    7224          523 :           if (n->sym->attr.omp_device_type != OMP_DEVICE_TYPE_UNSET
    7225           43 :               && n->sym->attr.omp_device_type != c->device_type)
    7226              :             {
    7227           12 :               const char *dt = "any";
    7228           12 :               if (n->sym->attr.omp_device_type == OMP_DEVICE_TYPE_NOHOST)
    7229              :                 dt = "nohost";
    7230            8 :               else if (n->sym->attr.omp_device_type == OMP_DEVICE_TYPE_HOST)
    7231            4 :                 dt = "host";
    7232           12 :               if (n->sym->attr.omp_groupprivate)
    7233            1 :                 gfc_error_now ("List item %qs at %L set in previous OMP "
    7234              :                                "GROUPPRIVATE directive to the different "
    7235              :                                "DEVICE_TYPE %qs", n->sym->name, &n->where, dt);
    7236              :               else
    7237           11 :                 gfc_error_now ("List item %qs at %L set in previous OMP "
    7238              :                                "DECLARE TARGET directive to the different "
    7239              :                                "DEVICE_TYPE %qs", n->sym->name, &n->where, dt);
    7240              :             }
    7241          523 :           n->sym->attr.omp_device_type = c->device_type;
    7242          523 :           if (c->indirect && c->device_type != OMP_DEVICE_TYPE_ANY)
    7243              :             {
    7244            1 :               gfc_error_now ("DEVICE_TYPE must be ANY when used with INDIRECT "
    7245              :                              "at %L", &n->where);
    7246            1 :               c->indirect = 0;
    7247              :             }
    7248          523 :           n->sym->attr.omp_declare_target_indirect = c->indirect;
    7249          523 :           if (list == OMP_LIST_LINK && c->device_type == OMP_DEVICE_TYPE_NOHOST)
    7250            3 :             gfc_error_now ("List item %qs at %L set with NOHOST specified may "
    7251              :                            "not appear in a LINK clause", n->sym->name,
    7252              :                            &n->where);
    7253          523 :           n->sym->mark = 1;
    7254              :         }
    7255              :       else  /* common block  */
    7256              :         {
    7257           42 :           if (n->u.common->omp_groupprivate && list != OMP_LIST_LOCAL)
    7258            7 :             gfc_error_now ("Common block %</%s/%> at %L not appear in the %qs "
    7259              :                            "clause as it was previously specified in a "
    7260              :                            "GROUPPRIVATE directive",
    7261            7 :                            n->u.common->name, &n->where,
    7262              :                            list == OMP_LIST_LINK
    7263            5 :                            ? "link" : list == OMP_LIST_TO ? "to" : "enter");
    7264           35 :           else if (n->u.common->head && n->u.common->head->mark)
    7265            4 :             gfc_error_now ("Common block %</%s/%> at %L mentioned multiple "
    7266              :                            "times in clauses of the same OMP DECLARE TARGET "
    7267            4 :                            "directive", n->u.common->name, &n->where);
    7268           31 :           else if ((n->u.common->omp_declare_target_link
    7269           27 :                     || n->u.common->omp_declare_target_local)
    7270              :                    && list != OMP_LIST_LINK
    7271            6 :                    && list != OMP_LIST_LOCAL)
    7272            2 :             gfc_error_now ("Common block %</%s/%> at %L previously mentioned "
    7273              :                            "in %s clause and later in %s clause",
    7274            1 :                            n->u.common->name, &n->where,
    7275              :                            n->u.common->omp_declare_target_link ? "LINK"
    7276              :                                                                 : "LOCAL",
    7277              :                            list == OMP_LIST_TO ? "TO" : "ENTER");
    7278           30 :           else if (n->u.common->omp_declare_target
    7279            4 :                    && (list == OMP_LIST_LINK || list == OMP_LIST_LOCAL))
    7280            1 :             gfc_error_now ("Common block %</%s/%> at %L previously mentioned "
    7281              :                            "in TO or ENTER clause and later in %s clause",
    7282            1 :                            n->u.common->name, &n->where,
    7283              :                            list == OMP_LIST_LINK ? "LINK" : "LOCAL");
    7284           42 :           if (n->u.common->omp_device_type != OMP_DEVICE_TYPE_UNSET
    7285           21 :               && n->u.common->omp_device_type != c->device_type)
    7286              :             {
    7287            1 :               const char *dt = "any";
    7288            1 :               if (n->u.common->omp_device_type == OMP_DEVICE_TYPE_NOHOST)
    7289              :                 dt = "nohost";
    7290            0 :               else if (n->u.common->omp_device_type == OMP_DEVICE_TYPE_HOST)
    7291            0 :                 dt = "host";
    7292            1 :               if (n->u.common->omp_groupprivate)
    7293            1 :                 gfc_error_now ("Common block %</%s/%> at %L set in previous OMP "
    7294              :                                "GROUPPRIVATE directive to the different "
    7295            1 :                                "DEVICE_TYPE %qs", n->u.common->name, &n->where,
    7296              :                                 dt);
    7297              :               else
    7298            0 :                 gfc_error_now ("Common block %</%s/%> at %L set in previous OMP "
    7299              :                                "DECLARE TARGET directive to the different "
    7300            0 :                                "DEVICE_TYPE %qs", n->u.common->name, &n->where,
    7301              :                                 dt);
    7302              :             }
    7303           42 :           n->u.common->omp_device_type = c->device_type;
    7304              : 
    7305           42 :           if (c->indirect && c->device_type != OMP_DEVICE_TYPE_ANY)
    7306              :             {
    7307            0 :               gfc_error_now ("DEVICE_TYPE must be ANY when used with INDIRECT "
    7308              :                              "at %L", &n->where);
    7309            0 :               c->indirect = 0;
    7310              :             }
    7311           42 :           if (list == OMP_LIST_LINK && c->device_type == OMP_DEVICE_TYPE_NOHOST)
    7312            1 :             gfc_error_now ("Common block %</%s/%> at %L set with NOHOST "
    7313              :                            "specified may not appear in a LINK clause",
    7314            1 :                            n->u.common->name, &n->where);
    7315              : 
    7316           42 :           if (list == OMP_LIST_TO || list == OMP_LIST_ENTER)
    7317           21 :             n->u.common->omp_declare_target = 1;
    7318           42 :           if (list == OMP_LIST_LINK)
    7319           15 :             n->u.common->omp_declare_target_link = 1;
    7320           42 :           if (list == OMP_LIST_LOCAL)
    7321            6 :             n->u.common->omp_declare_target_local = 1;
    7322              : 
    7323          112 :           for (s = n->u.common->head; s; s = s->common_next)
    7324              :             {
    7325           70 :               s->mark = 1;
    7326           70 :               if (list == OMP_LIST_TO || list == OMP_LIST_ENTER)
    7327           33 :                 gfc_add_omp_declare_target (&s->attr, s->name, &n->where);
    7328           70 :               if (list == OMP_LIST_LINK)
    7329           31 :                 gfc_add_omp_declare_target_link (&s->attr, s->name, &n->where);
    7330           70 :               if (list == OMP_LIST_LOCAL)
    7331            6 :                 gfc_add_omp_declare_target_local (&s->attr, s->name, &n->where);
    7332           70 :               s->attr.omp_device_type = c->device_type;
    7333           70 :               s->attr.omp_declare_target_indirect = c->indirect;
    7334              :             }
    7335              :         }
    7336          344 :   if ((c->device_type || c->indirect)
    7337          344 :       && !c->lists[OMP_LIST_ENTER]
    7338          161 :       && !c->lists[OMP_LIST_TO]
    7339           56 :       && !c->lists[OMP_LIST_LINK]
    7340           17 :       && !c->lists[OMP_LIST_LOCAL])
    7341            2 :     gfc_warning_now (OPT_Wopenmp,
    7342              :                      "OMP DECLARE TARGET directive at %L with only "
    7343              :                      "DEVICE_TYPE or INDIRECT clauses is ignored",
    7344              :                      &old_loc);
    7345              : 
    7346          344 :   gfc_buffer_error (true);
    7347              : 
    7348          344 :   if (c)
    7349          344 :     gfc_free_omp_clauses (c);
    7350              :   return MATCH_YES;
    7351              : 
    7352            0 : syntax:
    7353            0 :   gfc_error ("Syntax error in !$OMP DECLARE TARGET list at %C");
    7354              : 
    7355            2 : cleanup:
    7356            2 :   gfc_current_locus = old_loc;
    7357            2 :   if (c)
    7358            0 :     gfc_free_omp_clauses (c);
    7359              :   return MATCH_ERROR;
    7360              : }
    7361              : 
    7362              : /* Skip over and ignore trait-property-extensions.
    7363              : 
    7364              :    trait-property-extension :
    7365              :      trait-property-name
    7366              :      identifier (trait-property-extension[, trait-property-extension[, ...]])
    7367              :      constant integer expression
    7368              :  */
    7369              : 
    7370              : static match gfc_ignore_trait_property_extension_list (void);
    7371              : 
    7372              : static match
    7373            7 : gfc_ignore_trait_property_extension (void)
    7374              : {
    7375            7 :   char buf[GFC_MAX_SYMBOL_LEN + 1];
    7376            7 :   gfc_expr *expr;
    7377              : 
    7378              :   /* Identifier form of trait-property name, possibly followed by
    7379              :      a list of (recursive) trait-property-extensions.  */
    7380            7 :   if (gfc_match_name (buf) == MATCH_YES)
    7381              :     {
    7382            0 :       if (gfc_match (" (") == MATCH_YES)
    7383            0 :         return gfc_ignore_trait_property_extension_list ();
    7384              :       return MATCH_YES;
    7385              :     }
    7386              : 
    7387              :   /* Literal constant.  */
    7388            7 :   if (gfc_match_literal_constant (&expr, 0) == MATCH_YES)
    7389              :     return MATCH_YES;
    7390              : 
    7391              :   /* FIXME: constant integer expressions.  */
    7392            0 :   gfc_error ("Expected trait-property-extension at %C");
    7393            0 :   return MATCH_ERROR;
    7394              : }
    7395              : 
    7396              : static match
    7397            5 : gfc_ignore_trait_property_extension_list (void)
    7398              : {
    7399            9 :   while (1)
    7400              :     {
    7401            7 :       if (gfc_ignore_trait_property_extension () != MATCH_YES)
    7402              :         return MATCH_ERROR;
    7403            7 :       if (gfc_match (" ,") == MATCH_YES)
    7404            2 :         continue;
    7405            5 :       if (gfc_match (" )") == MATCH_YES)
    7406              :         return MATCH_YES;
    7407            0 :       gfc_error ("expected %<)%> at %C");
    7408            0 :       return MATCH_ERROR;
    7409              :     }
    7410              : }
    7411              : 
    7412              : 
    7413              : match
    7414          110 : gfc_match_omp_interop (void)
    7415              : {
    7416          110 :   return match_omp (EXEC_OMP_INTEROP, OMP_INTEROP_CLAUSES);
    7417              : }
    7418              : 
    7419              : 
    7420              : /* OpenMP 5.0:
    7421              : 
    7422              :    trait-selector:
    7423              :      trait-selector-name[([trait-score:]trait-property[,trait-property[,...]])]
    7424              : 
    7425              :    trait-score:
    7426              :      score(score-expression)  */
    7427              : 
    7428              : static match
    7429          650 : gfc_match_omp_context_selector (gfc_omp_set_selector *oss)
    7430              : {
    7431          789 :   do
    7432              :     {
    7433          789 :       char selector[GFC_MAX_SYMBOL_LEN + 1];
    7434              : 
    7435          789 :       if (gfc_match_name (selector) != MATCH_YES)
    7436              :         {
    7437            2 :           gfc_error ("expected trait selector name at %C");
    7438           39 :           return MATCH_ERROR;
    7439              :         }
    7440              : 
    7441          787 :       gfc_omp_selector *os = gfc_get_omp_selector ();
    7442          787 :       if (oss->code == OMP_TRAIT_SET_CONSTRUCT
    7443          341 :           && !strcmp (selector, "do"))
    7444           48 :         os->code = OMP_TRAIT_CONSTRUCT_FOR;
    7445          739 :       else if (oss->code == OMP_TRAIT_SET_CONSTRUCT
    7446          293 :                && !strcmp (selector, "for"))
    7447            1 :         os->code = OMP_TRAIT_INVALID;
    7448              :       else
    7449          738 :         os->code = omp_lookup_ts_code (oss->code, selector);
    7450          787 :       os->next = oss->trait_selectors;
    7451          787 :       oss->trait_selectors = os;
    7452              : 
    7453          787 :       if (os->code == OMP_TRAIT_INVALID)
    7454              :         {
    7455           18 :           gfc_warning (OPT_Wopenmp,
    7456              :                        "unknown selector %qs for context selector set %qs "
    7457              :                        "at %C",
    7458           18 :                        selector, omp_tss_map[oss->code]);
    7459           18 :           if (gfc_match (" (") == MATCH_YES
    7460           18 :               && gfc_ignore_trait_property_extension_list () != MATCH_YES)
    7461              :             return MATCH_ERROR;
    7462           18 :           if (gfc_match (" ,") == MATCH_YES)
    7463            1 :             continue;
    7464          611 :           break;
    7465              :         }
    7466              : 
    7467          769 :       enum omp_tp_type property_kind = omp_ts_map[os->code].tp_type;
    7468          769 :       bool allow_score = omp_ts_map[os->code].allow_score;
    7469              : 
    7470          769 :       if (gfc_match (" (") == MATCH_YES)
    7471              :         {
    7472          439 :           if (property_kind == OMP_TRAIT_PROPERTY_NONE)
    7473              :             {
    7474            6 :               gfc_error ("selector %qs does not accept any properties at %C",
    7475              :                          selector);
    7476            6 :               return MATCH_ERROR;
    7477              :             }
    7478              : 
    7479          433 :           if (gfc_match (" score") == MATCH_YES)
    7480              :             {
    7481           63 :               if (!allow_score)
    7482              :                 {
    7483           10 :                   gfc_error ("%<score%> cannot be specified in traits "
    7484              :                              "in the %qs trait-selector-set at %C",
    7485           10 :                              omp_tss_map[oss->code]);
    7486           10 :                   return MATCH_ERROR;
    7487              :                 }
    7488           53 :               if (gfc_match (" (") != MATCH_YES)
    7489              :                 {
    7490            0 :                   gfc_error ("expected %<(%> at %C");
    7491            0 :                   return MATCH_ERROR;
    7492              :                 }
    7493           53 :               if (gfc_match_expr (&os->score) != MATCH_YES)
    7494              :                 return MATCH_ERROR;
    7495              : 
    7496           52 :               if (gfc_match (" )") != MATCH_YES)
    7497              :                 {
    7498            0 :                   gfc_error ("expected %<)%> at %C");
    7499            0 :                   return MATCH_ERROR;
    7500              :                 }
    7501              : 
    7502           52 :               if (gfc_match (" :") != MATCH_YES)
    7503              :                 {
    7504            0 :                   gfc_error ("expected : at %C");
    7505            0 :                   return MATCH_ERROR;
    7506              :                 }
    7507              :             }
    7508              : 
    7509          422 :           gfc_omp_trait_property *otp = gfc_get_omp_trait_property ();
    7510          422 :           otp->property_kind = property_kind;
    7511          422 :           otp->next = os->properties;
    7512          422 :           os->properties = otp;
    7513              : 
    7514          422 :           switch (property_kind)
    7515              :             {
    7516           25 :             case OMP_TRAIT_PROPERTY_ID:
    7517           25 :               {
    7518           25 :                 char buf[GFC_MAX_SYMBOL_LEN + 1];
    7519           25 :                 if (gfc_match_name (buf) == MATCH_YES)
    7520              :                   {
    7521           24 :                     otp->name = XNEWVEC (char, strlen (buf) + 1);
    7522           24 :                     strcpy (otp->name, buf);
    7523              :                   }
    7524              :                 else
    7525              :                   {
    7526            1 :                     gfc_error ("expected identifier at %C");
    7527            1 :                     free (otp);
    7528            1 :                     os->properties = nullptr;
    7529            1 :                     return MATCH_ERROR;
    7530              :                   }
    7531              :               }
    7532           24 :               break;
    7533          290 :             case OMP_TRAIT_PROPERTY_NAME_LIST:
    7534          343 :               do
    7535              :                 {
    7536          290 :                   char buf[GFC_MAX_SYMBOL_LEN + 1];
    7537          290 :                   if (gfc_match_name (buf) == MATCH_YES)
    7538              :                     {
    7539          170 :                       otp->name = XNEWVEC (char, strlen (buf) + 1);
    7540          170 :                       strcpy (otp->name, buf);
    7541          170 :                       otp->is_name = true;
    7542              :                     }
    7543          120 :                   else if (gfc_match_literal_constant (&otp->expr, 0)
    7544              :                            != MATCH_YES
    7545          120 :                            || otp->expr->ts.type != BT_CHARACTER)
    7546              :                     {
    7547            5 :                       gfc_error ("expected identifier or string literal "
    7548              :                                  "at %C");
    7549            5 :                       free (otp);
    7550            5 :                       os->properties = nullptr;
    7551            5 :                       return MATCH_ERROR;
    7552              :                     }
    7553              : 
    7554          285 :                   if (gfc_match (" ,") == MATCH_YES)
    7555              :                     {
    7556           53 :                       otp = gfc_get_omp_trait_property ();
    7557           53 :                       otp->property_kind = property_kind;
    7558           53 :                       otp->next = os->properties;
    7559           53 :                       os->properties = otp;
    7560              :                     }
    7561              :                   else
    7562              :                     break;
    7563           53 :                 }
    7564              :               while (1);
    7565          232 :               break;
    7566          145 :             case OMP_TRAIT_PROPERTY_DEV_NUM_EXPR:
    7567          145 :             case OMP_TRAIT_PROPERTY_BOOL_EXPR:
    7568          145 :               if (gfc_match_expr (&otp->expr) != MATCH_YES)
    7569              :                 {
    7570            3 :                   gfc_error ("expected expression at %C");
    7571            3 :                   free (otp);
    7572            3 :                   os->properties = nullptr;
    7573            3 :                   return MATCH_ERROR;
    7574              :                 }
    7575              :               break;
    7576           15 :             case OMP_TRAIT_PROPERTY_CLAUSE_LIST:
    7577           15 :               {
    7578           15 :                 if (os->code == OMP_TRAIT_CONSTRUCT_SIMD)
    7579              :                   {
    7580           15 :                     gfc_matching_omp_context_selector = true;
    7581           15 :                     if (gfc_match_omp_clauses (&otp->clauses,
    7582           15 :                                                OMP_DECLARE_SIMD_CLAUSES,
    7583              :                                                true, false, false)
    7584              :                         != MATCH_YES)
    7585              :                       {
    7586            1 :                         gfc_matching_omp_context_selector = false;
    7587            1 :                         gfc_error ("expected simd clause at %C");
    7588            1 :                         return MATCH_ERROR;
    7589              :                       }
    7590           14 :                     gfc_matching_omp_context_selector = false;
    7591              :                   }
    7592            0 :                 else if (os->code == OMP_TRAIT_IMPLEMENTATION_REQUIRES)
    7593              :                   {
    7594              :                     /* FIXME: The "requires" selector was added in OpenMP 5.1.
    7595              :                        Currently only the now-deprecated syntax
    7596              :                        from OpenMP 5.0 is supported.
    7597              :                        TODO: When implementing, update modules.cc as well.  */
    7598            0 :                     sorry_at (gfc_get_location (&gfc_current_locus),
    7599              :                               "%<requires%> selector is not supported yet");
    7600            0 :                     return MATCH_ERROR;
    7601              :                   }
    7602              :                 else
    7603            0 :                   gcc_unreachable ();
    7604           14 :                 break;
    7605              :               }
    7606            0 :             default:
    7607            0 :               gcc_unreachable ();
    7608              :             }
    7609              : 
    7610          412 :           if (gfc_match (" )") != MATCH_YES)
    7611              :             {
    7612            2 :               gfc_error ("expected %<)%> at %C");
    7613            2 :               return MATCH_ERROR;
    7614              :             }
    7615              :         }
    7616          330 :       else if (property_kind != OMP_TRAIT_PROPERTY_NONE
    7617          330 :                && property_kind != OMP_TRAIT_PROPERTY_CLAUSE_LIST
    7618            8 :                && property_kind != OMP_TRAIT_PROPERTY_EXTENSION)
    7619              :         {
    7620            8 :           if (gfc_match (" (") != MATCH_YES)
    7621              :             {
    7622            8 :               gfc_error ("expected %<(%> at %C");
    7623            8 :               return MATCH_ERROR;
    7624              :             }
    7625              :         }
    7626              : 
    7627          732 :       if (gfc_match (" ,") != MATCH_YES)
    7628              :         break;
    7629              :     }
    7630              :   while (1);
    7631              : 
    7632          611 :   return MATCH_YES;
    7633              : }
    7634              : 
    7635              : /* OpenMP 5.0:
    7636              : 
    7637              :    trait-set-selector[,trait-set-selector[,...]]
    7638              : 
    7639              :    trait-set-selector:
    7640              :      trait-set-selector-name = { trait-selector[, trait-selector[, ...]] }
    7641              : 
    7642              :    trait-set-selector-name:
    7643              :      constructor
    7644              :      device
    7645              :      implementation
    7646              :      user  */
    7647              : 
    7648              : static match
    7649          590 : gfc_match_omp_context_selector_specification (gfc_omp_set_selector **oss_head)
    7650              : {
    7651          726 :   do
    7652              :     {
    7653          658 :       match m;
    7654          658 :       char buf[GFC_MAX_SYMBOL_LEN + 1];
    7655          658 :       enum omp_tss_code set = OMP_TRAIT_SET_INVALID;
    7656              : 
    7657          658 :       m = gfc_match_name (buf);
    7658          658 :       if (m == MATCH_YES)
    7659          656 :         set = omp_lookup_tss_code (buf);
    7660              : 
    7661          656 :       if (set == OMP_TRAIT_SET_INVALID)
    7662              :         {
    7663            5 :           gfc_error ("expected context selector set name at %C");
    7664           47 :           return MATCH_ERROR;
    7665              :         }
    7666              : 
    7667          653 :       m = gfc_match (" =");
    7668          653 :       if (m != MATCH_YES)
    7669              :         {
    7670            1 :           gfc_error ("expected %<=%> at %C");
    7671            1 :           return MATCH_ERROR;
    7672              :         }
    7673              : 
    7674          652 :       m = gfc_match (" {");
    7675          652 :       if (m != MATCH_YES)
    7676              :         {
    7677            2 :           gfc_error ("expected %<{%> at %C");
    7678            2 :           return MATCH_ERROR;
    7679              :         }
    7680              : 
    7681          650 :       gfc_omp_set_selector *oss = gfc_get_omp_set_selector ();
    7682          650 :       oss->next = *oss_head;
    7683          650 :       oss->code = set;
    7684          650 :       *oss_head = oss;
    7685              : 
    7686          650 :       if (gfc_match_omp_context_selector (oss) != MATCH_YES)
    7687              :         return MATCH_ERROR;
    7688              : 
    7689          611 :       m = gfc_match (" }");
    7690          611 :       if (m != MATCH_YES)
    7691              :         {
    7692            0 :           gfc_error ("expected %<}%> at %C");
    7693            0 :           return MATCH_ERROR;
    7694              :         }
    7695              : 
    7696          611 :       m = gfc_match (" ,");
    7697          611 :       if (m != MATCH_YES)
    7698              :         break;
    7699           68 :     }
    7700              :   while (1);
    7701              : 
    7702          543 :   return MATCH_YES;
    7703              : }
    7704              : 
    7705              : 
    7706              : match
    7707          426 : gfc_match_omp_declare_variant (void)
    7708              : {
    7709          426 :   char buf[GFC_MAX_SYMBOL_LEN + 1];
    7710              : 
    7711          426 :   if (gfc_match (" (") != MATCH_YES)
    7712              :     {
    7713            2 :       gfc_error ("expected %<(%> at %C");
    7714            2 :       return MATCH_ERROR;
    7715              :     }
    7716              : 
    7717          424 :   gfc_symtree *base_proc_st, *variant_proc_st;
    7718          424 :   if (gfc_match_name (buf) != MATCH_YES)
    7719              :     {
    7720            2 :       gfc_error ("expected name at %C");
    7721            2 :       return MATCH_ERROR;
    7722              :     }
    7723              : 
    7724          422 :   if (gfc_get_ha_sym_tree (buf, &base_proc_st))
    7725              :     return MATCH_ERROR;
    7726              : 
    7727          422 :   if (gfc_match (" :") == MATCH_YES)
    7728              :     {
    7729           16 :       if (gfc_match_name (buf) != MATCH_YES)
    7730              :         {
    7731            0 :           gfc_error ("expected variant name at %C");
    7732            0 :           return MATCH_ERROR;
    7733              :         }
    7734              : 
    7735           16 :       if (gfc_get_ha_sym_tree (buf, &variant_proc_st))
    7736              :         return MATCH_ERROR;
    7737              :     }
    7738              :   else
    7739              :     {
    7740              :       /* Base procedure not specified.  */
    7741          406 :       variant_proc_st = base_proc_st;
    7742          406 :       base_proc_st = NULL;
    7743              :     }
    7744              : 
    7745          422 :   gfc_omp_declare_variant *odv;
    7746          422 :   odv = gfc_get_omp_declare_variant ();
    7747          422 :   odv->where = gfc_current_locus;
    7748          422 :   odv->variant_proc_symtree = variant_proc_st;
    7749          422 :   odv->adjust_args_list = NULL;
    7750          422 :   odv->base_proc_symtree = base_proc_st;
    7751          422 :   odv->next = NULL;
    7752          422 :   odv->error_p = false;
    7753              : 
    7754              :   /* Add the new declare variant to the end of the list.  */
    7755          422 :   gfc_omp_declare_variant **prev_next = &gfc_current_ns->omp_declare_variant;
    7756          577 :   while (*prev_next)
    7757          155 :     prev_next = &((*prev_next)->next);
    7758          422 :   *prev_next = odv;
    7759              : 
    7760          422 :   if (gfc_match (" )") != MATCH_YES)
    7761              :     {
    7762            1 :       gfc_error ("expected %<)%> at %C");
    7763            1 :       return MATCH_ERROR;
    7764              :     }
    7765              : 
    7766          421 :   bool has_match = false, has_adjust_args = false, has_append_args = false;
    7767          421 :   bool error_p = false;
    7768          421 :   locus adjust_args_loc;
    7769          421 :   locus append_args_loc;
    7770              : 
    7771          421 :   gfc_gobble_whitespace ();
    7772          421 :   gfc_match_char (',');
    7773          639 :   for (;;)
    7774              :     {
    7775          530 :       gfc_gobble_whitespace ();
    7776              : 
    7777          530 :       enum clause
    7778              :       {
    7779              :         clause_match,
    7780              :         clause_adjust_args,
    7781              :         clause_append_args
    7782              :       } ccode;
    7783              : 
    7784          530 :       if (gfc_match ("match") == MATCH_YES)
    7785              :         ccode = clause_match;
    7786          119 :       else if (gfc_match ("adjust_args") == MATCH_YES)
    7787              :         {
    7788          524 :           ccode = clause_adjust_args;
    7789              :           adjust_args_loc = gfc_current_locus;
    7790              :         }
    7791           38 :       else if (gfc_match ("append_args") == MATCH_YES)
    7792              :         {
    7793          524 :           ccode = clause_append_args;
    7794              :           append_args_loc = gfc_current_locus;
    7795              :         }
    7796              :       else
    7797              :         {
    7798              :           error_p = true;
    7799              :           break;
    7800              :         }
    7801              : 
    7802          524 :       if (gfc_match (" ( ") != MATCH_YES)
    7803              :         {
    7804            1 :           gfc_error ("expected %<(%> at %C");
    7805            1 :           return MATCH_ERROR;
    7806              :         }
    7807              : 
    7808          523 :       if (ccode == clause_match)
    7809              :         {
    7810          410 :           if (has_match)
    7811              :             {
    7812            1 :               gfc_error ("%qs clause at %L specified more than once",
    7813              :                          "match", &gfc_current_locus);
    7814            1 :               return MATCH_ERROR;
    7815              :             }
    7816          409 :           has_match = true;
    7817          409 :           if (gfc_match_omp_context_selector_specification (&odv->set_selectors)
    7818              :               != MATCH_YES)
    7819              :             return MATCH_ERROR;
    7820          369 :           if (gfc_match (" )") != MATCH_YES)
    7821              :             {
    7822            0 :               gfc_error ("expected %<)%> at %C");
    7823            0 :               return MATCH_ERROR;
    7824              :             }
    7825              :         }
    7826          113 :       else if (ccode == clause_adjust_args)
    7827              :         {
    7828           81 :           has_adjust_args = true;
    7829           81 :           bool need_device_ptr_p = false;
    7830           81 :           bool need_device_addr_p = false;
    7831           81 :           if (gfc_match ("nothing ") == MATCH_YES)
    7832              :             ;
    7833           58 :           else if (gfc_match ("need_device_ptr ") == MATCH_YES)
    7834              :             need_device_ptr_p = true;
    7835            9 :           else if (gfc_match ("need_device_addr ") == MATCH_YES)
    7836              :             need_device_addr_p = true;
    7837              :           else
    7838              :             {
    7839            2 :               gfc_error ("expected %<nothing%>, %<need_device_ptr%> or "
    7840              :                          "%<need_device_addr%> at %C");
    7841            2 :               return MATCH_ERROR;
    7842              :             }
    7843           79 :           if (gfc_match (": ") != MATCH_YES)
    7844              :             {
    7845            1 :               gfc_error ("expected %<:%> at %C");
    7846            1 :               return MATCH_ERROR;
    7847              :             }
    7848              :           gfc_omp_namelist *tail = NULL;
    7849              :           bool need_range = false, have_range = false;
    7850          125 :           while (true)
    7851              :             {
    7852          125 :               gfc_omp_namelist *p = gfc_get_omp_namelist ();
    7853          125 :               p->where = gfc_current_locus;
    7854          125 :               p->u.adj_args.need_ptr = need_device_ptr_p;
    7855          125 :               p->u.adj_args.need_addr = need_device_addr_p;
    7856          125 :               if (tail)
    7857              :                 {
    7858           47 :                   tail->next = p;
    7859           47 :                   tail = tail->next;
    7860              :                 }
    7861              :               else
    7862              :                 {
    7863           78 :                   gfc_omp_namelist **q = &odv->adjust_args_list;
    7864           78 :                   if (*q)
    7865              :                     {
    7866           50 :                       for (; (*q)->next; q = &(*q)->next)
    7867              :                         ;
    7868           28 :                       (*q)->next = p;
    7869              :                     }
    7870              :                   else
    7871           50 :                     *q = p;
    7872              :                   tail = p;
    7873              :                 }
    7874          125 :               if (gfc_match (": ") == MATCH_YES)
    7875              :                 {
    7876            2 :                   if (have_range)
    7877              :                     {
    7878            0 :                       gfc_error ("unexpected %<:%> at %C");
    7879            2 :                       return MATCH_ERROR;
    7880              :                     }
    7881            2 :                   p->u.adj_args.range_start = have_range = true;
    7882            2 :                   need_range = false;
    7883           47 :                   continue;
    7884              :                 }
    7885          123 :               if (have_range && gfc_match (", ") == MATCH_YES)
    7886              :                 {
    7887            1 :                  have_range = false;
    7888            1 :                  continue;
    7889              :                 }
    7890          122 :               if (have_range && gfc_match (") ") == MATCH_YES)
    7891              :                 break;
    7892          121 :               locus saved_loc = gfc_current_locus;
    7893              : 
    7894              :               /* Without ranges, only arg names or integer literals permitted;
    7895              :                  handle literals here as gfc_match_expr simplifies the expr.  */
    7896          121 :               if (gfc_match_literal_constant (&p->expr, true) == MATCH_YES)
    7897              :                 {
    7898           17 :                   gfc_gobble_whitespace ();
    7899           17 :                   char c = gfc_peek_ascii_char ();
    7900           17 :                   if (c != ')' && c != ',' && c != ':')
    7901              :                     {
    7902            1 :                       gfc_free_expr (p->expr);
    7903            1 :                       p->expr = NULL;
    7904            1 :                       gfc_current_locus = saved_loc;
    7905              :                     }
    7906              :                 }
    7907          121 :               if (!p->expr && gfc_match ("omp_num_args") == MATCH_YES)
    7908              :                 {
    7909            6 :                   if (!have_range)
    7910            3 :                     p->u.adj_args.range_start = need_range = true;
    7911              :                   else
    7912              :                     need_range = false;
    7913              : 
    7914            6 :                   locus saved_loc2 = gfc_current_locus;
    7915            6 :                   gfc_gobble_whitespace ();
    7916            6 :                   char c = gfc_peek_ascii_char ();
    7917            6 :                   if (c == '+' || c == '-')
    7918              :                     {
    7919            5 :                       if (gfc_match ("+ %e", &p->expr) == MATCH_YES)
    7920            1 :                         p->u.adj_args.omp_num_args_plus = true;
    7921            4 :                       else if (gfc_match ("- %e", &p->expr) == MATCH_YES)
    7922            4 :                         p->u.adj_args.omp_num_args_minus = true;
    7923            0 :                       else if (!gfc_error_check ())
    7924              :                         {
    7925            0 :                           gfc_error ("expected constant integer expression "
    7926              :                                      "at %C");
    7927            0 :                           p->u.adj_args.error_p = true;
    7928            0 :                           return MATCH_ERROR;
    7929              :                         }
    7930            5 :                       p->where = gfc_get_location_range (&saved_loc, 1,
    7931              :                                                          &saved_loc, 1,
    7932              :                                                          &gfc_current_locus);
    7933              :                     }
    7934              :                   else
    7935              :                     {
    7936            1 :                       p->where = gfc_get_location_range (&saved_loc, 1,
    7937              :                                                          &saved_loc, 1,
    7938              :                                                          &saved_loc2);
    7939            1 :                       p->u.adj_args.omp_num_args_plus = true;
    7940              :                     }
    7941              :                 }
    7942          115 :               else if (!p->expr)
    7943              :                 {
    7944           99 :                   match m = gfc_match_expr (&p->expr);
    7945           99 :                   if (m != MATCH_YES)
    7946              :                     {
    7947            1 :                       gfc_error ("expected dummy parameter name, "
    7948              :                                  "%<omp_num_args%> or constant positive integer"
    7949              :                                  " at %C");
    7950            1 :                       p->u.adj_args.error_p = true;
    7951            1 :                       return MATCH_ERROR;
    7952              :                     }
    7953           98 :                   if (p->expr->expr_type == EXPR_CONSTANT && !have_range)
    7954           98 :                     need_range = true;  /* Constant expr but not literal.  */
    7955           98 :                   p->where = p->expr->where;
    7956              :                 }
    7957              :               else
    7958           16 :                 p->where = p->expr->where;
    7959          120 :               gfc_gobble_whitespace ();
    7960          120 :               match m = gfc_match (": ");
    7961          120 :               if (need_range && m != MATCH_YES)
    7962              :                 {
    7963            1 :                   gfc_error ("expected %<:%> at %C");
    7964            1 :                   return MATCH_ERROR;
    7965              :                 }
    7966          119 :               if (m == MATCH_YES)
    7967              :                 {
    7968            6 :                   p->u.adj_args.range_start = have_range = true;
    7969            6 :                   need_range = false;
    7970            6 :                   continue;
    7971              :                 }
    7972          113 :               need_range = have_range = false;
    7973          113 :               if (gfc_match (", ") == MATCH_YES)
    7974           38 :                 continue;
    7975           75 :               if (gfc_match (") ") == MATCH_YES)
    7976              :                 break;
    7977              :             }
    7978              :         }
    7979           32 :       else if (ccode == clause_append_args)
    7980              :         {
    7981           32 :           if (has_append_args)
    7982              :             {
    7983            1 :               gfc_error ("%qs clause at %L specified more than once",
    7984              :                          "append_args", &gfc_current_locus);
    7985            1 :               return MATCH_ERROR;
    7986              :             }
    7987           56 :           has_append_args = true;
    7988              :           gfc_omp_namelist *append_args_last = NULL;
    7989           81 :           do
    7990              :             {
    7991           56 :               gfc_gobble_whitespace ();
    7992           56 :               if (gfc_match ("interop ") != MATCH_YES)
    7993              :                 {
    7994            0 :                   gfc_error ("expected %<interop%> at %C");
    7995            3 :                   return MATCH_ERROR;
    7996              :                 }
    7997           56 :               if (gfc_match ("( ") != MATCH_YES)
    7998              :                 {
    7999            0 :                   gfc_error ("expected %<(%> at %C");
    8000            0 :                   return MATCH_ERROR;
    8001              :                 }
    8002              : 
    8003           56 :               bool target, targetsync;
    8004           56 :               char *type_str = NULL;
    8005           56 :               int type_str_len;
    8006           56 :               locus loc = gfc_current_locus;
    8007           56 :               if (gfc_parser_omp_clause_init_modifiers (target, targetsync,
    8008              :                                                         &type_str, type_str_len,
    8009              :                                                         false) == MATCH_ERROR)
    8010              :                 return MATCH_ERROR;
    8011              : 
    8012           54 :               gfc_omp_namelist *n = gfc_get_omp_namelist();
    8013           54 :               n->where = loc;
    8014           54 :               n->u.init.target = target;
    8015           54 :               n->u.init.targetsync = targetsync;
    8016           54 :               n->u.init.len = type_str_len;
    8017           54 :               n->u2.init_interop = type_str;
    8018           54 :               if (odv->append_args_list)
    8019              :                 {
    8020           25 :                   append_args_last->next = n;
    8021           25 :                   append_args_last = n;
    8022              :                 }
    8023              :               else
    8024           29 :                 append_args_last = odv->append_args_list = n;
    8025              : 
    8026           54 :               gfc_gobble_whitespace ();
    8027           54 :               if (gfc_match_char (',') == MATCH_YES)
    8028           25 :                 continue;
    8029           29 :               if (gfc_match_char (')') == MATCH_YES)
    8030              :                 break;
    8031            1 :               gfc_error ("Expected %<,%> or %<)%> at %C");
    8032            1 :               return MATCH_ERROR;
    8033           25 :             }
    8034              :           while (true);
    8035              :         }
    8036          473 :       gfc_gobble_whitespace ();
    8037          473 :       if (gfc_match_omp_eos () == MATCH_YES)
    8038              :         break;
    8039          109 :       gfc_match_char (',');
    8040          109 :     }
    8041              : 
    8042          370 :   if (error_p || (!has_match && !has_adjust_args && !has_append_args))
    8043              :     {
    8044            6 :       gfc_error ("expected %<match%>, %<adjust_args%> or %<append_args%> at %C");
    8045            6 :       return MATCH_ERROR;
    8046              :     }
    8047              : 
    8048          364 :   if (!has_match)
    8049              :     {
    8050            3 :       gfc_error ("expected %<match%> clause at %C");
    8051            3 :       return MATCH_ERROR;
    8052              :     }
    8053              : 
    8054              :   return MATCH_YES;
    8055              : }
    8056              : 
    8057              : 
    8058              : static match
    8059          166 : match_omp_metadirective (bool begin_p)
    8060              : {
    8061          166 :   locus old_loc = gfc_current_locus;
    8062          166 :   gfc_omp_variant *variants_head;
    8063          166 :   gfc_omp_variant **next_variant = &variants_head;
    8064          166 :   bool default_seen = false;
    8065              : 
    8066              :   /* Parse the context selectors.  */
    8067          674 :   for (;;)
    8068              :     {
    8069          420 :       bool default_p = false;
    8070          420 :       gfc_omp_set_selector *selectors = NULL;
    8071              : 
    8072          420 :       gfc_gobble_whitespace ();
    8073          420 :       if (gfc_match_eos () == MATCH_YES)
    8074              :         break;
    8075          272 :       gfc_match_char (',');
    8076          272 :       gfc_gobble_whitespace ();
    8077              : 
    8078          272 :       locus variant_locus = gfc_current_locus;
    8079              : 
    8080          272 :       if (gfc_match ("default ( ") == MATCH_YES)
    8081              :         {
    8082           82 :           default_p = true;
    8083           82 :           gfc_warning (OPT_Wdeprecated_openmp,
    8084              :                        "%<default%> clause with metadirective at %L "
    8085              :                        "deprecated since OpenMP 5.2", &variant_locus);
    8086              :         }
    8087          190 :       else if (gfc_match ("otherwise ( ") == MATCH_YES)
    8088              :         default_p = true;
    8089          183 :       else if (gfc_match ("when ( ") != MATCH_YES)
    8090              :         {
    8091            1 :           gfc_error ("expected %<when%>, %<otherwise%>, or %<default%> at %C");
    8092            1 :           gfc_current_locus = old_loc;
    8093           18 :           return MATCH_ERROR;
    8094              :         }
    8095           89 :       if (default_p && default_seen)
    8096              :         {
    8097            3 :           gfc_error ("too many %<otherwise%> or %<default%> clauses "
    8098              :                      "in %<metadirective%> at %C");
    8099            3 :           gfc_current_locus = old_loc;
    8100            3 :           return MATCH_ERROR;
    8101              :         }
    8102          268 :       else if (default_seen)
    8103              :         {
    8104            1 :           gfc_error ("%<otherwise%> or %<default%> clause "
    8105              :                      "must appear last in %<metadirective%> at %C");
    8106            1 :           gfc_current_locus = old_loc;
    8107            1 :           return MATCH_ERROR;
    8108              :         }
    8109              : 
    8110          267 :       if (!default_p)
    8111              :         {
    8112          181 :           if (gfc_match_omp_context_selector_specification (&selectors)
    8113              :               != MATCH_YES)
    8114              :             return MATCH_ERROR;
    8115              : 
    8116          174 :           if (gfc_match (" : ") != MATCH_YES)
    8117              :             {
    8118            1 :               gfc_error ("expected %<:%> at %C");
    8119            1 :               gfc_current_locus = old_loc;
    8120            1 :               return MATCH_ERROR;
    8121              :             }
    8122              : 
    8123          173 :           gfc_commit_symbols ();
    8124              :         }
    8125              : 
    8126          259 :       gfc_matching_omp_context_selector = true;
    8127          259 :       gfc_statement directive = match_omp_directive ();
    8128          259 :       gfc_matching_omp_context_selector = false;
    8129              : 
    8130          259 :       if (is_omp_declarative_stmt (directive))
    8131            0 :         sorry_at (gfc_get_location (&gfc_current_locus),
    8132              :                   "declarative directive variants are not supported");
    8133              : 
    8134          259 :       if (gfc_error_flag_test ())
    8135              :         {
    8136            2 :           gfc_current_locus = old_loc;
    8137            2 :           return MATCH_ERROR;
    8138              :         }
    8139              : 
    8140          257 :       if (gfc_match (" )") != MATCH_YES)
    8141              :         {
    8142            0 :           gfc_error ("Expected %<)%> at %C");
    8143            0 :           gfc_current_locus = old_loc;
    8144            0 :           return MATCH_ERROR;
    8145              :         }
    8146              : 
    8147          257 :       gfc_commit_symbols ();
    8148              : 
    8149          257 :       if (begin_p
    8150          257 :           && directive != ST_NONE
    8151          257 :           && gfc_omp_end_stmt (directive) == ST_NONE)
    8152              :         {
    8153            3 :           gfc_error ("variant directive used in OMP BEGIN METADIRECTIVE "
    8154              :                      "at %C must have a corresponding end directive");
    8155            3 :           gfc_current_locus = old_loc;
    8156            3 :           return MATCH_ERROR;
    8157              :         }
    8158              : 
    8159          254 :       if (default_p)
    8160              :         default_seen = true;
    8161              : 
    8162          254 :       gfc_omp_variant *omv = gfc_get_omp_variant ();
    8163          254 :       omv->selectors = selectors;
    8164          254 :       omv->stmt = directive;
    8165          254 :       omv->where = variant_locus;
    8166              : 
    8167          254 :       if (directive == ST_NONE)
    8168              :         {
    8169              :           /* The directive was a 'nothing' directive.  */
    8170           15 :           omv->code = gfc_get_code (EXEC_CONTINUE);
    8171           15 :           omv->code->ext.omp_clauses = NULL;
    8172              :         }
    8173              :       else
    8174              :         {
    8175          239 :           omv->code = gfc_get_code (new_st.op);
    8176          239 :           omv->code->ext.omp_clauses = new_st.ext.omp_clauses;
    8177              :           /* Prevent the OpenMP clauses from being freed via NEW_ST.  */
    8178          239 :           new_st.ext.omp_clauses = NULL;
    8179              :         }
    8180              : 
    8181          254 :       *next_variant = omv;
    8182          254 :       next_variant = &omv->next;
    8183          254 :     }
    8184              : 
    8185          148 :   if (gfc_match_omp_eos () != MATCH_YES)
    8186              :     {
    8187            0 :       gfc_error ("Unexpected junk after OMP METADIRECTIVE at %C");
    8188            0 :       gfc_current_locus = old_loc;
    8189            0 :       return MATCH_ERROR;
    8190              :     }
    8191              : 
    8192              :   /* Add a 'default (nothing)' clause if no default is explicitly given.  */
    8193          148 :   if (!default_seen)
    8194              :     {
    8195           71 :       gfc_omp_variant *omv = gfc_get_omp_variant ();
    8196           71 :       omv->stmt = ST_NONE;
    8197           71 :       omv->code = gfc_get_code (EXEC_CONTINUE);
    8198           71 :       omv->code->ext.omp_clauses = NULL;
    8199           71 :       omv->where = old_loc;
    8200           71 :       omv->selectors = NULL;
    8201              : 
    8202           71 :       *next_variant = omv;
    8203           71 :       next_variant = &omv->next;
    8204              :     }
    8205              : 
    8206          148 :   new_st.op = EXEC_OMP_METADIRECTIVE;
    8207          148 :   new_st.ext.omp_variants = variants_head;
    8208              : 
    8209          148 :   return MATCH_YES;
    8210              : }
    8211              : 
    8212              : match
    8213           46 : gfc_match_omp_begin_metadirective (void)
    8214              : {
    8215           46 :   return match_omp_metadirective (true);
    8216              : }
    8217              : 
    8218              : match
    8219          120 : gfc_match_omp_metadirective (void)
    8220              : {
    8221          120 :   return match_omp_metadirective (false);
    8222              : }
    8223              : 
    8224              : /* Match 'omp threadprivate' or 'omp groupprivate'.  */
    8225              : static match
    8226          262 : gfc_match_omp_thread_group_private (bool is_groupprivate)
    8227              : {
    8228          262 :   locus old_loc;
    8229          262 :   char n[GFC_MAX_SYMBOL_LEN+1];
    8230          262 :   gfc_symbol *sym;
    8231          262 :   match m;
    8232          262 :   gfc_symtree *st;
    8233          262 :   struct sym_loc_t { gfc_symbol *sym; gfc_common_head *com; locus loc; };
    8234          262 :   auto_vec<sym_loc_t> syms;
    8235              : 
    8236          262 :   old_loc = gfc_current_locus;
    8237              : 
    8238          262 :   m = gfc_match (" ( ");
    8239          262 :   if (m != MATCH_YES)
    8240              :     return m;
    8241              : 
    8242          372 :   for (;;)
    8243              :     {
    8244          317 :       locus sym_loc = gfc_current_locus;
    8245          317 :       m = gfc_match_symbol (&sym, 0);
    8246          317 :       switch (m)
    8247              :         {
    8248          212 :         case MATCH_YES:
    8249          212 :           if (sym->attr.in_common)
    8250            0 :             gfc_error_now ("%qs variable at %L is an element of a COMMON block",
    8251              :                            is_groupprivate ? "groupprivate" : "threadprivate",
    8252              :                            &sym_loc);
    8253          212 :           else if (!is_groupprivate
    8254          212 :                    && !gfc_add_threadprivate (&sym->attr, sym->name, &sym_loc))
    8255           16 :             goto cleanup;
    8256          210 :           else if (is_groupprivate)
    8257              :             {
    8258           33 :               if (!gfc_add_omp_groupprivate (&sym->attr, sym->name, &sym_loc))
    8259            4 :                 goto cleanup;
    8260           29 :               syms.safe_push ({sym, nullptr, sym_loc});
    8261              :             }
    8262          206 :           goto next_item;
    8263              :         case MATCH_NO:
    8264              :           break;
    8265            0 :         case MATCH_ERROR:
    8266            0 :           goto cleanup;
    8267              :         }
    8268              : 
    8269          105 :       m = gfc_match (" / %n /", n);
    8270          105 :       if (m == MATCH_ERROR)
    8271            0 :         goto cleanup;
    8272          105 :       if (m == MATCH_NO || n[0] == '\0')
    8273            0 :         goto syntax;
    8274              : 
    8275          105 :       st = gfc_find_symtree (gfc_current_ns->common_root, n);
    8276          105 :       if (st == NULL)
    8277              :         {
    8278            2 :           gfc_error ("COMMON block /%s/ not found at %L", n, &sym_loc);
    8279            2 :           goto cleanup;
    8280              :         }
    8281          103 :       syms.safe_push ({nullptr, st->n.common, sym_loc});
    8282          103 :       if (is_groupprivate)
    8283           30 :         st->n.common->omp_groupprivate = 1;
    8284              :       else
    8285           73 :         st->n.common->threadprivate = 1;
    8286          236 :       for (sym = st->n.common->head; sym; sym = sym->common_next)
    8287          141 :         if (!is_groupprivate
    8288          141 :             && !gfc_add_threadprivate (&sym->attr, sym->name, &sym_loc))
    8289            3 :           goto cleanup;
    8290          138 :         else if (is_groupprivate
    8291          138 :                  && !gfc_add_omp_groupprivate (&sym->attr, sym->name, &sym_loc))
    8292            5 :           goto cleanup;
    8293              : 
    8294           95 :     next_item:
    8295          301 :       if (gfc_match_char (')') == MATCH_YES)
    8296              :         break;
    8297           55 :       if (gfc_match_char (',') != MATCH_YES)
    8298            0 :         goto syntax;
    8299           55 :     }
    8300              : 
    8301          246 :   if (is_groupprivate)
    8302              :     {
    8303           42 :       gfc_omp_clauses *c;
    8304           42 :       m = gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_DEVICE_TYPE), false, false);
    8305           42 :       if (m == MATCH_ERROR)
    8306            0 :         return MATCH_ERROR;
    8307              : 
    8308           42 :       if (c->device_type == OMP_DEVICE_TYPE_UNSET)
    8309           19 :         c->device_type = OMP_DEVICE_TYPE_ANY;
    8310              : 
    8311           92 :       for (size_t i = 0; i < syms.length (); i++)
    8312           50 :         if (syms[i].sym)
    8313              :           {
    8314           27 :             sym_loc_t &n = syms[i];
    8315           27 :             if (n.sym->attr.in_common)
    8316            0 :               gfc_error_now ("Variable %qs at %L is an element of a COMMON "
    8317              :                              "block", n.sym->name, &n.loc);
    8318           27 :             else if (n.sym->attr.omp_declare_target
    8319           26 :                      || n.sym->attr.omp_declare_target_link)
    8320            2 :               gfc_error_now ("List item %qs at %L implies OMP DECLARE TARGET "
    8321              :                              "with the LOCAL clause, but it has been specified"
    8322              :                              " with a different clause before",
    8323              :                              n.sym->name, &n.loc);
    8324           27 :             if (n.sym->attr.omp_device_type != OMP_DEVICE_TYPE_UNSET
    8325            5 :                 && n.sym->attr.omp_device_type != c->device_type)
    8326              :               {
    8327            2 :               const char *dt = "any";
    8328            2 :               if (n.sym->attr.omp_device_type == OMP_DEVICE_TYPE_HOST)
    8329              :                 dt = "host";
    8330            0 :               else if (n.sym->attr.omp_device_type == OMP_DEVICE_TYPE_NOHOST)
    8331            0 :                 dt = "nohost";
    8332            2 :               gfc_error_now ("List item %qs at %L set in previous OMP DECLARE "
    8333              :                              "TARGET directive to the different DEVICE_TYPE %qs",
    8334              :                              n.sym->name, &n.loc, dt);
    8335              :               }
    8336           27 :             gfc_add_omp_declare_target_local (&n.sym->attr, n.sym->name,
    8337              :                                               &n.loc);
    8338           27 :             n.sym->attr.omp_device_type = c->device_type;
    8339              :           }
    8340              :         else  /* Common block.  */
    8341              :           {
    8342           23 :             sym_loc_t &n = syms[i];
    8343           23 :             if (n.com->omp_declare_target
    8344           22 :                 || n.com->omp_declare_target_link)
    8345            2 :               gfc_error_now ("List item %</%s/%> at %L implies OMP DECLARE "
    8346              :                              "TARGET with the LOCAL clause, but it has been "
    8347              :                              "specified with a different clause before",
    8348            2 :                              n.com->name, &n.loc);
    8349           23 :             if (n.com->omp_device_type != OMP_DEVICE_TYPE_UNSET
    8350            5 :                 && n.com->omp_device_type != c->device_type)
    8351              :               {
    8352            2 :                 const char *dt = "any";
    8353            2 :                 if (n.com->omp_device_type == OMP_DEVICE_TYPE_HOST)
    8354              :                   dt = "host";
    8355            0 :                 else if (n.com->omp_device_type == OMP_DEVICE_TYPE_NOHOST)
    8356            0 :                   dt = "nohost";
    8357            2 :                 gfc_error_now ("List item %qs at %L set in previous OMP DECLARE"
    8358              :                                " TARGET directive to the different DEVICE_TYPE "
    8359            2 :                                "%qs", n.com->name, &n.loc, dt);
    8360              :               }
    8361           23 :             n.com->omp_declare_target_local = 1;
    8362           23 :             n.com->omp_device_type = c->device_type;
    8363           46 :             for (gfc_symbol *s = n.com->head; s; s = s->common_next)
    8364              :               {
    8365           23 :                 gfc_add_omp_declare_target_local (&s->attr, s->name, &n.loc);
    8366           23 :                 s->attr.omp_device_type = c->device_type;
    8367              :               }
    8368              :           }
    8369           42 :       free (c);
    8370              :     }
    8371              : 
    8372          246 :   if (gfc_match_omp_eos () != MATCH_YES)
    8373              :     {
    8374            0 :       gfc_error ("Unexpected junk after OMP %s at %C",
    8375              :                  is_groupprivate ? "GROUPPRIVATE" : "THREADPRIVATE");
    8376            0 :       goto cleanup;
    8377              :     }
    8378              : 
    8379              :   return MATCH_YES;
    8380              : 
    8381            0 : syntax:
    8382            0 :   gfc_error ("Syntax error in !$OMP %s list at %C",
    8383              :              is_groupprivate ? "GROUPPRIVATE" : "THREADPRIVATE");
    8384              : 
    8385           16 : cleanup:
    8386           16 :   gfc_current_locus = old_loc;
    8387           16 :   return MATCH_ERROR;
    8388          262 : }
    8389              : 
    8390              : 
    8391              : match
    8392           51 : gfc_match_omp_groupprivate (void)
    8393              : {
    8394           51 :   return gfc_match_omp_thread_group_private (true);
    8395              : }
    8396              : 
    8397              : 
    8398              : match
    8399          211 : gfc_match_omp_threadprivate (void)
    8400              : {
    8401          211 :   return gfc_match_omp_thread_group_private (false);
    8402              : }
    8403              : 
    8404              : 
    8405              : match
    8406         2213 : gfc_match_omp_parallel (void)
    8407              : {
    8408         2213 :   return match_omp (EXEC_OMP_PARALLEL, OMP_PARALLEL_CLAUSES);
    8409              : }
    8410              : 
    8411              : 
    8412              : match
    8413         1203 : gfc_match_omp_parallel_do (void)
    8414              : {
    8415         1203 :   return match_omp (EXEC_OMP_PARALLEL_DO,
    8416         1203 :                     (OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES)
    8417         1203 :                     & ~(omp_mask (OMP_CLAUSE_NOWAIT)));
    8418              : }
    8419              : 
    8420              : 
    8421              : match
    8422          298 : gfc_match_omp_parallel_do_simd (void)
    8423              : {
    8424          298 :   return match_omp (EXEC_OMP_PARALLEL_DO_SIMD,
    8425          298 :                     (OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES | OMP_SIMD_CLAUSES)
    8426          298 :                     & ~(omp_mask (OMP_CLAUSE_NOWAIT)));
    8427              : }
    8428              : 
    8429              : 
    8430              : match
    8431           14 : gfc_match_omp_parallel_masked (void)
    8432              : {
    8433           14 :   return match_omp (EXEC_OMP_PARALLEL_MASKED,
    8434           14 :                     OMP_PARALLEL_CLAUSES | OMP_MASKED_CLAUSES);
    8435              : }
    8436              : 
    8437              : match
    8438           10 : gfc_match_omp_parallel_masked_taskloop (void)
    8439              : {
    8440           10 :   return match_omp (EXEC_OMP_PARALLEL_MASKED_TASKLOOP,
    8441           10 :                     (OMP_PARALLEL_CLAUSES | OMP_MASKED_CLAUSES
    8442           10 :                      | OMP_TASKLOOP_CLAUSES)
    8443           10 :                     & ~(omp_mask (OMP_CLAUSE_IN_REDUCTION)));
    8444              : }
    8445              : 
    8446              : match
    8447           13 : gfc_match_omp_parallel_masked_taskloop_simd (void)
    8448              : {
    8449           13 :   return match_omp (EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD,
    8450           13 :                     (OMP_PARALLEL_CLAUSES | OMP_MASKED_CLAUSES
    8451           13 :                      | OMP_TASKLOOP_CLAUSES | OMP_SIMD_CLAUSES)
    8452           13 :                     & ~(omp_mask (OMP_CLAUSE_IN_REDUCTION)));
    8453              : }
    8454              : 
    8455              : match
    8456           14 : gfc_match_omp_parallel_master (void)
    8457              : {
    8458           14 :   gfc_warning (OPT_Wdeprecated_openmp,
    8459              :                "%<master%> construct at %C deprecated since OpenMP 5.1, use "
    8460              :                "%<masked%>");
    8461           14 :   return match_omp (EXEC_OMP_PARALLEL_MASTER, OMP_PARALLEL_CLAUSES);
    8462              : }
    8463              : 
    8464              : match
    8465           15 : gfc_match_omp_parallel_master_taskloop (void)
    8466              : {
    8467           15 :   gfc_warning (OPT_Wdeprecated_openmp,
    8468              :                "%<master%> construct at %C deprecated since OpenMP 5.1, "
    8469              :                "use %<masked%>");
    8470           15 :   return match_omp (EXEC_OMP_PARALLEL_MASTER_TASKLOOP,
    8471           15 :                     (OMP_PARALLEL_CLAUSES | OMP_TASKLOOP_CLAUSES)
    8472           15 :                     & ~(omp_mask (OMP_CLAUSE_IN_REDUCTION)));
    8473              : }
    8474              : 
    8475              : match
    8476           21 : gfc_match_omp_parallel_master_taskloop_simd (void)
    8477              : {
    8478           21 :   gfc_warning (OPT_Wdeprecated_openmp,
    8479              :                "%<master%> construct at %C deprecated since OpenMP 5.1, "
    8480              :                "use %<masked%>");
    8481           21 :   return match_omp (EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD,
    8482           21 :                     (OMP_PARALLEL_CLAUSES | OMP_TASKLOOP_CLAUSES
    8483           21 :                      | OMP_SIMD_CLAUSES)
    8484           21 :                     & ~(omp_mask (OMP_CLAUSE_IN_REDUCTION)));
    8485              : }
    8486              : 
    8487              : match
    8488           59 : gfc_match_omp_parallel_sections (void)
    8489              : {
    8490           59 :   return match_omp (EXEC_OMP_PARALLEL_SECTIONS,
    8491           59 :                     (OMP_PARALLEL_CLAUSES | OMP_SECTIONS_CLAUSES)
    8492           59 :                     & ~(omp_mask (OMP_CLAUSE_NOWAIT)));
    8493              : }
    8494              : 
    8495              : 
    8496              : match
    8497           56 : gfc_match_omp_parallel_workshare (void)
    8498              : {
    8499           56 :   return match_omp (EXEC_OMP_PARALLEL_WORKSHARE, OMP_PARALLEL_CLAUSES);
    8500              : }
    8501              : 
    8502              : void
    8503        50464 : gfc_check_omp_requires (gfc_namespace *ns, int ref_omp_requires)
    8504              : {
    8505        50464 :   const char *msg = G_("Program unit at %L has OpenMP device "
    8506              :                        "constructs/routines but does not set !$OMP REQUIRES %s "
    8507              :                        "but other program units do");
    8508        50464 :   if (ns->omp_target_seen
    8509         1303 :       && (ns->omp_requires & OMP_REQ_TARGET_MASK)
    8510         1303 :          != (ref_omp_requires & OMP_REQ_TARGET_MASK))
    8511              :     {
    8512            6 :       gcc_assert (ns->proc_name);
    8513            6 :       if ((ref_omp_requires & OMP_REQ_REVERSE_OFFLOAD)
    8514            5 :           && !(ns->omp_requires & OMP_REQ_REVERSE_OFFLOAD))
    8515            4 :         gfc_error (msg, &ns->proc_name->declared_at, "REVERSE_OFFLOAD");
    8516            6 :       if ((ref_omp_requires & OMP_REQ_UNIFIED_ADDRESS)
    8517            1 :           && !(ns->omp_requires & OMP_REQ_UNIFIED_ADDRESS))
    8518            1 :         gfc_error (msg, &ns->proc_name->declared_at, "UNIFIED_ADDRESS");
    8519            6 :       if ((ref_omp_requires & OMP_REQ_UNIFIED_SHARED_MEMORY)
    8520            4 :           && !(ns->omp_requires & OMP_REQ_UNIFIED_SHARED_MEMORY))
    8521            2 :         gfc_error (msg, &ns->proc_name->declared_at, "UNIFIED_SHARED_MEMORY");
    8522            6 :       if ((ref_omp_requires & OMP_REQ_SELF_MAPS)
    8523            1 :           && !(ns->omp_requires & OMP_REQ_UNIFIED_SHARED_MEMORY))
    8524            1 :         gfc_error (msg, &ns->proc_name->declared_at, "SELF_MAPS");
    8525              :     }
    8526        50464 : }
    8527              : 
    8528              : bool
    8529          138 : gfc_omp_requires_add_clause (gfc_omp_requires_kind clause,
    8530              :                              const char *clause_name, locus *loc,
    8531              :                              const char *module_name)
    8532              : {
    8533          138 :   gfc_namespace *prog_unit = gfc_current_ns;
    8534          162 :   while (prog_unit->parent)
    8535              :     {
    8536           26 :       if (gfc_state_stack->previous
    8537           26 :           && gfc_state_stack->previous->state == COMP_INTERFACE)
    8538              :         break;
    8539              :       /* A submodule namespace may have its parent set to the ancestor module
    8540              :          for host-association purposes.  Do not escape the submodule boundary:
    8541              :          the submodule itself is the program unit for OMP REQUIRES purposes.  */
    8542           25 :       if (prog_unit->proc_name
    8543           25 :           && prog_unit->proc_name->attr.flavor == FL_MODULE)
    8544              :         break;
    8545           24 :       prog_unit = prog_unit->parent;
    8546              :     }
    8547              : 
    8548              :   /* Requires added after use.  */
    8549          138 :   if (prog_unit->omp_target_seen
    8550           24 :       && (clause & OMP_REQ_TARGET_MASK)
    8551           24 :       && !(prog_unit->omp_requires & clause))
    8552              :     {
    8553            0 :       if (module_name)
    8554            0 :         gfc_error ("!$OMP REQUIRES clause %qs specified via module %qs use "
    8555              :                    "at %L comes after using a device construct/routine",
    8556              :                    clause_name, module_name, loc);
    8557              :       else
    8558            0 :         gfc_error ("!$OMP REQUIRES clause %qs specified at %L comes after "
    8559              :                    "using a device construct/routine", clause_name, loc);
    8560              :       return false;
    8561              :     }
    8562              : 
    8563              :   /* Overriding atomic_default_mem_order clause value.  */
    8564          138 :   if ((clause & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
    8565           34 :       && (prog_unit->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
    8566            6 :       && (prog_unit->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
    8567            6 :          != (int) clause)
    8568              :     {
    8569            3 :       const char *other;
    8570            3 :       switch (prog_unit->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
    8571              :         {
    8572              :         case OMP_REQ_ATOMIC_MEM_ORDER_SEQ_CST: other = "seq_cst"; break;
    8573            0 :         case OMP_REQ_ATOMIC_MEM_ORDER_ACQ_REL: other = "acq_rel"; break;
    8574            1 :         case OMP_REQ_ATOMIC_MEM_ORDER_ACQUIRE: other = "acquire"; break;
    8575            1 :         case OMP_REQ_ATOMIC_MEM_ORDER_RELAXED: other = "relaxed"; break;
    8576            0 :         case OMP_REQ_ATOMIC_MEM_ORDER_RELEASE: other = "release"; break;
    8577            0 :         default: gcc_unreachable ();
    8578              :         }
    8579              : 
    8580            3 :       if (module_name)
    8581            0 :         gfc_error ("!$OMP REQUIRES clause %<atomic_default_mem_order(%s)%> "
    8582              :                    "specified via module %qs use at %L overrides a previous "
    8583              :                    "%<atomic_default_mem_order(%s)%> (which might be through "
    8584              :                    "using a module)", clause_name, module_name, loc, other);
    8585              :       else
    8586            3 :         gfc_error ("!$OMP REQUIRES clause %<atomic_default_mem_order(%s)%> "
    8587              :                    "specified at %L overrides a previous "
    8588              :                    "%<atomic_default_mem_order(%s)%> (which might be through "
    8589              :                    "using a module)", clause_name, loc, other);
    8590              :       return false;
    8591              :     }
    8592              : 
    8593              :   /* Requires via module not at program-unit level and not repeating clause.  */
    8594          135 :   if (prog_unit != gfc_current_ns && !(prog_unit->omp_requires & clause))
    8595              :     {
    8596            0 :       if (clause & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
    8597            0 :         gfc_error ("!$OMP REQUIRES clause %<atomic_default_mem_order(%s)%> "
    8598              :                    "specified via module %qs use at %L but same clause is "
    8599              :                    "not specified for the program unit", clause_name,
    8600              :                    module_name, loc);
    8601              :       else
    8602            0 :         gfc_error ("!$OMP REQUIRES clause %qs specified via module %qs use at "
    8603              :                    "%L but same clause is not specified for the program unit",
    8604              :                    clause_name, module_name, loc);
    8605              :       return false;
    8606              :     }
    8607              : 
    8608          135 :   if (!gfc_state_stack->previous
    8609          127 :       || gfc_state_stack->previous->state != COMP_INTERFACE)
    8610          134 :     prog_unit->omp_requires |= clause;
    8611              :   return true;
    8612              : }
    8613              : 
    8614              : match
    8615          110 : gfc_match_omp_requires (void)
    8616              : {
    8617          110 :   static const char *clauses[] = {"reverse_offload",
    8618              :                                   "unified_address",
    8619              :                                   "unified_shared_memory",
    8620              :                                   "self_maps",
    8621              :                                   "dynamic_allocators",
    8622              :                                   "atomic_default_mem_order"};
    8623          110 :   const char *clause = NULL;
    8624          110 :   int requires_clauses = 0;
    8625          110 :   int seen_clauses = 0;
    8626          110 :   bool first = true;
    8627          110 :   locus old_loc;
    8628              : 
    8629              :   /* A submodule's namespace may have its parent pointer set to the ancestor
    8630              :      module namespace for host-association purposes.  The submodule spec part
    8631              :      is still a valid program-unit spec part for OMP REQUIRES.  Only reject
    8632              :      the directive when we are genuinely nested inside a procedure.  */
    8633          110 :   if (gfc_current_ns->parent
    8634            8 :       && !(gfc_current_ns->proc_name
    8635            8 :            && gfc_current_ns->proc_name->attr.flavor == FL_MODULE)
    8636            7 :       && (!gfc_state_stack->previous
    8637            7 :           || gfc_state_stack->previous->state != COMP_INTERFACE))
    8638              :     {
    8639            6 :       gfc_error ("!$OMP REQUIRES at %C must appear in the specification part "
    8640              :                  "of a program unit");
    8641            6 :       return MATCH_ERROR;
    8642              :     }
    8643              : 
    8644              :   /* Specifying '<clause>(.false.)' in this directive does not affect requirements
    8645              :      set in another 'requires' directive in the same compilation unit; however,
    8646              :      specifying it multiple times in the same directive is disallowed.  */
    8647          336 :   while (true)
    8648              :     {
    8649          220 :       bool bval;
    8650          220 :       match m;
    8651          220 :       old_loc = gfc_current_locus;
    8652          220 :       gfc_omp_requires_kind requires_clause = OMP_REQ_NONE;
    8653          220 :       if (gfc_match_char (',') != MATCH_YES
    8654          220 :           && (first && gfc_match_space () != MATCH_YES))
    8655           17 :         goto error;
    8656          220 :       first = false;
    8657          220 :       gfc_gobble_whitespace ();
    8658          220 :       old_loc = gfc_current_locus;
    8659              : 
    8660          220 :       if (gfc_match_omp_eos () != MATCH_NO)
    8661              :         break;
    8662          133 :       if ((m = gfc_match_boolean_clause (&bval, clauses[0],
    8663          133 :                  seen_clauses & OMP_REQ_REVERSE_OFFLOAD)) != MATCH_NO)
    8664              :         {
    8665           40 :           if (m == MATCH_ERROR)
    8666            2 :             goto error;
    8667           38 :           clause = clauses[0];
    8668           38 :           seen_clauses |= OMP_REQ_REVERSE_OFFLOAD;
    8669           38 :           if (bval)
    8670              :             requires_clause = OMP_REQ_REVERSE_OFFLOAD;
    8671              :         }
    8672           93 :       else if ((m = gfc_match_boolean_clause (&bval, clauses[1],
    8673           93 :                       seen_clauses & OMP_REQ_UNIFIED_ADDRESS)) != MATCH_NO)
    8674              :         {
    8675           14 :           if (m == MATCH_ERROR)
    8676            2 :             goto error;
    8677           12 :           clause = clauses[1];
    8678           12 :           seen_clauses |= OMP_REQ_UNIFIED_ADDRESS;
    8679           12 :           if (bval)
    8680              :             requires_clause = OMP_REQ_UNIFIED_ADDRESS;
    8681              :         }
    8682           79 :       else if ((m = gfc_match_boolean_clause (&bval, clauses[2],
    8683           79 :                       seen_clauses & OMP_REQ_UNIFIED_SHARED_MEMORY))
    8684              :                != MATCH_NO)
    8685              :         {
    8686           17 :           if (m == MATCH_ERROR)
    8687            1 :             goto error;
    8688           16 :           clause = clauses[2];
    8689           16 :           seen_clauses |= OMP_REQ_UNIFIED_SHARED_MEMORY;
    8690           16 :           if (bval)
    8691              :             requires_clause = OMP_REQ_UNIFIED_SHARED_MEMORY;
    8692              :         }
    8693           62 :       else if ((m = gfc_match_boolean_clause (&bval, clauses[3],
    8694           62 :                       seen_clauses & OMP_REQ_SELF_MAPS)) != MATCH_NO)
    8695              :         {
    8696           19 :           if (m == MATCH_ERROR)
    8697            4 :             goto error;
    8698           15 :           clause = clauses[3];
    8699           15 :           seen_clauses |= OMP_REQ_SELF_MAPS;
    8700           15 :           if (bval)
    8701              :             requires_clause = OMP_REQ_SELF_MAPS;
    8702              :         }
    8703           43 :       else if ((m = gfc_match_boolean_clause (&bval, clauses[4],
    8704           43 :                       seen_clauses & OMP_REQ_DYNAMIC_ALLOCATORS)) != MATCH_NO)
    8705              :         {
    8706           11 :           if (m == MATCH_ERROR)
    8707            1 :             goto error;
    8708           10 :           clause = clauses[4];
    8709           10 :           seen_clauses |= OMP_REQ_DYNAMIC_ALLOCATORS;
    8710           10 :           if (bval)
    8711              :             requires_clause = OMP_REQ_DYNAMIC_ALLOCATORS;
    8712              :         }
    8713           32 :       else if ((m = gfc_match_dupl_check (
    8714           32 :                       !(seen_clauses & OMP_REQ_ATOMIC_MEM_ORDER_MASK),
    8715              :                       clauses[5], true)) != MATCH_NO)
    8716              :         {
    8717           31 :           if (m == MATCH_ERROR)
    8718            1 :             goto error;
    8719           30 :           seen_clauses |= OMP_REQ_ATOMIC_MEM_ORDER_MASK;
    8720           30 :           if (gfc_match (" seq_cst )") == MATCH_YES)
    8721              :             {
    8722              :               clause = "seq_cst";
    8723              :               requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_SEQ_CST;
    8724              :             }
    8725           18 :           else if (gfc_match (" acq_rel )") == MATCH_YES)
    8726              :             {
    8727              :               clause = "acq_rel";
    8728              :               requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_ACQ_REL;
    8729              :             }
    8730           12 :           else if (gfc_match (" acquire )") == MATCH_YES)
    8731              :             {
    8732              :               clause = "acquire";
    8733              :               requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_ACQUIRE;
    8734              :             }
    8735            9 :           else if (gfc_match (" relaxed )") == MATCH_YES)
    8736              :             {
    8737              :               clause = "relaxed";
    8738              :               requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_RELAXED;
    8739              :             }
    8740            5 :           else if (gfc_match (" release )") == MATCH_YES)
    8741              :             {
    8742              :               clause = "release";
    8743              :               requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_RELEASE;
    8744              :             }
    8745              :           else
    8746              :             {
    8747            2 :               gfc_error ("Expected ACQ_REL, ACQUIRE, RELAXED, RELEASE or "
    8748              :                          "SEQ_CST for ATOMIC_DEFAULT_MEM_ORDER clause at %C");
    8749            2 :               goto error;
    8750              :             }
    8751              :         }
    8752              :       else
    8753            1 :         goto error;
    8754              : 
    8755              :       if (requires_clause != OMP_REQ_NONE
    8756          107 :           && !gfc_omp_requires_add_clause (requires_clause, clause, &old_loc, NULL))
    8757            3 :         goto error;
    8758          116 :       requires_clauses |= requires_clause;
    8759          116 :     }
    8760              : 
    8761           87 :   if (requires_clauses == 0)
    8762            2 :     goto error;
    8763              :   return MATCH_YES;
    8764              : 
    8765           19 : error:
    8766           19 :   if (!gfc_error_flag_test ())
    8767            3 :     gfc_error ("Expected UNIFIED_ADDRESS, UNIFIED_SHARED_MEMORY, SELF_MAPS, "
    8768              :                "DYNAMIC_ALLOCATORS, REVERSE_OFFLOAD, or "
    8769              :                "ATOMIC_DEFAULT_MEM_ORDER clause at %L", &old_loc);
    8770              :   return MATCH_ERROR;
    8771              : }
    8772              : 
    8773              : 
    8774              : match
    8775           51 : gfc_match_omp_scan (void)
    8776              : {
    8777           51 :   bool incl;
    8778           51 :   gfc_omp_clauses *c = gfc_get_omp_clauses ();
    8779           51 :   gfc_gobble_whitespace ();
    8780           51 :   gfc_match (", ");  /* optionally  */
    8781           51 :   if ((incl = (gfc_match ("inclusive") == MATCH_YES))
    8782           51 :       || gfc_match ("exclusive") == MATCH_YES)
    8783              :     {
    8784           70 :       if (gfc_match_omp_variable_list (" (", &c->lists[incl ? OMP_LIST_SCAN_IN
    8785              :                                                             : OMP_LIST_SCAN_EX],
    8786              :                                        false) != MATCH_YES)
    8787              :         {
    8788            0 :           gfc_free_omp_clauses (c);
    8789            0 :           return MATCH_ERROR;
    8790              :         }
    8791              :     }
    8792              :   else
    8793              :     {
    8794            1 :       gfc_error ("Expected INCLUSIVE or EXCLUSIVE clause at %C");
    8795            1 :       gfc_free_omp_clauses (c);
    8796            1 :       return MATCH_ERROR;
    8797              :     }
    8798           50 :   if (gfc_match_omp_eos () != MATCH_YES)
    8799              :     {
    8800            1 :       gfc_error ("Unexpected junk after !$OMP SCAN at %C");
    8801            1 :       gfc_free_omp_clauses (c);
    8802            1 :       return MATCH_ERROR;
    8803              :     }
    8804              : 
    8805           49 :   new_st.op = EXEC_OMP_SCAN;
    8806           49 :   new_st.ext.omp_clauses = c;
    8807           49 :   return MATCH_YES;
    8808              : }
    8809              : 
    8810              : 
    8811              : match
    8812           58 : gfc_match_omp_scope (void)
    8813              : {
    8814           58 :   return match_omp (EXEC_OMP_SCOPE, OMP_SCOPE_CLAUSES);
    8815              : }
    8816              : 
    8817              : 
    8818              : match
    8819           82 : gfc_match_omp_sections (void)
    8820              : {
    8821           82 :   return match_omp (EXEC_OMP_SECTIONS, OMP_SECTIONS_CLAUSES);
    8822              : }
    8823              : 
    8824              : 
    8825              : match
    8826          785 : gfc_match_omp_simd (void)
    8827              : {
    8828          785 :   return match_omp (EXEC_OMP_SIMD, OMP_SIMD_CLAUSES);
    8829              : }
    8830              : 
    8831              : 
    8832              : match
    8833          574 : gfc_match_omp_single (void)
    8834              : {
    8835          574 :   return match_omp (EXEC_OMP_SINGLE, OMP_SINGLE_CLAUSES);
    8836              : }
    8837              : 
    8838              : 
    8839              : match
    8840         2250 : gfc_match_omp_target (void)
    8841              : {
    8842         2250 :   return match_omp (EXEC_OMP_TARGET, OMP_TARGET_CLAUSES);
    8843              : }
    8844              : 
    8845              : 
    8846              : match
    8847         1401 : gfc_match_omp_target_data (void)
    8848              : {
    8849         1401 :   return match_omp (EXEC_OMP_TARGET_DATA, OMP_TARGET_DATA_CLAUSES);
    8850              : }
    8851              : 
    8852              : 
    8853              : match
    8854          472 : gfc_match_omp_target_enter_data (void)
    8855              : {
    8856          472 :   return match_omp (EXEC_OMP_TARGET_ENTER_DATA, OMP_TARGET_ENTER_DATA_CLAUSES);
    8857              : }
    8858              : 
    8859              : 
    8860              : match
    8861          367 : gfc_match_omp_target_exit_data (void)
    8862              : {
    8863          367 :   return match_omp (EXEC_OMP_TARGET_EXIT_DATA, OMP_TARGET_EXIT_DATA_CLAUSES);
    8864              : }
    8865              : 
    8866              : 
    8867              : match
    8868           29 : gfc_match_omp_target_parallel (void)
    8869              : {
    8870           29 :   return match_omp (EXEC_OMP_TARGET_PARALLEL,
    8871           29 :                     (OMP_TARGET_CLAUSES | OMP_PARALLEL_CLAUSES)
    8872           29 :                     & ~(omp_mask (OMP_CLAUSE_COPYIN)));
    8873              : }
    8874              : 
    8875              : 
    8876              : match
    8877           81 : gfc_match_omp_target_parallel_do (void)
    8878              : {
    8879           81 :   return match_omp (EXEC_OMP_TARGET_PARALLEL_DO,
    8880           81 :                     (OMP_TARGET_CLAUSES | OMP_PARALLEL_CLAUSES
    8881           81 :                      | OMP_DO_CLAUSES) & ~(omp_mask (OMP_CLAUSE_COPYIN)));
    8882              : }
    8883              : 
    8884              : 
    8885              : match
    8886           20 : gfc_match_omp_target_parallel_do_simd (void)
    8887              : {
    8888           20 :   return match_omp (EXEC_OMP_TARGET_PARALLEL_DO_SIMD,
    8889           20 :                     (OMP_TARGET_CLAUSES | OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES
    8890           20 :                      | OMP_SIMD_CLAUSES) & ~(omp_mask (OMP_CLAUSE_COPYIN)));
    8891              : }
    8892              : 
    8893              : 
    8894              : match
    8895           34 : gfc_match_omp_target_simd (void)
    8896              : {
    8897           34 :   return match_omp (EXEC_OMP_TARGET_SIMD,
    8898           34 :                     OMP_TARGET_CLAUSES | OMP_SIMD_CLAUSES);
    8899              : }
    8900              : 
    8901              : 
    8902              : match
    8903           76 : gfc_match_omp_target_teams (void)
    8904              : {
    8905           76 :   return match_omp (EXEC_OMP_TARGET_TEAMS,
    8906           76 :                     OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES);
    8907              : }
    8908              : 
    8909              : 
    8910              : match
    8911           19 : gfc_match_omp_target_teams_distribute (void)
    8912              : {
    8913           19 :   return match_omp (EXEC_OMP_TARGET_TEAMS_DISTRIBUTE,
    8914           19 :                     OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES
    8915           19 :                     | OMP_DISTRIBUTE_CLAUSES);
    8916              : }
    8917              : 
    8918              : 
    8919              : match
    8920           66 : gfc_match_omp_target_teams_distribute_parallel_do (void)
    8921              : {
    8922           66 :   return match_omp (EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO,
    8923           66 :                     (OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES
    8924           66 :                      | OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
    8925           66 :                      | OMP_DO_CLAUSES)
    8926           66 :                     & ~(omp_mask (OMP_CLAUSE_ORDERED))
    8927           66 :                     & ~(omp_mask (OMP_CLAUSE_LINEAR)));
    8928              : }
    8929              : 
    8930              : 
    8931              : match
    8932           36 : gfc_match_omp_target_teams_distribute_parallel_do_simd (void)
    8933              : {
    8934           36 :   return match_omp (EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD,
    8935           36 :                     (OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES
    8936           36 :                      | OMP_DISTRIBUTE_CLAUSES | OMP_PARALLEL_CLAUSES
    8937           36 :                      | OMP_DO_CLAUSES | OMP_SIMD_CLAUSES)
    8938           36 :                     & ~(omp_mask (OMP_CLAUSE_ORDERED)));
    8939              : }
    8940              : 
    8941              : 
    8942              : match
    8943           21 : gfc_match_omp_target_teams_distribute_simd (void)
    8944              : {
    8945           21 :   return match_omp (EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD,
    8946           21 :                     OMP_TARGET_CLAUSES | OMP_TEAMS_CLAUSES
    8947           21 :                     | OMP_DISTRIBUTE_CLAUSES | OMP_SIMD_CLAUSES);
    8948              : }
    8949              : 
    8950              : 
    8951              : match
    8952         1727 : gfc_match_omp_target_update (void)
    8953              : {
    8954         1727 :   return match_omp (EXEC_OMP_TARGET_UPDATE, OMP_TARGET_UPDATE_CLAUSES);
    8955              : }
    8956              : 
    8957              : 
    8958              : match
    8959         1184 : gfc_match_omp_task (void)
    8960              : {
    8961         1184 :   return match_omp (EXEC_OMP_TASK, OMP_TASK_CLAUSES);
    8962              : }
    8963              : 
    8964              : 
    8965              : match
    8966           72 : gfc_match_omp_taskloop (void)
    8967              : {
    8968           72 :   return match_omp (EXEC_OMP_TASKLOOP, OMP_TASKLOOP_CLAUSES);
    8969              : }
    8970              : 
    8971              : 
    8972              : match
    8973           40 : gfc_match_omp_taskloop_simd (void)
    8974              : {
    8975           40 :   return match_omp (EXEC_OMP_TASKLOOP_SIMD,
    8976           40 :                     OMP_TASKLOOP_CLAUSES | OMP_SIMD_CLAUSES);
    8977              : }
    8978              : 
    8979              : 
    8980              : match
    8981          149 : gfc_match_omp_taskwait (void)
    8982              : {
    8983          149 :   if (gfc_match_omp_eos () == MATCH_YES)
    8984              :     {
    8985          135 :       new_st.op = EXEC_OMP_TASKWAIT;
    8986          135 :       new_st.ext.omp_clauses = NULL;
    8987          135 :       return MATCH_YES;
    8988              :     }
    8989           14 :   return match_omp (EXEC_OMP_TASKWAIT,
    8990           14 :                     omp_mask (OMP_CLAUSE_DEPEND) | OMP_CLAUSE_NOWAIT);
    8991              : }
    8992              : 
    8993              : 
    8994              : match
    8995           10 : gfc_match_omp_taskyield (void)
    8996              : {
    8997           10 :   if (gfc_match_omp_eos () != MATCH_YES)
    8998              :     {
    8999            0 :       gfc_error ("Unexpected junk after TASKYIELD clause at %C");
    9000            0 :       return MATCH_ERROR;
    9001              :     }
    9002           10 :   new_st.op = EXEC_OMP_TASKYIELD;
    9003           10 :   new_st.ext.omp_clauses = NULL;
    9004           10 :   return MATCH_YES;
    9005              : }
    9006              : 
    9007              : 
    9008              : match
    9009          218 : gfc_match_omp_teams (void)
    9010              : {
    9011          218 :   return match_omp (EXEC_OMP_TEAMS, OMP_TEAMS_CLAUSES);
    9012              : }
    9013              : 
    9014              : 
    9015              : match
    9016           22 : gfc_match_omp_teams_distribute (void)
    9017              : {
    9018           22 :   return match_omp (EXEC_OMP_TEAMS_DISTRIBUTE,
    9019           22 :                     OMP_TEAMS_CLAUSES | OMP_DISTRIBUTE_CLAUSES);
    9020              : }
    9021              : 
    9022              : 
    9023              : match
    9024           41 : gfc_match_omp_teams_distribute_parallel_do (void)
    9025              : {
    9026           41 :   return match_omp (EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO,
    9027           41 :                     (OMP_TEAMS_CLAUSES | OMP_DISTRIBUTE_CLAUSES
    9028           41 :                      | OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES)
    9029           41 :                     & ~(omp_mask (OMP_CLAUSE_ORDERED)
    9030           41 :                         | OMP_CLAUSE_LINEAR | OMP_CLAUSE_NOWAIT));
    9031              : }
    9032              : 
    9033              : 
    9034              : match
    9035           63 : gfc_match_omp_teams_distribute_parallel_do_simd (void)
    9036              : {
    9037           63 :   return match_omp (EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD,
    9038           63 :                     (OMP_TEAMS_CLAUSES | OMP_DISTRIBUTE_CLAUSES
    9039           63 :                      | OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES
    9040           63 :                      | OMP_SIMD_CLAUSES)
    9041           63 :                     & ~(omp_mask (OMP_CLAUSE_ORDERED) | OMP_CLAUSE_NOWAIT));
    9042              : }
    9043              : 
    9044              : 
    9045              : match
    9046           44 : gfc_match_omp_teams_distribute_simd (void)
    9047              : {
    9048           44 :   return match_omp (EXEC_OMP_TEAMS_DISTRIBUTE_SIMD,
    9049           44 :                     OMP_TEAMS_CLAUSES | OMP_DISTRIBUTE_CLAUSES
    9050           44 :                     | OMP_SIMD_CLAUSES);
    9051              : }
    9052              : 
    9053              : match
    9054          203 : gfc_match_omp_tile (void)
    9055              : {
    9056          203 :   return match_omp (EXEC_OMP_TILE, OMP_TILE_CLAUSES);
    9057              : }
    9058              : 
    9059              : match
    9060          424 : gfc_match_omp_unroll (void)
    9061              : {
    9062          424 :   return match_omp (EXEC_OMP_UNROLL, OMP_UNROLL_CLAUSES);
    9063              : }
    9064              : 
    9065              : match
    9066           39 : gfc_match_omp_workshare (void)
    9067              : {
    9068           39 :   return match_omp (EXEC_OMP_WORKSHARE, OMP_WORKSHARE_CLAUSES);
    9069              : }
    9070              : 
    9071              : 
    9072              : match
    9073           55 : gfc_match_omp_masked (void)
    9074              : {
    9075           55 :   return match_omp (EXEC_OMP_MASKED, OMP_MASKED_CLAUSES);
    9076              : }
    9077              : 
    9078              : match
    9079           10 : gfc_match_omp_masked_taskloop (void)
    9080              : {
    9081           10 :   return match_omp (EXEC_OMP_MASKED_TASKLOOP,
    9082           10 :                     OMP_MASKED_CLAUSES | OMP_TASKLOOP_CLAUSES);
    9083              : }
    9084              : 
    9085              : match
    9086           16 : gfc_match_omp_masked_taskloop_simd (void)
    9087              : {
    9088           16 :   return match_omp (EXEC_OMP_MASKED_TASKLOOP_SIMD,
    9089           16 :                     (OMP_MASKED_CLAUSES | OMP_TASKLOOP_CLAUSES
    9090           16 :                      | OMP_SIMD_CLAUSES));
    9091              : }
    9092              : 
    9093              : match
    9094          111 : gfc_match_omp_master (void)
    9095              : {
    9096          111 :   gfc_warning (OPT_Wdeprecated_openmp,
    9097              :                "%<master%> construct at %C deprecated since OpenMP 5.1, "
    9098              :                "use %<masked%>");
    9099          111 :   if (gfc_match_omp_eos () != MATCH_YES)
    9100              :     {
    9101            1 :       gfc_error ("Unexpected junk after $OMP MASTER statement at %C");
    9102            1 :       return MATCH_ERROR;
    9103              :     }
    9104          110 :   new_st.op = EXEC_OMP_MASTER;
    9105          110 :   new_st.ext.omp_clauses = NULL;
    9106          110 :   return MATCH_YES;
    9107              : }
    9108              : 
    9109              : match
    9110           16 : gfc_match_omp_master_taskloop (void)
    9111              : {
    9112           16 :   gfc_warning (OPT_Wdeprecated_openmp,
    9113              :                "%<master%> construct at %C deprecated since OpenMP 5.1, "
    9114              :                "use %<masked%>");
    9115           16 :   return match_omp (EXEC_OMP_MASTER_TASKLOOP, OMP_TASKLOOP_CLAUSES);
    9116              : }
    9117              : 
    9118              : match
    9119           21 : gfc_match_omp_master_taskloop_simd (void)
    9120              : {
    9121           21 :   gfc_warning (OPT_Wdeprecated_openmp,
    9122              :                "%<master%> construct at %C deprecated since OpenMP 5.1, use "
    9123              :                "%<masked%>");
    9124           21 :   return match_omp (EXEC_OMP_MASTER_TASKLOOP_SIMD,
    9125           21 :                     OMP_TASKLOOP_CLAUSES | OMP_SIMD_CLAUSES);
    9126              : }
    9127              : 
    9128              : match
    9129          239 : gfc_match_omp_ordered (void)
    9130              : {
    9131          239 :   return match_omp (EXEC_OMP_ORDERED, OMP_ORDERED_CLAUSES);
    9132              : }
    9133              : 
    9134              : match
    9135           24 : gfc_match_omp_nothing (void)
    9136              : {
    9137           24 :   if (gfc_match_omp_eos () != MATCH_YES)
    9138              :     {
    9139            1 :       gfc_error ("Unexpected junk after $OMP NOTHING statement at %C");
    9140            1 :       return MATCH_ERROR;
    9141              :     }
    9142              :   /* Will use ST_NONE; therefore, no EXEC_OMP_ is needed.  */
    9143              :   return MATCH_YES;
    9144              : }
    9145              : 
    9146              : match
    9147          317 : gfc_match_omp_ordered_depend (void)
    9148              : {
    9149          317 :   return match_omp (EXEC_OMP_ORDERED, omp_mask (OMP_CLAUSE_DOACROSS));
    9150              : }
    9151              : 
    9152              : 
    9153              : /* omp atomic [clause-list]
    9154              :    - atomic-clause:  read | write | update
    9155              :    - capture
    9156              :    - memory-order-clause: seq_cst | acq_rel | release | acquire | relaxed
    9157              :    - hint(hint-expr)
    9158              :    - OpenMP 5.1: compare | fail (seq_cst | acquire | relaxed ) | weak
    9159              : */
    9160              : 
    9161              : match
    9162         2188 : gfc_match_omp_atomic (void)
    9163              : {
    9164         2188 :   gfc_omp_clauses *c;
    9165         2188 :   locus loc = gfc_current_locus;
    9166              : 
    9167         2188 :   if (gfc_match_omp_clauses (&c, OMP_ATOMIC_CLAUSES, false, true) != MATCH_YES)
    9168              :     return MATCH_ERROR;
    9169              : 
    9170         2166 :   if (c->atomic_op == GFC_OMP_ATOMIC_UNSET)
    9171         1013 :     c->atomic_op = GFC_OMP_ATOMIC_UPDATE;
    9172              : 
    9173         2166 :   if (c->capture && c->atomic_op != GFC_OMP_ATOMIC_UPDATE)
    9174            3 :     gfc_error ("!$OMP ATOMIC at %L with %s clause is incompatible with "
    9175              :                "READ or WRITE", &loc, "CAPTURE");
    9176         2166 :   if (c->compare && c->atomic_op != GFC_OMP_ATOMIC_UPDATE)
    9177            3 :     gfc_error ("!$OMP ATOMIC at %L with %s clause is incompatible with "
    9178              :                "READ or WRITE", &loc, "COMPARE");
    9179         2166 :   if (c->fail != OMP_MEMORDER_UNSET && c->atomic_op != GFC_OMP_ATOMIC_UPDATE)
    9180            2 :     gfc_error ("!$OMP ATOMIC at %L with %s clause is incompatible with "
    9181              :                "READ or WRITE", &loc, "FAIL");
    9182         2166 :   if (c->weak && !c->compare)
    9183              :     {
    9184            5 :       gfc_error ("!$OMP ATOMIC at %L with %s clause requires %s clause", &loc,
    9185              :                  "WEAK", "COMPARE");
    9186            5 :       c->weak = false;
    9187              :     }
    9188              : 
    9189         2166 :   if (c->memorder == OMP_MEMORDER_UNSET)
    9190              :     {
    9191         1975 :       gfc_namespace *prog_unit = gfc_current_ns;
    9192         1975 :       while (prog_unit->parent
    9193         2537 :              && !(prog_unit->proc_name
    9194          562 :                   && prog_unit->proc_name->attr.flavor == FL_MODULE))
    9195          562 :         prog_unit = prog_unit->parent;
    9196         1975 :       switch (prog_unit->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
    9197              :         {
    9198         1942 :         case 0:
    9199         1942 :         case OMP_REQ_ATOMIC_MEM_ORDER_RELAXED:
    9200         1942 :           c->memorder = OMP_MEMORDER_RELAXED;
    9201         1942 :           break;
    9202            7 :         case OMP_REQ_ATOMIC_MEM_ORDER_SEQ_CST:
    9203            7 :           c->memorder = OMP_MEMORDER_SEQ_CST;
    9204            7 :           break;
    9205           16 :         case OMP_REQ_ATOMIC_MEM_ORDER_ACQ_REL:
    9206           16 :           if (c->capture)
    9207            5 :             c->memorder = OMP_MEMORDER_ACQ_REL;
    9208           11 :           else if (c->atomic_op == GFC_OMP_ATOMIC_READ)
    9209            3 :             c->memorder = OMP_MEMORDER_ACQUIRE;
    9210              :           else
    9211            8 :             c->memorder = OMP_MEMORDER_RELEASE;
    9212              :           break;
    9213            5 :         case OMP_REQ_ATOMIC_MEM_ORDER_ACQUIRE:
    9214            5 :           if (c->atomic_op == GFC_OMP_ATOMIC_WRITE)
    9215              :             {
    9216            1 :               gfc_error ("!$OMP ATOMIC WRITE at %L incompatible with "
    9217              :                          "ACQUIRES clause implicitly provided by a "
    9218              :                          "REQUIRES directive", &loc);
    9219            1 :               c->memorder = OMP_MEMORDER_SEQ_CST;
    9220              :             }
    9221              :           else
    9222            4 :             c->memorder = OMP_MEMORDER_ACQUIRE;
    9223              :           break;
    9224            5 :         case OMP_REQ_ATOMIC_MEM_ORDER_RELEASE:
    9225            5 :           if (c->atomic_op == GFC_OMP_ATOMIC_READ)
    9226              :             {
    9227            1 :               gfc_error ("!$OMP ATOMIC READ at %L incompatible with "
    9228              :                          "RELEASE clause implicitly provided by a "
    9229              :                          "REQUIRES directive", &loc);
    9230            1 :               c->memorder = OMP_MEMORDER_SEQ_CST;
    9231              :             }
    9232              :           else
    9233            4 :             c->memorder = OMP_MEMORDER_RELEASE;
    9234              :           break;
    9235            0 :         default:
    9236            0 :           gcc_unreachable ();
    9237              :         }
    9238              :     }
    9239              :   else
    9240          191 :     switch (c->atomic_op)
    9241              :       {
    9242           31 :       case GFC_OMP_ATOMIC_READ:
    9243           31 :         if (c->memorder == OMP_MEMORDER_RELEASE)
    9244              :           {
    9245            1 :             gfc_error ("!$OMP ATOMIC READ at %L incompatible with "
    9246              :                        "RELEASE clause", &loc);
    9247            1 :             c->memorder = OMP_MEMORDER_SEQ_CST;
    9248              :           }
    9249           30 :         else if (c->memorder == OMP_MEMORDER_ACQ_REL)
    9250            1 :           c->memorder = OMP_MEMORDER_ACQUIRE;
    9251              :         break;
    9252           37 :       case GFC_OMP_ATOMIC_WRITE:
    9253           37 :         if (c->memorder == OMP_MEMORDER_ACQUIRE)
    9254              :           {
    9255            1 :             gfc_error ("!$OMP ATOMIC WRITE at %L incompatible with "
    9256              :                        "ACQUIRE clause", &loc);
    9257            1 :             c->memorder = OMP_MEMORDER_SEQ_CST;
    9258              :           }
    9259           36 :         else if (c->memorder == OMP_MEMORDER_ACQ_REL)
    9260            3 :           c->memorder = OMP_MEMORDER_RELEASE;
    9261              :         break;
    9262              :       default:
    9263              :         break;
    9264              :       }
    9265         2166 :   gfc_error_check ();
    9266         2166 :   new_st.ext.omp_clauses = c;
    9267         2166 :   new_st.op = EXEC_OMP_ATOMIC;
    9268         2166 :   return MATCH_YES;
    9269              : }
    9270              : 
    9271              : 
    9272              : /* acc atomic [ read | write | update | capture]  */
    9273              : 
    9274              : match
    9275          552 : gfc_match_oacc_atomic (void)
    9276              : {
    9277          552 :   gfc_omp_clauses *c = gfc_get_omp_clauses ();
    9278          552 :   c->atomic_op = GFC_OMP_ATOMIC_UPDATE;
    9279          552 :   c->memorder = OMP_MEMORDER_RELAXED;
    9280          552 :   gfc_gobble_whitespace ();
    9281          552 :   if (gfc_match ("update") == MATCH_YES)
    9282              :     ;
    9283          373 :   else if (gfc_match ("read") == MATCH_YES)
    9284           17 :     c->atomic_op = GFC_OMP_ATOMIC_READ;
    9285          356 :   else if (gfc_match ("write") == MATCH_YES)
    9286           13 :     c->atomic_op = GFC_OMP_ATOMIC_WRITE;
    9287          343 :   else if (gfc_match ("capture") == MATCH_YES)
    9288          319 :     c->capture = true;
    9289          552 :   gfc_gobble_whitespace ();
    9290          552 :   if (gfc_match_omp_eos () != MATCH_YES)
    9291              :     {
    9292            9 :       gfc_error ("Unexpected junk after !$ACC ATOMIC statement at %C");
    9293            9 :       gfc_free_omp_clauses (c);
    9294            9 :       return MATCH_ERROR;
    9295              :     }
    9296          543 :   new_st.ext.omp_clauses = c;
    9297          543 :   new_st.op = EXEC_OACC_ATOMIC;
    9298          543 :   return MATCH_YES;
    9299              : }
    9300              : 
    9301              : 
    9302              : match
    9303          614 : gfc_match_omp_barrier (void)
    9304              : {
    9305          614 :   if (gfc_match_omp_eos () != MATCH_YES)
    9306              :     {
    9307            0 :       gfc_error ("Unexpected junk after $OMP BARRIER statement at %C");
    9308            0 :       return MATCH_ERROR;
    9309              :     }
    9310          614 :   new_st.op = EXEC_OMP_BARRIER;
    9311          614 :   new_st.ext.omp_clauses = NULL;
    9312          614 :   return MATCH_YES;
    9313              : }
    9314              : 
    9315              : 
    9316              : match
    9317          188 : gfc_match_omp_taskgroup (void)
    9318              : {
    9319          188 :   return match_omp (EXEC_OMP_TASKGROUP, OMP_TASKGROUP_CLAUSES);
    9320              : }
    9321              : 
    9322              : 
    9323              : static enum gfc_omp_cancel_kind
    9324          502 : gfc_match_omp_cancel_kind (void)
    9325              : {
    9326          502 :   if (gfc_match (" , ") != MATCH_YES
    9327          502 :       && gfc_match_space () != MATCH_YES)
    9328              :     return OMP_CANCEL_UNKNOWN;
    9329          502 :   if (gfc_match ("parallel") == MATCH_YES)
    9330              :     return OMP_CANCEL_PARALLEL;
    9331          352 :   if (gfc_match ("sections") == MATCH_YES)
    9332              :     return OMP_CANCEL_SECTIONS;
    9333          253 :   if (gfc_match ("do") == MATCH_YES)
    9334              :     return OMP_CANCEL_DO;
    9335          123 :   if (gfc_match ("taskgroup") == MATCH_YES)
    9336          121 :     return OMP_CANCEL_TASKGROUP;
    9337              :   return OMP_CANCEL_UNKNOWN;
    9338              : }
    9339              : 
    9340              : 
    9341              : match
    9342          324 : gfc_match_omp_cancel (void)
    9343              : {
    9344          324 :   gfc_omp_clauses *c;
    9345          324 :   enum gfc_omp_cancel_kind kind = gfc_match_omp_cancel_kind ();
    9346          324 :   if (kind == OMP_CANCEL_UNKNOWN)
    9347              :     return MATCH_ERROR;
    9348          324 :   if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_IF), false) != MATCH_YES)
    9349              :     return MATCH_ERROR;
    9350          321 :   c->cancel = kind;
    9351          321 :   new_st.op = EXEC_OMP_CANCEL;
    9352          321 :   new_st.ext.omp_clauses = c;
    9353          321 :   return MATCH_YES;
    9354              : }
    9355              : 
    9356              : 
    9357              : match
    9358          178 : gfc_match_omp_cancellation_point (void)
    9359              : {
    9360          178 :   gfc_omp_clauses *c;
    9361          178 :   enum gfc_omp_cancel_kind kind = gfc_match_omp_cancel_kind ();
    9362          178 :   if (kind == OMP_CANCEL_UNKNOWN)
    9363              :     {
    9364            2 :       gfc_error ("Expected construct-type PARALLEL, SECTIONS, DO or TASKGROUP "
    9365              :                  "in $OMP CANCELLATION POINT statement at %C");
    9366            2 :       return MATCH_ERROR;
    9367              :     }
    9368          176 :   if (gfc_match_omp_eos () != MATCH_YES)
    9369              :     {
    9370            0 :       gfc_error ("Unexpected junk after $OMP CANCELLATION POINT statement "
    9371              :                  "at %C");
    9372            0 :       return MATCH_ERROR;
    9373              :     }
    9374          176 :   c = gfc_get_omp_clauses ();
    9375          176 :   c->cancel = kind;
    9376          176 :   new_st.op = EXEC_OMP_CANCELLATION_POINT;
    9377          176 :   new_st.ext.omp_clauses = c;
    9378          176 :   return MATCH_YES;
    9379              : }
    9380              : 
    9381              : 
    9382              : match
    9383         2736 : gfc_match_omp_end_nowait (void)
    9384              : {
    9385         2736 :   bool nowait = false;
    9386         2736 :   if (gfc_match ("% nowait ") == MATCH_YES
    9387         2736 :       || gfc_match (" , nowait ") == MATCH_YES)
    9388              :     nowait = true;
    9389         2736 :   if (gfc_match_omp_eos () != MATCH_YES)
    9390              :     {
    9391            4 :       if (nowait)
    9392            3 :         gfc_error ("Unexpected junk after NOWAIT clause at %C");
    9393              :       else
    9394            1 :         gfc_error ("Unexpected junk at %C");
    9395              :       return MATCH_ERROR;
    9396              :     }
    9397         2732 :   new_st.op = EXEC_OMP_END_NOWAIT;
    9398         2732 :   new_st.ext.omp_bool = nowait;
    9399         2732 :   return MATCH_YES;
    9400              : }
    9401              : 
    9402              : 
    9403              : match
    9404          570 : gfc_match_omp_end_single (void)
    9405              : {
    9406          570 :   gfc_omp_clauses *c;
    9407          570 :   if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_COPYPRIVATE)
    9408              :                                            | OMP_CLAUSE_NOWAIT, false)
    9409              :       != MATCH_YES)
    9410              :     return MATCH_ERROR;
    9411          570 :   new_st.op = EXEC_OMP_END_SINGLE;
    9412          570 :   new_st.ext.omp_clauses = c;
    9413          570 :   return MATCH_YES;
    9414              : }
    9415              : 
    9416              : 
    9417              : static bool
    9418        37153 : oacc_is_loop (gfc_code *code)
    9419              : {
    9420        37153 :   return code->op == EXEC_OACC_PARALLEL_LOOP
    9421              :          || code->op == EXEC_OACC_KERNELS_LOOP
    9422        20098 :          || code->op == EXEC_OACC_SERIAL_LOOP
    9423        13457 :          || code->op == EXEC_OACC_LOOP;
    9424              : }
    9425              : 
    9426              : static void
    9427         5987 : resolve_scalar_int_expr (gfc_expr *expr, const char *clause)
    9428              : {
    9429         5987 :   if (!gfc_resolve_expr (expr)
    9430         5987 :       || expr->ts.type != BT_INTEGER
    9431        11903 :       || expr->rank != 0)
    9432           89 :     gfc_error ("%s clause at %L requires a scalar INTEGER expression",
    9433              :                clause, &expr->where);
    9434         5987 : }
    9435              : 
    9436              : static void
    9437         4090 : resolve_positive_int_expr (gfc_expr *expr, const char *clause)
    9438              : {
    9439         4090 :   resolve_scalar_int_expr (expr, clause);
    9440         4090 :   if (expr->expr_type == EXPR_CONSTANT
    9441         3660 :       && expr->ts.type == BT_INTEGER
    9442         3627 :       && mpz_sgn (expr->value.integer) <= 0)
    9443           54 :     gfc_warning ((flag_openmp || flag_openmp_simd) ? OPT_Wopenmp : 0,
    9444              :                  "INTEGER expression of %s clause at %L must be positive",
    9445              :                  clause, &expr->where);
    9446         4090 : }
    9447              : 
    9448              : static void
    9449           86 : resolve_nonnegative_int_expr (gfc_expr *expr, const char *clause)
    9450              : {
    9451           86 :   resolve_scalar_int_expr (expr, clause);
    9452           86 :   if (expr->expr_type == EXPR_CONSTANT
    9453           13 :       && expr->ts.type == BT_INTEGER
    9454           11 :       && mpz_sgn (expr->value.integer) < 0)
    9455            6 :     gfc_warning ((flag_openmp || flag_openmp_simd) ? OPT_Wopenmp : 0,
    9456              :                  "INTEGER expression of %s clause at %L must be non-negative",
    9457              :                  clause, &expr->where);
    9458           86 : }
    9459              : 
    9460              : /* Emits error when symbol is pointer, cray pointer or cray pointee
    9461              :    of derived of polymorphic type.  */
    9462              : 
    9463              : static void
    9464           98 : check_symbol_not_pointer (gfc_symbol *sym, locus loc, const char *name)
    9465              : {
    9466           98 :   if (sym->ts.type == BT_DERIVED && sym->attr.cray_pointer)
    9467            0 :     gfc_error ("Cray pointer object %qs of derived type in %s clause at %L",
    9468              :                sym->name, name, &loc);
    9469           98 :   if (sym->ts.type == BT_DERIVED && sym->attr.cray_pointee)
    9470            0 :     gfc_error ("Cray pointee object %qs of derived type in %s clause at %L",
    9471              :                sym->name, name, &loc);
    9472              : 
    9473           98 :   if ((sym->ts.type == BT_ASSUMED && sym->attr.pointer)
    9474           98 :       || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
    9475            0 :           && CLASS_DATA (sym)->attr.pointer))
    9476            0 :     gfc_error ("POINTER object %qs of polymorphic type in %s clause at %L",
    9477              :                sym->name, name, &loc);
    9478           98 :   if ((sym->ts.type == BT_ASSUMED && sym->attr.cray_pointer)
    9479           98 :       || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
    9480            0 :           && CLASS_DATA (sym)->attr.cray_pointer))
    9481            0 :     gfc_error ("Cray pointer object %qs of polymorphic type in %s clause at %L",
    9482              :                sym->name, name, &loc);
    9483           98 :   if ((sym->ts.type == BT_ASSUMED && sym->attr.cray_pointee)
    9484           98 :       || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
    9485            0 :           && CLASS_DATA (sym)->attr.cray_pointee))
    9486            0 :     gfc_error ("Cray pointee object %qs of polymorphic type in %s clause at %L",
    9487              :                sym->name, name, &loc);
    9488           98 : }
    9489              : 
    9490              : /* Emits error when symbol represents assumed size/rank array.  */
    9491              : 
    9492              : static void
    9493        14844 : check_array_not_assumed (gfc_symbol *sym, locus loc, const char *name)
    9494              : {
    9495        14844 :   if (sym->as && sym->as->type == AS_ASSUMED_SIZE)
    9496           13 :     gfc_error ("Assumed size array %qs in %s clause at %L",
    9497              :                sym->name, name, &loc);
    9498        14844 :   if (sym->as && sym->as->type == AS_ASSUMED_RANK)
    9499           11 :     gfc_error ("Assumed rank array %qs in %s clause at %L",
    9500              :                sym->name, name, &loc);
    9501        14844 : }
    9502              : 
    9503              : static void
    9504         5850 : resolve_oacc_data_clauses (gfc_symbol *sym, locus loc, const char *name)
    9505              : {
    9506            0 :   check_array_not_assumed (sym, loc, name);
    9507            0 : }
    9508              : 
    9509              : static void
    9510           65 : resolve_oacc_deviceptr_clause (gfc_symbol *sym, locus loc, const char *name)
    9511              : {
    9512           65 :   if (sym->attr.pointer
    9513           64 :       || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
    9514            0 :           && CLASS_DATA (sym)->attr.class_pointer))
    9515            1 :     gfc_error ("POINTER object %qs in %s clause at %L",
    9516              :                sym->name, name, &loc);
    9517           65 :   if (sym->attr.cray_pointer
    9518           63 :       || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
    9519            0 :           && CLASS_DATA (sym)->attr.cray_pointer))
    9520            2 :     gfc_error ("Cray pointer object %qs in %s clause at %L",
    9521              :                sym->name, name, &loc);
    9522           65 :   if (sym->attr.cray_pointee
    9523           63 :       || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
    9524            0 :           && CLASS_DATA (sym)->attr.cray_pointee))
    9525            2 :     gfc_error ("Cray pointee object %qs in %s clause at %L",
    9526              :                sym->name, name, &loc);
    9527           65 :   if (sym->attr.allocatable
    9528           64 :       || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)
    9529            0 :           && CLASS_DATA (sym)->attr.allocatable))
    9530            1 :     gfc_error ("ALLOCATABLE object %qs in %s clause at %L",
    9531              :                sym->name, name, &loc);
    9532           65 :   if (sym->attr.value)
    9533            1 :     gfc_error ("VALUE object %qs in %s clause at %L",
    9534              :                sym->name, name, &loc);
    9535           65 :   check_array_not_assumed (sym, loc, name);
    9536           65 : }
    9537              : 
    9538              : 
    9539              : struct resolve_omp_udr_callback_data
    9540              : {
    9541              :   gfc_symbol *sym1, *sym2;
    9542              : };
    9543              : 
    9544              : 
    9545              : static int
    9546         1413 : resolve_omp_udr_callback (gfc_expr **e, int *, void *data)
    9547              : {
    9548         1413 :   struct resolve_omp_udr_callback_data *rcd
    9549              :     = (struct resolve_omp_udr_callback_data *) data;
    9550         1413 :   if ((*e)->expr_type == EXPR_VARIABLE
    9551          801 :       && ((*e)->symtree->n.sym == rcd->sym1
    9552          255 :           || (*e)->symtree->n.sym == rcd->sym2))
    9553              :     {
    9554          801 :       gfc_ref *ref = gfc_get_ref ();
    9555          801 :       ref->type = REF_ARRAY;
    9556          801 :       ref->u.ar.where = (*e)->where;
    9557          801 :       ref->u.ar.as = (*e)->symtree->n.sym->as;
    9558          801 :       ref->u.ar.type = AR_FULL;
    9559          801 :       ref->u.ar.dimen = 0;
    9560          801 :       ref->next = (*e)->ref;
    9561          801 :       (*e)->ref = ref;
    9562              :     }
    9563         1413 :   return 0;
    9564              : }
    9565              : 
    9566              : 
    9567              : static int
    9568         3008 : resolve_omp_udr_callback2 (gfc_expr **e, int *, void *)
    9569              : {
    9570         3008 :   if ((*e)->expr_type == EXPR_FUNCTION
    9571          360 :       && (*e)->value.function.isym == NULL)
    9572              :     {
    9573          174 :       gfc_symbol *sym = (*e)->symtree->n.sym;
    9574          174 :       if (!sym->attr.intrinsic
    9575          174 :           && sym->attr.if_source == IFSRC_UNKNOWN)
    9576            4 :         gfc_error ("Implicitly declared function %s used in "
    9577              :                    "!$OMP DECLARE REDUCTION at %L", sym->name, &(*e)->where);
    9578              :     }
    9579         3008 :   return 0;
    9580              : }
    9581              : 
    9582              : 
    9583              : static gfc_code *
    9584          802 : resolve_omp_udr_clause (gfc_omp_namelist *n, gfc_namespace *ns,
    9585              :                         gfc_symbol *sym1, gfc_symbol *sym2)
    9586              : {
    9587          802 :   gfc_code *copy;
    9588          802 :   gfc_symbol sym1_copy, sym2_copy;
    9589              : 
    9590          802 :   if (ns->code->op == EXEC_ASSIGN)
    9591              :     {
    9592          630 :       copy = gfc_get_code (EXEC_ASSIGN);
    9593          630 :       copy->expr1 = gfc_copy_expr (ns->code->expr1);
    9594          630 :       copy->expr2 = gfc_copy_expr (ns->code->expr2);
    9595              :     }
    9596              :   else
    9597              :     {
    9598          172 :       copy = gfc_get_code (EXEC_CALL);
    9599          172 :       copy->symtree = ns->code->symtree;
    9600          172 :       copy->ext.actual = gfc_copy_actual_arglist (ns->code->ext.actual);
    9601              :     }
    9602          802 :   copy->loc = ns->code->loc;
    9603          802 :   sym1_copy = *sym1;
    9604          802 :   sym2_copy = *sym2;
    9605          802 :   *sym1 = *n->sym;
    9606          802 :   *sym2 = *n->sym;
    9607          802 :   sym1->name = sym1_copy.name;
    9608          802 :   sym2->name = sym2_copy.name;
    9609          802 :   ns->proc_name = ns->parent->proc_name;
    9610          802 :   if (n->sym->attr.dimension)
    9611              :     {
    9612          348 :       struct resolve_omp_udr_callback_data rcd;
    9613          348 :       rcd.sym1 = sym1;
    9614          348 :       rcd.sym2 = sym2;
    9615          348 :       gfc_code_walker (&copy, gfc_dummy_code_callback,
    9616              :                        resolve_omp_udr_callback, &rcd);
    9617              :     }
    9618          802 :   gfc_resolve_code (copy, gfc_current_ns);
    9619          802 :   if (copy->op == EXEC_CALL && copy->resolved_isym == NULL)
    9620              :     {
    9621          172 :       gfc_symbol *sym = copy->resolved_sym;
    9622          172 :       if (sym
    9623          170 :           && !sym->attr.intrinsic
    9624          170 :           && sym->attr.if_source == IFSRC_UNKNOWN)
    9625            4 :         gfc_error ("Implicitly declared subroutine %s used in "
    9626              :                    "!$OMP DECLARE REDUCTION at %L", sym->name,
    9627              :                    &copy->loc);
    9628              :     }
    9629          802 :   gfc_code_walker (&copy, gfc_dummy_code_callback,
    9630              :                    resolve_omp_udr_callback2, NULL);
    9631          802 :   *sym1 = sym1_copy;
    9632          802 :   *sym2 = sym2_copy;
    9633          802 :   return copy;
    9634              : }
    9635              : 
    9636              : /* Assume that a constant expression in the range 1 (omp_default_mem_alloc)
    9637              :    to GOMP_OMP_PREDEF_ALLOC_MAX, or GOMP_OMPX_PREDEF_ALLOC_MIN to
    9638              :    GOMP_OMPX_PREDEF_ALLOC_MAX is fine.  The original symbol name is already
    9639              :    lost during matching via gfc_match_expr.  */
    9640              : static bool
    9641          130 : is_predefined_allocator (gfc_expr *expr)
    9642              : {
    9643          130 :   return (gfc_resolve_expr (expr)
    9644          129 :           && expr->rank == 0
    9645          124 :           && expr->ts.type == BT_INTEGER
    9646          119 :           && expr->ts.kind == gfc_c_intptr_kind
    9647          114 :           && expr->expr_type == EXPR_CONSTANT
    9648          239 :           && ((mpz_sgn (expr->value.integer) > 0
    9649          107 :                && mpz_cmp_si (expr->value.integer,
    9650              :                               GOMP_OMP_PREDEF_ALLOC_MAX) <= 0)
    9651            4 :               || (mpz_cmp_si (expr->value.integer,
    9652              :                               GOMP_OMPX_PREDEF_ALLOC_MIN) >= 0
    9653            1 :                   && mpz_cmp_si (expr->value.integer,
    9654          130 :                                  GOMP_OMPX_PREDEF_ALLOC_MAX) <= 0)));
    9655              : }
    9656              : 
    9657              : /* Resolve declarative ALLOCATE statement. Note: Common block vars only appear
    9658              :    as /block/ not individual, which is ensured during parsing.  */
    9659              : 
    9660              : void
    9661           62 : gfc_resolve_omp_allocate (gfc_namespace *ns, gfc_omp_namelist *list)
    9662              : {
    9663          278 :   for (gfc_omp_namelist *n = list; n; n = n->next)
    9664              :     {
    9665          216 :       if (n->sym->attr.result || n->sym->result == n->sym)
    9666              :         {
    9667            1 :           gfc_error ("Unexpected function-result variable %qs at %L in "
    9668              :                      "declarative !$OMP ALLOCATE", n->sym->name, &n->where);
    9669           30 :           continue;
    9670              :         }
    9671          215 :       if (ns->omp_allocate->sym->attr.proc_pointer)
    9672              :         {
    9673            0 :           gfc_error ("Procedure pointer %qs not supported with !$OMP "
    9674              :                      "ALLOCATE at %L", n->sym->name, &n->where);
    9675            0 :           continue;
    9676              :         }
    9677          215 :       if (n->sym->attr.flavor != FL_VARIABLE)
    9678              :         {
    9679            3 :           gfc_error ("Argument %qs at %L to declarative !$OMP ALLOCATE "
    9680              :                      "directive must be a variable", n->sym->name,
    9681              :                      &n->where);
    9682            3 :           continue;
    9683              :         }
    9684          212 :       if (ns != n->sym->ns || n->sym->attr.use_assoc || n->sym->attr.imported)
    9685              :         {
    9686            8 :           gfc_error ("Argument %qs at %L to declarative !$OMP ALLOCATE shall be"
    9687              :                      " in the same scope as the variable declaration",
    9688              :                      n->sym->name, &n->where);
    9689            8 :           continue;
    9690              :         }
    9691          204 :       if (n->sym->attr.dummy)
    9692              :         {
    9693            3 :           gfc_error ("Unexpected dummy argument %qs as argument at %L to "
    9694              :                      "declarative !$OMP ALLOCATE", n->sym->name, &n->where);
    9695            3 :           continue;
    9696              :         }
    9697          201 :       if (n->sym->attr.codimension)
    9698              :         {
    9699            0 :           gfc_error ("Unexpected coarray argument %qs as argument at %L to "
    9700              :                      "declarative !$OMP ALLOCATE", n->sym->name, &n->where);
    9701            0 :           continue;
    9702              :         }
    9703          201 :       if (n->sym->attr.omp_allocate)
    9704              :         {
    9705            5 :           if (n->sym->attr.in_common)
    9706              :             {
    9707            1 :               gfc_error ("Duplicated common block %</%s/%> in !$OMP ALLOCATE "
    9708            1 :                          "at %L", n->sym->common_head->name, &n->where);
    9709            3 :               while (n->next && n->next->sym
    9710            3 :                      && n->sym->common_head == n->next->sym->common_head)
    9711              :                 n = n->next;
    9712              :             }
    9713              :           else
    9714            4 :             gfc_error ("Duplicated variable %qs in !$OMP ALLOCATE at %L",
    9715              :                        n->sym->name, &n->where);
    9716            5 :           continue;
    9717              :         }
    9718              :       /* For 'equivalence(a,b)', a 'union_type {<type> a,b} equiv.0' is created
    9719              :          with a value expression for 'a' as 'equiv.0.a' (likewise for b); while
    9720              :          this can be handled, EQUIVALENCE is marked as obsolescent since Fortran
    9721              :          2018 and also not widely used.  However, it could be supported,
    9722              :          if needed. */
    9723          196 :       if (n->sym->attr.in_equivalence)
    9724              :         {
    9725            2 :           gfc_error ("Sorry, EQUIVALENCE object %qs not supported with !$OMP "
    9726              :                      "ALLOCATE at %L", n->sym->name, &n->where);
    9727            2 :           continue;
    9728              :         }
    9729              :       /* Similar for Cray pointer/pointee - they could be implemented but as
    9730              :          common vendor extension but nowadays rarely used and requiring
    9731              :          -fcray-pointer, there is no need to support them.  */
    9732          194 :       if (n->sym->attr.cray_pointer || n->sym->attr.cray_pointee)
    9733              :         {
    9734            2 :           gfc_error ("Sorry, Cray pointers and pointees such as %qs are not "
    9735              :                      "supported with !$OMP ALLOCATE at %L",
    9736              :                      n->sym->name, &n->where);
    9737            2 :           continue;
    9738              :         }
    9739          192 :       n->sym->attr.omp_allocate = 1;
    9740          192 :       if ((n->sym->ts.type == BT_CLASS && n->sym->attr.class_ok
    9741            0 :            && CLASS_DATA (n->sym)->attr.allocatable)
    9742          192 :           || (n->sym->ts.type != BT_CLASS && n->sym->attr.allocatable))
    9743            1 :         gfc_error ("Unexpected allocatable variable %qs at %L in declarative "
    9744              :                    "!$OMP ALLOCATE directive", n->sym->name, &n->where);
    9745          191 :       else if ((n->sym->ts.type == BT_CLASS && n->sym->attr.class_ok
    9746            0 :                 && CLASS_DATA (n->sym)->attr.class_pointer)
    9747          191 :                || (n->sym->ts.type != BT_CLASS && n->sym->attr.pointer))
    9748            1 :         gfc_error ("Unexpected pointer variable %qs at %L in declarative "
    9749              :                    "!$OMP ALLOCATE directive", n->sym->name, &n->where);
    9750          192 :       HOST_WIDE_INT alignment = 0;
    9751          198 :       if (n->u.align
    9752          192 :           && (!gfc_resolve_expr (n->u.align)
    9753           27 :               || n->u.align->ts.type != BT_INTEGER
    9754           26 :               || n->u.align->rank != 0
    9755           24 :               || n->u.align->expr_type != EXPR_CONSTANT
    9756           23 :               || gfc_extract_hwi (n->u.align, &alignment)
    9757           23 :               || !pow2p_hwi (alignment)))
    9758              :         {
    9759            6 :           gfc_error ("ALIGN requires a scalar positive constant integer "
    9760              :                      "alignment expression at %L that is a power of two",
    9761            6 :                      &n->u.align->where);
    9762            6 :           while (n->sym->attr.in_common && n->next && n->next->sym
    9763            6 :                  && n->sym->common_head == n->next->sym->common_head)
    9764              :             n = n->next;
    9765            6 :           continue;
    9766              :         }
    9767          186 :       if (n->sym->attr.in_common || n->sym->attr.save || n->sym->ns->save_all
    9768           63 :           || (n->sym->ns->proc_name
    9769           63 :               && (n->sym->ns->proc_name->attr.flavor == FL_PROGRAM
    9770           55 :                   || n->sym->ns->proc_name->attr.flavor == FL_MODULE
    9771           55 :                   || n->sym->ns->proc_name->attr.flavor == FL_BLOCK_DATA)))
    9772              :         {
    9773          131 :           bool com = n->sym->attr.in_common;
    9774          131 :           if (!n->u2.allocator)
    9775            1 :             gfc_error ("An ALLOCATOR clause is required as the list item "
    9776              :                        "%<%s%s%s%> at %L has the SAVE attribute", com ? "/" : "",
    9777            0 :                        com ? n->sym->common_head->name : n->sym->name,
    9778              :                        com ? "/" : "", &n->where);
    9779          130 :           else if (!is_predefined_allocator (n->u2.allocator))
    9780           24 :             gfc_error ("Predefined allocator required in ALLOCATOR clause at %L"
    9781              :                        " as the list item %<%s%s%s%> at %L has the SAVE attribute",
    9782           24 :                        &n->u2.allocator->where, com ? "/" : "",
    9783           24 :                        com ? n->sym->common_head->name : n->sym->name,
    9784              :                        com ? "/" : "", &n->where);
    9785              :           /* Static variables may not use omp_cgroup_mem_alloc (6),
    9786              :              omp_pteam_mem_alloc (7), or omp_thread_mem_alloc (8).  */
    9787          106 :           else if (mpz_cmp_si (n->u2.allocator->value.integer,
    9788              :                                   6 /* cgroup */) >= 0
    9789           34 :                    && mpz_cmp_si (n->u2.allocator->value.integer,
    9790              :                                   8 /* thread */) <= 0)
    9791              :             {
    9792           33 :               STATIC_ASSERT (GOMP_OMP_PREDEF_ALLOC_CGROUP == 6);
    9793           33 :               STATIC_ASSERT (GOMP_OMP_PREDEF_ALLOC_PTEAM == 7);
    9794           33 :               STATIC_ASSERT (GOMP_OMP_PREDEF_ALLOC_THREAD == 8);
    9795           33 :               const char *alloc_name[] = {"omp_cgroup_mem_alloc",
    9796              :                                           "omp_pteam_mem_alloc",
    9797              :                                           "omp_thread_mem_alloc" };
    9798           33 :               gfc_error ("Predefined allocator %qs in ALLOCATOR clause at %L, "
    9799              :                          "used for list item %<%s%s%s%> at %L, may not be used"
    9800              :                          " for static variables",
    9801           33 :                          alloc_name[mpz_get_ui (n->u2.allocator->value.integer)
    9802           33 :                                     - 6 /* cgroup */], &n->u2.allocator->where,
    9803              :                          com ? "/" : "",
    9804           33 :                          com ? n->sym->common_head->name : n->sym->name,
    9805              :                          com ? "/" : "", &n->where);
    9806              :             }
    9807           67 :           while (n->sym->attr.in_common && n->next && n->next->sym
    9808          186 :                  && n->sym->common_head == n->next->sym->common_head)
    9809              :             n = n->next;
    9810              :         }
    9811           55 :       else if (n->u2.allocator
    9812           55 :           && (!gfc_resolve_expr (n->u2.allocator)
    9813           20 :               || n->u2.allocator->ts.type != BT_INTEGER
    9814           19 :               || n->u2.allocator->rank != 0
    9815           18 :               || n->u2.allocator->ts.kind != gfc_c_intptr_kind))
    9816            3 :         gfc_error ("Expected integer expression of the "
    9817              :                    "%<omp_allocator_handle_kind%> kind at %L",
    9818            3 :                    &n->u2.allocator->where);
    9819              :     }
    9820           62 : }
    9821              : 
    9822              : /* Resolve ASSUME's and ASSUMES' assumption clauses.  Note that absent/contains
    9823              :    is handled during parse time in omp_verify_merge_absent_contains.   */
    9824              : 
    9825              : void
    9826           34 : gfc_resolve_omp_assumptions (gfc_omp_assumptions *assume)
    9827              : {
    9828           54 :   for (gfc_expr_list *el = assume->holds; el; el = el->next)
    9829           20 :     if (!gfc_resolve_expr (el->expr)
    9830           20 :         || el->expr->ts.type != BT_LOGICAL
    9831           38 :         || el->expr->rank != 0)
    9832            4 :       gfc_error ("HOLDS expression at %L must be a scalar logical expression",
    9833            4 :                  &el->expr->where);
    9834           34 : }
    9835              : 
    9836              : 
    9837              : /* Resolve the OpenMP ALLOCATE clauses.  */
    9838              : 
    9839              : static void
    9840        33132 : resolve_omp_allocate_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
    9841              :                               gfc_namespace *ns)
    9842              : {
    9843        33132 :   gfc_omp_namelist *n;
    9844        33132 :   enum gfc_omp_list_type list;
    9845              : 
    9846        33132 :   if (!omp_clauses->lists[OMP_LIST_ALLOCATE])
    9847              :     return;
    9848          795 :   for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; n = n->next)
    9849              :     {
    9850          515 :       if (n->u2.allocator
    9851          515 :           && (!gfc_resolve_expr (n->u2.allocator)
    9852          290 :               || n->u2.allocator->ts.type != BT_INTEGER
    9853          288 :               || n->u2.allocator->rank != 0
    9854          287 :               || n->u2.allocator->ts.kind != gfc_c_intptr_kind))
    9855              :         {
    9856            8 :           gfc_error ("Expected integer expression of the "
    9857              :                      "%<omp_allocator_handle_kind%> kind at %L",
    9858            8 :                      &n->u2.allocator->where);
    9859           28 :           break;
    9860              :         }
    9861          507 :       if (!n->u.align)
    9862          399 :         continue;
    9863          108 :       HOST_WIDE_INT alignment = 0;
    9864          108 :       if (!gfc_resolve_expr (n->u.align)
    9865          108 :           || n->u.align->ts.type != BT_INTEGER
    9866          105 :           || n->u.align->rank != 0
    9867          102 :           || n->u.align->expr_type != EXPR_CONSTANT
    9868           99 :           || gfc_extract_hwi (n->u.align, &alignment)
    9869           99 :           || alignment <= 0
    9870          207 :           || !pow2p_hwi (alignment))
    9871              :         {
    9872           12 :           gfc_error ("ALIGN requires a scalar positive constant integer "
    9873              :                      "alignment expression at %L that is a power of two",
    9874           12 :                      &n->u.align->where);
    9875           12 :           break;
    9876              :         }
    9877              :     }
    9878              : 
    9879              :   /* Check for 2 things here.
    9880              :       1.  There is no duplication of variable in allocate clause.
    9881              :       2.  Variable in allocate clause are also present in some
    9882              :           privatization clase (non-composite case).  */
    9883          815 :   for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; n = n->next)
    9884          515 :     if (n->sym)
    9885          489 :       n->sym->mark = 0;
    9886              : 
    9887              :   gfc_omp_namelist *prev = NULL;
    9888          815 :   for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; )
    9889              :     {
    9890          515 :       if (n->sym == NULL)
    9891              :         {
    9892           26 :           n = n->next;
    9893           26 :           continue;
    9894              :         }
    9895          489 :       if (n->sym->mark == 1)
    9896              :         {
    9897            3 :           gfc_warning (OPT_Wopenmp, "%qs appears more than once in "
    9898              :                        "%<allocate%> at %L" , n->sym->name, &n->where);
    9899              :           /* We have already seen this variable so it is a duplicate.
    9900              :              Remove it.  */
    9901            3 :           if (prev != NULL && prev->next == n)
    9902              :             {
    9903            3 :               prev->next = n->next;
    9904            3 :               n->next = NULL;
    9905            3 :               gfc_free_omp_namelist (n, OMP_LIST_ALLOCATE);
    9906            3 :               n = prev->next;
    9907              :             }
    9908            3 :           continue;
    9909              :         }
    9910          486 :       n->sym->mark = 1;
    9911          486 :       prev = n;
    9912          486 :       n = n->next;
    9913              :     }
    9914              : 
    9915              :   /* Non-composite constructs.  */
    9916          300 :   if (code && code->op < EXEC_OMP_DO_SIMD)
    9917              :     {
    9918         4760 :       for (list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
    9919         4641 :            list = gfc_omp_list_type (list + 1))
    9920         4641 :         switch (list)
    9921              :           {
    9922         1071 :           case OMP_LIST_PRIVATE:
    9923         1071 :           case OMP_LIST_FIRSTPRIVATE:
    9924         1071 :           case OMP_LIST_LASTPRIVATE:
    9925         1071 :           case OMP_LIST_REDUCTION:
    9926         1071 :           case OMP_LIST_REDUCTION_INSCAN:
    9927         1071 :           case OMP_LIST_REDUCTION_TASK:
    9928         1071 :           case OMP_LIST_IN_REDUCTION:
    9929         1071 :           case OMP_LIST_TASK_REDUCTION:
    9930         1071 :           case OMP_LIST_LINEAR:
    9931         1370 :             for (n = omp_clauses->lists[list]; n; n = n->next)
    9932          299 :                  n->sym->mark = 0;
    9933              :             break;
    9934              :           default:
    9935              :             break;
    9936              :           }
    9937              : 
    9938          410 :       for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; n = n->next)
    9939          291 :         if (n->sym->mark == 1)
    9940            4 :           gfc_error ("%qs specified in %<allocate%> clause at %L but not "
    9941              :                      "in an explicit privatization clause",
    9942              :                      n->sym->name, &n->where);
    9943              :     }
    9944           71 :   if (!(code
    9945          300 :         && (code->op == EXEC_OMP_ALLOCATORS || code->op == EXEC_OMP_ALLOCATE)
    9946           73 :         && code->block
    9947           72 :         && code->block->next
    9948           71 :         && code->block->next->op == EXEC_ALLOCATE))
    9949              :     return;
    9950              : 
    9951           68 :   if (code->op == EXEC_OMP_ALLOCATE)
    9952           49 :     gfc_warning (OPT_Wdeprecated_openmp,
    9953              :                  "The use of one or more %<allocate%> directives with "
    9954              :                  "an associated %<allocate%> statement at %L is "
    9955              :                  "deprecated since OpenMP 5.2, use an %<allocators%> "
    9956              :                  "directive", &code->loc);
    9957           68 :   gfc_alloc *a;
    9958           68 :   gfc_omp_namelist *n_null = NULL;
    9959           68 :   bool missing_allocator = false;
    9960           68 :   gfc_symbol *missing_allocator_sym = NULL;
    9961          161 :   for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; n = n->next)
    9962              :     {
    9963           93 :       if (n->u2.allocator == NULL)
    9964              :         {
    9965           77 :           if (!missing_allocator_sym)
    9966           59 :             missing_allocator_sym = n->sym;
    9967              :           missing_allocator = true;
    9968              :         }
    9969           93 :       if (n->sym == NULL)
    9970              :         {
    9971           26 :           n_null = n;
    9972           26 :           continue;
    9973              :         }
    9974           67 :       if (n->sym->attr.codimension)
    9975            2 :         gfc_error ("Unexpected coarray %qs in %<allocate%> at %L",
    9976              :                            n->sym->name, &n->where);
    9977          103 :       for (a = code->block->next->ext.alloc.list; a; a = a->next)
    9978          101 :         if (a->expr->expr_type == EXPR_VARIABLE
    9979          101 :             && a->expr->symtree->n.sym == n->sym)
    9980              :           {
    9981           65 :             gfc_ref *ref;
    9982           82 :             for (ref = a->expr->ref; ref; ref = ref->next)
    9983           17 :               if (ref->type == REF_COMPONENT)
    9984              :                 break;
    9985              :             if (ref == NULL)
    9986              :               break;
    9987              :           }
    9988           67 :       if (a == NULL)
    9989            2 :         gfc_error ("%qs specified in %<allocate%> at %L but not "
    9990              :                    "in the associated ALLOCATE statement",
    9991            2 :                    n->sym->name, &n->where);
    9992              :     }
    9993              :   /* If there is an ALLOCATE directive without list argument, a
    9994              :      namelist with its allocator/align clauses and n->sym = NULL is
    9995              :      created during parsing; here, we add all not otherwise specified
    9996              :      items from the Fortran allocate to that list.
    9997              :      For an ALLOCATORS directive, not listed items use the normal
    9998              :      Fortran way.
    9999              :      The behavior of an ALLOCATE directive that does not list all
   10000              :      arguments but there is no directive without list argument is not
   10001              :      well specified.  Thus, we reject such code below. In OpenMP 5.2
   10002              :      the executable ALLOCATE directive is deprecated and in 6.0
   10003              :      deleted such that no spec clarification is to be expected.  */
   10004          125 :   for (a = code->block->next->ext.alloc.list; a; a = a->next)
   10005           89 :     if (a->expr->expr_type == EXPR_VARIABLE)
   10006              :       {
   10007          154 :         for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; n = n->next)
   10008          122 :           if (a->expr->symtree->n.sym == n->sym)
   10009              :             {
   10010           57 :               gfc_ref *ref;
   10011           72 :               for (ref = a->expr->ref; ref; ref = ref->next)
   10012           15 :                 if (ref->type == REF_COMPONENT)
   10013              :                   break;
   10014              :               if (ref == NULL)
   10015              :                 break;
   10016              :             }
   10017           89 :         if (n == NULL && n_null == NULL)
   10018              :           {
   10019              :             /* OK for ALLOCATORS but for ALLOCATE: Unspecified whether
   10020              :                    that should use the default allocator of OpenMP or the
   10021              :                    Fortran allocator. Thus, just reject it.  */
   10022            7 :             if (code->op == EXEC_OMP_ALLOCATE)
   10023            1 :               gfc_error ("%qs listed in %<allocate%> statement at %L "
   10024              :                          "but it is neither explicitly in listed in "
   10025              :                          "the %<!$OMP ALLOCATE%> directive nor exists"
   10026              :                          " a directive without argument list",
   10027            1 :                          a->expr->symtree->n.sym->name,
   10028              :                          &a->expr->where);
   10029              :             break;
   10030              :           }
   10031           82 :         if (n == NULL)
   10032              :           {
   10033           25 :             if (a->expr->symtree->n.sym->attr.codimension)
   10034            1 :               gfc_error ("Unexpected coarray %qs in %<allocate%> at "
   10035              :                          "%L, implicitly listed in %<!$OMP ALLOCATE%>"
   10036              :                          " at %L", a->expr->symtree->n.sym->name,
   10037              :                          &a->expr->where, &n_null->where);
   10038              :             break;
   10039              :           }
   10040              :       }
   10041           68 :   gfc_namespace *prog_unit = ns;
   10042           87 :   while (prog_unit->parent)
   10043              :     prog_unit = prog_unit->parent;
   10044              :   gfc_namespace *fn_ns = ns;
   10045           72 :   while (fn_ns)
   10046              :     {
   10047           70 :       if (ns->proc_name
   10048           70 :           && (ns->proc_name->attr.subroutine
   10049            6 :               || ns->proc_name->attr.function))
   10050              :         break;
   10051            4 :       fn_ns = fn_ns->parent;
   10052              :     }
   10053           68 :   if (missing_allocator
   10054           58 :       && !(prog_unit->omp_requires & OMP_REQ_DYNAMIC_ALLOCATORS)
   10055           58 :       && ((fn_ns && fn_ns->proc_name->attr.omp_declare_target)
   10056           55 :           || omp_clauses->contained_in_target_construct))
   10057              :     {
   10058            6 :       if (code->op == EXEC_OMP_ALLOCATORS)
   10059            2 :         gfc_error ("ALLOCATORS directive at %L inside a target region "
   10060              :                    "must specify an ALLOCATOR modifier for %qs",
   10061              :                    &code->loc, missing_allocator_sym->name);
   10062            4 :       else if (missing_allocator_sym)
   10063            2 :         gfc_error ("ALLOCATE directive at %L inside a target region "
   10064              :                    "must specify an ALLOCATOR clause for %qs",
   10065              :                    &code->loc, missing_allocator_sym->name);
   10066              :       else
   10067            2 :         gfc_error ("ALLOCATE directive at %L inside a target region "
   10068              :                    "must specify an ALLOCATOR clause", &code->loc);
   10069              :     }
   10070              : }
   10071              : 
   10072              : 
   10073              : /* Diagnose list items that appear multiple times in OpenMP or OpenACC clauses,
   10074              :    unless permitted by the specification.  */
   10075              : 
   10076              : static void
   10077        33132 : check_omp_clauses_dupl_syms (gfc_code *code, gfc_omp_clauses *omp_clauses,
   10078              :                             bool openacc)
   10079              : {
   10080        33132 :   gfc_omp_namelist *n;
   10081        33132 :   enum gfc_omp_list_type list;
   10082              : 
   10083              :   /* Check that no symbol appears on multiple clauses, except that
   10084              :      a symbol can appear on both firstprivate and lastprivate.  */
   10085      1325280 :   for (list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
   10086      1292148 :        list = gfc_omp_list_type (list + 1))
   10087      1338028 :     for (n = omp_clauses->lists[list]; n; n = n->next)
   10088              :       {
   10089        45880 :         if (!n->sym)  /* omp_all_memory.  */
   10090           47 :           continue;
   10091        45833 :         n->sym->mark = 0;
   10092        45833 :         n->sym->comp_mark = 0;
   10093        45833 :         n->sym->data_mark = 0;
   10094        45833 :         n->sym->dev_mark = 0;
   10095        45833 :         n->sym->gen_mark = 0;
   10096        45833 :         n->sym->reduc_mark = 0;
   10097              :       }
   10098      1325280 :   for (list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
   10099      1292148 :        list = gfc_omp_list_type (list + 1))
   10100      1292148 :     if (list != OMP_LIST_FIRSTPRIVATE
   10101      1292148 :         && list != OMP_LIST_LASTPRIVATE
   10102      1292148 :         && list != OMP_LIST_ALIGNED
   10103      1192752 :         && list != OMP_LIST_DEPEND
   10104      1192752 :         && list != OMP_LIST_FROM
   10105      1126488 :         && list != OMP_LIST_TO
   10106      1126488 :         && list != OMP_LIST_INTEROP
   10107      1060224 :         && (list != OMP_LIST_REDUCTION || !openacc)
   10108      1047229 :         && list != OMP_LIST_ALLOCATE)
   10109      1049062 :       for (n = omp_clauses->lists[list]; n; n = n->next)
   10110              :         {
   10111        34965 :           bool component_ref_p = false;
   10112              : 
   10113              :           /* Allow multiple components of the same (e.g. derived-type)
   10114              :              variable here.  Duplicate components are detected elsewhere.  */
   10115        34965 :           if (n->expr && n->expr->expr_type == EXPR_VARIABLE)
   10116        16021 :             for (gfc_ref *ref = n->expr->ref; ref; ref = ref->next)
   10117         9744 :               if (ref->type == REF_COMPONENT)
   10118         3197 :                 component_ref_p = true;
   10119        34965 :           if ((list == OMP_LIST_IS_DEVICE_PTR
   10120        34965 :                || list == OMP_LIST_HAS_DEVICE_ADDR)
   10121          314 :               && !component_ref_p)
   10122              :             {
   10123          314 :               if (n->sym->gen_mark
   10124          312 :                   || n->sym->dev_mark
   10125          311 :                   || n->sym->reduc_mark
   10126          311 :                   || n->sym->mark)
   10127            5 :                 gfc_error ("Symbol %qs present on multiple clauses at %L",
   10128              :                            n->sym->name, &n->where);
   10129              :               else
   10130          309 :                 n->sym->dev_mark = 1;
   10131              :             }
   10132        34651 :           else if ((list == OMP_LIST_USE_DEVICE_PTR
   10133        34651 :                     || list == OMP_LIST_USE_DEVICE_ADDR
   10134        34651 :                     || list == OMP_LIST_PRIVATE
   10135              :                     || list == OMP_LIST_SHARED)
   10136        12861 :                    && !component_ref_p)
   10137              :             {
   10138        12861 :               if (n->sym->gen_mark || n->sym->dev_mark || n->sym->reduc_mark)
   10139           13 :                 gfc_error ("Symbol %qs present on multiple clauses at %L",
   10140              :                            n->sym->name, &n->where);
   10141              :               else
   10142              :                 {
   10143        12848 :                   n->sym->gen_mark = 1;
   10144              :                   /* Set both generic and device bits if we have
   10145              :                      use_device_*(x) or shared(x).  This allows us to diagnose
   10146              :                      "map(x) private(x)" below.  */
   10147        12848 :                   if (list != OMP_LIST_PRIVATE)
   10148         3456 :                     n->sym->dev_mark = 1;
   10149              :                 }
   10150              :             }
   10151        21790 :           else if ((list == OMP_LIST_REDUCTION
   10152        21790 :                     || list == OMP_LIST_REDUCTION_TASK
   10153        19329 :                     || list == OMP_LIST_REDUCTION_INSCAN
   10154        19329 :                     || list == OMP_LIST_IN_REDUCTION
   10155        19116 :                     || list == OMP_LIST_TASK_REDUCTION)
   10156         2674 :                    && !component_ref_p)
   10157              :             {
   10158              :               /* Attempts to mix reduction types are diagnosed below.  */
   10159         2674 :               if (n->sym->gen_mark || n->sym->dev_mark)
   10160            2 :                 gfc_error ("Symbol %qs present on multiple clauses at %L",
   10161              :                            n->sym->name, &n->where);
   10162         2674 :               n->sym->reduc_mark = 1;
   10163              :             }
   10164        19116 :           else if ((!component_ref_p && n->sym->comp_mark)
   10165        19115 :                    || (component_ref_p && n->sym->mark))
   10166              :             {
   10167           42 :               if (openacc)
   10168            3 :                 gfc_error ("Symbol %qs has mixed component and non-component "
   10169            3 :                            "accesses at %L", n->sym->name, &n->where);
   10170              :             }
   10171        19074 :           else if ((openacc || list != OMP_LIST_MAP) && n->sym->mark)
   10172           88 :             gfc_error ("Symbol %qs present on multiple clauses at %L",
   10173              :                        n->sym->name, &n->where);
   10174              :           else
   10175              :             {
   10176        18986 :               if (component_ref_p)
   10177         2473 :                 n->sym->comp_mark = 1;
   10178              :               else
   10179        16513 :                 n->sym->mark = 1;
   10180              :             }
   10181              :         }
   10182              : 
   10183              :   /* Detect specifically the case where we have "map(x) private(x)" and raise
   10184              :      an error.  If we have "...simd" combined directives though, the "private"
   10185              :      applies to the simd part, so this is permitted though.  */
   10186        42532 :   for (n = omp_clauses->lists[OMP_LIST_PRIVATE]; n; n = n->next)
   10187         9400 :     if (n->sym->mark
   10188            6 :         && n->sym->gen_mark
   10189            6 :         && !n->sym->dev_mark
   10190            6 :         && !n->sym->reduc_mark
   10191            5 :         && code->op != EXEC_OMP_TARGET_SIMD
   10192              :         && code->op != EXEC_OMP_TARGET_PARALLEL_DO_SIMD
   10193              :         && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD
   10194              :         && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD)
   10195            1 :       gfc_error ("Symbol %qs present on multiple clauses at %L",
   10196              :                  n->sym->name, &n->where);
   10197              : 
   10198              :   gcc_assert (OMP_LIST_LASTPRIVATE == OMP_LIST_FIRSTPRIVATE + 1);
   10199        99396 :   for (list = OMP_LIST_FIRSTPRIVATE; list <= OMP_LIST_LASTPRIVATE;
   10200        66264 :        list = gfc_omp_list_type (list + 1))
   10201        70491 :     for (n = omp_clauses->lists[list]; n; n = n->next)
   10202         4227 :       if (n->sym->data_mark || n->sym->gen_mark || n->sym->dev_mark)
   10203              :         {
   10204            9 :           gfc_error ("Symbol %qs present on multiple clauses at %L",
   10205              :                      n->sym->name, &n->where);
   10206            9 :           n->sym->data_mark = n->sym->gen_mark = n->sym->dev_mark = 0;
   10207              :         }
   10208         4218 :       else if (n->sym->mark
   10209           18 :                && code->op != EXEC_OMP_TARGET_TEAMS
   10210              :                && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE
   10211              :                && code->op != EXEC_OMP_TARGET_TEAMS_LOOP
   10212              :                && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD
   10213              :                && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO
   10214              :                && code->op != EXEC_OMP_TARGET_PARALLEL
   10215              :                && code->op != EXEC_OMP_TARGET_PARALLEL_DO
   10216              :                && code->op != EXEC_OMP_TARGET_PARALLEL_LOOP
   10217              :                && code->op != EXEC_OMP_TARGET_PARALLEL_DO_SIMD
   10218              :                && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD)
   10219            7 :         gfc_error ("Symbol %qs present on both data and map clauses "
   10220              :                    "at %L", n->sym->name, &n->where);
   10221              : 
   10222        35051 :   for (n = omp_clauses->lists[OMP_LIST_FIRSTPRIVATE]; n; n = n->next)
   10223              :     {
   10224         1919 :       if (n->sym->data_mark || n->sym->gen_mark || n->sym->dev_mark)
   10225            7 :         gfc_error ("Symbol %qs present on multiple clauses at %L",
   10226              :                    n->sym->name, &n->where);
   10227              :       else
   10228         1912 :         n->sym->data_mark = 1;
   10229              :     }
   10230              : 
   10231              :   /* LASTPRIVATE clauses.  */
   10232        35440 :   for (n = omp_clauses->lists[OMP_LIST_LASTPRIVATE]; n; n = n->next)
   10233         2308 :     n->sym->data_mark = 0;
   10234        35440 :   for (n = omp_clauses->lists[OMP_LIST_LASTPRIVATE]; n; n = n->next)
   10235              :     {
   10236         2308 :       if (n->sym->data_mark || n->sym->gen_mark || n->sym->dev_mark)
   10237            0 :         gfc_error ("Symbol %qs present on multiple clauses at %L",
   10238              :                    n->sym->name, &n->where);
   10239              :       else
   10240         2308 :         n->sym->data_mark = 1;
   10241              :     }
   10242              : 
   10243              :   /* ALIGNED clauses.  */
   10244        33282 :   for (n = omp_clauses->lists[OMP_LIST_ALIGNED]; n; n = n->next)
   10245          150 :     n->sym->mark = 0;
   10246              : 
   10247        33282 :   for (n = omp_clauses->lists[OMP_LIST_ALIGNED]; n; n = n->next)
   10248              :     {
   10249          150 :       if (n->sym->mark)
   10250            0 :         gfc_error ("Symbol %qs present on multiple clauses at %L",
   10251              :                    n->sym->name, &n->where);
   10252              :       else
   10253          150 :         n->sym->mark = 1;
   10254              :     }
   10255              : 
   10256              :   /* FROM and TO clauses.  */
   10257        33902 :   for (n = omp_clauses->lists[OMP_LIST_TO]; n; n = n->next)
   10258          770 :     n->sym->mark = 0;
   10259        34167 :   for (n = omp_clauses->lists[OMP_LIST_FROM]; n; n = n->next)
   10260         1035 :     if (n->expr == NULL)
   10261         1017 :       n->sym->mark = 1;
   10262        33902 :   for (n = omp_clauses->lists[OMP_LIST_TO]; n; n = n->next)
   10263              :     {
   10264          770 :       if (n->expr == NULL && n->sym->mark)
   10265            0 :         gfc_error ("Symbol %qs present on both FROM and TO clauses at %L",
   10266              :                    n->sym->name, &n->where);
   10267              :       else
   10268          770 :         n->sym->mark = 1;
   10269              :     }
   10270              : 
   10271              :   /* OpenACC reductions.  */
   10272        33132 :   if (openacc)
   10273              :     {
   10274        15131 :       for (n = omp_clauses->lists[OMP_LIST_REDUCTION]; n; n = n->next)
   10275         2136 :         n->sym->mark = 0;
   10276        15131 :       for (n = omp_clauses->lists[OMP_LIST_REDUCTION]; n; n = n->next)
   10277              :         {
   10278         2136 :           if (n->sym->mark)
   10279            0 :             gfc_error ("Symbol %qs present on multiple clauses at %L",
   10280              :                        n->sym->name, &n->where);
   10281              :           else
   10282         2136 :             n->sym->mark = 1;
   10283              : 
   10284              :           /* OpenACC does not support reductions on arrays.  */
   10285         2136 :           if (n->sym->as)
   10286           71 :             gfc_error ("Array %qs is not permitted in reduction at %L",
   10287              :                        n->sym->name, &n->where);
   10288              :         }
   10289              :     }
   10290        33132 : }
   10291              : 
   10292              : /* OpenMP/OpenACC: Resolve the list item of a MAP, TO, FROM, CACHE, AFFINITY
   10293              :    or DEPEND clause.  */
   10294              : 
   10295              : static void
   10296        20963 : resolve_omp_clauses_aff_dep_map_cache (gfc_code *code,
   10297              :                                        gfc_omp_namelist *n,
   10298              :                                        const char *name,
   10299              :                                        enum gfc_omp_list_type list,
   10300              :                                        gfc_omp_clauses *omp_clauses,
   10301              :                                        bool openacc)
   10302              : {
   10303        20963 :   gcc_checking_assert (list == OMP_LIST_AFFINITY || list == OMP_LIST_DEPEND
   10304              :                        || list == OMP_LIST_MAP || list == OMP_LIST_TO
   10305              :                        || list == OMP_LIST_FROM || list == OMP_LIST_CACHE);
   10306              : 
   10307        20963 :   if (list != OMP_LIST_CACHE && n->u2.ns && !n->u2.ns->resolved)
   10308              :     {
   10309          109 :       n->u2.ns->resolved = 1;
   10310          109 :       for (gfc_symbol *sym = n->u2.ns->omp_affinity_iterators;
   10311          235 :            sym; sym = sym->tlink)
   10312              :         {
   10313          126 :           gfc_constructor *c;
   10314          126 :           c = gfc_constructor_first (sym->value->value.constructor);
   10315          126 :           if (!gfc_resolve_expr (c->expr)
   10316          126 :               || c->expr->ts.type != BT_INTEGER
   10317          250 :               || c->expr->rank != 0)
   10318            2 :             gfc_error ("Scalar integer expression for range begin expected "
   10319            2 :                        "at %L", &c->expr->where);
   10320          126 :           c = gfc_constructor_next (c);
   10321          126 :           if (!gfc_resolve_expr (c->expr)
   10322          126 :               || c->expr->ts.type != BT_INTEGER
   10323          250 :               || c->expr->rank != 0)
   10324            2 :             gfc_error ("Scalar integer expression for range end expected at %L",
   10325            2 :                        &c->expr->where);
   10326          126 :           c = gfc_constructor_next (c);
   10327          126 :           if (c && (!gfc_resolve_expr (c->expr)
   10328           16 :                     || c->expr->ts.type != BT_INTEGER
   10329           14 :                     || c->expr->rank != 0))
   10330            2 :             gfc_error ("Scalar integer expression for range step expected "
   10331            2 :                        "at %L", &c->expr->where);
   10332          124 :           else if (c
   10333           14 :                    && c->expr->expr_type == EXPR_CONSTANT
   10334           12 :                    && mpz_cmp_si (c->expr->value.integer, 0) == 0)
   10335            2 :             gfc_error ("Nonzero range step expected at %L", &c->expr->where);
   10336              :         }
   10337              :     }
   10338        20862 :   if (list == OMP_LIST_DEPEND)
   10339              :     {
   10340         1964 :       if (n->u.depend_doacross_op == OMP_DEPEND_SINK_FIRST
   10341              :           || n->u.depend_doacross_op == OMP_DOACROSS_SINK_FIRST
   10342         1964 :           || n->u.depend_doacross_op == OMP_DOACROSS_SINK)
   10343              :         {
   10344         1233 :           if (omp_clauses->doacross_source)
   10345              :             {
   10346            0 :               gfc_error ("Dependence-type SINK used together with SOURCE on "
   10347              :                          "the same construct at %L", &n->where);
   10348            0 :               omp_clauses->doacross_source = false;
   10349              :             }
   10350         1233 :           else if (n->expr)
   10351              :             {
   10352          571 :               if (!gfc_resolve_expr (n->expr)
   10353          571 :                   || n->expr->ts.type != BT_INTEGER
   10354         1142 :                   || n->expr->rank != 0)
   10355            0 :                 gfc_error ("SINK addend not a constant integer at %L",
   10356              :                            &n->where);
   10357              :             }
   10358         1233 :           if (n->sym == NULL
   10359            4 :               && (n->expr == NULL
   10360            3 :                   || mpz_cmp_si (n->expr->value.integer, -1) != 0))
   10361            2 :             gfc_error ("omp_cur_iteration at %L requires %<-1%> as "
   10362              :                        "logical offset", &n->where);
   10363              :           return;
   10364              :         }
   10365          731 :       if (n->u.depend_doacross_op == OMP_DEPEND_DEPOBJ
   10366           38 :           && !n->expr
   10367           22 :           && (n->sym->ts.type != BT_INTEGER
   10368           22 :               || n->sym->ts.kind != 2 * gfc_index_integer_kind
   10369           22 :               || n->sym->attr.dimension))
   10370            0 :         gfc_error ("Locator %qs at %L in DEPEND clause of depobj type shall be "
   10371              :                    "a scalar integer of OMP_DEPEND_KIND kind",
   10372              :                    n->sym->name, &n->where);
   10373          731 :       else if (n->u.depend_doacross_op == OMP_DEPEND_DEPOBJ
   10374           38 :                && n->expr
   10375          747 :                && (!gfc_resolve_expr (n->expr)
   10376           16 :                    || n->expr->ts.type != BT_INTEGER
   10377           16 :                    || n->expr->ts.kind != 2 * gfc_index_integer_kind
   10378           16 :                    || n->expr->rank != 0))
   10379            0 :         gfc_error ("Locator at %L in DEPEND clause of depobj type shall be a "
   10380            0 :                    "scalar integer of OMP_DEPEND_KIND kind", &n->expr->where);
   10381              :     }
   10382        19730 :   gfc_ref *lastref = NULL, *lastslice = NULL;
   10383        19730 :   bool resolved = false;
   10384        19730 :   if (n->expr)
   10385              :     {
   10386         6546 :       lastref = n->expr->ref;
   10387         6546 :       resolved = gfc_resolve_expr (n->expr);
   10388              : 
   10389              :       /* Look through component refs to find last array reference.  */
   10390         6546 :       if (resolved)
   10391              :         {
   10392        16585 :           for (gfc_ref *ref = n->expr->ref; ref; ref = ref->next)
   10393        10057 :             if (ref->type == REF_COMPONENT
   10394              :                 || ref->type == REF_SUBSTRING
   10395        10057 :                 || ref->type == REF_INQUIRY)
   10396              :               lastref = ref;
   10397         6799 :             else if (ref->type == REF_ARRAY)
   10398              :               {
   10399        14290 :                 for (int i = 0; i < ref->u.ar.dimen; i++)
   10400         7491 :                   if (ref->u.ar.dimen_type[i] == DIMEN_RANGE)
   10401         6277 :                     lastslice = ref;
   10402              :                 lastref = ref;
   10403              :               }
   10404              : 
   10405              :           /* The "!$acc cache" directive allows rectangular subarrays to be
   10406              :               specified, with some restrictions on the form of bounds (not
   10407              :               implemented).  Only raise an error here if we're really sure the
   10408              :               array isn't contiguous.  An expression such as arr(-n:n,-n:n)
   10409              :               could be contiguous even if it looks like it may not be.  */
   10410         6528 :           if (code
   10411         6502 :               && code->op != EXEC_OACC_UPDATE
   10412         5720 :               && list != OMP_LIST_CACHE
   10413         5720 :               && list != OMP_LIST_DEPEND
   10414         5398 :               && !gfc_is_simply_contiguous (n->expr, false, true)
   10415         1517 :               && gfc_is_not_contiguous (n->expr)
   10416         6541 :               && !(lastslice && (lastslice->next
   10417            3 :                                  || lastslice->type != REF_ARRAY)))
   10418            3 :             gfc_error ("Array is not contiguous at %L", &n->where);
   10419              :         }
   10420              :     }
   10421        19730 :   if (list == OMP_LIST_MAP
   10422        17058 :       && (n->sym->attr.omp_groupprivate
   10423        17057 :           || n->sym->attr.omp_declare_target_local))
   10424            2 :     gfc_error ("%qs argument to MAP clause at %L must not be a device-local "
   10425              :                "variable, including GROUPPRIVATE", n->sym->name, &n->where);
   10426        19730 :   if (openacc
   10427        19730 :       && list == OMP_LIST_MAP
   10428         9571 :       && (n->u.map.op == OMP_MAP_ATTACH || n->u.map.op == OMP_MAP_DETACH))
   10429              :     {
   10430          117 :       symbol_attribute attr;
   10431          117 :       if (n->expr)
   10432           99 :         attr = gfc_expr_attr (n->expr);
   10433              :       else
   10434           18 :         attr = n->sym->attr;
   10435          117 :       if (!attr.pointer && !attr.allocatable)
   10436            7 :         gfc_error ("%qs clause argument must be ALLOCATABLE or a POINTER at %L",
   10437            7 :                    (n->u.map.op == OMP_MAP_ATTACH) ? "attach" : "detach",
   10438              :                    &n->where);
   10439              :     }
   10440        19730 :   if (lastref
   10441        13196 :       || (n->expr && (!resolved || n->expr->expr_type != EXPR_VARIABLE)))
   10442              :     {
   10443         6546 :       if (!lastslice && lastref && lastref->type == REF_SUBSTRING)
   10444           11 :         gfc_error ("Unexpected substring reference in %s clause at %L",
   10445              :                    name, &n->where);
   10446         6535 :       else if (!lastslice && lastref && lastref->type == REF_INQUIRY)
   10447              :         {
   10448           12 :           gcc_assert (lastref->u.i == INQUIRY_RE || lastref->u.i == INQUIRY_IM);
   10449           12 :           gfc_error ("Unexpected complex-parts designator reference in %s "
   10450              :                      "clause at %L", name, &n->where);
   10451              :         }
   10452         6523 :       else if (!resolved
   10453         6505 :                || n->expr->expr_type != EXPR_VARIABLE
   10454         6493 :                || (lastslice
   10455         5615 :                    && (lastslice->next || lastslice->type != REF_ARRAY)))
   10456           46 :         gfc_error ("%qs in %s clause at %L is not a proper array section",
   10457           46 :                        n->sym->name, name, &n->where);
   10458              :       else if (lastslice)
   10459              :         {
   10460              :           int i;
   10461              :           gfc_array_ref *ar = &lastslice->u.ar;
   10462        11873 :           for (i = 0; i < ar->dimen; i++)
   10463         6275 :             if (ar->stride[i] && code && code->op != EXEC_OACC_UPDATE)
   10464              :               {
   10465            1 :                 gfc_error ("Stride should not be specified for array section "
   10466              :                            "in %s clause at %L", name, &n->where);
   10467            1 :                 break;
   10468              :               }
   10469         6274 :             else if (ar->dimen_type[i] != DIMEN_ELEMENT
   10470         6274 :                          && ar->dimen_type[i] != DIMEN_RANGE)
   10471              :               {
   10472            0 :                 gfc_error ("%qs in %s clause at %L is not a proper array "
   10473            0 :                            "section", n->sym->name, name, &n->where);
   10474            0 :                 break;
   10475              :               }
   10476         6274 :             else if ((list == OMP_LIST_DEPEND || list == OMP_LIST_AFFINITY)
   10477          161 :                      && ar->start[i]
   10478          133 :                      && ar->start[i]->expr_type == EXPR_CONSTANT
   10479           97 :                      && ar->end[i]
   10480           72 :                      && ar->end[i]->expr_type == EXPR_CONSTANT
   10481           72 :                      && mpz_cmp (ar->start[i]->value.integer,
   10482           72 :                                  ar->end[i]->value.integer) > 0)
   10483              :               {
   10484            0 :                 gfc_error ("%qs in %s clause at %L is a zero size array "
   10485            0 :                            "section", n->sym->name,
   10486              :                            list == OMP_LIST_DEPEND ? "DEPEND" : "AFFINITY",
   10487              :                            &n->where);
   10488            0 :                 break;
   10489              :               }
   10490              :         }
   10491              :     }
   10492        13184 :   else if (openacc)
   10493              :     {
   10494         5915 :       if (list == OMP_LIST_MAP && n->u.map.op == OMP_MAP_FORCE_DEVICEPTR)
   10495           65 :         resolve_oacc_deviceptr_clause (n->sym, n->where, name);
   10496              :       else
   10497         5850 :         resolve_oacc_data_clauses (n->sym, n->where, name);
   10498              :     }
   10499         7269 :   else if (list != OMP_LIST_DEPEND
   10500         6775 :                && n->sym->as
   10501         3340 :                && n->sym->as->type == AS_ASSUMED_SIZE)
   10502            5 :     gfc_error ("Assumed size array %qs in %s clause at %L",
   10503              :                    n->sym->name, name, &n->where);
   10504        19730 :   if (code && list == OMP_LIST_MAP && !openacc)
   10505         7442 :     switch (code->op)
   10506              :       {
   10507         6161 :       case EXEC_OMP_TARGET:
   10508         6161 :       case EXEC_OMP_TARGET_PARALLEL:
   10509         6161 :       case EXEC_OMP_TARGET_PARALLEL_DO:
   10510         6161 :       case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
   10511         6161 :       case EXEC_OMP_TARGET_PARALLEL_LOOP:
   10512         6161 :       case EXEC_OMP_TARGET_SIMD:
   10513         6161 :       case EXEC_OMP_TARGET_TEAMS:
   10514         6161 :       case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
   10515         6161 :       case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
   10516         6161 :       case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
   10517         6161 :       case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
   10518         6161 :       case EXEC_OMP_TARGET_TEAMS_LOOP:
   10519         6161 :       case EXEC_OMP_TARGET_DATA:
   10520         6161 :         switch (n->u.map.op)
   10521              :           {
   10522              :           case OMP_MAP_TO:
   10523              :           case OMP_MAP_ALWAYS_TO:
   10524              :           case OMP_MAP_PRESENT_TO:
   10525              :           case OMP_MAP_ALWAYS_PRESENT_TO:
   10526              :           case OMP_MAP_FROM:
   10527              :           case OMP_MAP_ALWAYS_FROM:
   10528              :           case OMP_MAP_PRESENT_FROM:
   10529              :           case OMP_MAP_ALWAYS_PRESENT_FROM:
   10530              :           case OMP_MAP_TOFROM:
   10531              :           case OMP_MAP_ALWAYS_TOFROM:
   10532              :           case OMP_MAP_PRESENT_TOFROM:
   10533              :           case OMP_MAP_ALWAYS_PRESENT_TOFROM:
   10534              :           case OMP_MAP_ALLOC:
   10535              :           case OMP_MAP_PRESENT_ALLOC:
   10536              :             break;
   10537            2 :           default:
   10538            2 :             gfc_error ("TARGET%s with map-type other than TO, "
   10539              :                        "FROM, TOFROM, or ALLOC on MAP clause "
   10540              :                        "at %L",
   10541              :                        code->op == EXEC_OMP_TARGET_DATA
   10542              :                        ? " DATA" : "", &n->where);
   10543            2 :             break;
   10544              :           }
   10545              :         break;
   10546          701 :       case EXEC_OMP_TARGET_ENTER_DATA:
   10547          701 :         switch (n->u.map.op)
   10548              :           {
   10549              :           case OMP_MAP_TO:
   10550              :           case OMP_MAP_ALWAYS_TO:
   10551              :           case OMP_MAP_PRESENT_TO:
   10552              :           case OMP_MAP_ALWAYS_PRESENT_TO:
   10553              :           case OMP_MAP_ALLOC:
   10554              :           case OMP_MAP_PRESENT_ALLOC:
   10555              :             break;
   10556          181 :           case OMP_MAP_TOFROM:
   10557          181 :             n->u.map.op = OMP_MAP_TO;
   10558          181 :             break;
   10559            3 :           case OMP_MAP_ALWAYS_TOFROM:
   10560            3 :             n->u.map.op = OMP_MAP_ALWAYS_TO;
   10561            3 :             break;
   10562            2 :           case OMP_MAP_PRESENT_TOFROM:
   10563            2 :             n->u.map.op = OMP_MAP_PRESENT_TO;
   10564            2 :             break;
   10565            2 :           case OMP_MAP_ALWAYS_PRESENT_TOFROM:
   10566            2 :             n->u.map.op = OMP_MAP_ALWAYS_PRESENT_TO;
   10567            2 :             break;
   10568            2 :           default:
   10569            2 :             gfc_error ("TARGET ENTER DATA with map-type other "
   10570              :                        "than TO, TOFROM or ALLOC on MAP clause "
   10571              :                        "at %L", &n->where);
   10572            2 :             break;
   10573              :           }
   10574              :         break;
   10575          580 :       case EXEC_OMP_TARGET_EXIT_DATA:
   10576          580 :         switch (n->u.map.op)
   10577              :           {
   10578              :           case OMP_MAP_FROM:
   10579              :           case OMP_MAP_ALWAYS_FROM:
   10580              :           case OMP_MAP_PRESENT_FROM:
   10581              :           case OMP_MAP_ALWAYS_PRESENT_FROM:
   10582              :           case OMP_MAP_RELEASE:
   10583              :           case OMP_MAP_DELETE:
   10584              :             break;
   10585          134 :           case OMP_MAP_TOFROM:
   10586          134 :             n->u.map.op = OMP_MAP_FROM;
   10587          134 :             break;
   10588            1 :           case OMP_MAP_ALWAYS_TOFROM:
   10589            1 :             n->u.map.op = OMP_MAP_ALWAYS_FROM;
   10590            1 :             break;
   10591            0 :           case OMP_MAP_PRESENT_TOFROM:
   10592            0 :             n->u.map.op = OMP_MAP_PRESENT_FROM;
   10593            0 :             break;
   10594            0 :           case OMP_MAP_ALWAYS_PRESENT_TOFROM:
   10595            0 :             n->u.map.op = OMP_MAP_ALWAYS_PRESENT_FROM;
   10596            0 :             break;
   10597            2 :           default:
   10598            2 :             gfc_error ("TARGET EXIT DATA with map-type other "
   10599              :                        "than FROM, TOFROM, RELEASE, or DELETE on "
   10600              :                        "MAP clause at %L", &n->where);
   10601            2 :             break;
   10602              :           }
   10603              :         break;
   10604              :       default:
   10605              :         break;
   10606              :       }
   10607        19730 :   if (list == OMP_LIST_MAP || list == OMP_LIST_TO || list == OMP_LIST_FROM)
   10608              :     {
   10609        18863 :       gfc_typespec *ts = n->expr ? &n->expr->ts : &n->sym->ts;
   10610              : 
   10611        18863 :       if (ts->type == BT_DERIVED || ts->type == BT_CLASS)
   10612              :         {
   10613           10 :           const char *mapper_id = (n->u3.udm
   10614         1002 :                                    ? n->u3.udm->requested_mapper_id : "");
   10615         1002 :           gfc_omp_udm *udm = gfc_find_omp_udm (gfc_current_ns, mapper_id, ts);
   10616         1002 :           if (mapper_id[0] != '\0' && !udm)
   10617            1 :             gfc_error ("User-defined mapper %qs not found at %L",
   10618              :                        mapper_id, &n->where);
   10619          997 :           else if (udm)
   10620              :             {
   10621           27 :               if (!n->u3.udm)
   10622              :                 {
   10623           18 :                   gcc_assert (mapper_id[0] == '\0');
   10624           18 :                   n->u3.udm = gfc_get_omp_namelist_udm ();
   10625           18 :                   n->u3.udm->requested_mapper_id = mapper_id;
   10626              :                 }
   10627           27 :               n->u3.udm->resolved_udm = udm;
   10628              :             }
   10629              :         }
   10630              :     }
   10631              : 
   10632        19730 :   if (list != OMP_LIST_DEPEND)
   10633              :     {
   10634        18999 :       n->sym->attr.referenced = 1;
   10635        18999 :       if (n->sym->attr.threadprivate)
   10636            1 :         gfc_error ("THREADPRIVATE object %qs in %s clause at %L",
   10637              :                    n->sym->name, name, &n->where);
   10638        18999 :       if (n->sym->attr.cray_pointee)
   10639           14 :         gfc_error ("Cray pointee %qs in %s clause at %L",
   10640              :                    n->sym->name, name, &n->where);
   10641              :     }
   10642              : }
   10643              : 
   10644              : /* OpenMP directive resolving routines.  */
   10645              : 
   10646              : static void
   10647        33132 : resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
   10648              :                      gfc_namespace *ns, bool openacc = false)
   10649              : {
   10650        33132 :   gfc_omp_namelist *n, *last;
   10651        33132 :   gfc_expr_list *el;
   10652        33132 :   enum gfc_omp_list_type list;
   10653        33132 :   int ifc;
   10654        33132 :   bool if_without_mod = false;
   10655        33132 :   gfc_omp_linear_op linear_op = OMP_LINEAR_DEFAULT;
   10656        33132 :   static const char *clause_names[]
   10657              :     = { "PRIVATE", "FIRSTPRIVATE", "LASTPRIVATE", "COPYPRIVATE", "SHARED",
   10658              :         "COPYIN", "UNIFORM", "AFFINITY", "ALIGNED", "LINEAR", "DEPEND", "MAP",
   10659              :         "TO", "FROM", "INCLUSIVE", "EXCLUSIVE",
   10660              :         "REDUCTION", "REDUCTION" /*inscan*/, "REDUCTION" /*task*/,
   10661              :         "IN_REDUCTION", "TASK_REDUCTION",
   10662              :         "DEVICE_RESIDENT", "LINK", "LOCAL", "USE_DEVICE",
   10663              :         "CACHE", "IS_DEVICE_PTR", "USE_DEVICE_PTR", "USE_DEVICE_ADDR",
   10664              :         "NONTEMPORAL", "ALLOCATE", "HAS_DEVICE_ADDR", "ENTER",
   10665              :         "USES_ALLOCATORS", "INIT", "USE", "DESTROY", "INTEROP", "ADJUST_ARGS" };
   10666        33132 :   STATIC_ASSERT (ARRAY_SIZE (clause_names) == OMP_LIST_NUM);
   10667              : 
   10668        33132 :   if (omp_clauses == NULL)
   10669              :     return;
   10670              : 
   10671        33132 :   if (ns == NULL)
   10672        32670 :     ns = gfc_current_ns;
   10673              : 
   10674        33132 :   check_omp_clauses_dupl_syms (code, omp_clauses, openacc);
   10675              : 
   10676        33132 :   if (omp_clauses->orderedc && omp_clauses->orderedc < omp_clauses->collapse)
   10677            0 :     gfc_error ("ORDERED clause parameter is less than COLLAPSE at %L",
   10678              :                &code->loc);
   10679        33132 :   if (omp_clauses->order_concurrent && omp_clauses->ordered)
   10680            4 :     gfc_error ("ORDER clause must not be used together with ORDERED at %L",
   10681              :                &code->loc);
   10682        33132 :   if (omp_clauses->if_expr)
   10683              :     {
   10684         1299 :       gfc_expr *expr = omp_clauses->if_expr;
   10685         1299 :       if (!gfc_resolve_expr (expr)
   10686         1299 :           || expr->ts.type != BT_LOGICAL || expr->rank != 0)
   10687           16 :         gfc_error ("IF clause at %L requires a scalar LOGICAL expression",
   10688              :                    &expr->where);
   10689              :       if_without_mod = true;
   10690              :     }
   10691       364452 :   for (ifc = 0; ifc < OMP_IF_LAST; ifc++)
   10692       331320 :     if (omp_clauses->if_exprs[ifc])
   10693              :       {
   10694          141 :         gfc_expr *expr = omp_clauses->if_exprs[ifc];
   10695          141 :         bool ok = true;
   10696          141 :         if (!gfc_resolve_expr (expr)
   10697          141 :             || expr->ts.type != BT_LOGICAL || expr->rank != 0)
   10698            0 :           gfc_error ("IF clause at %L requires a scalar LOGICAL expression",
   10699              :                      &expr->where);
   10700          141 :         else if (if_without_mod)
   10701              :           {
   10702            1 :             gfc_error ("IF clause without modifier at %L used together with "
   10703              :                        "IF clauses with modifiers",
   10704            1 :                        &omp_clauses->if_expr->where);
   10705            1 :             if_without_mod = false;
   10706              :           }
   10707              :         else
   10708          140 :           switch (code->op)
   10709              :             {
   10710           13 :             case EXEC_OMP_CANCEL:
   10711           13 :               ok = ifc == OMP_IF_CANCEL;
   10712           13 :               break;
   10713              : 
   10714           16 :             case EXEC_OMP_PARALLEL:
   10715           16 :             case EXEC_OMP_PARALLEL_DO:
   10716           16 :             case EXEC_OMP_PARALLEL_LOOP:
   10717           16 :             case EXEC_OMP_PARALLEL_MASKED:
   10718           16 :             case EXEC_OMP_PARALLEL_MASTER:
   10719           16 :             case EXEC_OMP_PARALLEL_SECTIONS:
   10720           16 :             case EXEC_OMP_PARALLEL_WORKSHARE:
   10721           16 :             case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
   10722           16 :             case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
   10723           16 :               ok = ifc == OMP_IF_PARALLEL;
   10724           16 :               break;
   10725              : 
   10726           28 :             case EXEC_OMP_PARALLEL_DO_SIMD:
   10727           28 :             case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
   10728           28 :             case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
   10729           28 :               ok = ifc == OMP_IF_PARALLEL || ifc == OMP_IF_SIMD;
   10730           28 :               break;
   10731              : 
   10732            8 :             case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
   10733            8 :             case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
   10734            8 :               ok = ifc == OMP_IF_PARALLEL || ifc == OMP_IF_TASKLOOP;
   10735            8 :               break;
   10736              : 
   10737           12 :             case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
   10738           12 :             case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
   10739           12 :               ok = (ifc == OMP_IF_PARALLEL
   10740           12 :                     || ifc == OMP_IF_TASKLOOP
   10741              :                     || ifc == OMP_IF_SIMD);
   10742              :               break;
   10743              : 
   10744            0 :             case EXEC_OMP_SIMD:
   10745            0 :             case EXEC_OMP_DO_SIMD:
   10746            0 :             case EXEC_OMP_DISTRIBUTE_SIMD:
   10747            0 :             case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
   10748            0 :               ok = ifc == OMP_IF_SIMD;
   10749            0 :               break;
   10750              : 
   10751            1 :             case EXEC_OMP_TASK:
   10752            1 :               ok = ifc == OMP_IF_TASK;
   10753            1 :               break;
   10754              : 
   10755            5 :             case EXEC_OMP_TASKLOOP:
   10756            5 :             case EXEC_OMP_MASKED_TASKLOOP:
   10757            5 :             case EXEC_OMP_MASTER_TASKLOOP:
   10758            5 :               ok = ifc == OMP_IF_TASKLOOP;
   10759            5 :               break;
   10760              : 
   10761           20 :             case EXEC_OMP_TASKLOOP_SIMD:
   10762           20 :             case EXEC_OMP_MASKED_TASKLOOP_SIMD:
   10763           20 :             case EXEC_OMP_MASTER_TASKLOOP_SIMD:
   10764           20 :               ok = ifc == OMP_IF_TASKLOOP || ifc == OMP_IF_SIMD;
   10765           20 :               break;
   10766              : 
   10767            5 :             case EXEC_OMP_TARGET:
   10768            5 :             case EXEC_OMP_TARGET_TEAMS:
   10769            5 :             case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
   10770            5 :             case EXEC_OMP_TARGET_TEAMS_LOOP:
   10771            5 :               ok = ifc == OMP_IF_TARGET;
   10772            5 :               break;
   10773              : 
   10774            4 :             case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
   10775            4 :             case EXEC_OMP_TARGET_SIMD:
   10776            4 :               ok = ifc == OMP_IF_TARGET || ifc == OMP_IF_SIMD;
   10777            4 :               break;
   10778              : 
   10779            2 :             case EXEC_OMP_TARGET_DATA:
   10780            2 :               ok = ifc == OMP_IF_TARGET_DATA;
   10781            2 :               break;
   10782              : 
   10783            2 :             case EXEC_OMP_TARGET_UPDATE:
   10784            2 :               ok = ifc == OMP_IF_TARGET_UPDATE;
   10785            2 :               break;
   10786              : 
   10787            2 :             case EXEC_OMP_TARGET_ENTER_DATA:
   10788            2 :               ok = ifc == OMP_IF_TARGET_ENTER_DATA;
   10789            2 :               break;
   10790              : 
   10791            2 :             case EXEC_OMP_TARGET_EXIT_DATA:
   10792            2 :               ok = ifc == OMP_IF_TARGET_EXIT_DATA;
   10793            2 :               break;
   10794              : 
   10795           10 :             case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
   10796           10 :             case EXEC_OMP_TARGET_PARALLEL:
   10797           10 :             case EXEC_OMP_TARGET_PARALLEL_DO:
   10798           10 :             case EXEC_OMP_TARGET_PARALLEL_LOOP:
   10799           10 :               ok = ifc == OMP_IF_TARGET || ifc == OMP_IF_PARALLEL;
   10800           10 :               break;
   10801              : 
   10802           10 :             case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
   10803           10 :             case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
   10804           10 :               ok = (ifc == OMP_IF_TARGET
   10805           10 :                     || ifc == OMP_IF_PARALLEL
   10806              :                     || ifc == OMP_IF_SIMD);
   10807              :               break;
   10808              : 
   10809              :             default:
   10810              :               ok = false;
   10811              :               break;
   10812              :           }
   10813          119 :         if (!ok)
   10814              :           {
   10815            2 :             static const char *ifs[] = {
   10816              :               "CANCEL",
   10817              :               "PARALLEL",
   10818              :               "SIMD",
   10819              :               "TASK",
   10820              :               "TASKLOOP",
   10821              :               "TARGET",
   10822              :               "TARGET DATA",
   10823              :               "TARGET UPDATE",
   10824              :               "TARGET ENTER DATA",
   10825              :               "TARGET EXIT DATA"
   10826              :             };
   10827            2 :             gfc_error ("IF clause modifier %s at %L not appropriate for "
   10828              :                        "the current OpenMP construct", ifs[ifc], &expr->where);
   10829              :           }
   10830              :       }
   10831              : 
   10832        33132 :   if (omp_clauses->self_expr)
   10833              :     {
   10834          177 :       gfc_expr *expr = omp_clauses->self_expr;
   10835          177 :       if (!gfc_resolve_expr (expr)
   10836          177 :           || expr->ts.type != BT_LOGICAL || expr->rank != 0)
   10837            6 :         gfc_error ("SELF clause at %L requires a scalar LOGICAL expression",
   10838              :                    &expr->where);
   10839              :     }
   10840              : 
   10841        33132 :   if (omp_clauses->final_expr)
   10842              :     {
   10843           64 :       gfc_expr *expr = omp_clauses->final_expr;
   10844           64 :       if (!gfc_resolve_expr (expr)
   10845           64 :           || expr->ts.type != BT_LOGICAL || expr->rank != 0)
   10846            0 :         gfc_error ("FINAL clause at %L requires a scalar LOGICAL expression",
   10847              :                    &expr->where);
   10848              :     }
   10849        33132 :   if (omp_clauses->novariants)
   10850              :     {
   10851            9 :       gfc_expr *expr = omp_clauses->novariants;
   10852           18 :       if (!gfc_resolve_expr (expr) || expr->ts.type != BT_LOGICAL
   10853           17 :           || expr->rank != 0)
   10854            1 :         gfc_error (
   10855              :           "NOVARIANTS clause at %L requires a scalar LOGICAL expression",
   10856              :           &expr->where);
   10857        33132 :       if_without_mod = true;
   10858              :     }
   10859        33132 :   if (omp_clauses->nocontext)
   10860              :     {
   10861           12 :       gfc_expr *expr = omp_clauses->nocontext;
   10862           24 :       if (!gfc_resolve_expr (expr) || expr->ts.type != BT_LOGICAL
   10863           23 :           || expr->rank != 0)
   10864            1 :         gfc_error (
   10865              :           "NOCONTEXT clause at %L requires a scalar LOGICAL expression",
   10866              :           &expr->where);
   10867        33132 :       if_without_mod = true;
   10868              :     }
   10869              : 
   10870        34148 :   for (el = omp_clauses->num_threads_list; el; el = el->next)
   10871         1016 :     resolve_positive_int_expr (el->expr, "NUM_THREADS");
   10872              : 
   10873        33132 :   if (omp_clauses->dyn_groupprivate)
   10874           10 :     resolve_nonnegative_int_expr (omp_clauses->dyn_groupprivate,
   10875              :                                   "DYN_GROUPPRIVATE");
   10876        33132 :   if (omp_clauses->chunk_size)
   10877              :     {
   10878          510 :       gfc_expr *expr = omp_clauses->chunk_size;
   10879          510 :       if (!gfc_resolve_expr (expr)
   10880          510 :           || expr->ts.type != BT_INTEGER || expr->rank != 0)
   10881            0 :         gfc_error ("SCHEDULE clause's chunk_size at %L requires "
   10882              :                    "a scalar INTEGER expression", &expr->where);
   10883          510 :       else if (expr->expr_type == EXPR_CONSTANT
   10884              :                && expr->ts.type == BT_INTEGER
   10885          485 :                && mpz_sgn (expr->value.integer) <= 0)
   10886            2 :         gfc_warning (OPT_Wopenmp, "INTEGER expression of SCHEDULE clause's "
   10887              :                      "chunk_size at %L must be positive", &expr->where);
   10888              :     }
   10889        33132 :   if (omp_clauses->sched_kind != OMP_SCHED_NONE
   10890          891 :       && omp_clauses->sched_nonmonotonic)
   10891              :     {
   10892           34 :       if (omp_clauses->sched_monotonic)
   10893            2 :         gfc_error ("Both MONOTONIC and NONMONOTONIC schedule modifiers "
   10894              :                    "specified at %L", &code->loc);
   10895           32 :       else if (omp_clauses->ordered)
   10896            4 :         gfc_error ("NONMONOTONIC schedule modifier specified with ORDERED "
   10897              :                    "clause at %L", &code->loc);
   10898              :     }
   10899              : 
   10900        33132 :   if (omp_clauses->depobj
   10901        33132 :       && (!gfc_resolve_expr (omp_clauses->depobj)
   10902          118 :           || omp_clauses->depobj->ts.type != BT_INTEGER
   10903          117 :           || omp_clauses->depobj->ts.kind != 2 * gfc_index_integer_kind
   10904          116 :           || omp_clauses->depobj->rank != 0))
   10905            4 :     gfc_error ("DEPOBJ in DEPOBJ construct at %L shall be a scalar integer "
   10906            4 :                "of OMP_DEPEND_KIND kind", &omp_clauses->depobj->where);
   10907              : 
   10908              :   /* Check that list items are variables.  */
   10909      1325280 :   for (list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
   10910      1292148 :        list = gfc_omp_list_type (list + 1))
   10911      1338028 :     for (n = omp_clauses->lists[list]; n; n = n->next)
   10912              :       {
   10913        45880 :         if (!n->sym)  /* omp_all_memory.  */
   10914           47 :           continue;
   10915        45833 :         if (n->sym->attr.flavor == FL_VARIABLE
   10916          277 :             || n->sym->attr.proc_pointer
   10917          236 :             || (!code
   10918            0 :                 && !ns->omp_udm_ns
   10919            0 :                 && (!n->sym->attr.dummy || n->sym->ns != ns)))
   10920              :           {
   10921        45597 :             if (!code
   10922          322 :                 && !ns->omp_udm_ns
   10923          277 :                 && (!n->sym->attr.dummy || n->sym->ns != ns))
   10924            0 :               gfc_error ("Variable %qs is not a dummy argument at %L",
   10925              :                          n->sym->name, &n->where);
   10926        45597 :             continue;
   10927              :           }
   10928          236 :         if (n->sym->attr.flavor == FL_PROCEDURE
   10929          153 :             && n->sym->result == n->sym
   10930          138 :             && n->sym->attr.function)
   10931              :           {
   10932          138 :             if (ns->proc_name == n->sym
   10933           44 :                 || (ns->parent && ns->parent->proc_name == n->sym))
   10934          101 :               continue;
   10935           37 :             if (ns->proc_name->attr.entry_master)
   10936              :               {
   10937           32 :                 gfc_entry_list *el = ns->entries;
   10938           51 :                 for (; el; el = el->next)
   10939           51 :                   if (el->sym == n->sym)
   10940              :                     break;
   10941           32 :                 if (el)
   10942           32 :                   continue;
   10943              :               }
   10944            5 :             if (ns->parent
   10945            3 :                 && ns->parent->proc_name->attr.entry_master)
   10946              :               {
   10947            2 :                 gfc_entry_list *el = ns->parent->entries;
   10948            3 :                 for (; el; el = el->next)
   10949            3 :                   if (el->sym == n->sym)
   10950              :                     break;
   10951            2 :                 if (el)
   10952            2 :                   continue;
   10953              :               }
   10954              :           }
   10955          101 :         if (list == OMP_LIST_MAP
   10956           18 :             && n->sym->attr.flavor == FL_PARAMETER)
   10957              :           {
   10958              :             /* OpenACC since 3.4 permits for Fortran named constants, but
   10959              :                permits removing then as optimization is not needed and such
   10960              :                ignore them. Likewise below for FIRSTPRIVATE.  */
   10961           12 :             if (openacc)
   10962           10 :               gfc_warning (OPT_Wsurprising, "Clause for object %qs at %L is "
   10963              :                            "ignored as parameters need not be copied",
   10964              :                            n->sym->name, &n->where);
   10965              :             else
   10966            2 :               gfc_error ("Object %qs is not a variable at %L; parameters"
   10967              :                          " cannot be and need not be mapped", n->sym->name,
   10968              :                          &n->where);
   10969              :           }
   10970           89 :         else if (openacc && n->sym->attr.flavor == FL_PARAMETER)
   10971            9 :           gfc_warning (OPT_Wsurprising, "Clause for object %qs at %L is ignored"
   10972              :                        " as it is a parameter", n->sym->name, &n->where);
   10973           80 :         else if (list != OMP_LIST_USES_ALLOCATORS)
   10974           30 :           gfc_error ("Object %qs is not a variable at %L", n->sym->name,
   10975              :                      &n->where);
   10976              :       }
   10977              : 
   10978        33132 :   if (omp_clauses->lists[OMP_LIST_REDUCTION_INSCAN])
   10979              :     {
   10980           69 :       locus *loc = &omp_clauses->lists[OMP_LIST_REDUCTION_INSCAN]->where;
   10981           69 :       if (code->op != EXEC_OMP_DO
   10982              :           && code->op != EXEC_OMP_SIMD
   10983              :           && code->op != EXEC_OMP_DO_SIMD
   10984              :           && code->op != EXEC_OMP_PARALLEL_DO
   10985              :           && code->op != EXEC_OMP_PARALLEL_DO_SIMD)
   10986           23 :         gfc_error ("%<inscan%> REDUCTION clause on construct other than DO, "
   10987              :                    "SIMD, DO SIMD, PARALLEL DO, PARALLEL DO SIMD at %L",
   10988              :                    loc);
   10989           69 :       if (omp_clauses->ordered)
   10990            2 :         gfc_error ("ORDERED clause specified together with %<inscan%> "
   10991              :                    "REDUCTION clause at %L", loc);
   10992           69 :       if (omp_clauses->sched_kind != OMP_SCHED_NONE)
   10993            3 :         gfc_error ("SCHEDULE clause specified together with %<inscan%> "
   10994              :                    "REDUCTION clause at %L", loc);
   10995              :     }
   10996              : 
   10997        33132 :   if (code
   10998        32873 :       && code->op == EXEC_OMP_INTEROP
   10999           63 :       && omp_clauses->lists[OMP_LIST_DEPEND])
   11000              :     {
   11001           12 :       if (!omp_clauses->lists[OMP_LIST_INIT]
   11002            5 :           && !omp_clauses->lists[OMP_LIST_USE]
   11003            1 :           && !omp_clauses->lists[OMP_LIST_DESTROY])
   11004              :         {
   11005            1 :           gfc_error ("DEPEND clause at %L requires action clause with "
   11006              :                      "%<targetsync%> interop-type",
   11007              :                      &omp_clauses->lists[OMP_LIST_DEPEND]->where);
   11008              :         }
   11009           22 :       for (n = omp_clauses->lists[OMP_LIST_INIT]; n; n = n->next)
   11010           12 :         if (!n->u.init.targetsync)
   11011              :           {
   11012            2 :             gfc_error ("DEPEND clause at %L requires %<targetsync%> "
   11013              :                        "interop-type, lacking it for %qs at %L",
   11014            2 :                        &omp_clauses->lists[OMP_LIST_DEPEND]->where,
   11015            2 :                        n->sym->name, &n->where);
   11016            2 :             break;
   11017              :           }
   11018              :     }
   11019        32873 :   if (code && (code->op == EXEC_OMP_INTEROP || code->op == EXEC_OMP_DISPATCH))
   11020         1085 :     for (list = OMP_LIST_INIT; list <= OMP_LIST_INTEROP;
   11021          868 :          list = gfc_omp_list_type (list + 1))
   11022         1123 :       for (n = omp_clauses->lists[list]; n; n = n->next)
   11023              :         {
   11024          255 :           if (n->sym->ts.type != BT_INTEGER
   11025          252 :               || n->sym->ts.kind != gfc_index_integer_kind
   11026          248 :               || n->sym->attr.dimension
   11027          243 :               || n->sym->attr.flavor != FL_VARIABLE)
   11028           16 :             gfc_error ("%qs at %L in %qs clause must be a scalar integer "
   11029              :                        "variable of %<omp_interop_kind%> kind", n->sym->name,
   11030              :                        &n->where, clause_names[list]);
   11031          255 :           if (list != OMP_LIST_USE && list != OMP_LIST_INTEROP
   11032          109 :               && n->sym->attr.intent == INTENT_IN)
   11033            2 :             gfc_error ("%qs at %L in %qs clause must be definable",
   11034              :                        n->sym->name, &n->where, clause_names[list]);
   11035              :         }
   11036              : 
   11037        33132 :   resolve_omp_allocate_clauses (code, omp_clauses, ns);
   11038              : 
   11039        33132 :   bool has_inscan = false, has_notinscan = false;
   11040      1358412 :   for (enum gfc_omp_list_type list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
   11041      1292148 :        list = gfc_omp_list_type (list + 1))
   11042      1292148 :     if ((n = omp_clauses->lists[list]) != NULL)
   11043              :       {
   11044        29338 :         const char *name = clause_names[list];
   11045              : 
   11046        29338 :         switch (list)
   11047              :           {
   11048              :           case OMP_LIST_COPYIN:
   11049          267 :             for (; n != NULL; n = n->next)
   11050              :               {
   11051          170 :                 if (!n->sym->attr.threadprivate)
   11052            0 :                   gfc_error ("Non-THREADPRIVATE object %qs in COPYIN clause"
   11053              :                              " at %L", n->sym->name, &n->where);
   11054              :               }
   11055              :             break;
   11056           83 :           case OMP_LIST_COPYPRIVATE:
   11057           83 :             if (omp_clauses->nowait)
   11058            6 :               gfc_error ("NOWAIT clause must not be used with COPYPRIVATE "
   11059              :                          "clause at %L", &n->where);
   11060          376 :             for (; n != NULL; n = n->next)
   11061              :               {
   11062          293 :                 if (n->sym->as && n->sym->as->type == AS_ASSUMED_SIZE)
   11063            0 :                   gfc_error ("Assumed size array %qs in COPYPRIVATE clause "
   11064              :                              "at %L", n->sym->name, &n->where);
   11065          293 :                 if (n->sym->attr.pointer && n->sym->attr.intent == INTENT_IN)
   11066            1 :                   gfc_error ("INTENT(IN) POINTER %qs in COPYPRIVATE clause "
   11067              :                              "at %L", n->sym->name, &n->where);
   11068              :               }
   11069              :             break;
   11070              :           case OMP_LIST_SHARED:
   11071         2604 :             for (; n != NULL; n = n->next)
   11072              :               {
   11073         1642 :                 if (n->sym->attr.threadprivate)
   11074            0 :                   gfc_error ("THREADPRIVATE object %qs in SHARED clause at "
   11075              :                              "%L", n->sym->name, &n->where);
   11076         1642 :                 if (n->sym->attr.cray_pointee)
   11077            1 :                   gfc_error ("Cray pointee %qs in SHARED clause at %L",
   11078              :                             n->sym->name, &n->where);
   11079         1642 :                 if (n->sym->attr.associate_var)
   11080            8 :                   gfc_error ("Associate name %qs in SHARED clause at %L",
   11081            8 :                              n->sym->attr.select_type_temporary
   11082            4 :                              ? n->sym->assoc->target->symtree->n.sym->name
   11083              :                              : n->sym->name, &n->where);
   11084         1642 :                 if (omp_clauses->detach
   11085            1 :                     && n->sym == omp_clauses->detach->symtree->n.sym)
   11086            1 :                   gfc_error ("DETACH event handle %qs in SHARED clause at %L",
   11087              :                              n->sym->name, &n->where);
   11088              :               }
   11089              :             break;
   11090              :           case OMP_LIST_ALIGNED:
   11091          256 :             for (; n != NULL; n = n->next)
   11092              :               {
   11093          150 :                 if (!n->sym->attr.pointer
   11094           45 :                     && !n->sym->attr.allocatable
   11095           30 :                     && !n->sym->attr.cray_pointer
   11096           18 :                     && (n->sym->ts.type != BT_DERIVED
   11097           18 :                         || (n->sym->ts.u.derived->from_intmod
   11098              :                             != INTMOD_ISO_C_BINDING)
   11099           18 :                         || (n->sym->ts.u.derived->intmod_sym_id
   11100              :                             != ISOCBINDING_PTR)))
   11101            0 :                   gfc_error ("%qs in ALIGNED clause must be POINTER, "
   11102              :                              "ALLOCATABLE, Cray pointer or C_PTR at %L",
   11103              :                              n->sym->name, &n->where);
   11104          150 :                 else if (n->expr)
   11105              :                   {
   11106          147 :                     if (!gfc_resolve_expr (n->expr)
   11107          147 :                         || n->expr->ts.type != BT_INTEGER
   11108          146 :                         || n->expr->rank != 0
   11109          146 :                         || n->expr->expr_type != EXPR_CONSTANT
   11110          292 :                         || mpz_sgn (n->expr->value.integer) <= 0)
   11111            4 :                       gfc_error ("%qs in ALIGNED clause at %L requires a scalar"
   11112              :                                  " positive constant integer alignment "
   11113            4 :                                  "expression", n->sym->name, &n->where);
   11114              :                   }
   11115              :               }
   11116              :             break;
   11117              :           case OMP_LIST_AFFINITY:
   11118              :           case OMP_LIST_DEPEND:
   11119              :           case OMP_LIST_MAP:
   11120              :           case OMP_LIST_TO:
   11121              :           case OMP_LIST_FROM:
   11122              :           case OMP_LIST_CACHE:
   11123        33236 :             for (; n != NULL; n = n->next)
   11124        20963 :               resolve_omp_clauses_aff_dep_map_cache (code, n, name, list,
   11125              :                                                      omp_clauses, openacc);
   11126              :             break;
   11127              :           case OMP_LIST_IS_DEVICE_PTR:
   11128              :             last = NULL;
   11129          377 :             for (n = omp_clauses->lists[list]; n != NULL; )
   11130              :               {
   11131          257 :                 if ((n->sym->ts.type != BT_DERIVED
   11132           71 :                      || !n->sym->ts.u.derived->ts.is_iso_c
   11133           71 :                      || (n->sym->ts.u.derived->intmod_sym_id
   11134              :                          != ISOCBINDING_PTR))
   11135          187 :                     && code->op == EXEC_OMP_DISPATCH)
   11136              :                   /* Non-TARGET (i.e. DISPATCH) requires a C_PTR.  */
   11137            3 :                   gfc_error ("List item %qs in %s clause at %L must be of "
   11138              :                              "TYPE(C_PTR)", n->sym->name, name, &n->where);
   11139          254 :                 else if (n->sym->ts.type != BT_DERIVED
   11140           70 :                          || !n->sym->ts.u.derived->ts.is_iso_c
   11141           70 :                          || (n->sym->ts.u.derived->intmod_sym_id
   11142              :                              != ISOCBINDING_PTR))
   11143              :                   {
   11144              :                     /* For TARGET, non-C_PTR are deprecated and handled as
   11145              :                        has_device_addr.  */
   11146          184 :                     gfc_warning (OPT_Wdeprecated_openmp,
   11147              :                                  "Non-C_PTR type argument at %L is deprecated, "
   11148              :                                  "use HAS_DEVICE_ADDR", &n->where);
   11149          184 :                     gfc_omp_namelist *n2 = n;
   11150          184 :                     n = n->next;
   11151          184 :                     if (last)
   11152            0 :                       last->next = n;
   11153              :                     else
   11154          184 :                       omp_clauses->lists[list] = n;
   11155          184 :                     n2->next = omp_clauses->lists[OMP_LIST_HAS_DEVICE_ADDR];
   11156          184 :                     omp_clauses->lists[OMP_LIST_HAS_DEVICE_ADDR] = n2;
   11157          184 :                     continue;
   11158          184 :                   }
   11159           73 :                 last = n;
   11160           73 :                 n = n->next;
   11161              :               }
   11162              :             break;
   11163              :           case OMP_LIST_HAS_DEVICE_ADDR:
   11164              :           case OMP_LIST_USE_DEVICE_ADDR:
   11165              :             break;
   11166              :           case OMP_LIST_USE_DEVICE_PTR:
   11167              :             /* Non-C_PTR are deprecated and handled as use_device_ADDR.  */
   11168              :             last = NULL;
   11169          475 :             for (n = omp_clauses->lists[list]; n != NULL; )
   11170              :               {
   11171          312 :                 gfc_omp_namelist *n2 = n;
   11172          312 :                 if (n->sym->ts.type != BT_DERIVED
   11173           18 :                     || !n->sym->ts.u.derived->ts.is_iso_c)
   11174              :                   {
   11175          294 :                     gfc_warning (OPT_Wdeprecated_openmp,
   11176              :                                  "Non-C_PTR type argument at %L is "
   11177              :                                  "deprecated, use USE_DEVICE_ADDR", &n->where);
   11178          294 :                     n = n->next;
   11179          294 :                     if (last)
   11180            0 :                       last->next = n;
   11181              :                     else
   11182          294 :                       omp_clauses->lists[list] = n;
   11183          294 :                     n2->next = omp_clauses->lists[OMP_LIST_USE_DEVICE_ADDR];
   11184          294 :                     omp_clauses->lists[OMP_LIST_USE_DEVICE_ADDR] = n2;
   11185          294 :                     continue;
   11186              :                   }
   11187           18 :                 last = n;
   11188           18 :                 n = n->next;
   11189              :               }
   11190              :             break;
   11191           65 :           case OMP_LIST_USES_ALLOCATORS:
   11192           65 :             {
   11193           65 :               if (n != NULL
   11194           65 :                   && n->u.memspace_sym
   11195           20 :                   && (n->u.memspace_sym->attr.flavor != FL_PARAMETER
   11196           18 :                       || n->u.memspace_sym->ts.type != BT_INTEGER
   11197           18 :                       || n->u.memspace_sym->ts.kind != gfc_c_intptr_kind
   11198           18 :                       || n->u.memspace_sym->attr.dimension
   11199           18 :                       || (!startswith (n->u.memspace_sym->name, "omp_")
   11200            0 :                           && !startswith (n->u.memspace_sym->name, "ompx_"))
   11201           18 :                       || !endswith (n->u.memspace_sym->name, "_mem_space")))
   11202            3 :                 gfc_error ("Memspace %qs at %L in USES_ALLOCATORS must be "
   11203              :                            "a predefined memory space",
   11204              :                            n->u.memspace_sym->name, &n->where);
   11205          180 :               for (; n != NULL; n = n->next)
   11206              :                 {
   11207          122 :                   if (n->sym->ts.type != BT_INTEGER
   11208          121 :                       || n->sym->ts.kind != gfc_c_intptr_kind
   11209          120 :                       || n->sym->attr.dimension)
   11210            3 :                     gfc_error ("Allocator %qs at %L in USES_ALLOCATORS must "
   11211              :                                "be a scalar integer of kind "
   11212              :                                "%<omp_allocator_handle_kind%>", n->sym->name,
   11213              :                                &n->where);
   11214          119 :                   else if (n->sym->attr.flavor != FL_VARIABLE
   11215           50 :                            && strcmp (n->sym->name, "omp_null_allocator") != 0
   11216          165 :                            && ((!startswith (n->sym->name, "omp_")
   11217            1 :                                 && !startswith (n->sym->name, "ompx_"))
   11218           45 :                                || !endswith (n->sym->name, "_mem_alloc")))
   11219            2 :                     gfc_error ("Allocator %qs at %L in USES_ALLOCATORS must "
   11220              :                                "either a variable or a predefined allocator",
   11221              :                                n->sym->name, &n->where);
   11222          117 :                   else if ((n->u.memspace_sym || n->u2.traits_sym)
   11223           61 :                            && n->sym->attr.flavor != FL_VARIABLE)
   11224            3 :                     gfc_error ("A memory space or traits array may not be "
   11225              :                                "specified for predefined allocator %qs at %L",
   11226              :                                n->sym->name, &n->where);
   11227          122 :                   if (n->u2.traits_sym
   11228           50 :                       && (n->u2.traits_sym->attr.flavor != FL_PARAMETER
   11229           47 :                           || !n->u2.traits_sym->attr.dimension
   11230           45 :                           || n->u2.traits_sym->as->rank != 1
   11231           45 :                           || n->u2.traits_sym->ts.type != BT_DERIVED
   11232           43 :                           || strcmp (n->u2.traits_sym->ts.u.derived->name,
   11233              :                                      "omp_alloctrait") != 0))
   11234              :                     {
   11235            7 :                       gfc_error ("Traits array %qs in USES_ALLOCATORS %L must "
   11236              :                                  "be a one-dimensional named constant array of "
   11237              :                                  "type %<omp_alloctrait%>",
   11238              :                                  n->u2.traits_sym->name, &n->where);
   11239            7 :                       break;
   11240              :                     }
   11241              :                 }
   11242              :               break;
   11243              :             }
   11244              :           default:
   11245        34818 :             for (; n != NULL; n = n->next)
   11246              :               {
   11247        20404 :                 if (n->sym == NULL)
   11248              :                   {
   11249           26 :                     gcc_assert (code->op == EXEC_OMP_ALLOCATORS
   11250              :                                 || code->op == EXEC_OMP_ALLOCATE);
   11251           26 :                     continue;
   11252              :                   }
   11253        20378 :                 bool bad = false;
   11254        20378 :                 bool is_reduction = (list == OMP_LIST_REDUCTION
   11255              :                                      || list == OMP_LIST_REDUCTION_INSCAN
   11256              :                                      || list == OMP_LIST_REDUCTION_TASK
   11257              :                                      || list == OMP_LIST_IN_REDUCTION
   11258        20378 :                                      || list == OMP_LIST_TASK_REDUCTION);
   11259        20378 :                 if (list == OMP_LIST_REDUCTION_INSCAN)
   11260              :                   has_inscan = true;
   11261        20306 :                 else if (is_reduction)
   11262         4738 :                   has_notinscan = true;
   11263        20378 :                 if (has_inscan && has_notinscan && is_reduction)
   11264              :                   {
   11265            3 :                     gfc_error ("%<inscan%> and non-%<inscan%> %<reduction%> "
   11266              :                                "clauses on the same construct at %L",
   11267              :                                &n->where);
   11268            3 :                     break;
   11269              :                   }
   11270        20375 :                 if (n->sym->attr.threadprivate)
   11271            1 :                   gfc_error ("THREADPRIVATE object %qs in %s clause at %L",
   11272              :                              n->sym->name, name, &n->where);
   11273        20375 :                 if (n->sym->attr.cray_pointee)
   11274           14 :                   gfc_error ("Cray pointee %qs in %s clause at %L",
   11275              :                             n->sym->name, name, &n->where);
   11276        20375 :                 if (n->sym->attr.associate_var)
   11277           22 :                   gfc_error ("Associate name %qs in %s clause at %L",
   11278           22 :                              n->sym->attr.select_type_temporary
   11279            4 :                              ? n->sym->assoc->target->symtree->n.sym->name
   11280              :                              : n->sym->name, name, &n->where);
   11281        20375 :                 if (list != OMP_LIST_PRIVATE && is_reduction)
   11282              :                   {
   11283         4807 :                     if (n->sym->attr.proc_pointer)
   11284            1 :                       gfc_error ("Procedure pointer %qs in %s clause at %L",
   11285              :                                  n->sym->name, name, &n->where);
   11286         4807 :                     if (n->sym->attr.pointer)
   11287            3 :                       gfc_error ("POINTER object %qs in %s clause at %L",
   11288              :                                  n->sym->name, name, &n->where);
   11289         4807 :                     if (n->sym->attr.cray_pointer)
   11290            5 :                       gfc_error ("Cray pointer %qs in %s clause at %L",
   11291              :                                  n->sym->name, name, &n->where);
   11292              :                   }
   11293        20375 :                 if (code
   11294        20375 :                     && (oacc_is_loop (code)
   11295              :                         || code->op == EXEC_OACC_PARALLEL
   11296              :                         || code->op == EXEC_OACC_SERIAL))
   11297         8741 :                   check_array_not_assumed (n->sym, n->where, name);
   11298        11634 :                 else if (list != OMP_LIST_UNIFORM
   11299        11517 :                          && n->sym->as && n->sym->as->type == AS_ASSUMED_SIZE)
   11300            2 :                   gfc_error ("Assumed size array %qs in %s clause at %L",
   11301              :                              n->sym->name, name, &n->where);
   11302        20375 :                 if (n->sym->attr.in_namelist && !is_reduction)
   11303            0 :                   gfc_error ("Variable %qs in %s clause is used in "
   11304              :                              "NAMELIST statement at %L",
   11305              :                              n->sym->name, name, &n->where);
   11306        20375 :                 if (n->sym->attr.pointer && n->sym->attr.intent == INTENT_IN)
   11307            3 :                   switch (list)
   11308              :                     {
   11309            3 :                     case OMP_LIST_PRIVATE:
   11310            3 :                     case OMP_LIST_LASTPRIVATE:
   11311            3 :                     case OMP_LIST_LINEAR:
   11312              :                     /* case OMP_LIST_REDUCTION: */
   11313            3 :                       gfc_error ("INTENT(IN) POINTER %qs in %s clause at %L",
   11314              :                                  n->sym->name, name, &n->where);
   11315            3 :                       break;
   11316              :                     default:
   11317              :                       break;
   11318              :                     }
   11319        20375 :                 if (omp_clauses->detach
   11320            3 :                     && (list == OMP_LIST_PRIVATE
   11321              :                         || list == OMP_LIST_FIRSTPRIVATE
   11322              :                         || list == OMP_LIST_LASTPRIVATE)
   11323            3 :                     && n->sym == omp_clauses->detach->symtree->n.sym)
   11324            1 :                   gfc_error ("DETACH event handle %qs in %s clause at %L",
   11325              :                              n->sym->name, name, &n->where);
   11326              : 
   11327        20375 :                 if (!openacc
   11328        20375 :                     && (list == OMP_LIST_PRIVATE
   11329        20375 :                         || list == OMP_LIST_FIRSTPRIVATE)
   11330         4714 :                     && ((n->sym->ts.type == BT_DERIVED
   11331          158 :                          && n->sym->ts.u.derived->attr.alloc_comp)
   11332         4604 :                         || n->sym->ts.type == BT_CLASS))
   11333          170 :                   switch (code->op)
   11334              :                     {
   11335            8 :                     case EXEC_OMP_TARGET:
   11336            8 :                     case EXEC_OMP_TARGET_PARALLEL:
   11337            8 :                     case EXEC_OMP_TARGET_PARALLEL_DO:
   11338            8 :                     case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
   11339            8 :                     case EXEC_OMP_TARGET_PARALLEL_LOOP:
   11340            8 :                     case EXEC_OMP_TARGET_SIMD:
   11341            8 :                     case EXEC_OMP_TARGET_TEAMS:
   11342            8 :                     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
   11343            8 :                     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
   11344            8 :                     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
   11345            8 :                     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
   11346            8 :                     case EXEC_OMP_TARGET_TEAMS_LOOP:
   11347            8 :                       if (n->sym->ts.type == BT_DERIVED
   11348            2 :                           && n->sym->ts.u.derived->attr.alloc_comp)
   11349            3 :                         gfc_error ("Sorry, list item %qs at %L with allocatable"
   11350              :                                    " components is not yet supported in %s "
   11351              :                                    "clause", n->sym->name, &n->where,
   11352              :                                    list == OMP_LIST_PRIVATE ? "PRIVATE"
   11353              :                                                             : "FIRSTPRIVATE");
   11354              :                       else
   11355            9 :                         gfc_error ("Polymorphic list item %qs at %L in %s "
   11356              :                                    "clause has unspecified behavior and "
   11357              :                                    "unsupported", n->sym->name, &n->where,
   11358              :                                    list == OMP_LIST_PRIVATE ? "PRIVATE"
   11359              :                                                             : "FIRSTPRIVATE");
   11360              :                       break;
   11361              :                     default:
   11362              :                       break;
   11363              :                     }
   11364              : 
   11365        20375 :                 switch (list)
   11366              :                   {
   11367          104 :                   case OMP_LIST_REDUCTION_TASK:
   11368          104 :                     if (code
   11369          104 :                         && (code->op == EXEC_OMP_LOOP
   11370              :                             || code->op == EXEC_OMP_TASKLOOP
   11371              :                             || code->op == EXEC_OMP_TASKLOOP_SIMD
   11372              :                             || code->op == EXEC_OMP_MASKED_TASKLOOP
   11373              :                             || code->op == EXEC_OMP_MASKED_TASKLOOP_SIMD
   11374              :                             || code->op == EXEC_OMP_MASTER_TASKLOOP
   11375              :                             || code->op == EXEC_OMP_MASTER_TASKLOOP_SIMD
   11376              :                             || code->op == EXEC_OMP_PARALLEL_LOOP
   11377              :                             || code->op == EXEC_OMP_PARALLEL_MASKED_TASKLOOP
   11378              :                             || code->op == EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD
   11379              :                             || code->op == EXEC_OMP_PARALLEL_MASTER_TASKLOOP
   11380              :                             || code->op == EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD
   11381              :                             || code->op == EXEC_OMP_TARGET_PARALLEL_LOOP
   11382              :                             || code->op == EXEC_OMP_TARGET_TEAMS_LOOP
   11383              :                             || code->op == EXEC_OMP_TEAMS
   11384              :                             || code->op == EXEC_OMP_TEAMS_DISTRIBUTE
   11385              :                             || code->op == EXEC_OMP_TEAMS_LOOP))
   11386              :                       {
   11387           17 :                         gfc_error ("Only DEFAULT permitted as reduction-"
   11388              :                                    "modifier in REDUCTION clause at %L",
   11389              :                                    &n->where);
   11390           17 :                         break;
   11391              :                       }
   11392         4790 :                     gcc_fallthrough ();
   11393         4790 :                   case OMP_LIST_REDUCTION:
   11394         4790 :                   case OMP_LIST_IN_REDUCTION:
   11395         4790 :                   case OMP_LIST_TASK_REDUCTION:
   11396         4790 :                   case OMP_LIST_REDUCTION_INSCAN:
   11397         4790 :                     switch (n->u.reduction_op)
   11398              :                       {
   11399         2655 :                       case OMP_REDUCTION_PLUS:
   11400         2655 :                       case OMP_REDUCTION_TIMES:
   11401         2655 :                       case OMP_REDUCTION_MINUS:
   11402         2655 :                         if (!gfc_numeric_ts (&n->sym->ts))
   11403              :                           bad = true;
   11404              :                         break;
   11405         1112 :                       case OMP_REDUCTION_AND:
   11406         1112 :                       case OMP_REDUCTION_OR:
   11407         1112 :                       case OMP_REDUCTION_EQV:
   11408         1112 :                       case OMP_REDUCTION_NEQV:
   11409         1112 :                         if (n->sym->ts.type != BT_LOGICAL)
   11410              :                           bad = true;
   11411              :                         break;
   11412          480 :                       case OMP_REDUCTION_MAX:
   11413          480 :                       case OMP_REDUCTION_MIN:
   11414          480 :                         if (n->sym->ts.type != BT_INTEGER
   11415          212 :                             && n->sym->ts.type != BT_REAL)
   11416              :                           bad = true;
   11417              :                         break;
   11418          192 :                       case OMP_REDUCTION_IAND:
   11419          192 :                       case OMP_REDUCTION_IOR:
   11420          192 :                       case OMP_REDUCTION_IEOR:
   11421          192 :                         if (n->sym->ts.type != BT_INTEGER)
   11422              :                           bad = true;
   11423              :                         break;
   11424              :                       case OMP_REDUCTION_USER:
   11425              :                         bad = true;
   11426              :                         break;
   11427              :                       default:
   11428              :                         break;
   11429              :                       }
   11430              :                     if (!bad)
   11431         4215 :                       n->u2.udr = NULL;
   11432              :                     else
   11433              :                       {
   11434          575 :                         const char *udr_name = NULL;
   11435          575 :                         if (n->u2.udr)
   11436              :                           {
   11437          471 :                             udr_name = n->u2.udr->udr->name;
   11438          471 :                             n->u2.udr->udr
   11439          942 :                               = gfc_find_omp_udr (NULL, udr_name,
   11440          471 :                                                   &n->sym->ts);
   11441          471 :                             if (n->u2.udr->udr == NULL)
   11442              :                               {
   11443            0 :                                 free (n->u2.udr);
   11444            0 :                                 n->u2.udr = NULL;
   11445              :                               }
   11446              :                           }
   11447          575 :                         if (n->u2.udr == NULL)
   11448              :                           {
   11449          104 :                             if (udr_name == NULL)
   11450          104 :                               switch (n->u.reduction_op)
   11451              :                                 {
   11452           50 :                                 case OMP_REDUCTION_PLUS:
   11453           50 :                                 case OMP_REDUCTION_TIMES:
   11454           50 :                                 case OMP_REDUCTION_MINUS:
   11455           50 :                                 case OMP_REDUCTION_AND:
   11456           50 :                                 case OMP_REDUCTION_OR:
   11457           50 :                                 case OMP_REDUCTION_EQV:
   11458           50 :                                 case OMP_REDUCTION_NEQV:
   11459           50 :                                   udr_name = gfc_op2string ((gfc_intrinsic_op)
   11460              :                                                             n->u.reduction_op);
   11461           50 :                                   break;
   11462              :                                 case OMP_REDUCTION_MAX:
   11463              :                                   udr_name = "max";
   11464              :                                   break;
   11465            9 :                                 case OMP_REDUCTION_MIN:
   11466            9 :                                   udr_name = "min";
   11467            9 :                                   break;
   11468           12 :                                 case OMP_REDUCTION_IAND:
   11469           12 :                                   udr_name = "iand";
   11470           12 :                                   break;
   11471           12 :                                 case OMP_REDUCTION_IOR:
   11472           12 :                                   udr_name = "ior";
   11473           12 :                                   break;
   11474            9 :                                 case OMP_REDUCTION_IEOR:
   11475            9 :                                   udr_name = "ieor";
   11476            9 :                                   break;
   11477            0 :                                 default:
   11478            0 :                                   gcc_unreachable ();
   11479              :                                 }
   11480          104 :                             gfc_error ("!$OMP DECLARE REDUCTION %s not found "
   11481              :                                        "for type %s at %L", udr_name,
   11482          104 :                                        gfc_typename (&n->sym->ts), &n->where);
   11483              :                           }
   11484              :                         else
   11485              :                           {
   11486          471 :                             gfc_omp_udr *udr = n->u2.udr->udr;
   11487          471 :                             n->u.reduction_op = OMP_REDUCTION_USER;
   11488          471 :                             n->u2.udr->combiner
   11489          942 :                               = resolve_omp_udr_clause (n, udr->combiner_ns,
   11490          471 :                                                         udr->omp_out,
   11491          471 :                                                         udr->omp_in);
   11492          471 :                             if (udr->initializer_ns)
   11493          331 :                               n->u2.udr->initializer
   11494          331 :                                 = resolve_omp_udr_clause (n,
   11495              :                                                           udr->initializer_ns,
   11496          331 :                                                           udr->omp_priv,
   11497          331 :                                                           udr->omp_orig);
   11498              :                           }
   11499              :                       }
   11500              :                     break;
   11501          887 :                   case OMP_LIST_LINEAR:
   11502          887 :                     if (code)
   11503              :                       {
   11504          727 :                         bool is_worksharing_for = false;
   11505          727 :                         switch (code->op)
   11506              :                           {
   11507           54 :                           case EXEC_OMP_DO:
   11508           54 :                           case EXEC_OMP_PARALLEL_DO:
   11509           54 :                           case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
   11510           54 :                           case EXEC_OMP_TARGET_PARALLEL_DO:
   11511           54 :                           case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
   11512           54 :                           case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
   11513           54 :                             is_worksharing_for = true;
   11514           54 :                             break;
   11515              :                           default:
   11516              :                             break;
   11517              :                           }
   11518              : 
   11519           54 :                         if (is_worksharing_for
   11520           54 :                             && (n->sym->attr.dimension
   11521           53 :                                 || n->sym->attr.allocatable))
   11522              :                           {
   11523            1 :                             if (n->sym->attr.allocatable)
   11524            0 :                               gfc_error ("Sorry, ALLOCATABLE object %qs in "
   11525              :                                          "LINEAR clause on worksharing-loop "
   11526              :                                          "construct at %L is not yet supported",
   11527              :                                          n->sym->name, &n->where);
   11528              :                             else
   11529            1 :                               gfc_error ("Sorry, array %qs in LINEAR clause "
   11530              :                                          "on worksharing-loop construct at %L "
   11531              :                                          "is not yet supported",
   11532              :                                          n->sym->name, &n->where);
   11533              :                             break;
   11534              :                           }
   11535              :                       }
   11536              : 
   11537          726 :                     if (code
   11538          726 :                         && n->u.linear.op != OMP_LINEAR_DEFAULT
   11539           23 :                         && n->u.linear.op != linear_op)
   11540              :                       {
   11541           23 :                         if (n->u.linear.old_modifier)
   11542              :                           {
   11543            9 :                             gfc_error ("LINEAR clause modifier used on DO or "
   11544              :                                        "SIMD construct at %L", &n->where);
   11545            9 :                             linear_op = n->u.linear.op;
   11546              :                           }
   11547           14 :                         else if (n->u.linear.op != OMP_LINEAR_VAL)
   11548              :                           {
   11549            6 :                             gfc_error ("LINEAR clause modifier other than VAL "
   11550              :                                        "used on DO or SIMD construct at %L",
   11551              :                                        &n->where);
   11552            6 :                             linear_op = n->u.linear.op;
   11553              :                           }
   11554              :                       }
   11555          863 :                     else if (n->u.linear.op != OMP_LINEAR_REF
   11556          813 :                              && n->sym->ts.type != BT_INTEGER)
   11557            1 :                       gfc_error ("LINEAR variable %qs must be INTEGER "
   11558              :                                  "at %L", n->sym->name, &n->where);
   11559          862 :                     else if ((n->u.linear.op == OMP_LINEAR_REF
   11560          812 :                               || n->u.linear.op == OMP_LINEAR_UVAL)
   11561           61 :                              && n->sym->attr.value)
   11562            0 :                       gfc_error ("LINEAR dummy argument %qs with VALUE "
   11563              :                                  "attribute with %s modifier at %L",
   11564              :                                  n->sym->name,
   11565              :                                  n->u.linear.op == OMP_LINEAR_REF
   11566              :                                  ? "REF" : "UVAL", &n->where);
   11567          862 :                     else if (n->expr)
   11568              :                       {
   11569          843 :                         gfc_expr *expr = n->expr;
   11570          843 :                         if (!gfc_resolve_expr (expr)
   11571          843 :                             || expr->ts.type != BT_INTEGER
   11572         1686 :                             || expr->rank != 0)
   11573            0 :                           gfc_error ("%qs in LINEAR clause at %L requires "
   11574              :                                      "a scalar integer linear-step expression",
   11575            0 :                                      n->sym->name, &n->where);
   11576          843 :                         else if (!code && expr->expr_type != EXPR_CONSTANT)
   11577              :                           {
   11578           11 :                             if (expr->expr_type == EXPR_VARIABLE
   11579            7 :                                 && expr->symtree->n.sym->attr.dummy
   11580            6 :                                 && expr->symtree->n.sym->ns == ns)
   11581              :                               {
   11582            6 :                                 gfc_omp_namelist *n2;
   11583            6 :                                 for (n2 = omp_clauses->lists[OMP_LIST_UNIFORM];
   11584            6 :                                      n2; n2 = n2->next)
   11585            6 :                                   if (n2->sym == expr->symtree->n.sym)
   11586              :                                     break;
   11587            6 :                                 if (n2)
   11588              :                                   break;
   11589              :                               }
   11590            5 :                             gfc_error ("%qs in LINEAR clause at %L requires "
   11591              :                                        "a constant integer linear-step "
   11592              :                                        "expression or dummy argument "
   11593              :                                        "specified in UNIFORM clause",
   11594            5 :                                        n->sym->name, &n->where);
   11595              :                           }
   11596              :                       }
   11597              :                     break;
   11598              :                   /* Workaround for PR middle-end/26316, nothing really needs
   11599              :                      to be done here for OMP_LIST_PRIVATE.  */
   11600         9400 :                   case OMP_LIST_PRIVATE:
   11601         9400 :                     gcc_assert (code && code->op != EXEC_NOP);
   11602              :                     break;
   11603           98 :                   case OMP_LIST_USE_DEVICE:
   11604           98 :                       if (n->sym->attr.allocatable
   11605           98 :                           || (n->sym->ts.type == BT_CLASS && CLASS_DATA (n->sym)
   11606            0 :                               && CLASS_DATA (n->sym)->attr.allocatable))
   11607            0 :                         gfc_error ("ALLOCATABLE object %qs in %s clause at %L",
   11608              :                                    n->sym->name, name, &n->where);
   11609           98 :                       if (n->sym->ts.type == BT_CLASS
   11610            0 :                           && CLASS_DATA (n->sym)
   11611            0 :                           && CLASS_DATA (n->sym)->attr.class_pointer)
   11612            0 :                         gfc_error ("POINTER object %qs of polymorphic type in "
   11613              :                                    "%s clause at %L", n->sym->name, name,
   11614              :                                    &n->where);
   11615           98 :                       if (n->sym->attr.cray_pointer)
   11616            2 :                         gfc_error ("Cray pointer object %qs in %s clause at %L",
   11617              :                                    n->sym->name, name, &n->where);
   11618           96 :                       else if (n->sym->attr.cray_pointee)
   11619            2 :                         gfc_error ("Cray pointee object %qs in %s clause at %L",
   11620              :                                    n->sym->name, name, &n->where);
   11621           94 :                       else if (n->sym->attr.flavor == FL_VARIABLE
   11622           93 :                                && !n->sym->as
   11623           54 :                                && !n->sym->attr.pointer)
   11624           13 :                         gfc_error ("%s clause variable %qs at %L is neither "
   11625              :                                    "a POINTER nor an array", name,
   11626              :                                    n->sym->name, &n->where);
   11627              :                       /* FALLTHRU */
   11628           98 :                   case OMP_LIST_DEVICE_RESIDENT:
   11629           98 :                     check_symbol_not_pointer (n->sym, n->where, name);
   11630           98 :                     check_array_not_assumed (n->sym, n->where, name);
   11631           98 :                     break;
   11632              :                   default:
   11633              :                     break;
   11634              :                   }
   11635              :               }
   11636              :             break;
   11637              :           }
   11638              :       }
   11639              :   /* OpenMP 5.1: use_device_ptr acts like use_device_addr, except for
   11640              :      type(c_ptr).  */
   11641        33132 :   if (omp_clauses->lists[OMP_LIST_USE_DEVICE_PTR])
   11642              :     {
   11643            9 :       gfc_omp_namelist *n_prev, *n_next, *n_addr;
   11644            9 :       n_addr = omp_clauses->lists[OMP_LIST_USE_DEVICE_ADDR];
   11645           28 :       for (; n_addr && n_addr->next; n_addr = n_addr->next)
   11646              :         ;
   11647              :       n_prev = NULL;
   11648              :       n = omp_clauses->lists[OMP_LIST_USE_DEVICE_PTR];
   11649           27 :       while (n)
   11650              :         {
   11651           18 :           n_next = n->next;
   11652           18 :           if (n->sym->ts.type != BT_DERIVED
   11653           18 :               || n->sym->ts.u.derived->ts.f90_type != BT_VOID)
   11654              :             {
   11655            0 :               n->next = NULL;
   11656            0 :               if (n_addr)
   11657            0 :                 n_addr->next = n;
   11658              :               else
   11659            0 :                 omp_clauses->lists[OMP_LIST_USE_DEVICE_ADDR] = n;
   11660            0 :               n_addr = n;
   11661            0 :               if (n_prev)
   11662            0 :                 n_prev->next = n_next;
   11663              :               else
   11664            0 :                 omp_clauses->lists[OMP_LIST_USE_DEVICE_PTR] = n_next;
   11665              :             }
   11666              :           else
   11667              :             n_prev = n;
   11668           18 :           n = n_next;
   11669              :         }
   11670              :     }
   11671        33132 :   if (omp_clauses->safelen_expr)
   11672           93 :     resolve_positive_int_expr (omp_clauses->safelen_expr, "SAFELEN");
   11673        33132 :   if (omp_clauses->simdlen_expr)
   11674          123 :     resolve_positive_int_expr (omp_clauses->simdlen_expr, "SIMDLEN");
   11675        33326 :   for (el = omp_clauses->num_teams_list; el; el = el->next)
   11676          194 :     resolve_positive_int_expr (el->expr, "NUM_TEAMS");
   11677        33132 :   if (omp_clauses->num_teams_list
   11678          153 :       && omp_clauses->num_teams_list->next
   11679           34 :       && !omp_clauses->num_teams_dims
   11680           27 :       && omp_clauses->num_teams_list->expr->expr_type == EXPR_CONSTANT
   11681           13 :       && omp_clauses->num_teams_list->next->expr->expr_type == EXPR_CONSTANT
   11682           13 :       && mpz_cmp (omp_clauses->num_teams_list->expr->value.integer,
   11683           13 :                   omp_clauses->num_teams_list->next->expr->value.integer) > 0)
   11684            2 :     gfc_warning (OPT_Wopenmp, "NUM_TEAMS lower bound at %L larger than upper "
   11685              :                  "bound at %L", &omp_clauses->num_teams_list->expr->where,
   11686              :                  &omp_clauses->num_teams_list->next->expr->where);
   11687        33132 :   if (omp_clauses->device)
   11688          333 :     resolve_scalar_int_expr (omp_clauses->device, "DEVICE");
   11689        33132 :   if (omp_clauses->filter)
   11690           42 :     resolve_nonnegative_int_expr (omp_clauses->filter, "FILTER");
   11691        33132 :   if (omp_clauses->hint)
   11692              :     {
   11693           47 :       resolve_scalar_int_expr (omp_clauses->hint, "HINT");
   11694           47 :     if (omp_clauses->hint->ts.type != BT_INTEGER
   11695           45 :         || omp_clauses->hint->expr_type != EXPR_CONSTANT
   11696           43 :         || mpz_sgn (omp_clauses->hint->value.integer) < 0)
   11697            5 :       gfc_error ("Value of HINT clause at %L shall be a valid "
   11698              :                  "constant hint expression", &omp_clauses->hint->where);
   11699              :     }
   11700        33132 :   if (omp_clauses->priority)
   11701           34 :     resolve_nonnegative_int_expr (omp_clauses->priority, "PRIORITY");
   11702        33132 :   if (omp_clauses->dist_chunk_size)
   11703              :     {
   11704           83 :       gfc_expr *expr = omp_clauses->dist_chunk_size;
   11705           83 :       if (!gfc_resolve_expr (expr)
   11706           83 :           || expr->ts.type != BT_INTEGER || expr->rank != 0)
   11707            0 :         gfc_error ("DIST_SCHEDULE clause's chunk_size at %L requires "
   11708              :                    "a scalar INTEGER expression", &expr->where);
   11709              :     }
   11710        33254 :   for (el = omp_clauses->thread_limit_list; el; el = el->next)
   11711          122 :     resolve_positive_int_expr (el->expr, "THREAD_LIMIT");
   11712        33132 :   if (omp_clauses->grainsize)
   11713           34 :     resolve_positive_int_expr (omp_clauses->grainsize, "GRAINSIZE");
   11714        33132 :   if (omp_clauses->num_tasks)
   11715           26 :     resolve_positive_int_expr (omp_clauses->num_tasks, "NUM_TASKS");
   11716        33132 :   if (omp_clauses->grainsize && omp_clauses->num_tasks)
   11717            1 :     gfc_error ("%<GRAINSIZE%> clause at %L must not be used together with "
   11718              :                "%<NUM_TASKS%> clause", &omp_clauses->grainsize->where);
   11719        33132 :   if (omp_clauses->lists[OMP_LIST_REDUCTION] && omp_clauses->nogroup)
   11720            1 :     gfc_error ("%<REDUCTION%> clause at %L must not be used together with "
   11721              :                "%<NOGROUP%> clause",
   11722              :                &omp_clauses->lists[OMP_LIST_REDUCTION]->where);
   11723        33132 :   if (omp_clauses->full && omp_clauses->partial)
   11724            0 :     gfc_error ("%<FULL%> clause at %C must not be used together with "
   11725              :                "%<PARTIAL%> clause");
   11726        33132 :   if (omp_clauses->async)
   11727          610 :     if (omp_clauses->async_expr)
   11728          610 :       resolve_scalar_int_expr (omp_clauses->async_expr, "ASYNC");
   11729        33132 :   if (omp_clauses->device_num_expr)
   11730          105 :     resolve_scalar_int_expr (omp_clauses->device_num_expr, "DEVICE_NUM");
   11731        33132 :   if (code && code->op == EXEC_OACC_SET
   11732          121 :       && !omp_clauses->device_num_expr
   11733           52 :       && !omp_clauses->oacc_device_type_present)
   11734            2 :     gfc_error ("At least one of the clauses %<DEVICE_TYPE%> and %<DEVICE_NUM%> "
   11735              :                "should be present in %<SET%> directive at %L", &code->loc);
   11736        33132 :   if (omp_clauses->num_gangs_expr)
   11737          682 :     resolve_positive_int_expr (omp_clauses->num_gangs_expr, "NUM_GANGS");
   11738        33132 :   if (omp_clauses->num_workers_expr)
   11739          599 :     resolve_positive_int_expr (omp_clauses->num_workers_expr, "NUM_WORKERS");
   11740        33132 :   if (omp_clauses->vector_length_expr)
   11741          569 :     resolve_positive_int_expr (omp_clauses->vector_length_expr,
   11742              :                                "VECTOR_LENGTH");
   11743        33132 :   if (omp_clauses->gang_num_expr)
   11744          114 :     resolve_positive_int_expr (omp_clauses->gang_num_expr, "GANG");
   11745        33132 :   if (omp_clauses->gang_static_expr)
   11746           94 :     resolve_positive_int_expr (omp_clauses->gang_static_expr, "GANG");
   11747        33132 :   if (omp_clauses->worker_expr)
   11748          101 :     resolve_positive_int_expr (omp_clauses->worker_expr, "WORKER");
   11749        33132 :   if (omp_clauses->vector_expr)
   11750          132 :     resolve_positive_int_expr (omp_clauses->vector_expr, "VECTOR");
   11751        33471 :   for (el = omp_clauses->wait_list; el; el = el->next)
   11752          339 :     resolve_scalar_int_expr (el->expr, "WAIT");
   11753        33132 :   if (omp_clauses->collapse && omp_clauses->tile_list)
   11754            4 :     gfc_error ("Incompatible use of TILE and COLLAPSE at %L", &code->loc);
   11755        33132 :   if (omp_clauses->message)
   11756              :     {
   11757           58 :       gfc_expr *expr = omp_clauses->message;
   11758           58 :       if (!gfc_resolve_expr (expr)
   11759           58 :           || expr->ts.kind != gfc_default_character_kind
   11760          113 :           || expr->ts.type != BT_CHARACTER || expr->rank != 0)
   11761            4 :         gfc_error ("MESSAGE clause at %L requires a scalar default-kind "
   11762              :                    "CHARACTER expression", &expr->where);
   11763              :     }
   11764        33132 :   if (!openacc
   11765        33132 :       && code
   11766        19878 :       && omp_clauses->lists[OMP_LIST_MAP] == NULL
   11767        16081 :       && omp_clauses->lists[OMP_LIST_USE_DEVICE_PTR] == NULL
   11768        16078 :       && omp_clauses->lists[OMP_LIST_USE_DEVICE_ADDR] == NULL)
   11769              :     {
   11770        16055 :       const char *p = NULL;
   11771        16055 :       switch (code->op)
   11772              :         {
   11773            1 :         case EXEC_OMP_TARGET_ENTER_DATA: p = "TARGET ENTER DATA"; break;
   11774            1 :         case EXEC_OMP_TARGET_EXIT_DATA: p = "TARGET EXIT DATA"; break;
   11775              :         default: break;
   11776              :         }
   11777        16055 :       if (code->op == EXEC_OMP_TARGET_DATA)
   11778            1 :         gfc_error ("TARGET DATA must contain at least one MAP, USE_DEVICE_PTR, "
   11779              :                    "or USE_DEVICE_ADDR clause at %L", &code->loc);
   11780        16054 :       else if (p)
   11781            2 :         gfc_error ("%s must contain at least one MAP clause at %L",
   11782              :                    p, &code->loc);
   11783              :     }
   11784        33132 :   if (omp_clauses->sizes_list)
   11785              :     {
   11786              :       gfc_expr_list *el;
   11787          572 :       for (el = omp_clauses->sizes_list; el; el = el->next)
   11788              :         {
   11789          377 :           resolve_scalar_int_expr (el->expr, "SIZES");
   11790          377 :           if (el->expr->expr_type != EXPR_CONSTANT)
   11791            1 :             gfc_error ("SIZES requires constant expression at %L",
   11792              :                        &el->expr->where);
   11793          376 :           else if (el->expr->expr_type == EXPR_CONSTANT
   11794          376 :                    && el->expr->ts.type == BT_INTEGER
   11795          376 :                    && mpz_sgn (el->expr->value.integer) <= 0)
   11796            2 :             gfc_error ("INTEGER expression of %s clause at %L must be "
   11797              :                        "positive", "SIZES", &el->expr->where);
   11798              :         }
   11799              :     }
   11800              : 
   11801        33132 :   if (!openacc && omp_clauses->detach)
   11802              :     {
   11803          125 :       if (!gfc_resolve_expr (omp_clauses->detach)
   11804          125 :           || omp_clauses->detach->ts.type != BT_INTEGER
   11805          124 :           || omp_clauses->detach->ts.kind != gfc_c_intptr_kind
   11806          248 :           || omp_clauses->detach->rank != 0)
   11807            3 :         gfc_error ("%qs at %L should be a scalar of type "
   11808              :                    "integer(kind=omp_event_handle_kind)",
   11809            3 :                    omp_clauses->detach->symtree->n.sym->name,
   11810            3 :                    &omp_clauses->detach->where);
   11811          122 :       else if (omp_clauses->detach->symtree->n.sym->attr.dimension > 0)
   11812            1 :         gfc_error ("The event handle at %L must not be an array element",
   11813              :                    &omp_clauses->detach->where);
   11814          121 :       else if (omp_clauses->detach->symtree->n.sym->ts.type == BT_DERIVED
   11815          120 :                || omp_clauses->detach->symtree->n.sym->ts.type == BT_CLASS)
   11816            1 :         gfc_error ("The event handle at %L must not be part of "
   11817              :                    "a derived type or class", &omp_clauses->detach->where);
   11818              : 
   11819          125 :       if (omp_clauses->mergeable)
   11820            2 :         gfc_error ("%<DETACH%> clause at %L must not be used together with "
   11821            2 :                    "%<MERGEABLE%> clause", &omp_clauses->detach->where);
   11822              :     }
   11823              : 
   11824              :   if (openacc
   11825        12995 :       && code->op == EXEC_OACC_HOST_DATA
   11826           60 :       && omp_clauses->lists[OMP_LIST_USE_DEVICE] == NULL)
   11827            1 :     gfc_error ("%<host_data%> construct at %L requires %<use_device%> clause",
   11828              :                &code->loc);
   11829              : 
   11830        33132 :   if (omp_clauses->assume)
   11831           18 :     gfc_resolve_omp_assumptions (omp_clauses->assume);
   11832              : }
   11833              : 
   11834              : 
   11835              : /* Return true if SYM is ever referenced in EXPR except in the SE node.  */
   11836              : 
   11837              : static bool
   11838         5008 : expr_references_sym (gfc_expr *e, gfc_symbol *s, gfc_expr *se)
   11839              : {
   11840         6641 :   gfc_actual_arglist *arg;
   11841         6641 :   if (e == NULL || e == se)
   11842              :     return false;
   11843         5386 :   switch (e->expr_type)
   11844              :     {
   11845         3133 :     case EXPR_CONSTANT:
   11846         3133 :     case EXPR_NULL:
   11847         3133 :     case EXPR_VARIABLE:
   11848         3133 :     case EXPR_STRUCTURE:
   11849         3133 :     case EXPR_ARRAY:
   11850         3133 :       if (e->symtree != NULL
   11851         1157 :           && e->symtree->n.sym == s)
   11852          470 :         return true;
   11853              :       return false;
   11854            0 :     case EXPR_SUBSTRING:
   11855            0 :       if (e->ref != NULL
   11856            0 :           && (expr_references_sym (e->ref->u.ss.start, s, se)
   11857            0 :               || expr_references_sym (e->ref->u.ss.end, s, se)))
   11858            0 :         return true;
   11859              :       return false;
   11860         1742 :     case EXPR_OP:
   11861         1742 :       if (expr_references_sym (e->value.op.op2, s, se))
   11862              :         return true;
   11863         1633 :       return expr_references_sym (e->value.op.op1, s, se);
   11864          511 :     case EXPR_FUNCTION:
   11865          896 :       for (arg = e->value.function.actual; arg; arg = arg->next)
   11866          586 :         if (expr_references_sym (arg->expr, s, se))
   11867              :           return true;
   11868              :       return false;
   11869            0 :     default:
   11870            0 :       gcc_unreachable ();
   11871              :     }
   11872              : }
   11873              : 
   11874              : 
   11875              : /* If EXPR is a conversion function that widens the type
   11876              :    if WIDENING is true or narrows the type if NARROW is true,
   11877              :    return the inner expression, otherwise return NULL.  */
   11878              : 
   11879              : static gfc_expr *
   11880         5928 : is_conversion (gfc_expr *expr, bool narrowing, bool widening)
   11881              : {
   11882         5928 :   gfc_typespec *ts1, *ts2;
   11883              : 
   11884         5928 :   if (expr->expr_type != EXPR_FUNCTION
   11885          917 :       || expr->value.function.isym == NULL
   11886          894 :       || expr->value.function.esym != NULL
   11887          894 :       || expr->value.function.isym->id != GFC_ISYM_CONVERSION
   11888          388 :       || (!narrowing && !widening))
   11889              :     return NULL;
   11890              : 
   11891          388 :   if (narrowing && widening)
   11892          267 :     return expr->value.function.actual->expr;
   11893              : 
   11894          121 :   if (widening)
   11895              :     {
   11896          121 :       ts1 = &expr->ts;
   11897          121 :       ts2 = &expr->value.function.actual->expr->ts;
   11898              :     }
   11899              :   else
   11900              :     {
   11901            0 :       ts1 = &expr->value.function.actual->expr->ts;
   11902            0 :       ts2 = &expr->ts;
   11903              :     }
   11904              : 
   11905          121 :   if (ts1->type > ts2->type
   11906           49 :       || (ts1->type == ts2->type && ts1->kind > ts2->kind))
   11907          121 :     return expr->value.function.actual->expr;
   11908              : 
   11909              :   return NULL;
   11910              : }
   11911              : 
   11912              : static bool
   11913         6883 : is_scalar_intrinsic_expr (gfc_expr *expr, bool must_be_var, bool conv_ok)
   11914              : {
   11915         6883 :   if (must_be_var
   11916         4034 :       && (expr->expr_type != EXPR_VARIABLE || !expr->symtree))
   11917              :     {
   11918           37 :       if (!conv_ok)
   11919              :         return false;
   11920           37 :       gfc_expr *conv = is_conversion (expr, true, true);
   11921           37 :       if (!conv)
   11922              :         return false;
   11923           36 :       if (conv->expr_type != EXPR_VARIABLE || !conv->symtree)
   11924              :         return false;
   11925              :     }
   11926         6880 :   return (expr->rank == 0
   11927         6876 :           && !gfc_is_coindexed (expr)
   11928        13756 :           && (expr->ts.type == BT_INTEGER
   11929         1522 :               || expr->ts.type == BT_REAL
   11930          590 :               || expr->ts.type == BT_COMPLEX
   11931          572 :               || expr->ts.type == BT_LOGICAL));
   11932              : }
   11933              : 
   11934              : static void
   11935         2710 : resolve_omp_atomic (gfc_code *code)
   11936              : {
   11937         2710 :   gfc_code *atomic_code = code->block;
   11938         2710 :   gfc_symbol *var;
   11939         2710 :   gfc_expr *stmt_expr2, *capt_expr2;
   11940         2710 :   gfc_omp_atomic_op aop
   11941         2710 :     = (gfc_omp_atomic_op) (atomic_code->ext.omp_clauses->atomic_op
   11942              :                            & GFC_OMP_ATOMIC_MASK);
   11943         2710 :   gfc_code *stmt = NULL, *capture_stmt = NULL, *tailing_stmt = NULL;
   11944         2710 :   gfc_expr *comp_cond = NULL;
   11945         2710 :   locus *loc = NULL;
   11946              : 
   11947         2710 :   code = code->block->next;
   11948              :   /* resolve_blocks asserts this is initially EXEC_ASSIGN or EXEC_IF
   11949              :      If it changed to EXEC_NOP, assume an error has been emitted already.  */
   11950         2710 :   if (code->op == EXEC_NOP)
   11951              :     return;
   11952              : 
   11953         2709 :   if (atomic_code->ext.omp_clauses->compare
   11954          157 :       && atomic_code->ext.omp_clauses->capture)
   11955              :     {
   11956              :       /* Must be either "if (x == e) then; x = d; else; v = x; end if"
   11957              :          or "v = expr" followed/preceded by
   11958              :          "if (x == e) then; x = d; end if" or "if (x == e) x = d".  */
   11959          103 :       gfc_code *next = code;
   11960          103 :       if (code->op == EXEC_ASSIGN)
   11961              :         {
   11962           19 :           capture_stmt = code;
   11963           19 :           next = code->next;
   11964              :         }
   11965          103 :       if (next->op == EXEC_IF
   11966          103 :           && next->block
   11967          103 :           && next->block->op == EXEC_IF
   11968          103 :           && next->block->next
   11969          102 :           && next->block->next->op == EXEC_ASSIGN)
   11970              :         {
   11971          102 :           comp_cond = next->block->expr1;
   11972          102 :           stmt = next->block->next;
   11973          102 :           if (stmt->next)
   11974              :             {
   11975            0 :               loc = &stmt->loc;
   11976            0 :               goto unexpected;
   11977              :             }
   11978              :         }
   11979            1 :       else if (capture_stmt)
   11980              :         {
   11981            0 :           gfc_error ("Expected IF at %L in atomic compare capture",
   11982              :                      &next->loc);
   11983            0 :           return;
   11984              :         }
   11985          103 :       if (stmt && !capture_stmt && next->block->block)
   11986              :         {
   11987           64 :           if (next->block->block->expr1)
   11988              :             {
   11989            0 :               gfc_error ("Expected ELSE at %L in atomic compare capture",
   11990              :                          &next->block->block->expr1->where);
   11991            0 :               return;
   11992              :             }
   11993           64 :           if (!code->block->block->next
   11994           64 :               || code->block->block->next->op != EXEC_ASSIGN)
   11995              :             {
   11996            0 :               loc = (code->block->block->next ? &code->block->block->next->loc
   11997              :                                               : &code->block->block->loc);
   11998            0 :               goto unexpected;
   11999              :             }
   12000           64 :           capture_stmt = code->block->block->next;
   12001           64 :           if (capture_stmt->next)
   12002              :             {
   12003            0 :               loc = &capture_stmt->next->loc;
   12004            0 :               goto unexpected;
   12005              :             }
   12006              :         }
   12007          103 :       if (stmt && !capture_stmt && next->next->op == EXEC_ASSIGN)
   12008              :         capture_stmt = next->next;
   12009           84 :       else if (!capture_stmt)
   12010              :         {
   12011            1 :           loc = &code->loc;
   12012            1 :           goto unexpected;
   12013              :         }
   12014              :     }
   12015         2606 :   else if (atomic_code->ext.omp_clauses->compare)
   12016              :     {
   12017              :       /* Must be: "if (x == e) then; x = d; end if" or "if (x == e) x = d".  */
   12018           54 :       if (code->op == EXEC_IF
   12019           54 :           && code->block
   12020           54 :           && code->block->op == EXEC_IF
   12021           54 :           && code->block->next
   12022           52 :           && code->block->next->op == EXEC_ASSIGN)
   12023              :         {
   12024           52 :           comp_cond = code->block->expr1;
   12025           52 :           stmt = code->block->next;
   12026           52 :           if (stmt->next || code->block->block)
   12027              :             {
   12028            0 :               loc = stmt->next ? &stmt->next->loc : &code->block->block->loc;
   12029            0 :               goto unexpected;
   12030              :             }
   12031              :         }
   12032              :       else
   12033              :         {
   12034            2 :           loc = &code->loc;
   12035            2 :           goto unexpected;
   12036              :         }
   12037              :     }
   12038         2552 :   else if (atomic_code->ext.omp_clauses->capture)
   12039              :     {
   12040              :       /* Must be: "v = x" followed/preceded by "x = ...". */
   12041          489 :       if (code->op != EXEC_ASSIGN)
   12042            0 :         goto unexpected;
   12043          489 :       if (code->next->op != EXEC_ASSIGN)
   12044              :         {
   12045            0 :           loc = &code->next->loc;
   12046            0 :           goto unexpected;
   12047              :         }
   12048          489 :       gfc_expr *expr2, *expr2_next;
   12049          489 :       expr2 = is_conversion (code->expr2, true, true);
   12050          489 :       if (expr2 == NULL)
   12051          447 :         expr2 = code->expr2;
   12052          489 :       expr2_next = is_conversion (code->next->expr2, true, true);
   12053          489 :       if (expr2_next == NULL)
   12054          478 :         expr2_next = code->next->expr2;
   12055          489 :       if (code->expr1->expr_type == EXPR_VARIABLE
   12056          489 :           && code->next->expr1->expr_type == EXPR_VARIABLE
   12057          489 :           && expr2->expr_type == EXPR_VARIABLE
   12058          243 :           && expr2_next->expr_type == EXPR_VARIABLE)
   12059              :         {
   12060            1 :           if (code->expr1->symtree->n.sym == expr2_next->symtree->n.sym)
   12061              :             {
   12062              :               stmt = code;
   12063              :               capture_stmt = code->next;
   12064              :             }
   12065              :           else
   12066              :             {
   12067          489 :               capture_stmt = code;
   12068          489 :               stmt = code->next;
   12069              :             }
   12070              :         }
   12071          488 :       else if (expr2->expr_type == EXPR_VARIABLE)
   12072              :         {
   12073              :           capture_stmt = code;
   12074              :           stmt = code->next;
   12075              :         }
   12076              :       else
   12077              :         {
   12078          247 :           stmt = code;
   12079          247 :           capture_stmt = code->next;
   12080              :         }
   12081              :       /* Shall be NULL but can happen for invalid code. */
   12082          489 :       tailing_stmt = code->next->next;
   12083              :     }
   12084              :   else
   12085              :     {
   12086              :       /* x = ... */
   12087         2063 :       stmt = code;
   12088         2063 :       if (!atomic_code->ext.omp_clauses->compare && stmt->op != EXEC_ASSIGN)
   12089            1 :         goto unexpected;
   12090              :       /* Shall be NULL but can happen for invalid code. */
   12091         2062 :       tailing_stmt = code->next;
   12092              :     }
   12093              : 
   12094         2705 :   if (comp_cond)
   12095              :     {
   12096          154 :       if (comp_cond->expr_type != EXPR_OP
   12097          154 :           || (comp_cond->value.op.op != INTRINSIC_EQ
   12098              :               && comp_cond->value.op.op != INTRINSIC_EQ_OS
   12099              :               && comp_cond->value.op.op != INTRINSIC_EQV))
   12100              :         {
   12101            0 :           gfc_error ("Expected %<==%>, %<.EQ.%> or %<.EQV.%> atomic comparison "
   12102              :                      "expression at %L", &comp_cond->where);
   12103            0 :           return;
   12104              :         }
   12105          154 :       if (!is_scalar_intrinsic_expr (comp_cond->value.op.op1, true, true))
   12106              :         {
   12107            1 :           gfc_error ("Expected scalar intrinsic variable at %L in atomic "
   12108            1 :                      "comparison", &comp_cond->value.op.op1->where);
   12109            1 :           return;
   12110              :         }
   12111          153 :       if (!gfc_resolve_expr (comp_cond->value.op.op2))
   12112              :         return;
   12113          153 :       if (!is_scalar_intrinsic_expr (comp_cond->value.op.op2, false, false))
   12114              :         {
   12115            0 :           gfc_error ("Expected scalar intrinsic expression at %L in atomic "
   12116            0 :                      "comparison", &comp_cond->value.op.op1->where);
   12117            0 :           return;
   12118              :         }
   12119              :     }
   12120              : 
   12121         2704 :   if (!is_scalar_intrinsic_expr (stmt->expr1, true, false))
   12122              :     {
   12123            4 :       gfc_error ("!$OMP ATOMIC statement must set a scalar variable of "
   12124            4 :                  "intrinsic type at %L", &stmt->expr1->where);
   12125            4 :       return;
   12126              :     }
   12127              : 
   12128         2700 :   if (!gfc_resolve_expr (stmt->expr2))
   12129              :     return;
   12130         2696 :   if (!is_scalar_intrinsic_expr (stmt->expr2, false, false))
   12131              :     {
   12132            0 :       gfc_error ("!$OMP ATOMIC statement must assign an expression of "
   12133            0 :                  "intrinsic type at %L", &stmt->expr2->where);
   12134            0 :       return;
   12135              :     }
   12136              : 
   12137         2696 :   if (gfc_expr_attr (stmt->expr1).allocatable)
   12138              :     {
   12139            0 :       gfc_error ("!$OMP ATOMIC with ALLOCATABLE variable at %L",
   12140            0 :                  &stmt->expr1->where);
   12141            0 :       return;
   12142              :     }
   12143              : 
   12144              :   /* Should be diagnosed above already. */
   12145         2696 :   gcc_assert (tailing_stmt == NULL);
   12146              : 
   12147         2696 :   var = stmt->expr1->symtree->n.sym;
   12148         2696 :   stmt_expr2 = is_conversion (stmt->expr2, true, true);
   12149         2696 :   if (stmt_expr2 == NULL)
   12150         2540 :     stmt_expr2 = stmt->expr2;
   12151              : 
   12152         2696 :   switch (aop)
   12153              :     {
   12154          506 :     case GFC_OMP_ATOMIC_READ:
   12155          506 :       if (stmt_expr2->expr_type != EXPR_VARIABLE)
   12156            0 :         gfc_error ("!$OMP ATOMIC READ statement must read from a scalar "
   12157              :                    "variable of intrinsic type at %L", &stmt_expr2->where);
   12158              :       return;
   12159          426 :     case GFC_OMP_ATOMIC_WRITE:
   12160          426 :       if (expr_references_sym (stmt_expr2, var, NULL))
   12161            0 :         gfc_error ("expr in !$OMP ATOMIC WRITE assignment var = expr "
   12162              :                    "must be scalar and cannot reference var at %L",
   12163              :                    &stmt_expr2->where);
   12164              :       return;
   12165         1764 :     default:
   12166         1764 :       break;
   12167              :     }
   12168              : 
   12169         1764 :   if (atomic_code->ext.omp_clauses->capture)
   12170              :     {
   12171          588 :       if (!is_scalar_intrinsic_expr (capture_stmt->expr1, true, false))
   12172              :         {
   12173            0 :           gfc_error ("!$OMP ATOMIC capture-statement must set a scalar "
   12174              :                      "variable of intrinsic type at %L",
   12175            0 :                      &capture_stmt->expr1->where);
   12176            0 :           return;
   12177              :         }
   12178              : 
   12179          588 :       if (!is_scalar_intrinsic_expr (capture_stmt->expr2, true, true))
   12180              :         {
   12181            2 :           gfc_error ("!$OMP ATOMIC capture-statement requires a scalar variable"
   12182            2 :                      " of intrinsic type at %L", &capture_stmt->expr2->where);
   12183            2 :           return;
   12184              :         }
   12185          586 :       capt_expr2 = is_conversion (capture_stmt->expr2, true, true);
   12186          586 :       if (capt_expr2 == NULL)
   12187          564 :         capt_expr2 = capture_stmt->expr2;
   12188              : 
   12189          586 :       if (capt_expr2->symtree->n.sym != var)
   12190              :         {
   12191            1 :           gfc_error ("!$OMP ATOMIC CAPTURE capture statement reads from "
   12192              :                      "different variable than update statement writes "
   12193              :                      "into at %L", &capture_stmt->expr2->where);
   12194            1 :               return;
   12195              :         }
   12196              :     }
   12197              : 
   12198         1761 :   if (atomic_code->ext.omp_clauses->compare)
   12199              :     {
   12200          150 :       gfc_expr *var_expr;
   12201          150 :       if (comp_cond->value.op.op1->expr_type == EXPR_VARIABLE)
   12202              :         var_expr = comp_cond->value.op.op1;
   12203              :       else
   12204           12 :         var_expr = comp_cond->value.op.op1->value.function.actual->expr;
   12205          150 :       if (var_expr->symtree->n.sym != var)
   12206              :         {
   12207            2 :           gfc_error ("For !$OMP ATOMIC COMPARE, the first operand in comparison"
   12208              :                      " at %L must be the variable %qs that the update statement"
   12209              :                      " writes into at %L", &var_expr->where, var->name,
   12210            2 :                      &stmt->expr1->where);
   12211            2 :           return;
   12212              :         }
   12213          148 :       if (stmt_expr2->rank != 0 || expr_references_sym (stmt_expr2, var, NULL))
   12214              :         {
   12215            1 :           gfc_error ("expr in !$OMP ATOMIC COMPARE assignment var = expr "
   12216              :                      "must be scalar and cannot reference var at %L",
   12217              :                      &stmt_expr2->where);
   12218            1 :           return;
   12219              :         }
   12220              :     }
   12221         1611 :   else if (atomic_code->ext.omp_clauses->capture
   12222         1611 :            && !expr_references_sym (stmt_expr2, var, NULL))
   12223           22 :     atomic_code->ext.omp_clauses->atomic_op
   12224           22 :       = (gfc_omp_atomic_op) (atomic_code->ext.omp_clauses->atomic_op
   12225              :                              | GFC_OMP_ATOMIC_SWAP);
   12226         1589 :   else if (stmt_expr2->expr_type == EXPR_OP)
   12227              :     {
   12228         1233 :       gfc_expr *v = NULL, *e, *c;
   12229         1233 :       gfc_intrinsic_op op = stmt_expr2->value.op.op;
   12230         1233 :       gfc_intrinsic_op alt_op = INTRINSIC_NONE;
   12231              : 
   12232         1233 :       if (atomic_code->ext.omp_clauses->fail != OMP_MEMORDER_UNSET)
   12233            3 :         gfc_error ("!$OMP ATOMIC UPDATE at %L with FAIL clause requires either"
   12234              :                    " the COMPARE clause or using the intrinsic MIN/MAX "
   12235              :                    "procedure", &atomic_code->loc);
   12236         1233 :       switch (op)
   12237              :         {
   12238          746 :         case INTRINSIC_PLUS:
   12239          746 :           alt_op = INTRINSIC_MINUS;
   12240          746 :           break;
   12241           94 :         case INTRINSIC_TIMES:
   12242           94 :           alt_op = INTRINSIC_DIVIDE;
   12243           94 :           break;
   12244          120 :         case INTRINSIC_MINUS:
   12245          120 :           alt_op = INTRINSIC_PLUS;
   12246          120 :           break;
   12247           94 :         case INTRINSIC_DIVIDE:
   12248           94 :           alt_op = INTRINSIC_TIMES;
   12249           94 :           break;
   12250              :         case INTRINSIC_AND:
   12251              :         case INTRINSIC_OR:
   12252              :           break;
   12253           43 :         case INTRINSIC_EQV:
   12254           43 :           alt_op = INTRINSIC_NEQV;
   12255           43 :           break;
   12256           43 :         case INTRINSIC_NEQV:
   12257           43 :           alt_op = INTRINSIC_EQV;
   12258           43 :           break;
   12259            1 :         default:
   12260            1 :           gfc_error ("!$OMP ATOMIC assignment operator must be binary "
   12261              :                      "+, *, -, /, .AND., .OR., .EQV. or .NEQV. at %L",
   12262              :                      &stmt_expr2->where);
   12263            1 :           return;
   12264              :         }
   12265              : 
   12266              :       /* Check for var = var op expr resp. var = expr op var where
   12267              :          expr doesn't reference var and var op expr is mathematically
   12268              :          equivalent to var op (expr) resp. expr op var equivalent to
   12269              :          (expr) op var.  We rely here on the fact that the matcher
   12270              :          for x op1 y op2 z where op1 and op2 have equal precedence
   12271              :          returns (x op1 y) op2 z.  */
   12272         1232 :       e = stmt_expr2->value.op.op2;
   12273         1232 :       if (e->expr_type == EXPR_VARIABLE
   12274          288 :           && e->symtree != NULL
   12275          288 :           && e->symtree->n.sym == var)
   12276              :         v = e;
   12277         1003 :       else if ((c = is_conversion (e, false, true)) != NULL
   12278           48 :                && c->expr_type == EXPR_VARIABLE
   12279           48 :                && c->symtree != NULL
   12280         1051 :                && c->symtree->n.sym == var)
   12281              :         v = c;
   12282              :       else
   12283              :         {
   12284          955 :           gfc_expr **p = NULL, **q;
   12285         1053 :           for (q = &stmt_expr2->value.op.op1; (e = *q) != NULL; )
   12286         1053 :             if (e->expr_type == EXPR_VARIABLE
   12287          952 :                 && e->symtree != NULL
   12288          952 :                 && e->symtree->n.sym == var)
   12289              :               {
   12290              :                 v = e;
   12291              :                 break;
   12292              :               }
   12293          101 :             else if ((c = is_conversion (e, false, true)) != NULL)
   12294           60 :               q = &e->value.function.actual->expr;
   12295           41 :             else if (e->expr_type != EXPR_OP
   12296           41 :                      || (e->value.op.op != op
   12297           15 :                          && e->value.op.op != alt_op)
   12298           38 :                      || e->rank != 0)
   12299              :               break;
   12300              :             else
   12301              :               {
   12302           38 :                 p = q;
   12303           38 :                 q = &e->value.op.op1;
   12304              :               }
   12305              : 
   12306          955 :           if (v == NULL)
   12307              :             {
   12308            3 :               gfc_error ("!$OMP ATOMIC assignment must be var = var op expr "
   12309              :                          "or var = expr op var at %L", &stmt_expr2->where);
   12310            3 :               return;
   12311              :             }
   12312              : 
   12313          952 :           if (p != NULL)
   12314              :             {
   12315           38 :               e = *p;
   12316           38 :               switch (e->value.op.op)
   12317              :                 {
   12318            8 :                 case INTRINSIC_MINUS:
   12319            8 :                 case INTRINSIC_DIVIDE:
   12320            8 :                 case INTRINSIC_EQV:
   12321            8 :                 case INTRINSIC_NEQV:
   12322            8 :                   gfc_error ("!$OMP ATOMIC var = var op expr not "
   12323              :                              "mathematically equivalent to var = var op "
   12324              :                              "(expr) at %L", &stmt_expr2->where);
   12325            8 :                   break;
   12326              :                 default:
   12327              :                   break;
   12328              :                 }
   12329              : 
   12330              :               /* Canonicalize into var = var op (expr).  */
   12331           38 :               *p = e->value.op.op2;
   12332           38 :               e->value.op.op2 = stmt_expr2;
   12333           38 :               e->ts = stmt_expr2->ts;
   12334           38 :               if (stmt->expr2 == stmt_expr2)
   12335           26 :                 stmt->expr2 = stmt_expr2 = e;
   12336              :               else
   12337           12 :                 stmt->expr2->value.function.actual->expr = stmt_expr2 = e;
   12338              : 
   12339           38 :               if (!gfc_compare_types (&stmt_expr2->value.op.op1->ts,
   12340              :                                       &stmt_expr2->ts))
   12341              :                 {
   12342           24 :                   for (p = &stmt_expr2->value.op.op1; *p != v;
   12343           12 :                        p = &(*p)->value.function.actual->expr)
   12344              :                     ;
   12345           12 :                   *p = NULL;
   12346           12 :                   gfc_free_expr (stmt_expr2->value.op.op1);
   12347           12 :                   stmt_expr2->value.op.op1 = v;
   12348           12 :                   gfc_convert_type (v, &stmt_expr2->ts, 2);
   12349              :                 }
   12350              :             }
   12351              :         }
   12352              : 
   12353         1229 :       if (e->rank != 0 || expr_references_sym (stmt->expr2, var, v))
   12354              :         {
   12355            1 :           gfc_error ("expr in !$OMP ATOMIC assignment var = var op expr "
   12356              :                      "must be scalar and cannot reference var at %L",
   12357              :                      &stmt_expr2->where);
   12358            1 :           return;
   12359              :         }
   12360              :     }
   12361          356 :   else if (stmt_expr2->expr_type == EXPR_FUNCTION
   12362          355 :            && stmt_expr2->value.function.isym != NULL
   12363          355 :            && stmt_expr2->value.function.esym == NULL
   12364          355 :            && stmt_expr2->value.function.actual != NULL
   12365          355 :            && stmt_expr2->value.function.actual->next != NULL)
   12366              :     {
   12367          355 :       gfc_actual_arglist *arg, *var_arg;
   12368              : 
   12369          355 :       switch (stmt_expr2->value.function.isym->id)
   12370              :         {
   12371              :         case GFC_ISYM_MIN:
   12372              :         case GFC_ISYM_MAX:
   12373              :           break;
   12374          147 :         case GFC_ISYM_IAND:
   12375          147 :         case GFC_ISYM_IOR:
   12376          147 :         case GFC_ISYM_IEOR:
   12377          147 :           if (stmt_expr2->value.function.actual->next->next != NULL)
   12378              :             {
   12379            0 :               gfc_error ("!$OMP ATOMIC assignment intrinsic IAND, IOR "
   12380              :                          "or IEOR must have two arguments at %L",
   12381              :                          &stmt_expr2->where);
   12382            0 :               return;
   12383              :             }
   12384              :           break;
   12385            1 :         default:
   12386            1 :           gfc_error ("!$OMP ATOMIC assignment intrinsic must be "
   12387              :                      "MIN, MAX, IAND, IOR or IEOR at %L",
   12388              :                      &stmt_expr2->where);
   12389            1 :           return;
   12390              :         }
   12391              : 
   12392              :       var_arg = NULL;
   12393         1088 :       for (arg = stmt_expr2->value.function.actual; arg; arg = arg->next)
   12394              :         {
   12395          741 :           gfc_expr *e = NULL;
   12396          741 :           if (arg == stmt_expr2->value.function.actual
   12397          387 :               || (var_arg == NULL && arg->next == NULL))
   12398              :             {
   12399          527 :               e = is_conversion (arg->expr, false, true);
   12400          527 :               if (!e)
   12401          514 :                 e = arg->expr;
   12402          527 :               if (e->expr_type == EXPR_VARIABLE
   12403          453 :                   && e->symtree != NULL
   12404          453 :                   && e->symtree->n.sym == var)
   12405          741 :                 var_arg = arg;
   12406              :             }
   12407          741 :           if ((!var_arg || !e) && expr_references_sym (arg->expr, var, NULL))
   12408              :             {
   12409            7 :               gfc_error ("!$OMP ATOMIC intrinsic arguments except one must "
   12410              :                          "not reference %qs at %L",
   12411              :                          var->name, &arg->expr->where);
   12412            7 :               return;
   12413              :             }
   12414          734 :           if (arg->expr->rank != 0)
   12415              :             {
   12416            0 :               gfc_error ("!$OMP ATOMIC intrinsic arguments must be scalar "
   12417              :                          "at %L", &arg->expr->where);
   12418            0 :               return;
   12419              :             }
   12420              :         }
   12421              : 
   12422          347 :       if (var_arg == NULL)
   12423              :         {
   12424            1 :           gfc_error ("First or last !$OMP ATOMIC intrinsic argument must "
   12425              :                      "be %qs at %L", var->name, &stmt_expr2->where);
   12426            1 :           return;
   12427              :         }
   12428              : 
   12429          346 :       if (var_arg != stmt_expr2->value.function.actual)
   12430              :         {
   12431              :           /* Canonicalize, so that var comes first.  */
   12432          172 :           gcc_assert (var_arg->next == NULL);
   12433              :           for (arg = stmt_expr2->value.function.actual;
   12434          185 :                arg->next != var_arg; arg = arg->next)
   12435              :             ;
   12436          172 :           var_arg->next = stmt_expr2->value.function.actual;
   12437          172 :           stmt_expr2->value.function.actual = var_arg;
   12438          172 :           arg->next = NULL;
   12439              :         }
   12440              :     }
   12441              :   else
   12442            1 :     gfc_error ("!$OMP ATOMIC assignment must have an operator or "
   12443              :                "intrinsic on right hand side at %L", &stmt_expr2->where);
   12444              :   return;
   12445              : 
   12446            4 : unexpected:
   12447            4 :   gfc_error ("unexpected !$OMP ATOMIC expression at %L",
   12448              :              loc ? loc : &code->loc);
   12449            4 :   return;
   12450              : }
   12451              : 
   12452              : 
   12453              : static struct fortran_omp_context
   12454              : {
   12455              :   gfc_code *code;
   12456              :   hash_set<gfc_symbol *> *sharing_clauses;
   12457              :   hash_set<gfc_symbol *> *private_iterators;
   12458              :   struct fortran_omp_context *previous;
   12459              :   bool is_openmp;
   12460              : } *omp_current_ctx;
   12461              : static gfc_code *omp_current_do_code;
   12462              : static int omp_current_do_collapse;
   12463              : 
   12464              : /* Forward declaration for mutually recursive functions.  */
   12465              : static gfc_code *
   12466              : find_nested_loop_in_block (gfc_code *block);
   12467              : 
   12468              : /* Return the first nested DO loop in CHAIN, or NULL if there
   12469              :    isn't one.  Does no error checking on intervening code.  */
   12470              : 
   12471              : static gfc_code *
   12472        27482 : find_nested_loop_in_chain (gfc_code *chain)
   12473              : {
   12474        27482 :   gfc_code *code;
   12475              : 
   12476        27482 :   if (!chain)
   12477              :     return NULL;
   12478              : 
   12479        31643 :   for (code = chain; code; code = code->next)
   12480        31222 :     switch (code->op)
   12481              :       {
   12482              :       case EXEC_DO:
   12483              :       case EXEC_OMP_TILE:
   12484              :       case EXEC_OMP_UNROLL:
   12485              :         return code;
   12486          621 :       case EXEC_BLOCK:
   12487          621 :         if (gfc_code *c = find_nested_loop_in_block (code))
   12488              :           return c;
   12489              :         break;
   12490              :       default:
   12491              :         break;
   12492              :       }
   12493              :   return NULL;
   12494              : }
   12495              : 
   12496              : /* Return the first nested DO loop in BLOCK, or NULL if there
   12497              :    isn't one.  Does no error checking on intervening code.  */
   12498              : static gfc_code *
   12499          939 : find_nested_loop_in_block (gfc_code *block)
   12500              : {
   12501          939 :   gfc_namespace *ns;
   12502          939 :   gcc_assert (block->op == EXEC_BLOCK);
   12503          939 :   ns = block->ext.block.ns;
   12504          939 :   gcc_assert (ns);
   12505          939 :   return find_nested_loop_in_chain (ns->code);
   12506              : }
   12507              : 
   12508              : void
   12509         5441 : gfc_resolve_omp_do_blocks (gfc_code *code, gfc_namespace *ns)
   12510              : {
   12511         5441 :   if (code->block->next && code->block->next->op == EXEC_DO)
   12512              :     {
   12513         5088 :       int i;
   12514              : 
   12515         5088 :       omp_current_do_code = code->block->next;
   12516         5088 :       if (code->ext.omp_clauses->orderedc)
   12517          142 :         omp_current_do_collapse = code->ext.omp_clauses->orderedc;
   12518         4946 :       else if (code->ext.omp_clauses->collapse)
   12519         1121 :         omp_current_do_collapse = code->ext.omp_clauses->collapse;
   12520         3825 :       else if (code->ext.omp_clauses->sizes_list)
   12521          175 :         omp_current_do_collapse
   12522          175 :           = gfc_expr_list_len (code->ext.omp_clauses->sizes_list);
   12523              :       else
   12524         3650 :         omp_current_do_collapse = 1;
   12525         5088 :       if (code->ext.omp_clauses->lists[OMP_LIST_REDUCTION_INSCAN])
   12526              :         {
   12527              :           /* Checking that there is a matching EXEC_OMP_SCAN in the
   12528              :              innermost body cannot be deferred to resolve_omp_do because
   12529              :              we process directives nested in the loop before we get
   12530              :              there.  */
   12531           60 :           locus *loc
   12532              :             = &code->ext.omp_clauses->lists[OMP_LIST_REDUCTION_INSCAN]->where;
   12533           60 :           gfc_code *c;
   12534              : 
   12535           80 :           for (i = 1, c = omp_current_do_code;
   12536           80 :                i < omp_current_do_collapse; i++)
   12537              :             {
   12538           22 :               c = find_nested_loop_in_chain (c->block->next);
   12539           22 :               if (!c || c->op != EXEC_DO || c->block == NULL)
   12540              :                 break;
   12541              :             }
   12542              : 
   12543              :           /* Skip this if we don't have enough nested loops.  That
   12544              :              problem will be diagnosed elsewhere.  */
   12545           60 :           if (c && c->op == EXEC_DO)
   12546              :             {
   12547           58 :               gfc_code *block = c->block ? c->block->next : NULL;
   12548           58 :               if (block && block->op != EXEC_OMP_SCAN)
   12549           54 :                 while (block && block->next
   12550           54 :                        && block->next->op != EXEC_OMP_SCAN)
   12551              :                   block = block->next;
   12552           43 :               if (!block
   12553           46 :                   || (block->op != EXEC_OMP_SCAN
   12554           43 :                       && (!block->next || block->next->op != EXEC_OMP_SCAN)))
   12555           19 :                 gfc_error ("With INSCAN at %L, expected loop body with "
   12556              :                            "!$OMP SCAN between two "
   12557              :                            "structured block sequences", loc);
   12558              :               else
   12559              :                 {
   12560           39 :                   if (block->op == EXEC_OMP_SCAN)
   12561            3 :                     gfc_warning (OPT_Wopenmp,
   12562              :                                  "!$OMP SCAN at %L with zero executable "
   12563              :                                  "statements in preceding structured block "
   12564              :                                  "sequence", &block->loc);
   12565           39 :                   if ((block->op == EXEC_OMP_SCAN && !block->next)
   12566           38 :                       || (block->next && block->next->op == EXEC_OMP_SCAN
   12567           36 :                           && !block->next->next))
   12568            3 :                     gfc_warning (OPT_Wopenmp,
   12569              :                                  "!$OMP SCAN at %L with zero executable "
   12570              :                                  "statements in succeeding structured block "
   12571              :                                  "sequence", block->op == EXEC_OMP_SCAN
   12572            1 :                                  ? &block->loc : &block->next->loc);
   12573              :                 }
   12574           58 :               if (block && block->op != EXEC_OMP_SCAN)
   12575           43 :                 block = block->next;
   12576           46 :               if (block && block->op == EXEC_OMP_SCAN)
   12577              :                 /* Mark 'omp scan' as checked; flag will be unset later.  */
   12578           39 :                 block->ext.omp_clauses->if_present = true;
   12579              :             }
   12580              :         }
   12581              :     }
   12582         5441 :   gfc_resolve_blocks (code->block, ns);
   12583         5441 :   omp_current_do_collapse = 0;
   12584         5441 :   omp_current_do_code = NULL;
   12585         5441 : }
   12586              : 
   12587              : 
   12588              : void
   12589         6114 : gfc_resolve_omp_parallel_blocks (gfc_code *code, gfc_namespace *ns)
   12590              : {
   12591         6114 :   struct fortran_omp_context ctx;
   12592         6114 :   gfc_omp_clauses *omp_clauses = code->ext.omp_clauses;
   12593         6114 :   gfc_omp_namelist *n;
   12594              : 
   12595         6114 :   ctx.code = code;
   12596         6114 :   ctx.sharing_clauses = new hash_set<gfc_symbol *>;
   12597         6114 :   ctx.private_iterators = new hash_set<gfc_symbol *>;
   12598         6114 :   ctx.previous = omp_current_ctx;
   12599         6114 :   ctx.is_openmp = true;
   12600         6114 :   omp_current_ctx = &ctx;
   12601              : 
   12602       244560 :   for (enum gfc_omp_list_type list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
   12603       238446 :        list = gfc_omp_list_type (list + 1))
   12604       238446 :     switch (list)
   12605              :       {
   12606        61140 :       case OMP_LIST_SHARED:
   12607        61140 :       case OMP_LIST_PRIVATE:
   12608        61140 :       case OMP_LIST_FIRSTPRIVATE:
   12609        61140 :       case OMP_LIST_LASTPRIVATE:
   12610        61140 :       case OMP_LIST_REDUCTION:
   12611        61140 :       case OMP_LIST_REDUCTION_INSCAN:
   12612        61140 :       case OMP_LIST_REDUCTION_TASK:
   12613        61140 :       case OMP_LIST_IN_REDUCTION:
   12614        61140 :       case OMP_LIST_TASK_REDUCTION:
   12615        61140 :       case OMP_LIST_LINEAR:
   12616        70135 :         for (n = omp_clauses->lists[list]; n; n = n->next)
   12617         8995 :           ctx.sharing_clauses->add (n->sym);
   12618              :         break;
   12619              :       default:
   12620              :         break;
   12621              :       }
   12622              : 
   12623         6114 :   switch (code->op)
   12624              :     {
   12625         2368 :     case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
   12626         2368 :     case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
   12627         2368 :     case EXEC_OMP_MASKED_TASKLOOP:
   12628         2368 :     case EXEC_OMP_MASKED_TASKLOOP_SIMD:
   12629         2368 :     case EXEC_OMP_MASTER_TASKLOOP:
   12630         2368 :     case EXEC_OMP_MASTER_TASKLOOP_SIMD:
   12631         2368 :     case EXEC_OMP_PARALLEL_DO:
   12632         2368 :     case EXEC_OMP_PARALLEL_DO_SIMD:
   12633         2368 :     case EXEC_OMP_PARALLEL_LOOP:
   12634         2368 :     case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
   12635         2368 :     case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
   12636         2368 :     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
   12637         2368 :     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
   12638         2368 :     case EXEC_OMP_TARGET_PARALLEL_DO:
   12639         2368 :     case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
   12640         2368 :     case EXEC_OMP_TARGET_PARALLEL_LOOP:
   12641         2368 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
   12642         2368 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
   12643         2368 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
   12644         2368 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
   12645         2368 :     case EXEC_OMP_TARGET_TEAMS_LOOP:
   12646         2368 :     case EXEC_OMP_TASKLOOP:
   12647         2368 :     case EXEC_OMP_TASKLOOP_SIMD:
   12648         2368 :     case EXEC_OMP_TEAMS_DISTRIBUTE:
   12649         2368 :     case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
   12650         2368 :     case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
   12651         2368 :     case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
   12652         2368 :     case EXEC_OMP_TEAMS_LOOP:
   12653         2368 :       gfc_resolve_omp_do_blocks (code, ns);
   12654         2368 :       break;
   12655         3746 :     default:
   12656         3746 :       gfc_resolve_blocks (code->block, ns);
   12657              :     }
   12658              : 
   12659         6114 :   omp_current_ctx = ctx.previous;
   12660        12228 :   delete ctx.sharing_clauses;
   12661        12228 :   delete ctx.private_iterators;
   12662         6114 : }
   12663              : 
   12664              : 
   12665              : /* Save and clear openmp.cc private state.  */
   12666              : 
   12667              : void
   12668       302800 : gfc_omp_save_and_clear_state (struct gfc_omp_saved_state *state)
   12669              : {
   12670       302800 :   state->ptrs[0] = omp_current_ctx;
   12671       302800 :   state->ptrs[1] = omp_current_do_code;
   12672       302800 :   state->ints[0] = omp_current_do_collapse;
   12673       302800 :   omp_current_ctx = NULL;
   12674       302800 :   omp_current_do_code = NULL;
   12675       302800 :   omp_current_do_collapse = 0;
   12676       302800 : }
   12677              : 
   12678              : 
   12679              : /* Restore openmp.cc private state from the saved state.  */
   12680              : 
   12681              : void
   12682       302799 : gfc_omp_restore_state (struct gfc_omp_saved_state *state)
   12683              : {
   12684       302799 :   omp_current_ctx = (struct fortran_omp_context *) state->ptrs[0];
   12685       302799 :   omp_current_do_code = (gfc_code *) state->ptrs[1];
   12686       302799 :   omp_current_do_collapse = state->ints[0];
   12687       302799 : }
   12688              : 
   12689              : 
   12690              : /* Note a DO iterator variable.  This is special in !$omp parallel
   12691              :    construct, where they are predetermined private.  */
   12692              : 
   12693              : void
   12694        33424 : gfc_resolve_do_iterator (gfc_code *code, gfc_symbol *sym, bool add_clause)
   12695              : {
   12696        33424 :   if (omp_current_ctx == NULL)
   12697              :     return;
   12698              : 
   12699        13113 :   int i = omp_current_do_collapse;
   12700        13113 :   gfc_code *c = omp_current_do_code;
   12701              : 
   12702        13113 :   if (sym->attr.threadprivate)
   12703              :     return;
   12704              : 
   12705              :   /* !$omp do and !$omp parallel do iteration variable is predetermined
   12706              :      private just in the !$omp do resp. !$omp parallel do construct,
   12707              :      with no implications for the outer parallel constructs.  */
   12708              : 
   12709        17948 :   while (i-- >= 1 && c)
   12710              :     {
   12711         9502 :       if (code == c)
   12712              :         return;
   12713         4835 :       c = find_nested_loop_in_chain (c->block->next);
   12714         4835 :       if (c && (c->op == EXEC_OMP_TILE || c->op == EXEC_OMP_UNROLL))
   12715              :         return;
   12716              :     }
   12717              : 
   12718              :   /* An openacc context may represent a data clause.  Abort if so.  */
   12719         8446 :   if (!omp_current_ctx->is_openmp && !oacc_is_loop (omp_current_ctx->code))
   12720              :     return;
   12721              : 
   12722         7468 :   if (omp_current_ctx->sharing_clauses->contains (sym))
   12723              :     return;
   12724              : 
   12725         6466 :   if (! omp_current_ctx->private_iterators->add (sym) && add_clause)
   12726              :     {
   12727         6276 :       gfc_omp_clauses *omp_clauses = omp_current_ctx->code->ext.omp_clauses;
   12728         6276 :       gfc_omp_namelist *p;
   12729              : 
   12730         6276 :       p = gfc_get_omp_namelist ();
   12731         6276 :       p->sym = sym;
   12732         6276 :       p->where = omp_current_ctx->code->loc;
   12733         6276 :       p->next = omp_clauses->lists[OMP_LIST_PRIVATE];
   12734         6276 :       omp_clauses->lists[OMP_LIST_PRIVATE] = p;
   12735              :     }
   12736              : }
   12737              : 
   12738              : static void
   12739          775 : handle_local_var (gfc_symbol *sym)
   12740              : {
   12741          775 :   if (sym->attr.flavor != FL_VARIABLE
   12742          180 :       || sym->as != NULL
   12743          139 :       || (sym->ts.type != BT_INTEGER && sym->ts.type != BT_REAL))
   12744              :     return;
   12745           72 :   gfc_resolve_do_iterator (sym->ns->code, sym, false);
   12746              : }
   12747              : 
   12748              : void
   12749       350685 : gfc_resolve_omp_local_vars (gfc_namespace *ns)
   12750              : {
   12751       350685 :   if (omp_current_ctx)
   12752          469 :     gfc_traverse_ns (ns, handle_local_var);
   12753       350685 : }
   12754              : 
   12755              : 
   12756              : /* Error checking on intervening code uses a code walker.  */
   12757              : 
   12758              : struct icode_error_state
   12759              : {
   12760              :   const char *name;
   12761              :   bool errorp;
   12762              :   gfc_code *nested;
   12763              :   gfc_code *next;
   12764              : };
   12765              : 
   12766              : static int
   12767          944 : icode_code_error_callback (gfc_code **codep,
   12768              :                            int *walk_subtrees ATTRIBUTE_UNUSED, void *opaque)
   12769              : {
   12770          944 :   gfc_code *code = *codep;
   12771          944 :   icode_error_state *state = (icode_error_state *)opaque;
   12772              : 
   12773              :   /* gfc_code_walker walks down CODE's next chain as well as
   12774              :      walking things that are actually nested in CODE.  We need to
   12775              :      special-case traversal of outer blocks, so stop immediately if we
   12776              :      are heading down such a next chain.  */
   12777          944 :   if (code == state->next)
   12778              :     return 1;
   12779              : 
   12780          647 :   switch (code->op)
   12781              :     {
   12782            1 :     case EXEC_DO:
   12783            1 :     case EXEC_DO_WHILE:
   12784            1 :     case EXEC_DO_CONCURRENT:
   12785            1 :       gfc_error ("%s cannot contain loop in intervening code at %L",
   12786              :                  state->name, &code->loc);
   12787            1 :       state->errorp = true;
   12788            1 :       break;
   12789            0 :     case EXEC_CYCLE:
   12790            0 :     case EXEC_EXIT:
   12791              :       /* Errors have already been diagnosed in match_exit_cycle.  */
   12792            0 :       state->errorp = true;
   12793            0 :       break;
   12794              :     case EXEC_OMP_ASSUME:
   12795              :     case EXEC_OMP_METADIRECTIVE:
   12796              :       /* Per OpenMP 6.0, some non-executable directives are allowed in
   12797              :          intervening code.  */
   12798              :       break;
   12799          477 :     case EXEC_CALL:
   12800              :       /* Per OpenMP 5.2, the "omp_" prefix is reserved, so we don't have to
   12801              :          consider the possibility that some locally-bound definition
   12802              :          overrides the runtime routine.  */
   12803          477 :       if (code->resolved_sym
   12804          477 :           && omp_runtime_api_procname (code->resolved_sym->name))
   12805              :         {
   12806            1 :           gfc_error ("%s cannot contain OpenMP API call in intervening code "
   12807              :                      "at %L",
   12808              :                  state->name, &code->loc);
   12809            1 :           state->errorp = true;
   12810              :         }
   12811              :       break;
   12812          168 :     default:
   12813          168 :       if (code->op >= EXEC_OMP_FIRST_OPENMP_EXEC
   12814          168 :           && code->op <= EXEC_OMP_LAST_OPENMP_EXEC)
   12815              :         {
   12816            2 :           gfc_error ("%s cannot contain OpenMP directive in intervening code "
   12817              :                      "at %L",
   12818              :                      state->name, &code->loc);
   12819            2 :           state->errorp = true;
   12820              :         }
   12821              :     }
   12822              :   return 0;
   12823              : }
   12824              : 
   12825              : static int
   12826         1081 : icode_expr_error_callback (gfc_expr **expr,
   12827              :                            int *walk_subtrees ATTRIBUTE_UNUSED, void *opaque)
   12828              : {
   12829         1081 :   icode_error_state *state = (icode_error_state *)opaque;
   12830              : 
   12831         1081 :   switch ((*expr)->expr_type)
   12832              :     {
   12833              :       /* As for EXPR_CALL with "omp_"-prefixed symbols.  */
   12834            2 :     case EXPR_FUNCTION:
   12835            2 :       {
   12836            2 :         gfc_symbol *sym = (*expr)->value.function.esym;
   12837            2 :         if (sym && omp_runtime_api_procname (sym->name))
   12838              :           {
   12839            1 :             gfc_error ("%s cannot contain OpenMP API call in intervening code "
   12840              :                        "at %L",
   12841            1 :                        state->name, &((*expr)->where));
   12842            1 :             state->errorp = true;
   12843              :           }
   12844              :         }
   12845              : 
   12846              :       break;
   12847              :     default:
   12848              :       break;
   12849              :     }
   12850              : 
   12851              :   /* FIXME: The description of canonical loop form in the OpenMP standard
   12852              :      also says "array expressions" are not permitted in intervening code.
   12853              :      That term is not defined in either the OpenMP spec or the Fortran
   12854              :      standard, although the latter uses it informally to refer to any
   12855              :      expression that is not scalar-valued.  It is also apparently not the
   12856              :      thing GCC internally calls EXPR_ARRAY.  It seems the intent of the
   12857              :      OpenMP restriction is to disallow elemental operations/intrinsics
   12858              :      (including things that are not expressions, like assignment
   12859              :      statements) that generate implicit loops over array operands
   12860              :      (even if the result is a scalar), but even if the spec said
   12861              :      that there is no list of all the cases that would be forbidden.
   12862              :      This is OpenMP issue 3326.  */
   12863              : 
   12864         1081 :   return 0;
   12865              : }
   12866              : 
   12867              : static void
   12868          267 : diagnose_intervening_code_errors_1 (gfc_code *chain,
   12869              :                                     struct icode_error_state *state)
   12870              : {
   12871          267 :   gfc_code *code;
   12872         1080 :   for (code = chain; code; code = code->next)
   12873              :     {
   12874          813 :       if (code == state->nested)
   12875              :         /* Do not walk the nested loop or its body, we are only
   12876              :            interested in intervening code.  */
   12877              :         ;
   12878          636 :       else if (code->op == EXEC_BLOCK
   12879          636 :                && find_nested_loop_in_block (code) == state->nested)
   12880              :         /* This block contains the nested loop, recurse on its
   12881              :            statements.  */
   12882              :         {
   12883           90 :           gfc_namespace* ns = code->ext.block.ns;
   12884           90 :           diagnose_intervening_code_errors_1 (ns->code, state);
   12885              :         }
   12886              :       else
   12887              :         /* Treat the whole statement as a unit.  */
   12888              :         {
   12889          546 :           gfc_code *temp = state->next;
   12890          546 :           state->next = code->next;
   12891          546 :           gfc_code_walker (&code, icode_code_error_callback,
   12892              :                            icode_expr_error_callback, state);
   12893          546 :           state->next = temp;
   12894              :         }
   12895              :     }
   12896          267 : }
   12897              : 
   12898              : /* Diagnose intervening code errors in BLOCK with nested loop NESTED.
   12899              :    NAME is the user-friendly name of the OMP directive, used for error
   12900              :    messages.  Returns true if any error was found.  */
   12901              : static bool
   12902          177 : diagnose_intervening_code_errors (gfc_code *chain, const char *name,
   12903              :                                   gfc_code *nested)
   12904              : {
   12905          177 :   struct icode_error_state state;
   12906          177 :   state.name = name;
   12907          177 :   state.errorp = false;
   12908          177 :   state.nested = nested;
   12909          177 :   state.next = NULL;
   12910            0 :   diagnose_intervening_code_errors_1 (chain, &state);
   12911          177 :   return state.errorp;
   12912              : }
   12913              : 
   12914              : /* Helper function for restructure_intervening_code:  wrap CHAIN in
   12915              :    a marker to indicate that it is a structured block sequence.  That
   12916              :    information will be used later on (in omp-low.cc) for error checking.  */
   12917              : static gfc_code *
   12918          461 : make_structured_block (gfc_code *chain)
   12919              : {
   12920          461 :   gcc_assert (chain);
   12921          461 :   gfc_namespace *ns = gfc_build_block_ns (gfc_current_ns);
   12922          461 :   gfc_code *result = gfc_get_code (EXEC_BLOCK);
   12923          461 :   result->op = EXEC_BLOCK;
   12924          461 :   result->ext.block.ns = ns;
   12925          461 :   result->ext.block.assoc = NULL;
   12926          461 :   result->loc = chain->loc;
   12927          461 :   ns->omp_structured_block = 1;
   12928          461 :   ns->code = chain;
   12929          461 :   return result;
   12930              : }
   12931              : 
   12932              : /* Push intervening code surrounding a loop, including nested scopes,
   12933              :    into the body of the loop.  CHAINP is the pointer to the head of
   12934              :    the next-chain to scan, OUTER_LOOP is the EXEC_DO for the next outer
   12935              :    loop level, and COLLAPSE is the number of nested loops we need to
   12936              :    process.
   12937              :    Note that CHAINP may point at outer_loop->block->next when we
   12938              :    are scanning the body of a loop, but if there is an intervening block
   12939              :    CHAINP points into the block's chain rather than its enclosing outer
   12940              :    loop.  This is why OUTER_LOOP is passed separately.  */
   12941              : static gfc_code *
   12942         7191 : restructure_intervening_code (gfc_code **chainp, gfc_code *outer_loop,
   12943              :                               int count)
   12944              : {
   12945         7191 :   gfc_code *code;
   12946         7191 :   gfc_code *head = *chainp;
   12947         7191 :   gfc_code *tail = NULL;
   12948         7191 :   gfc_code *innermost_loop = NULL;
   12949              : 
   12950         7455 :   for (code = *chainp; code; code = code->next, chainp = &(*chainp)->next)
   12951              :     {
   12952         7455 :       if (code->op == EXEC_DO)
   12953              :         {
   12954              :           /* Cut CODE free from its chain, leaving the ends dangling.  */
   12955         7107 :           *chainp = NULL;
   12956         7107 :           tail = code->next;
   12957         7107 :           code->next = NULL;
   12958              : 
   12959         7107 :           if (count == 1)
   12960              :             innermost_loop = code;
   12961              :           else
   12962         2090 :             innermost_loop
   12963         2090 :               = restructure_intervening_code (&code->block->next,
   12964              :                                               code, count - 1);
   12965              :           break;
   12966              :         }
   12967          348 :       else if (code->op == EXEC_BLOCK
   12968          348 :                && find_nested_loop_in_block (code))
   12969              :         {
   12970           84 :           gfc_namespace *ns = code->ext.block.ns;
   12971              : 
   12972              :           /* Cut CODE free from its chain, leaving the ends dangling.  */
   12973           84 :           *chainp = NULL;
   12974           84 :           tail = code->next;
   12975           84 :           code->next = NULL;
   12976              : 
   12977           84 :           innermost_loop
   12978           84 :             = restructure_intervening_code (&ns->code, outer_loop,
   12979              :                                             count);
   12980              : 
   12981              :           /* At this point we have already pulled out the nested loop and
   12982              :              pointed outer_loop at it, and moved the intervening code that
   12983              :              was previously in the block into the body of innermost_loop.
   12984              :              Now we want to move the BLOCK itself so it wraps the entire
   12985              :              current body of innermost_loop.  */
   12986           84 :           ns->code = innermost_loop->block->next;
   12987           84 :           innermost_loop->block->next = code;
   12988           84 :           break;
   12989              :         }
   12990              :     }
   12991              : 
   12992         2174 :   gcc_assert (innermost_loop);
   12993              : 
   12994              :   /* Now we have split the intervening code into two parts:
   12995              :      head is the start of the part before the loop/block, terminating
   12996              :      at *chainp, and tail is the part after it.  Mark each part as
   12997              :      a structured block sequence, and splice the two parts around the
   12998              :      existing body of the innermost loop.  */
   12999         7191 :   if (head != code)
   13000              :     {
   13001          222 :       gfc_code *block = make_structured_block (head);
   13002          222 :       if (innermost_loop->block->next)
   13003          221 :         gfc_append_code (block, innermost_loop->block->next);
   13004          222 :       innermost_loop->block->next = block;
   13005              :     }
   13006         7191 :   if (tail)
   13007              :     {
   13008          239 :       gfc_code *block = make_structured_block (tail);
   13009          239 :       if (innermost_loop->block->next)
   13010          237 :         gfc_append_code (innermost_loop->block->next, block);
   13011              :       else
   13012            2 :         innermost_loop->block->next = block;
   13013              :     }
   13014              : 
   13015              :   /* For loops, finally splice CODE into OUTER_LOOP.  We already handled
   13016              :      relinking EXEC_BLOCK above.  */
   13017         7191 :   if (code->op == EXEC_DO && outer_loop)
   13018         7107 :     outer_loop->block->next = code;
   13019              : 
   13020         7191 :   return innermost_loop;
   13021              : }
   13022              : 
   13023              : /* CODE is an OMP loop construct.  Return true if VAR matches an iteration
   13024              :    variable outer to level DEPTH.  */
   13025              : static bool
   13026         8104 : is_outer_iteration_variable (gfc_code *code, int depth, gfc_symbol *var)
   13027              : {
   13028         8104 :   int i;
   13029         8104 :   gfc_code *do_code = code;
   13030              : 
   13031        12631 :   for (i = 1; i < depth; i++)
   13032              :     {
   13033         5028 :       do_code = find_nested_loop_in_chain (do_code->block->next);
   13034         5028 :       gcc_assert (do_code);
   13035         5028 :       if (do_code->op == EXEC_OMP_TILE || do_code->op == EXEC_OMP_UNROLL)
   13036              :         {
   13037           51 :           --i;
   13038           51 :           continue;
   13039              :         }
   13040         4977 :       gfc_symbol *ivar = do_code->ext.iterator->var->symtree->n.sym;
   13041         4977 :       if (var == ivar)
   13042              :         return true;
   13043              :     }
   13044              :   return false;
   13045              : }
   13046              : 
   13047              : /* Forward declaration for recursive functions.  */
   13048              : static gfc_code *
   13049              : check_nested_loop_in_block (gfc_code *block, gfc_expr *expr, gfc_symbol *sym,
   13050              :                             bool *bad);
   13051              : 
   13052              : /* Like find_nested_loop_in_chain, but additionally check that EXPR
   13053              :    does not reference any variables bound in intervening EXEC_BLOCKs
   13054              :    and that SYM is not bound in such intervening blocks.  Either EXPR or SYM
   13055              :    may be null.  Sets *BAD to true if either test fails.  */
   13056              : static gfc_code *
   13057        48249 : check_nested_loop_in_chain (gfc_code *chain, gfc_expr *expr, gfc_symbol *sym,
   13058              :                             bool *bad)
   13059              : {
   13060        51853 :   for (gfc_code *code = chain; code; code = code->next)
   13061              :     {
   13062        51565 :       if (code->op == EXEC_DO)
   13063              :         return code;
   13064         4123 :       else if (code->op == EXEC_OMP_TILE || code->op == EXEC_OMP_UNROLL)
   13065         1682 :         return check_nested_loop_in_chain (code->block->next, expr, sym, bad);
   13066         2441 :       else if (code->op == EXEC_BLOCK)
   13067              :         {
   13068          807 :           gfc_code *c = check_nested_loop_in_block (code, expr, sym, bad);
   13069          807 :           if (c)
   13070              :             return c;
   13071              :         }
   13072              :     }
   13073              :   return NULL;
   13074              : }
   13075              : 
   13076              : /* Code walker for block symtrees.  It doesn't take any kind of state
   13077              :    argument, so use a static variable.  */
   13078              : static struct check_nested_loop_in_block_state_t {
   13079              :   gfc_expr *expr;
   13080              :   gfc_symbol *sym;
   13081              :   bool *bad;
   13082              : } check_nested_loop_in_block_state;
   13083              : 
   13084              : static void
   13085          766 : check_nested_loop_in_block_symbol (gfc_symbol *sym)
   13086              : {
   13087          766 :   if (sym == check_nested_loop_in_block_state.sym
   13088          766 :       || (check_nested_loop_in_block_state.expr
   13089          567 :           && gfc_find_sym_in_expr (sym,
   13090              :                                    check_nested_loop_in_block_state.expr)))
   13091            5 :     *check_nested_loop_in_block_state.bad = true;
   13092          766 : }
   13093              : 
   13094              : /* Return the first nested DO loop in BLOCK, or NULL if there
   13095              :    isn't one.  Set *BAD to true if EXPR references any variables in BLOCK, or
   13096              :    SYM is bound in BLOCK.  Either EXPR or SYM may be null.  */
   13097              : static gfc_code *
   13098          807 : check_nested_loop_in_block (gfc_code *block, gfc_expr *expr,
   13099              :                             gfc_symbol *sym, bool *bad)
   13100              : {
   13101          807 :   gfc_namespace *ns;
   13102          807 :   gcc_assert (block->op == EXEC_BLOCK);
   13103          807 :   ns = block->ext.block.ns;
   13104          807 :   gcc_assert (ns);
   13105              : 
   13106              :   /* Skip the check if this block doesn't contain the nested loop, or
   13107              :      if we already know it's bad.  */
   13108          807 :   gfc_code *result = check_nested_loop_in_chain (ns->code, expr, sym, bad);
   13109          807 :   if (result && !*bad)
   13110              :     {
   13111          519 :       check_nested_loop_in_block_state.expr = expr;
   13112          519 :       check_nested_loop_in_block_state.sym = sym;
   13113          519 :       check_nested_loop_in_block_state.bad = bad;
   13114          519 :       gfc_traverse_ns (ns, check_nested_loop_in_block_symbol);
   13115          519 :       check_nested_loop_in_block_state.expr = NULL;
   13116          519 :       check_nested_loop_in_block_state.sym = NULL;
   13117          519 :       check_nested_loop_in_block_state.bad = NULL;
   13118              :     }
   13119          807 :   return result;
   13120              : }
   13121              : 
   13122              : /* CODE is an OMP loop construct.  Return true if EXPR references
   13123              :    any variables bound in intervening code, to level DEPTH.  */
   13124              : static bool
   13125        22780 : expr_uses_intervening_var (gfc_code *code, int depth, gfc_expr *expr)
   13126              : {
   13127        22780 :   int i;
   13128        22780 :   gfc_code *do_code = code;
   13129              : 
   13130        58339 :   for (i = 0; i < depth; i++)
   13131              :     {
   13132        35562 :       bool bad = false;
   13133        35562 :       do_code = check_nested_loop_in_chain (do_code->block->next,
   13134              :                                             expr, NULL, &bad);
   13135        35562 :       if (bad)
   13136            3 :         return true;
   13137              :     }
   13138              :   return false;
   13139              : }
   13140              : 
   13141              : /* CODE is an OMP loop construct.  Return true if SYM is bound in
   13142              :    intervening code, to level DEPTH.  */
   13143              : static bool
   13144         7603 : is_intervening_var (gfc_code *code, int depth, gfc_symbol *sym)
   13145              : {
   13146         7603 :   int i;
   13147         7603 :   gfc_code *do_code = code;
   13148              : 
   13149        19481 :   for (i = 0; i < depth; i++)
   13150              :     {
   13151        11880 :       bool bad = false;
   13152        11880 :       do_code = check_nested_loop_in_chain (do_code->block->next,
   13153              :                                             NULL, sym, &bad);
   13154        11880 :       if (bad)
   13155            2 :         return true;
   13156              :     }
   13157              :   return false;
   13158              : }
   13159              : 
   13160              : /* CODE is an OMP loop construct.  Return true if EXPR does not reference
   13161              :    any iteration variables outer to level DEPTH.  */
   13162              : static bool
   13163        23859 : expr_is_invariant (gfc_code *code, int depth, gfc_expr *expr)
   13164              : {
   13165        23859 :   int i;
   13166        23859 :   gfc_code *do_code = code;
   13167              : 
   13168        37181 :   for (i = 1; i < depth; i++)
   13169              :     {
   13170        14388 :       do_code = find_nested_loop_in_chain (do_code->block->next);
   13171        14388 :       gcc_assert (do_code);
   13172        14388 :       if (do_code->op == EXEC_OMP_TILE || do_code->op == EXEC_OMP_UNROLL)
   13173              :         {
   13174          136 :           --i;
   13175          136 :           continue;
   13176              :         }
   13177        14252 :       gfc_symbol *ivar = do_code->ext.iterator->var->symtree->n.sym;
   13178        14252 :       if (gfc_find_sym_in_expr (ivar, expr))
   13179              :         return false;
   13180              :     }
   13181              :   return true;
   13182              : }
   13183              : 
   13184              : /* CODE is an OMP loop construct.  Return true if EXPR matches one of the
   13185              :    canonical forms for a bound expression.  It may include references to
   13186              :    an iteration variable outer to level DEPTH; set OUTER_VARP if so.  */
   13187              : static bool
   13188        15197 : bound_expr_is_canonical (gfc_code *code, int depth, gfc_expr *expr,
   13189              :                          gfc_symbol **outer_varp)
   13190              : {
   13191        15197 :   gfc_expr *expr2 = NULL;
   13192              : 
   13193              :   /* Rectangular case.  */
   13194        15197 :   if (depth == 0 || expr_is_invariant (code, depth, expr))
   13195              :     return true;
   13196              : 
   13197              :   /* Any simple variable that didn't pass expr_is_invariant must be
   13198              :      an outer_var.  */
   13199          568 :   if (expr->expr_type == EXPR_VARIABLE && expr->rank == 0)
   13200              :     {
   13201           63 :       *outer_varp = expr->symtree->n.sym;
   13202           63 :       return true;
   13203              :     }
   13204              : 
   13205              :   /* All other permitted forms are binary operators.  */
   13206          505 :   if (expr->expr_type != EXPR_OP)
   13207              :     return false;
   13208              : 
   13209              :   /* Check for plus/minus a loop invariant expr.  */
   13210          503 :   if (expr->value.op.op == INTRINSIC_PLUS
   13211          503 :       || expr->value.op.op == INTRINSIC_MINUS)
   13212              :     {
   13213          483 :       if (expr_is_invariant (code, depth, expr->value.op.op1))
   13214           48 :         expr2 = expr->value.op.op2;
   13215          435 :       else if (expr_is_invariant (code, depth, expr->value.op.op2))
   13216          434 :         expr2 = expr->value.op.op1;
   13217              :       else
   13218              :         return false;
   13219              :     }
   13220              :   else
   13221              :     expr2 = expr;
   13222              : 
   13223              :   /* Check for a product with a loop-invariant expr.  */
   13224          502 :   if (expr2->expr_type == EXPR_OP
   13225           96 :       && expr2->value.op.op == INTRINSIC_TIMES)
   13226              :     {
   13227           96 :       if (expr_is_invariant (code, depth, expr2->value.op.op1))
   13228           40 :         expr2 = expr2->value.op.op2;
   13229           56 :       else if (expr_is_invariant (code, depth, expr2->value.op.op2))
   13230           53 :         expr2 = expr2->value.op.op1;
   13231              :       else
   13232              :         return false;
   13233              :     }
   13234              : 
   13235              :   /* What's left must be a reference to an outer loop variable.  */
   13236          499 :   if (expr2->expr_type == EXPR_VARIABLE
   13237          499 :       && expr2->rank == 0
   13238          998 :       && is_outer_iteration_variable (code, depth, expr2->symtree->n.sym))
   13239              :     {
   13240          499 :       *outer_varp = expr2->symtree->n.sym;
   13241          499 :       return true;
   13242              :     }
   13243              : 
   13244              :   return false;
   13245              : }
   13246              : 
   13247              : static void
   13248         5441 : resolve_omp_do (gfc_code *code)
   13249              : {
   13250         5441 :   gfc_code *do_code, *next;
   13251         5441 :   int i, count, non_generated_count;
   13252         5441 :   gfc_omp_namelist *n;
   13253         5441 :   gfc_symbol *dovar;
   13254         5441 :   const char *name;
   13255         5441 :   bool is_simd = false;
   13256         5441 :   bool errorp = false;
   13257         5441 :   bool perfect_nesting_errorp = false;
   13258         5441 :   bool imperfect = false;
   13259              : 
   13260         5441 :   switch (code->op)
   13261              :     {
   13262              :     case EXEC_OMP_DISTRIBUTE: name = "!$OMP DISTRIBUTE"; break;
   13263           49 :     case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
   13264           49 :       name = "!$OMP DISTRIBUTE PARALLEL DO";
   13265           49 :       break;
   13266           32 :     case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
   13267           32 :       name = "!$OMP DISTRIBUTE PARALLEL DO SIMD";
   13268           32 :       is_simd = true;
   13269           32 :       break;
   13270           50 :     case EXEC_OMP_DISTRIBUTE_SIMD:
   13271           50 :       name = "!$OMP DISTRIBUTE SIMD";
   13272           50 :       is_simd = true;
   13273           50 :       break;
   13274         1338 :     case EXEC_OMP_DO: name = "!$OMP DO"; break;
   13275          136 :     case EXEC_OMP_DO_SIMD: name = "!$OMP DO SIMD"; is_simd = true; break;
   13276           64 :     case EXEC_OMP_LOOP: name = "!$OMP LOOP"; break;
   13277         1220 :     case EXEC_OMP_PARALLEL_DO: name = "!$OMP PARALLEL DO"; break;
   13278          304 :     case EXEC_OMP_PARALLEL_DO_SIMD:
   13279          304 :       name = "!$OMP PARALLEL DO SIMD";
   13280          304 :       is_simd = true;
   13281          304 :       break;
   13282           46 :     case EXEC_OMP_PARALLEL_LOOP: name = "!$OMP PARALLEL LOOP"; break;
   13283            7 :     case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
   13284            7 :       name = "!$OMP PARALLEL MASKED TASKLOOP";
   13285            7 :       break;
   13286           10 :     case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
   13287           10 :       name = "!$OMP PARALLEL MASKED TASKLOOP SIMD";
   13288           10 :       is_simd = true;
   13289           10 :       break;
   13290           12 :     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
   13291           12 :       name = "!$OMP PARALLEL MASTER TASKLOOP";
   13292           12 :       break;
   13293           18 :     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
   13294           18 :       name = "!$OMP PARALLEL MASTER TASKLOOP SIMD";
   13295           18 :       is_simd = true;
   13296           18 :       break;
   13297            8 :     case EXEC_OMP_MASKED_TASKLOOP: name = "!$OMP MASKED TASKLOOP"; break;
   13298           14 :     case EXEC_OMP_MASKED_TASKLOOP_SIMD:
   13299           14 :       name = "!$OMP MASKED TASKLOOP SIMD";
   13300           14 :       is_simd = true;
   13301           14 :       break;
   13302           14 :     case EXEC_OMP_MASTER_TASKLOOP: name = "!$OMP MASTER TASKLOOP"; break;
   13303           19 :     case EXEC_OMP_MASTER_TASKLOOP_SIMD:
   13304           19 :       name = "!$OMP MASTER TASKLOOP SIMD";
   13305           19 :       is_simd = true;
   13306           19 :       break;
   13307          786 :     case EXEC_OMP_SIMD: name = "!$OMP SIMD"; is_simd = true; break;
   13308           88 :     case EXEC_OMP_TARGET_PARALLEL_DO: name = "!$OMP TARGET PARALLEL DO"; break;
   13309           20 :     case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
   13310           20 :       name = "!$OMP TARGET PARALLEL DO SIMD";
   13311           20 :       is_simd = true;
   13312           20 :       break;
   13313           16 :     case EXEC_OMP_TARGET_PARALLEL_LOOP:
   13314           16 :       name = "!$OMP TARGET PARALLEL LOOP";
   13315           16 :       break;
   13316           33 :     case EXEC_OMP_TARGET_SIMD:
   13317           33 :       name = "!$OMP TARGET SIMD";
   13318           33 :       is_simd = true;
   13319           33 :       break;
   13320           20 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
   13321           20 :       name = "!$OMP TARGET TEAMS DISTRIBUTE";
   13322           20 :       break;
   13323           77 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
   13324           77 :       name = "!$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO";
   13325           77 :       break;
   13326           38 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
   13327           38 :       name = "!$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD";
   13328           38 :       is_simd = true;
   13329           38 :       break;
   13330           20 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
   13331           20 :       name = "!$OMP TARGET TEAMS DISTRIBUTE SIMD";
   13332           20 :       is_simd = true;
   13333           20 :       break;
   13334           19 :     case EXEC_OMP_TARGET_TEAMS_LOOP: name = "!$OMP TARGET TEAMS LOOP"; break;
   13335           69 :     case EXEC_OMP_TASKLOOP: name = "!$OMP TASKLOOP"; break;
   13336           38 :     case EXEC_OMP_TASKLOOP_SIMD:
   13337           38 :       name = "!$OMP TASKLOOP SIMD";
   13338           38 :       is_simd = true;
   13339           38 :       break;
   13340           20 :     case EXEC_OMP_TEAMS_DISTRIBUTE: name = "!$OMP TEAMS DISTRIBUTE"; break;
   13341           39 :     case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
   13342           39 :       name = "!$OMP TEAMS DISTRIBUTE PARALLEL DO";
   13343           39 :       break;
   13344           61 :     case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
   13345           61 :       name = "!$OMP TEAMS DISTRIBUTE PARALLEL DO SIMD";
   13346           61 :       is_simd = true;
   13347           61 :       break;
   13348           42 :     case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
   13349           42 :       name = "!$OMP TEAMS DISTRIBUTE SIMD";
   13350           42 :       is_simd = true;
   13351           42 :       break;
   13352           48 :     case EXEC_OMP_TEAMS_LOOP: name = "!$OMP TEAMS LOOP"; break;
   13353          195 :     case EXEC_OMP_TILE: name = "!$OMP TILE"; break;
   13354          417 :     case EXEC_OMP_UNROLL: name = "!$OMP UNROLL"; break;
   13355            0 :     default: gcc_unreachable ();
   13356              :     }
   13357              : 
   13358         5441 :   if (code->ext.omp_clauses)
   13359         5441 :     resolve_omp_clauses (code, code->ext.omp_clauses, NULL);
   13360              : 
   13361         5441 :   if (code->op == EXEC_OMP_TILE && code->ext.omp_clauses->sizes_list == NULL)
   13362            0 :     gfc_error ("SIZES clause is required on !$OMP TILE construct at %L",
   13363              :                &code->loc);
   13364              : 
   13365         5441 :   do_code = code->block->next;
   13366         5441 :   if (code->ext.omp_clauses->orderedc)
   13367              :     count = code->ext.omp_clauses->orderedc;
   13368         5297 :   else if (code->ext.omp_clauses->sizes_list)
   13369          195 :     count = gfc_expr_list_len (code->ext.omp_clauses->sizes_list);
   13370              :   else
   13371              :     {
   13372         5102 :       count = code->ext.omp_clauses->collapse;
   13373         5102 :       if (count <= 0)
   13374              :         count = 1;
   13375              :     }
   13376              : 
   13377         5441 :   non_generated_count = count;
   13378              :   /* While the spec defines the loop nest depth independently of the COLLAPSE
   13379              :      clause, in practice the middle end only pays attention to the COLLAPSE
   13380              :      depth and treats any further inner loops as the final-loop-body.  So
   13381              :      here we also check canonical loop nest form only for the number of
   13382              :      outer loops specified by the COLLAPSE clause too.  */
   13383         8081 :   for (i = 1; i <= count; i++)
   13384              :     {
   13385         8081 :       gfc_symbol *start_var = NULL, *end_var = NULL;
   13386              :       /* Parse errors are not recoverable.  */
   13387         8081 :       if (do_code->op == EXEC_DO_WHILE)
   13388              :         {
   13389            6 :           gfc_error ("%s cannot be a DO WHILE or DO without loop control "
   13390              :                      "at %L", name, &do_code->loc);
   13391          106 :           goto fail;
   13392              :         }
   13393         8075 :       if (do_code->op == EXEC_DO_CONCURRENT)
   13394              :         {
   13395            4 :           gfc_error ("%s cannot be a DO CONCURRENT loop at %L", name,
   13396              :                      &do_code->loc);
   13397            4 :           goto fail;
   13398              :         }
   13399         8071 :       if (do_code->op == EXEC_OMP_TILE || do_code->op == EXEC_OMP_UNROLL)
   13400              :         {
   13401          466 :           if (do_code->op == EXEC_OMP_UNROLL)
   13402              :             {
   13403          308 :               if (!do_code->ext.omp_clauses->partial)
   13404              :                 {
   13405           53 :                   gfc_error ("Generated loop of UNROLL construct at %L "
   13406              :                              "without PARTIAL clause does not have "
   13407              :                              "canonical form", &do_code->loc);
   13408           53 :                   goto fail;
   13409              :                 }
   13410          255 :               else if (i != count)
   13411              :                 {
   13412            5 :                   gfc_error ("UNROLL construct at %L with PARTIAL clause "
   13413              :                              "generates just one loop with canonical form "
   13414              :                              "but %d loops are needed",
   13415            5 :                              &do_code->loc, count - i + 1);
   13416            5 :                   goto fail;
   13417              :                 }
   13418              :             }
   13419          158 :           else if (do_code->op == EXEC_OMP_TILE)
   13420              :             {
   13421          158 :               if (do_code->ext.omp_clauses->sizes_list == NULL)
   13422              :                 /* This should have been diagnosed earlier already.  */
   13423            0 :                 return;
   13424          158 :               int l = gfc_expr_list_len (do_code->ext.omp_clauses->sizes_list);
   13425          158 :               if (count - i + 1 > l)
   13426              :                 {
   13427           14 :                   gfc_error ("TILE construct at %L generates %d loops "
   13428              :                              "with canonical form but %d loops are needed",
   13429              :                              &do_code->loc, l, count - i + 1);
   13430           14 :                   goto fail;
   13431              :                 }
   13432              :             }
   13433          394 :           if (do_code->ext.omp_clauses && do_code->ext.omp_clauses->erroneous)
   13434           17 :             goto fail;
   13435          377 :           if (imperfect && !perfect_nesting_errorp)
   13436              :             {
   13437            4 :               sorry_at (gfc_get_location (&do_code->loc),
   13438              :                         "Imperfectly nested loop using generated loops");
   13439            4 :               errorp = true;
   13440              :             }
   13441          377 :           if (non_generated_count == count)
   13442          329 :             non_generated_count = i - 1;
   13443          377 :           --i;
   13444          377 :           do_code = do_code->block->next;
   13445          377 :           continue;
   13446          377 :         }
   13447         7605 :       gcc_assert (do_code->op == EXEC_DO);
   13448         7605 :       if (do_code->ext.iterator->var->ts.type != BT_INTEGER)
   13449              :         {
   13450            3 :           gfc_error ("%s iteration variable must be of type integer at %L",
   13451              :                      name, &do_code->loc);
   13452            3 :           errorp = true;
   13453              :         }
   13454         7605 :       dovar = do_code->ext.iterator->var->symtree->n.sym;
   13455         7605 :       if (dovar->attr.threadprivate)
   13456              :         {
   13457            0 :           gfc_error ("%s iteration variable must not be THREADPRIVATE "
   13458              :                      "at %L", name, &do_code->loc);
   13459            0 :           errorp = true;
   13460              :         }
   13461         7605 :       if (code->ext.omp_clauses)
   13462       304200 :         for (enum gfc_omp_list_type list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
   13463       296595 :              list = gfc_omp_list_type (list + 1))
   13464        97773 :           if (!is_simd || code->ext.omp_clauses->collapse > 1
   13465       296595 :               ? (list != OMP_LIST_PRIVATE && list != OMP_LIST_LASTPRIVATE
   13466       255177 :                   && list != OMP_LIST_ALLOCATE)
   13467        41418 :               : (list != OMP_LIST_PRIVATE && list != OMP_LIST_LASTPRIVATE
   13468        41418 :                  && list != OMP_LIST_ALLOCATE && list != OMP_LIST_LINEAR))
   13469       277104 :             for (n = code->ext.omp_clauses->lists[list]; n; n = n->next)
   13470         4386 :               if (dovar == n->sym)
   13471              :                 {
   13472            5 :                   if (!is_simd || code->ext.omp_clauses->collapse > 1)
   13473            4 :                     gfc_error ("%s iteration variable present on clause "
   13474              :                                "other than PRIVATE, LASTPRIVATE or "
   13475              :                                "ALLOCATE at %L", name, &do_code->loc);
   13476              :                   else
   13477            1 :                     gfc_error ("%s iteration variable present on clause "
   13478              :                                "other than PRIVATE, LASTPRIVATE, ALLOCATE or "
   13479              :                                "LINEAR at %L", name, &do_code->loc);
   13480              :                   errorp = true;
   13481              :                 }
   13482         7605 :       if (is_outer_iteration_variable (code, i, dovar))
   13483              :         {
   13484            2 :           gfc_error ("%s iteration variable used in more than one loop at %L",
   13485              :                      name, &do_code->loc);
   13486            2 :           errorp = true;
   13487              :         }
   13488         7603 :       else if (is_intervening_var (code, i, dovar))
   13489              :         {
   13490            2 :           gfc_error ("%s iteration variable at %L is bound in "
   13491              :                      "intervening code",
   13492              :                      name, &do_code->loc);
   13493            2 :           errorp = true;
   13494              :         }
   13495         7601 :       else if (!bound_expr_is_canonical (code, i,
   13496         7601 :                                          do_code->ext.iterator->start,
   13497              :                                          &start_var))
   13498              :         {
   13499            4 :           gfc_error ("%s loop start expression not in canonical form at %L",
   13500              :                      name, &do_code->loc);
   13501            4 :           errorp = true;
   13502              :         }
   13503         7597 :       else if (expr_uses_intervening_var (code, i,
   13504         7597 :                                           do_code->ext.iterator->start))
   13505              :         {
   13506            1 :           gfc_error ("%s loop start expression at %L uses variable bound in "
   13507              :                      "intervening code",
   13508              :                      name, &do_code->loc);
   13509            1 :           errorp = true;
   13510              :         }
   13511         7596 :       else if (!bound_expr_is_canonical (code, i,
   13512         7596 :                                          do_code->ext.iterator->end,
   13513              :                                          &end_var))
   13514              :         {
   13515            2 :           gfc_error ("%s loop end expression not in canonical form at %L",
   13516              :                      name, &do_code->loc);
   13517            2 :           errorp = true;
   13518              :         }
   13519         7594 :       else if (expr_uses_intervening_var (code, i,
   13520         7594 :                                           do_code->ext.iterator->end))
   13521              :         {
   13522            1 :           gfc_error ("%s loop end expression at %L uses variable bound in "
   13523              :                      "intervening code",
   13524              :                      name, &do_code->loc);
   13525            1 :           errorp = true;
   13526              :         }
   13527         7593 :       else if (start_var && end_var && start_var != end_var)
   13528              :         {
   13529            1 :           gfc_error ("%s loop bounds reference different "
   13530              :                      "iteration variables at %L", name, &do_code->loc);
   13531            1 :           errorp = true;
   13532              :         }
   13533         7592 :       else if (!expr_is_invariant (code, i, do_code->ext.iterator->step))
   13534              :         {
   13535            3 :           gfc_error ("%s loop increment not in canonical form at %L",
   13536              :                      name, &do_code->loc);
   13537            3 :           errorp = true;
   13538              :         }
   13539         7589 :       else if (expr_uses_intervening_var (code, i,
   13540         7589 :                                           do_code->ext.iterator->step))
   13541              :         {
   13542            1 :           gfc_error ("%s loop increment expression at %L uses variable "
   13543              :                      "bound in intervening code",
   13544              :                      name, &do_code->loc);
   13545            1 :           errorp = true;
   13546              :         }
   13547         7605 :       if (start_var || end_var)
   13548              :         {
   13549          528 :           code->ext.omp_clauses->non_rectangular = 1;
   13550          528 :           if (i > non_generated_count)
   13551              :             {
   13552            3 :               sorry_at (gfc_get_location (&do_code->loc),
   13553              :                         "Non-rectangular loops from generated loops "
   13554              :                         "unsupported");
   13555            3 :               errorp = true;
   13556              :             }
   13557              :         }
   13558              : 
   13559              :       /* Only parse loop body into nested loop and intervening code if
   13560              :          there are supposed to be more loops in the nest to collapse.  */
   13561         7605 :       if (i == count)
   13562              :         break;
   13563              : 
   13564         2270 :       next = find_nested_loop_in_chain (do_code->block->next);
   13565              : 
   13566         2270 :       if (!next)
   13567              :         {
   13568              :           /* Parse error, can't recover from this.  */
   13569            7 :           gfc_error ("not enough DO loops for collapsed %s (level %d) at %L",
   13570              :                      name, i, &code->loc);
   13571            7 :           goto fail;
   13572              :         }
   13573         2263 :       else if (next != do_code->block->next
   13574         2103 :                || (next->next && next->next->op != EXEC_CONTINUE))
   13575              :         /* Imperfectly nested loop found.  */
   13576              :         {
   13577              :           /* Only diagnose violation of imperfect nesting constraints once.  */
   13578          177 :           if (!perfect_nesting_errorp)
   13579              :             {
   13580          176 :               if (code->ext.omp_clauses->orderedc)
   13581              :                 {
   13582            3 :                   gfc_error ("%s inner loops must be perfectly nested with "
   13583              :                              "ORDERED clause at %L",
   13584              :                              name, &code->loc);
   13585            3 :                   perfect_nesting_errorp = true;
   13586              :                 }
   13587          173 :               else if (code->ext.omp_clauses->lists[OMP_LIST_REDUCTION_INSCAN])
   13588              :                 {
   13589            2 :                   gfc_error ("%s inner loops must be perfectly nested with "
   13590              :                              "REDUCTION INSCAN clause at %L",
   13591              :                              name, &code->loc);
   13592            2 :                   perfect_nesting_errorp = true;
   13593              :                 }
   13594          171 :               else if (code->op == EXEC_OMP_TILE)
   13595              :                 {
   13596            8 :                   gfc_error ("%s inner loops must be perfectly nested at %L",
   13597              :                              name, &code->loc);
   13598            8 :                   perfect_nesting_errorp = true;
   13599              :                 }
   13600           13 :               if (perfect_nesting_errorp)
   13601              :                 errorp = true;
   13602              :             }
   13603          177 :           if (diagnose_intervening_code_errors (do_code->block->next,
   13604              :                                                 name, next))
   13605            5 :             errorp = true;
   13606              :           imperfect = true;
   13607              :         }
   13608         2263 :       do_code = next;
   13609              :     }
   13610              : 
   13611              :   /* Give up now if we found any constraint violations.  */
   13612         5335 :   if (errorp)
   13613              :     {
   13614           48 :     fail:
   13615          154 :       if (code->ext.omp_clauses)
   13616          154 :         code->ext.omp_clauses->erroneous = 1;
   13617              :       return;
   13618              :     }
   13619              : 
   13620         5287 :   if (non_generated_count)
   13621         5017 :     restructure_intervening_code (&code->block->next, code,
   13622              :                                   non_generated_count);
   13623              : }
   13624              : 
   13625              : /* Resolve the context selector. In particular, SKIP_P is set to true,
   13626              :    the context can never be matched.  */
   13627              : 
   13628              : static void
   13629          785 : gfc_resolve_omp_context_selector (gfc_omp_set_selector *oss,
   13630              :                                   bool is_metadirective, bool *skip_p)
   13631              : {
   13632          785 :   if (skip_p)
   13633          324 :     *skip_p = false;
   13634         1488 :   for (gfc_omp_set_selector *set_selector = oss; set_selector;
   13635          703 :        set_selector = set_selector->next)
   13636         1514 :     for (gfc_omp_selector *os = set_selector->trait_selectors; os; os = os->next)
   13637              :       {
   13638          829 :         if (os->score)
   13639              :           {
   13640           52 :             if (!gfc_resolve_expr (os->score)
   13641           52 :                 || os->score->ts.type != BT_INTEGER
   13642          104 :                 || os->score->rank != 0)
   13643              :               {
   13644            0 :                 gfc_error ("%<score%> argument must be constant integer "
   13645            0 :                            "expression at %L", &os->score->where);
   13646            0 :                 gfc_free_expr (os->score);
   13647            0 :                 os->score = nullptr;
   13648              :               }
   13649           52 :             else if (os->score->expr_type == EXPR_CONSTANT
   13650           52 :                      && mpz_sgn (os->score->value.integer) < 0)
   13651              :               {
   13652            1 :                 gfc_error ("%<score%> argument must be non-negative at %L",
   13653              :                            &os->score->where);
   13654            1 :                 gfc_free_expr (os->score);
   13655            1 :                 os->score = nullptr;
   13656              :               }
   13657              :           }
   13658              : 
   13659          829 :         if (os->code == OMP_TRAIT_INVALID)
   13660              :           break;
   13661          811 :         enum omp_tp_type property_kind = omp_ts_map[os->code].tp_type;
   13662          811 :         gfc_omp_trait_property *otp = os->properties;
   13663              : 
   13664          811 :         if (!otp)
   13665          415 :           continue;
   13666          396 :         switch (property_kind)
   13667              :           {
   13668          148 :           case OMP_TRAIT_PROPERTY_DEV_NUM_EXPR:
   13669          148 :           case OMP_TRAIT_PROPERTY_BOOL_EXPR:
   13670          148 :             if (!gfc_resolve_expr (otp->expr)
   13671          147 :                 || (property_kind == OMP_TRAIT_PROPERTY_BOOL_EXPR
   13672          133 :                     && otp->expr->ts.type != BT_LOGICAL)
   13673          146 :                 || (property_kind == OMP_TRAIT_PROPERTY_DEV_NUM_EXPR
   13674           14 :                     && otp->expr->ts.type != BT_INTEGER)
   13675          146 :                 || otp->expr->rank != 0
   13676          294 :                 || (!is_metadirective && otp->expr->expr_type != EXPR_CONSTANT))
   13677              :               {
   13678            3 :                 if (is_metadirective)
   13679              :                   {
   13680            0 :                     if (property_kind == OMP_TRAIT_PROPERTY_BOOL_EXPR)
   13681            0 :                       gfc_error ("property must be a "
   13682              :                                  "logical expression at %L",
   13683            0 :                                  &otp->expr->where);
   13684              :                     else
   13685            0 :                       gfc_error ("property must be an "
   13686              :                                  "integer expression at %L",
   13687            0 :                                  &otp->expr->where);
   13688              :                   }
   13689              :                 else
   13690              :                   {
   13691            3 :                     if (property_kind == OMP_TRAIT_PROPERTY_BOOL_EXPR)
   13692            2 :                       gfc_error ("property must be a constant "
   13693              :                                  "logical expression at %L",
   13694            2 :                                  &otp->expr->where);
   13695              :                     else
   13696            1 :                       gfc_error ("property must be a constant "
   13697              :                                  "integer expression at %L",
   13698            1 :                                  &otp->expr->where);
   13699              :                   }
   13700              :                 /* Prevent later ICEs. */
   13701            3 :                 gfc_expr *e;
   13702            3 :                 if (property_kind == OMP_TRAIT_PROPERTY_BOOL_EXPR)
   13703            2 :                   e = gfc_get_logical_expr (gfc_default_logical_kind,
   13704            2 :                                             &otp->expr->where, true);
   13705              :                 else
   13706            1 :                   e = gfc_get_int_expr (gfc_default_integer_kind,
   13707            1 :                                         &otp->expr->where, 0);
   13708            3 :                 gfc_free_expr (otp->expr);
   13709            3 :                 otp->expr = e;
   13710            3 :                 continue;
   13711            3 :               }
   13712              :             /* Device number must be conforming, which includes
   13713              :                omp_initial_device (-1), omp_invalid_device (-4),
   13714              :                and omp_default_device (-5).  */
   13715          145 :             if (property_kind == OMP_TRAIT_PROPERTY_DEV_NUM_EXPR
   13716           14 :                 && otp->expr->expr_type == EXPR_CONSTANT
   13717            5 :                 && mpz_sgn (otp->expr->value.integer) < 0
   13718            3 :                 && mpz_cmp_si (otp->expr->value.integer, -1) != 0
   13719            2 :                 && mpz_cmp_si (otp->expr->value.integer, -4) != 0
   13720            1 :                 && mpz_cmp_si (otp->expr->value.integer, -5) != 0)
   13721            1 :               gfc_error ("property must be a conforming device number at %L",
   13722              :                          &otp->expr->where);
   13723              :             break;
   13724              :           default:
   13725              :             break;
   13726              :           }
   13727              :         /* This only handles one specific case: User condition.
   13728              :            FIXME: Handle more cases by calling omp_context_selector_matches;
   13729              :            unfortunately, we cannot generate the tree here as, e.g., PARM_DECL
   13730              :            backend decl are not available at this stage - but might be used in,
   13731              :            e.g. user conditions. See PR122361.  */
   13732          393 :         if (skip_p && otp
   13733          145 :             && os->code == OMP_TRAIT_USER_CONDITION
   13734           88 :             && otp->expr->expr_type == EXPR_CONSTANT
   13735           14 :             && otp->expr->value.logical == false)
   13736           12 :           *skip_p = true;
   13737              :       }
   13738          785 : }
   13739              : 
   13740              : 
   13741              : static void
   13742          145 : resolve_omp_metadirective (gfc_code *code, gfc_namespace *ns)
   13743              : {
   13744          145 :   gfc_omp_variant *variant = code->ext.omp_variants;
   13745          145 :   gfc_omp_variant *prev_variant = variant;
   13746              : 
   13747          469 :   while (variant)
   13748              :     {
   13749          324 :       bool skip;
   13750          324 :       gfc_resolve_omp_context_selector (variant->selectors, true, &skip);
   13751          324 :       gfc_code *variant_code = variant->code;
   13752          324 :       gfc_resolve_code (variant_code, ns);
   13753          324 :       if (skip)
   13754              :         {
   13755              :           /* The following should only be true if an error occurred
   13756              :              as the 'otherwise' clause should always match.  */
   13757           12 :           if (variant == code->ext.omp_variants && !variant->next)
   13758              :             break;
   13759           12 :           gfc_omp_variant *tmp = variant;
   13760           12 :           if (variant == code->ext.omp_variants)
   13761           11 :             variant = prev_variant = code->ext.omp_variants = variant->next;
   13762              :           else
   13763            1 :             variant = prev_variant->next = variant->next;
   13764           12 :           gfc_free_omp_set_selector_list (tmp->selectors);
   13765           12 :           free (tmp);
   13766              :         }
   13767              :       else
   13768              :         {
   13769          312 :           prev_variant = variant;
   13770          312 :           variant = variant->next;
   13771              :         }
   13772              :     }
   13773              :   /* Replace metadirective by its body if only 'nothing' remains.  */
   13774          145 :   if (!code->ext.omp_variants->next && code->ext.omp_variants->stmt == ST_NONE)
   13775              :     {
   13776           11 :       gfc_code *next = code->next;
   13777           11 :       gfc_code *inner = code->ext.omp_variants->code;
   13778           11 :       gfc_free_omp_set_selector_list (code->ext.omp_variants->selectors);
   13779           11 :       free (code->ext.omp_variants);
   13780           11 :       *code = *inner;
   13781           11 :       free (inner);
   13782           11 :       while (code->next)
   13783              :         code = code->next;
   13784           11 :       code->next = next;
   13785              :     }
   13786          145 : }
   13787              : 
   13788              : 
   13789              : static gfc_statement
   13790           63 : omp_code_to_statement (gfc_code *code)
   13791              : {
   13792           63 :   switch (code->op)
   13793              :     {
   13794              :     case EXEC_OMP_PARALLEL:
   13795              :       return ST_OMP_PARALLEL;
   13796            0 :     case EXEC_OMP_PARALLEL_MASKED:
   13797            0 :       return ST_OMP_PARALLEL_MASKED;
   13798            0 :     case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
   13799            0 :       return ST_OMP_PARALLEL_MASKED_TASKLOOP;
   13800            0 :     case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
   13801            0 :       return ST_OMP_PARALLEL_MASKED_TASKLOOP_SIMD;
   13802            0 :     case EXEC_OMP_PARALLEL_MASTER:
   13803            0 :       return ST_OMP_PARALLEL_MASTER;
   13804            0 :     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
   13805            0 :       return ST_OMP_PARALLEL_MASTER_TASKLOOP;
   13806            0 :     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
   13807            0 :       return ST_OMP_PARALLEL_MASTER_TASKLOOP_SIMD;
   13808            1 :     case EXEC_OMP_PARALLEL_SECTIONS:
   13809            1 :       return ST_OMP_PARALLEL_SECTIONS;
   13810            1 :     case EXEC_OMP_SECTIONS:
   13811            1 :       return ST_OMP_SECTIONS;
   13812            1 :     case EXEC_OMP_ORDERED:
   13813            1 :       return ST_OMP_ORDERED;
   13814            1 :     case EXEC_OMP_CRITICAL:
   13815            1 :       return ST_OMP_CRITICAL;
   13816            0 :     case EXEC_OMP_MASKED:
   13817            0 :       return ST_OMP_MASKED;
   13818            0 :     case EXEC_OMP_MASKED_TASKLOOP:
   13819            0 :       return ST_OMP_MASKED_TASKLOOP;
   13820            0 :     case EXEC_OMP_MASKED_TASKLOOP_SIMD:
   13821            0 :       return ST_OMP_MASKED_TASKLOOP_SIMD;
   13822            1 :     case EXEC_OMP_MASTER:
   13823            1 :       return ST_OMP_MASTER;
   13824            0 :     case EXEC_OMP_MASTER_TASKLOOP:
   13825            0 :       return ST_OMP_MASTER_TASKLOOP;
   13826            0 :     case EXEC_OMP_MASTER_TASKLOOP_SIMD:
   13827            0 :       return ST_OMP_MASTER_TASKLOOP_SIMD;
   13828            1 :     case EXEC_OMP_SINGLE:
   13829            1 :       return ST_OMP_SINGLE;
   13830            1 :     case EXEC_OMP_TASK:
   13831            1 :       return ST_OMP_TASK;
   13832            1 :     case EXEC_OMP_WORKSHARE:
   13833            1 :       return ST_OMP_WORKSHARE;
   13834            1 :     case EXEC_OMP_PARALLEL_WORKSHARE:
   13835            1 :       return ST_OMP_PARALLEL_WORKSHARE;
   13836            3 :     case EXEC_OMP_DO:
   13837            3 :       return ST_OMP_DO;
   13838            0 :     case EXEC_OMP_LOOP:
   13839            0 :       return ST_OMP_LOOP;
   13840            0 :     case EXEC_OMP_ALLOCATE:
   13841            0 :       return ST_OMP_ALLOCATE_EXEC;
   13842            0 :     case EXEC_OMP_ALLOCATORS:
   13843            0 :       return ST_OMP_ALLOCATORS;
   13844            0 :     case EXEC_OMP_ASSUME:
   13845            0 :       return ST_OMP_ASSUME;
   13846            1 :     case EXEC_OMP_ATOMIC:
   13847            1 :       return ST_OMP_ATOMIC;
   13848            1 :     case EXEC_OMP_BARRIER:
   13849            1 :       return ST_OMP_BARRIER;
   13850            1 :     case EXEC_OMP_CANCEL:
   13851            1 :       return ST_OMP_CANCEL;
   13852            1 :     case EXEC_OMP_CANCELLATION_POINT:
   13853            1 :       return ST_OMP_CANCELLATION_POINT;
   13854            0 :     case EXEC_OMP_ERROR:
   13855            0 :       return ST_OMP_ERROR;
   13856            1 :     case EXEC_OMP_FLUSH:
   13857            1 :       return ST_OMP_FLUSH;
   13858            0 :     case EXEC_OMP_INTEROP:
   13859            0 :       return ST_OMP_INTEROP;
   13860            1 :     case EXEC_OMP_DISTRIBUTE:
   13861            1 :       return ST_OMP_DISTRIBUTE;
   13862            1 :     case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
   13863            1 :       return ST_OMP_DISTRIBUTE_PARALLEL_DO;
   13864            1 :     case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
   13865            1 :       return ST_OMP_DISTRIBUTE_PARALLEL_DO_SIMD;
   13866            1 :     case EXEC_OMP_DISTRIBUTE_SIMD:
   13867            1 :       return ST_OMP_DISTRIBUTE_SIMD;
   13868            1 :     case EXEC_OMP_DO_SIMD:
   13869            1 :       return ST_OMP_DO_SIMD;
   13870            0 :     case EXEC_OMP_SCAN:
   13871            0 :       return ST_OMP_SCAN;
   13872            0 :     case EXEC_OMP_SCOPE:
   13873            0 :       return ST_OMP_SCOPE;
   13874            1 :     case EXEC_OMP_SIMD:
   13875            1 :       return ST_OMP_SIMD;
   13876            1 :     case EXEC_OMP_TARGET:
   13877            1 :       return ST_OMP_TARGET;
   13878            1 :     case EXEC_OMP_TARGET_DATA:
   13879            1 :       return ST_OMP_TARGET_DATA;
   13880            1 :     case EXEC_OMP_TARGET_ENTER_DATA:
   13881            1 :       return ST_OMP_TARGET_ENTER_DATA;
   13882            1 :     case EXEC_OMP_TARGET_EXIT_DATA:
   13883            1 :       return ST_OMP_TARGET_EXIT_DATA;
   13884            1 :     case EXEC_OMP_TARGET_PARALLEL:
   13885            1 :       return ST_OMP_TARGET_PARALLEL;
   13886            1 :     case EXEC_OMP_TARGET_PARALLEL_DO:
   13887            1 :       return ST_OMP_TARGET_PARALLEL_DO;
   13888            1 :     case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
   13889            1 :       return ST_OMP_TARGET_PARALLEL_DO_SIMD;
   13890            0 :     case EXEC_OMP_TARGET_PARALLEL_LOOP:
   13891            0 :       return ST_OMP_TARGET_PARALLEL_LOOP;
   13892            1 :     case EXEC_OMP_TARGET_SIMD:
   13893            1 :       return ST_OMP_TARGET_SIMD;
   13894            1 :     case EXEC_OMP_TARGET_TEAMS:
   13895            1 :       return ST_OMP_TARGET_TEAMS;
   13896            1 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
   13897            1 :       return ST_OMP_TARGET_TEAMS_DISTRIBUTE;
   13898            1 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
   13899            1 :       return ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO;
   13900            1 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
   13901            1 :       return ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD;
   13902            1 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
   13903            1 :       return ST_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD;
   13904            0 :     case EXEC_OMP_TARGET_TEAMS_LOOP:
   13905            0 :       return ST_OMP_TARGET_TEAMS_LOOP;
   13906            1 :     case EXEC_OMP_TARGET_UPDATE:
   13907            1 :       return ST_OMP_TARGET_UPDATE;
   13908            1 :     case EXEC_OMP_TASKGROUP:
   13909            1 :       return ST_OMP_TASKGROUP;
   13910            1 :     case EXEC_OMP_TASKLOOP:
   13911            1 :       return ST_OMP_TASKLOOP;
   13912            1 :     case EXEC_OMP_TASKLOOP_SIMD:
   13913            1 :       return ST_OMP_TASKLOOP_SIMD;
   13914            1 :     case EXEC_OMP_TASKWAIT:
   13915            1 :       return ST_OMP_TASKWAIT;
   13916            1 :     case EXEC_OMP_TASKYIELD:
   13917            1 :       return ST_OMP_TASKYIELD;
   13918            1 :     case EXEC_OMP_TEAMS:
   13919            1 :       return ST_OMP_TEAMS;
   13920            1 :     case EXEC_OMP_TEAMS_DISTRIBUTE:
   13921            1 :       return ST_OMP_TEAMS_DISTRIBUTE;
   13922            1 :     case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
   13923            1 :       return ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO;
   13924            1 :     case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
   13925            1 :       return ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD;
   13926            1 :     case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
   13927            1 :       return ST_OMP_TEAMS_DISTRIBUTE_SIMD;
   13928            0 :     case EXEC_OMP_TEAMS_LOOP:
   13929            0 :       return ST_OMP_TEAMS_LOOP;
   13930            6 :     case EXEC_OMP_PARALLEL_DO:
   13931            6 :       return ST_OMP_PARALLEL_DO;
   13932            1 :     case EXEC_OMP_PARALLEL_DO_SIMD:
   13933            1 :       return ST_OMP_PARALLEL_DO_SIMD;
   13934            0 :     case EXEC_OMP_PARALLEL_LOOP:
   13935            0 :       return ST_OMP_PARALLEL_LOOP;
   13936            1 :     case EXEC_OMP_DEPOBJ:
   13937            1 :       return ST_OMP_DEPOBJ;
   13938            0 :     case EXEC_OMP_TILE:
   13939            0 :       return ST_OMP_TILE;
   13940            0 :     case EXEC_OMP_UNROLL:
   13941            0 :       return ST_OMP_UNROLL;
   13942            0 :     case EXEC_OMP_DISPATCH:
   13943            0 :       return ST_OMP_DISPATCH;
   13944            0 :     default:
   13945            0 :       gcc_unreachable ();
   13946              :     }
   13947              : }
   13948              : 
   13949              : static gfc_statement
   13950           63 : oacc_code_to_statement (gfc_code *code)
   13951              : {
   13952           63 :   switch (code->op)
   13953              :     {
   13954              :     case EXEC_OACC_PARALLEL:
   13955              :       return ST_OACC_PARALLEL;
   13956              :     case EXEC_OACC_KERNELS:
   13957              :       return ST_OACC_KERNELS;
   13958              :     case EXEC_OACC_SERIAL:
   13959              :       return ST_OACC_SERIAL;
   13960              :     case EXEC_OACC_DATA:
   13961              :       return ST_OACC_DATA;
   13962              :     case EXEC_OACC_HOST_DATA:
   13963              :       return ST_OACC_HOST_DATA;
   13964              :     case EXEC_OACC_PARALLEL_LOOP:
   13965              :       return ST_OACC_PARALLEL_LOOP;
   13966              :     case EXEC_OACC_KERNELS_LOOP:
   13967              :       return ST_OACC_KERNELS_LOOP;
   13968              :     case EXEC_OACC_SERIAL_LOOP:
   13969              :       return ST_OACC_SERIAL_LOOP;
   13970              :     case EXEC_OACC_LOOP:
   13971              :       return ST_OACC_LOOP;
   13972              :     case EXEC_OACC_ATOMIC:
   13973              :       return ST_OACC_ATOMIC;
   13974              :     case EXEC_OACC_ROUTINE:
   13975              :       return ST_OACC_ROUTINE;
   13976              :     case EXEC_OACC_UPDATE:
   13977              :       return ST_OACC_UPDATE;
   13978              :     case EXEC_OACC_WAIT:
   13979              :       return ST_OACC_WAIT;
   13980              :     case EXEC_OACC_CACHE:
   13981              :       return ST_OACC_CACHE;
   13982              :     case EXEC_OACC_ENTER_DATA:
   13983              :       return ST_OACC_ENTER_DATA;
   13984              :     case EXEC_OACC_EXIT_DATA:
   13985              :       return ST_OACC_EXIT_DATA;
   13986              :     case EXEC_OACC_DECLARE:
   13987              :       return ST_OACC_DECLARE;
   13988              :     case EXEC_OACC_INIT:
   13989              :       return ST_OACC_INIT;
   13990              :     case EXEC_OACC_SHUTDOWN:
   13991              :       return ST_OACC_SHUTDOWN;
   13992              :     case EXEC_OACC_SET:
   13993              :       return ST_OACC_SET;
   13994            0 :     default:
   13995            0 :       gcc_unreachable ();
   13996              :     }
   13997              : }
   13998              : 
   13999              : static void
   14000        13538 : resolve_oacc_directive_inside_omp_region (gfc_code *code)
   14001              : {
   14002        13538 :   if (omp_current_ctx != NULL && omp_current_ctx->is_openmp)
   14003              :     {
   14004           11 :       gfc_statement st = omp_code_to_statement (omp_current_ctx->code);
   14005           11 :       gfc_statement oacc_st = oacc_code_to_statement (code);
   14006           11 :       gfc_error ("The %s directive cannot be specified within "
   14007              :                  "a %s region at %L", gfc_ascii_statement (oacc_st),
   14008              :                  gfc_ascii_statement (st), &code->loc);
   14009              :     }
   14010        13538 : }
   14011              : 
   14012              : static void
   14013        21349 : resolve_omp_directive_inside_oacc_region (gfc_code *code)
   14014              : {
   14015        21349 :   if (omp_current_ctx != NULL && !omp_current_ctx->is_openmp)
   14016              :     {
   14017           52 :       gfc_statement st = oacc_code_to_statement (omp_current_ctx->code);
   14018           52 :       gfc_statement omp_st = omp_code_to_statement (code);
   14019           52 :       gfc_error ("The %s directive cannot be specified within "
   14020              :                  "a %s region at %L", gfc_ascii_statement (omp_st),
   14021              :                  gfc_ascii_statement (st), &code->loc);
   14022              :     }
   14023        21349 : }
   14024              : 
   14025              : 
   14026              : static void
   14027         5272 : resolve_oacc_nested_loops (gfc_code *code, gfc_code* do_code, int collapse,
   14028              :                           const char *clause)
   14029              : {
   14030         5272 :   gfc_symbol *dovar;
   14031         5272 :   gfc_code *c;
   14032         5272 :   int i;
   14033              : 
   14034         5792 :   for (i = 1; i <= collapse; i++)
   14035              :     {
   14036         5792 :       if (do_code->op == EXEC_DO_WHILE)
   14037              :         {
   14038           10 :           gfc_error ("!$ACC LOOP cannot be a DO WHILE or DO without loop control "
   14039              :                      "at %L", &do_code->loc);
   14040           10 :           break;
   14041              :         }
   14042         5782 :       if (do_code->op == EXEC_DO_CONCURRENT)
   14043              :         {
   14044            3 :           gfc_error ("!$ACC LOOP cannot be a DO CONCURRENT loop at %L",
   14045              :                      &do_code->loc);
   14046            3 :           break;
   14047              :         }
   14048         5779 :       gcc_assert (do_code->op == EXEC_DO);
   14049         5779 :       if (do_code->ext.iterator->var->ts.type != BT_INTEGER)
   14050            6 :         gfc_error ("!$ACC LOOP iteration variable must be of type integer at %L",
   14051              :                    &do_code->loc);
   14052         5779 :       dovar = do_code->ext.iterator->var->symtree->n.sym;
   14053         5779 :       if (i > 1)
   14054              :         {
   14055          518 :           gfc_code *do_code2 = code->block->next;
   14056          518 :           int j;
   14057              : 
   14058         1218 :           for (j = 1; j < i; j++)
   14059              :             {
   14060          710 :               gfc_symbol *ivar = do_code2->ext.iterator->var->symtree->n.sym;
   14061          710 :               if (dovar == ivar
   14062          710 :                   || gfc_find_sym_in_expr (ivar, do_code->ext.iterator->start)
   14063          701 :                   || gfc_find_sym_in_expr (ivar, do_code->ext.iterator->end)
   14064         1410 :                   || gfc_find_sym_in_expr (ivar, do_code->ext.iterator->step))
   14065              :                 {
   14066           10 :                   gfc_error ("!$ACC LOOP %s loops don't form rectangular "
   14067              :                              "iteration space at %L", clause, &do_code->loc);
   14068           10 :                   break;
   14069              :                 }
   14070          700 :               do_code2 = do_code2->block->next;
   14071              :             }
   14072              :         }
   14073         5779 :       if (i == collapse)
   14074              :         break;
   14075          577 :       for (c = do_code->next; c; c = c->next)
   14076           48 :         if (c->op != EXEC_NOP && c->op != EXEC_CONTINUE)
   14077              :           {
   14078            0 :             gfc_error ("%s !$ACC LOOP loops not perfectly nested at %L",
   14079              :                        clause, &c->loc);
   14080            0 :             break;
   14081              :           }
   14082          529 :       if (c)
   14083              :         break;
   14084          529 :       do_code = do_code->block;
   14085          529 :       if (do_code->op != EXEC_DO && do_code->op != EXEC_DO_WHILE
   14086            0 :           && do_code->op != EXEC_DO_CONCURRENT)
   14087              :         {
   14088            0 :           gfc_error ("not enough DO loops for %s !$ACC LOOP at %L",
   14089              :                      clause, &code->loc);
   14090            0 :           break;
   14091              :         }
   14092          529 :       do_code = do_code->next;
   14093          529 :       if (do_code == NULL
   14094          522 :           || (do_code->op != EXEC_DO && do_code->op != EXEC_DO_WHILE
   14095            2 :               && do_code->op != EXEC_DO_CONCURRENT))
   14096              :         {
   14097            9 :           gfc_error ("not enough DO loops for %s !$ACC LOOP at %L",
   14098              :                      clause, &code->loc);
   14099            9 :           break;
   14100              :         }
   14101              :     }
   14102         5272 : }
   14103              : 
   14104              : 
   14105              : static void
   14106        10119 : resolve_oacc_loop_blocks (gfc_code *code)
   14107              : {
   14108        10119 :   if (!oacc_is_loop (code))
   14109              :     return;
   14110              : 
   14111         5272 :   if (code->ext.omp_clauses->tile_list && code->ext.omp_clauses->gang
   14112           24 :       && code->ext.omp_clauses->worker && code->ext.omp_clauses->vector)
   14113            0 :     gfc_error ("Tiled loop cannot be parallelized across gangs, workers and "
   14114              :                "vectors at the same time at %L", &code->loc);
   14115              : 
   14116         5272 :   if (code->ext.omp_clauses->tile_list)
   14117              :     {
   14118              :       gfc_expr_list *el;
   14119          501 :       for (el = code->ext.omp_clauses->tile_list; el; el = el->next)
   14120              :         {
   14121          304 :           if (el->expr == NULL)
   14122              :             {
   14123              :               /* NULL expressions are used to represent '*' arguments.
   14124              :                  Convert those to a 0 expressions.  */
   14125          113 :               el->expr = gfc_get_constant_expr (BT_INTEGER,
   14126              :                                                 gfc_default_integer_kind,
   14127              :                                                 &code->loc);
   14128          113 :               mpz_set_si (el->expr->value.integer, 0);
   14129              :             }
   14130              :           else
   14131              :             {
   14132          191 :               resolve_positive_int_expr (el->expr, "TILE");
   14133          191 :               if (el->expr->expr_type != EXPR_CONSTANT)
   14134           14 :                 gfc_error ("TILE requires constant expression at %L",
   14135              :                            &code->loc);
   14136              :             }
   14137              :         }
   14138              :     }
   14139              : }
   14140              : 
   14141              : 
   14142              : void
   14143        10119 : gfc_resolve_oacc_blocks (gfc_code *code, gfc_namespace *ns)
   14144              : {
   14145        10119 :   fortran_omp_context ctx;
   14146        10119 :   gfc_omp_clauses *omp_clauses = code->ext.omp_clauses;
   14147        10119 :   gfc_omp_namelist *n;
   14148              : 
   14149        10119 :   resolve_oacc_loop_blocks (code);
   14150              : 
   14151        10119 :   ctx.code = code;
   14152        10119 :   ctx.sharing_clauses = new hash_set<gfc_symbol *>;
   14153        10119 :   ctx.private_iterators = new hash_set<gfc_symbol *>;
   14154        10119 :   ctx.previous = omp_current_ctx;
   14155        10119 :   ctx.is_openmp = false;
   14156        10119 :   omp_current_ctx = &ctx;
   14157              : 
   14158       404760 :   for (enum gfc_omp_list_type list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
   14159       394641 :        list = gfc_omp_list_type (list + 1))
   14160       394641 :     switch (list)
   14161              :       {
   14162        10119 :       case OMP_LIST_PRIVATE:
   14163        10710 :         for (n = omp_clauses->lists[list]; n; n = n->next)
   14164          591 :           ctx.sharing_clauses->add (n->sym);
   14165              :         break;
   14166              :       default:
   14167              :         break;
   14168              :       }
   14169              : 
   14170        10119 :   gfc_resolve_blocks (code->block, ns);
   14171              : 
   14172        10119 :   omp_current_ctx = ctx.previous;
   14173        20238 :   delete ctx.sharing_clauses;
   14174        20238 :   delete ctx.private_iterators;
   14175        10119 : }
   14176              : 
   14177              : 
   14178              : static void
   14179         5272 : resolve_oacc_loop (gfc_code *code)
   14180              : {
   14181         5272 :   gfc_code *do_code;
   14182         5272 :   int collapse;
   14183              : 
   14184         5272 :   if (code->ext.omp_clauses)
   14185         5272 :     resolve_omp_clauses (code, code->ext.omp_clauses, NULL, true);
   14186              : 
   14187         5272 :   do_code = code->block->next;
   14188         5272 :   collapse = code->ext.omp_clauses->collapse;
   14189              : 
   14190              :   /* Both collapsed and tiled loops are lowered the same way, but are not
   14191              :      compatible.  In gfc_trans_omp_do, the tile is prioritized.  */
   14192         5272 :   if (code->ext.omp_clauses->tile_list)
   14193              :     {
   14194              :       int num = 0;
   14195              :       gfc_expr_list *el;
   14196          501 :       for (el = code->ext.omp_clauses->tile_list; el; el = el->next)
   14197          304 :         ++num;
   14198          197 :       resolve_oacc_nested_loops (code, code->block->next, num, "tiled");
   14199          197 :       return;
   14200              :     }
   14201              : 
   14202         5075 :   if (collapse <= 0)
   14203              :     collapse = 1;
   14204         5075 :   resolve_oacc_nested_loops (code, do_code, collapse, "collapsed");
   14205              : }
   14206              : 
   14207              : void
   14208       350685 : gfc_resolve_oacc_declare (gfc_namespace *ns)
   14209              : {
   14210       350685 :   enum gfc_omp_list_type list;
   14211       350685 :   gfc_omp_namelist *n;
   14212       350685 :   gfc_oacc_declare *oc;
   14213              : 
   14214       350685 :   if (ns->oacc_declare == NULL)
   14215              :     return;
   14216              : 
   14217          290 :   for (oc = ns->oacc_declare; oc; oc = oc->next)
   14218              :     {
   14219         6480 :       for (list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
   14220         6318 :            list = gfc_omp_list_type (list + 1))
   14221         6574 :         for (n = oc->clauses->lists[list]; n; n = n->next)
   14222              :           {
   14223          256 :             n->sym->mark = 0;
   14224          256 :             if (n->sym->attr.flavor != FL_VARIABLE
   14225           16 :                 && (n->sym->attr.flavor != FL_PROCEDURE
   14226            8 :                     || n->sym->result != n->sym))
   14227              :               {
   14228           14 :                 if (n->sym->attr.flavor != FL_PARAMETER)
   14229              :                   {
   14230            8 :                     gfc_error ("Object %qs is not a variable at %L",
   14231              :                                n->sym->name, &oc->loc);
   14232            8 :                     continue;
   14233              :                   }
   14234              :                 /* Note that OpenACC 3.4 permits name constants, but the
   14235              :                    implementation is permitted to ignore the clause;
   14236              :                    as semantically, device_resident kind of makes sense
   14237              :                    (and the wording with it is a bit odd), the warning
   14238              :                    is suppressed.  */
   14239            6 :                 if (list != OMP_LIST_DEVICE_RESIDENT)
   14240            5 :                   gfc_warning (OPT_Wsurprising, "Object %qs at %L is ignored as"
   14241              :                                " parameters need not be copied", n->sym->name,
   14242              :                                &oc->loc);
   14243              :               }
   14244              : 
   14245          248 :             if (n->expr && n->expr->ref->type == REF_ARRAY)
   14246              :               {
   14247            1 :                 gfc_error ("Array sections: %qs not allowed in"
   14248            1 :                            " !$ACC DECLARE at %L", n->sym->name, &oc->loc);
   14249            1 :                 continue;
   14250              :               }
   14251              :           }
   14252              : 
   14253          252 :       for (n = oc->clauses->lists[OMP_LIST_DEVICE_RESIDENT]; n; n = n->next)
   14254           90 :         check_array_not_assumed (n->sym, oc->loc, "DEVICE_RESIDENT");
   14255              :     }
   14256              : 
   14257          290 :   for (oc = ns->oacc_declare; oc; oc = oc->next)
   14258              :     {
   14259         6480 :       for (list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
   14260         6318 :            list = gfc_omp_list_type (list + 1))
   14261         6574 :         for (n = oc->clauses->lists[list]; n; n = n->next)
   14262              :           {
   14263          256 :             if (n->sym->mark)
   14264              :               {
   14265            9 :                 gfc_error ("Symbol %qs present on multiple clauses at %L",
   14266              :                            n->sym->name, &oc->loc);
   14267            9 :                 continue;
   14268              :               }
   14269              :             else
   14270          247 :               n->sym->mark = 1;
   14271              :           }
   14272              :     }
   14273              : 
   14274          290 :   for (oc = ns->oacc_declare; oc; oc = oc->next)
   14275              :     {
   14276         6480 :       for (list = OMP_LIST_FIRST; list < OMP_LIST_NUM;
   14277         6318 :            list = gfc_omp_list_type (list + 1))
   14278         6574 :         for (n = oc->clauses->lists[list]; n; n = n->next)
   14279          256 :           n->sym->mark = 0;
   14280              :     }
   14281              : }
   14282              : 
   14283              : 
   14284              : void
   14285       350685 : gfc_resolve_oacc_routines (gfc_namespace *ns)
   14286              : {
   14287       350685 :   for (gfc_oacc_routine_name *orn = ns->oacc_routine_names;
   14288       350785 :        orn;
   14289          100 :        orn = orn->next)
   14290              :     {
   14291          100 :       gfc_symbol *sym = orn->sym;
   14292          100 :       if (!sym->attr.external
   14293           29 :           && !sym->attr.function
   14294           27 :           && !sym->attr.subroutine)
   14295              :         {
   14296            7 :           gfc_error ("NAME %qs does not refer to a subroutine or function"
   14297              :                      " in !$ACC ROUTINE ( NAME ) at %L", sym->name, &orn->loc);
   14298            7 :           continue;
   14299              :         }
   14300           93 :       if (!gfc_add_omp_declare_target (&sym->attr, sym->name, &orn->loc))
   14301              :         {
   14302           20 :           gfc_error ("NAME %qs invalid"
   14303              :                      " in !$ACC ROUTINE ( NAME ) at %L", sym->name, &orn->loc);
   14304           20 :           continue;
   14305              :         }
   14306              :     }
   14307       350685 : }
   14308              : 
   14309              : 
   14310              : void
   14311        13538 : gfc_resolve_oacc_directive (gfc_code *code, gfc_namespace *ns ATTRIBUTE_UNUSED)
   14312              : {
   14313        13538 :   resolve_oacc_directive_inside_omp_region (code);
   14314              : 
   14315        13538 :   switch (code->op)
   14316              :     {
   14317         7723 :     case EXEC_OACC_PARALLEL:
   14318         7723 :     case EXEC_OACC_KERNELS:
   14319         7723 :     case EXEC_OACC_SERIAL:
   14320         7723 :     case EXEC_OACC_DATA:
   14321         7723 :     case EXEC_OACC_HOST_DATA:
   14322         7723 :     case EXEC_OACC_UPDATE:
   14323         7723 :     case EXEC_OACC_ENTER_DATA:
   14324         7723 :     case EXEC_OACC_EXIT_DATA:
   14325         7723 :     case EXEC_OACC_WAIT:
   14326         7723 :     case EXEC_OACC_CACHE:
   14327         7723 :     case EXEC_OACC_INIT:
   14328         7723 :     case EXEC_OACC_SHUTDOWN:
   14329         7723 :     case EXEC_OACC_SET:
   14330         7723 :       resolve_omp_clauses (code, code->ext.omp_clauses, NULL, true);
   14331         7723 :       break;
   14332         5272 :     case EXEC_OACC_PARALLEL_LOOP:
   14333         5272 :     case EXEC_OACC_KERNELS_LOOP:
   14334         5272 :     case EXEC_OACC_SERIAL_LOOP:
   14335         5272 :     case EXEC_OACC_LOOP:
   14336         5272 :       resolve_oacc_loop (code);
   14337         5272 :       break;
   14338          543 :     case EXEC_OACC_ATOMIC:
   14339          543 :       resolve_omp_atomic (code);
   14340          543 :       break;
   14341              :     default:
   14342              :       break;
   14343              :     }
   14344        13538 : }
   14345              : 
   14346              : 
   14347              : static void
   14348         2185 : resolve_omp_target (gfc_code *code)
   14349              : {
   14350              : #define GFC_IS_TEAMS_CONSTRUCT(op)                      \
   14351              :   (op == EXEC_OMP_TEAMS                                 \
   14352              :    || op == EXEC_OMP_TEAMS_DISTRIBUTE                   \
   14353              :    || op == EXEC_OMP_TEAMS_DISTRIBUTE_SIMD              \
   14354              :    || op == EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO       \
   14355              :    || op == EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD  \
   14356              :    || op == EXEC_OMP_TEAMS_LOOP)
   14357              : 
   14358         2185 :   if (!code->ext.omp_clauses->contains_teams_construct)
   14359              :     return;
   14360          203 :   gfc_code *c = code->block->next;
   14361          203 :   if (c->op == EXEC_BLOCK)
   14362           30 :     c = c->ext.block.ns->code;
   14363          203 :   if (code->ext.omp_clauses->target_first_st_is_teams_or_meta)
   14364              :     {
   14365          192 :       if (c->op == EXEC_OMP_METADIRECTIVE)
   14366              :         {
   14367           15 :           struct gfc_omp_variant *mc
   14368              :             = c->ext.omp_variants;
   14369              :           /* All mc->(next...->)code should be identical with regards
   14370              :              to the diagnostic below.  */
   14371           16 :           do
   14372              :             {
   14373           16 :               if (mc->stmt != ST_NONE
   14374           15 :                   && GFC_IS_TEAMS_CONSTRUCT (mc->code->op))
   14375              :                 {
   14376           14 :                   if (c->next == NULL && mc->code->next == NULL)
   14377              :                     return;
   14378           23 :                   c = mc->code;
   14379              :                   break;
   14380              :                 }
   14381            2 :               mc = mc->next;
   14382              :             }
   14383            2 :           while (mc);
   14384              :         }
   14385          177 :       else if (GFC_IS_TEAMS_CONSTRUCT (c->op) && c->next == NULL)
   14386              :         return;
   14387              :     }
   14388              : 
   14389           31 :   while (c && !GFC_IS_TEAMS_CONSTRUCT (c->op))
   14390            8 :     c = c->next;
   14391           23 :   if (c)
   14392           19 :     gfc_error ("!$OMP TARGET region at %L with a nested TEAMS at %L may not "
   14393              :                "contain any other statement, declaration or directive outside "
   14394              :                "of the single TEAMS construct", &c->loc, &code->loc);
   14395              :   else
   14396            4 :     gfc_error ("!$OMP TARGET region at %L with a nested TEAMS may not "
   14397              :                "contain any other statement, declaration or directive outside "
   14398              :                "of the single TEAMS construct", &code->loc);
   14399              : #undef GFC_IS_TEAMS_CONSTRUCT
   14400              : }
   14401              : 
   14402              : static void
   14403          154 : resolve_omp_dispatch (gfc_code *code)
   14404              : {
   14405          154 :   gfc_code *next = code->block->next;
   14406          154 :   if (next == NULL)
   14407              :     return;
   14408              : 
   14409          151 :   gfc_exec_op op = next->op;
   14410          151 :   gcc_assert (op == EXEC_CALL || op == EXEC_ASSIGN);
   14411          151 :   if (op != EXEC_CALL
   14412           74 :       && (op != EXEC_ASSIGN || next->expr2->expr_type != EXPR_FUNCTION))
   14413            3 :     gfc_error (
   14414              :       "%<OMP DISPATCH%> directive at %L must be followed by a procedure "
   14415              :       "call with optional assignment",
   14416              :       &code->loc);
   14417              : 
   14418           77 :   if ((op == EXEC_CALL && next->resolved_sym != NULL
   14419           76 :        && next->resolved_sym->attr.proc_pointer)
   14420          151 :       || (op == EXEC_ASSIGN && gfc_expr_attr (next->expr2).proc_pointer))
   14421            1 :     gfc_error ("%<OMP DISPATCH%> directive at %L cannot be followed by a "
   14422              :                "procedure pointer",
   14423              :                &code->loc);
   14424              : }
   14425              : 
   14426              : /* Resolve OpenMP directive clauses and check various requirements
   14427              :    of each directive.  */
   14428              : 
   14429              : void
   14430        21349 : gfc_resolve_omp_directive (gfc_code *code, gfc_namespace *ns)
   14431              : {
   14432        21349 :   resolve_omp_directive_inside_oacc_region (code);
   14433              : 
   14434        21349 :   if (code->op != EXEC_OMP_ATOMIC)
   14435        19182 :     gfc_maybe_initialize_eh ();
   14436              : 
   14437        21349 :   switch (code->op)
   14438              :     {
   14439         5441 :     case EXEC_OMP_DISTRIBUTE:
   14440         5441 :     case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
   14441         5441 :     case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
   14442         5441 :     case EXEC_OMP_DISTRIBUTE_SIMD:
   14443         5441 :     case EXEC_OMP_DO:
   14444         5441 :     case EXEC_OMP_DO_SIMD:
   14445         5441 :     case EXEC_OMP_LOOP:
   14446         5441 :     case EXEC_OMP_PARALLEL_DO:
   14447         5441 :     case EXEC_OMP_PARALLEL_DO_SIMD:
   14448         5441 :     case EXEC_OMP_PARALLEL_LOOP:
   14449         5441 :     case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
   14450         5441 :     case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
   14451         5441 :     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
   14452         5441 :     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
   14453         5441 :     case EXEC_OMP_MASKED_TASKLOOP:
   14454         5441 :     case EXEC_OMP_MASKED_TASKLOOP_SIMD:
   14455         5441 :     case EXEC_OMP_MASTER_TASKLOOP:
   14456         5441 :     case EXEC_OMP_MASTER_TASKLOOP_SIMD:
   14457         5441 :     case EXEC_OMP_SIMD:
   14458         5441 :     case EXEC_OMP_TARGET_PARALLEL_DO:
   14459         5441 :     case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
   14460         5441 :     case EXEC_OMP_TARGET_PARALLEL_LOOP:
   14461         5441 :     case EXEC_OMP_TARGET_SIMD:
   14462         5441 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
   14463         5441 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
   14464         5441 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
   14465         5441 :     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
   14466         5441 :     case EXEC_OMP_TARGET_TEAMS_LOOP:
   14467         5441 :     case EXEC_OMP_TASKLOOP:
   14468         5441 :     case EXEC_OMP_TASKLOOP_SIMD:
   14469         5441 :     case EXEC_OMP_TEAMS_DISTRIBUTE:
   14470         5441 :     case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
   14471         5441 :     case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
   14472         5441 :     case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
   14473         5441 :     case EXEC_OMP_TEAMS_LOOP:
   14474         5441 :     case EXEC_OMP_TILE:
   14475         5441 :     case EXEC_OMP_UNROLL:
   14476         5441 :       resolve_omp_do (code);
   14477         5441 :       break;
   14478         2185 :     case EXEC_OMP_TARGET:
   14479         2185 :       resolve_omp_target (code);
   14480        10323 :       gcc_fallthrough ();
   14481        10323 :     case EXEC_OMP_ALLOCATE:
   14482        10323 :     case EXEC_OMP_ALLOCATORS:
   14483        10323 :     case EXEC_OMP_ASSUME:
   14484        10323 :     case EXEC_OMP_CANCEL:
   14485        10323 :     case EXEC_OMP_ERROR:
   14486        10323 :     case EXEC_OMP_INTEROP:
   14487        10323 :     case EXEC_OMP_MASKED:
   14488        10323 :     case EXEC_OMP_ORDERED:
   14489        10323 :     case EXEC_OMP_PARALLEL_WORKSHARE:
   14490        10323 :     case EXEC_OMP_PARALLEL:
   14491        10323 :     case EXEC_OMP_PARALLEL_MASKED:
   14492        10323 :     case EXEC_OMP_PARALLEL_MASTER:
   14493        10323 :     case EXEC_OMP_PARALLEL_SECTIONS:
   14494        10323 :     case EXEC_OMP_SCOPE:
   14495        10323 :     case EXEC_OMP_SECTIONS:
   14496        10323 :     case EXEC_OMP_SINGLE:
   14497        10323 :     case EXEC_OMP_TARGET_DATA:
   14498        10323 :     case EXEC_OMP_TARGET_ENTER_DATA:
   14499        10323 :     case EXEC_OMP_TARGET_EXIT_DATA:
   14500        10323 :     case EXEC_OMP_TARGET_PARALLEL:
   14501        10323 :     case EXEC_OMP_TARGET_TEAMS:
   14502        10323 :     case EXEC_OMP_TASK:
   14503        10323 :     case EXEC_OMP_TASKWAIT:
   14504        10323 :     case EXEC_OMP_TEAMS:
   14505        10323 :     case EXEC_OMP_WORKSHARE:
   14506        10323 :     case EXEC_OMP_DEPOBJ:
   14507        10323 :       if (code->ext.omp_clauses)
   14508        10182 :         resolve_omp_clauses (code, code->ext.omp_clauses, NULL);
   14509              :       break;
   14510         1720 :     case EXEC_OMP_TARGET_UPDATE:
   14511         1720 :       if (code->ext.omp_clauses)
   14512         1720 :         resolve_omp_clauses (code, code->ext.omp_clauses, NULL);
   14513         1720 :       if (code->ext.omp_clauses == NULL
   14514         1720 :           || (code->ext.omp_clauses->lists[OMP_LIST_TO] == NULL
   14515          996 :               && code->ext.omp_clauses->lists[OMP_LIST_FROM] == NULL))
   14516            0 :         gfc_error ("OMP TARGET UPDATE at %L requires at least one TO or "
   14517              :                    "FROM clause", &code->loc);
   14518              :       break;
   14519         2167 :     case EXEC_OMP_ATOMIC:
   14520         2167 :       resolve_omp_clauses (code, code->block->ext.omp_clauses, NULL);
   14521         2167 :       resolve_omp_atomic (code);
   14522         2167 :       break;
   14523          165 :     case EXEC_OMP_CRITICAL:
   14524          165 :       resolve_omp_clauses (code, code->ext.omp_clauses, NULL);
   14525          165 :       if (!code->ext.omp_clauses->critical_name
   14526          114 :           && code->ext.omp_clauses->hint
   14527            5 :           && code->ext.omp_clauses->hint->ts.type == BT_INTEGER
   14528            5 :           && code->ext.omp_clauses->hint->expr_type == EXPR_CONSTANT
   14529            5 :           && mpz_sgn (code->ext.omp_clauses->hint->value.integer) != 0)
   14530            1 :         gfc_error ("OMP CRITICAL at %L with HINT clause requires a NAME, "
   14531              :                    "except when omp_sync_hint_none is used", &code->loc);
   14532              :       break;
   14533           49 :     case EXEC_OMP_SCAN:
   14534              :       /* Flag is only used to checking, hence, it is unset afterwards.  */
   14535           49 :       if (!code->ext.omp_clauses->if_present)
   14536           10 :         gfc_error ("Unexpected !$OMP SCAN at %L outside loop construct with "
   14537              :                    "%<inscan%> REDUCTION clause", &code->loc);
   14538           49 :       code->ext.omp_clauses->if_present = false;
   14539           49 :       resolve_omp_clauses (code, code->ext.omp_clauses, ns);
   14540           49 :       break;
   14541          154 :     case EXEC_OMP_DISPATCH:
   14542          154 :       if (code->ext.omp_clauses)
   14543          154 :         resolve_omp_clauses (code, code->ext.omp_clauses, ns);
   14544          154 :       resolve_omp_dispatch (code);
   14545          154 :       break;
   14546          145 :     case EXEC_OMP_METADIRECTIVE:
   14547          145 :       resolve_omp_metadirective (code, ns);
   14548          145 :       break;
   14549              :     default:
   14550              :       break;
   14551              :     }
   14552        21349 : }
   14553              : 
   14554              : /* Resolve !$omp declare {variant|simd} constructs in NS.
   14555              :    Note that !$omp declare target is resolved in resolve_symbol.  */
   14556              : 
   14557              : void
   14558       362782 : gfc_resolve_omp_declare (gfc_namespace *ns)
   14559              : {
   14560       362782 :   gfc_omp_declare_simd *ods;
   14561       363029 :   for (ods = ns->omp_declare_simd; ods; ods = ods->next)
   14562              :     {
   14563          247 :       if (ods->proc_name != NULL
   14564          197 :           && ods->proc_name != ns->proc_name)
   14565            6 :         gfc_error ("!$OMP DECLARE SIMD should refer to containing procedure "
   14566              :                    "%qs at %L", ns->proc_name->name, &ods->where);
   14567          247 :       if (ods->clauses)
   14568          229 :         resolve_omp_clauses (NULL, ods->clauses, ns);
   14569              :     }
   14570              : 
   14571       362782 :   gfc_omp_declare_variant *odv;
   14572       362782 :   gfc_omp_namelist *range_begin = NULL;
   14573              : 
   14574       363243 :   for (odv = ns->omp_declare_variant; odv; odv = odv->next)
   14575          461 :     gfc_resolve_omp_context_selector (odv->set_selectors, false, nullptr);
   14576       363243 :   for (odv = ns->omp_declare_variant; odv; odv = odv->next)
   14577          664 :     for (gfc_omp_namelist *n = odv->adjust_args_list; n != NULL; n = n->next)
   14578              :       {
   14579          203 :         if ((n->expr == NULL
   14580            6 :              && (range_begin
   14581            4 :                  || n->u.adj_args.range_start
   14582            1 :                  || n->u.adj_args.omp_num_args_plus
   14583            1 :                  || n->u.adj_args.omp_num_args_minus))
   14584          198 :             || n->u.adj_args.error_p)
   14585              :           {
   14586              :           }
   14587          197 :         else if (range_begin
   14588          191 :                  || n->u.adj_args.range_start
   14589          186 :                  || n->u.adj_args.omp_num_args_plus
   14590          186 :                  || n->u.adj_args.omp_num_args_minus)
   14591              :           {
   14592           11 :             if (!n->expr
   14593           11 :                 || !gfc_resolve_expr (n->expr)
   14594           11 :                 || n->expr->expr_type != EXPR_CONSTANT
   14595           10 :                 || n->expr->ts.type != BT_INTEGER
   14596           10 :                 || n->expr->rank != 0
   14597           10 :                 || mpz_sgn (n->expr->value.integer) < 0
   14598           20 :                 || ((n->u.adj_args.omp_num_args_plus
   14599            8 :                      || n->u.adj_args.omp_num_args_minus)
   14600            5 :                     && mpz_sgn (n->expr->value.integer) == 0))
   14601              :               {
   14602            2 :                 if (n->u.adj_args.omp_num_args_plus
   14603            2 :                     || n->u.adj_args.omp_num_args_minus)
   14604            0 :                   gfc_error ("Expected constant non-negative scalar integer "
   14605              :                              "offset expression at %L", &n->where);
   14606              :                 else
   14607            2 :                   gfc_error ("For range-based %<adjust_args%>, a constant "
   14608              :                              "positive scalar integer expression is required "
   14609              :                              "at %L", &n->where);
   14610              :               }
   14611              :           }
   14612          186 :         else if (n->expr
   14613          186 :                  && n->expr->expr_type == EXPR_CONSTANT
   14614           21 :                  && n->expr->ts.type == BT_INTEGER
   14615           20 :                  && mpz_sgn (n->expr->value.integer) > 0)
   14616              :           {
   14617              :           }
   14618          166 :         else if (!n->expr
   14619          166 :                  || !gfc_resolve_expr (n->expr)
   14620          331 :                  || n->expr->expr_type != EXPR_VARIABLE)
   14621            2 :           gfc_error ("Expected dummy parameter name or a positive integer "
   14622              :                      "at %L", &n->where);
   14623          164 :         else if (n->expr->expr_type == EXPR_VARIABLE)
   14624          164 :           n->sym = n->expr->symtree->n.sym;
   14625              : 
   14626          203 :         range_begin = n->u.adj_args.range_start ? n : NULL;
   14627              :       }
   14628       362782 : }
   14629              : 
   14630              : struct omp_udr_callback_data
   14631              : {
   14632              :   gfc_omp_udr *omp_udr;
   14633              :   bool is_initializer;
   14634              : };
   14635              : 
   14636              : static int
   14637         3746 : omp_udr_callback (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
   14638              :                   void *data)
   14639              : {
   14640         3746 :   struct omp_udr_callback_data *cd = (struct omp_udr_callback_data *) data;
   14641         3746 :   if ((*e)->expr_type == EXPR_VARIABLE)
   14642              :     {
   14643         2303 :       if (cd->is_initializer)
   14644              :         {
   14645          545 :           if ((*e)->symtree->n.sym != cd->omp_udr->omp_priv
   14646          140 :               && (*e)->symtree->n.sym != cd->omp_udr->omp_orig)
   14647            4 :             gfc_error ("Variable other than OMP_PRIV or OMP_ORIG used in "
   14648              :                        "INITIALIZER clause of !$OMP DECLARE REDUCTION at %L",
   14649              :                        &(*e)->where);
   14650              :         }
   14651              :       else
   14652              :         {
   14653         1758 :           if ((*e)->symtree->n.sym != cd->omp_udr->omp_out
   14654          626 :               && (*e)->symtree->n.sym != cd->omp_udr->omp_in)
   14655            6 :             gfc_error ("Variable other than OMP_OUT or OMP_IN used in "
   14656              :                        "combiner of !$OMP DECLARE REDUCTION at %L",
   14657              :                        &(*e)->where);
   14658              :         }
   14659              :     }
   14660         3746 :   return 0;
   14661              : }
   14662              : 
   14663              : /* Resolve !$omp declare reduction constructs.  */
   14664              : 
   14665              : static void
   14666          633 : gfc_resolve_omp_udr (gfc_omp_udr *omp_udr)
   14667              : {
   14668          633 :   gfc_actual_arglist *a;
   14669          633 :   const char *predef_name = NULL;
   14670              : 
   14671          633 :   switch (omp_udr->rop)
   14672              :     {
   14673          632 :     case OMP_REDUCTION_PLUS:
   14674          632 :     case OMP_REDUCTION_TIMES:
   14675          632 :     case OMP_REDUCTION_MINUS:
   14676          632 :     case OMP_REDUCTION_AND:
   14677          632 :     case OMP_REDUCTION_OR:
   14678          632 :     case OMP_REDUCTION_EQV:
   14679          632 :     case OMP_REDUCTION_NEQV:
   14680          632 :     case OMP_REDUCTION_MAX:
   14681          632 :     case OMP_REDUCTION_USER:
   14682          632 :       break;
   14683            1 :     default:
   14684            1 :       gfc_error ("Invalid operator for !$OMP DECLARE REDUCTION %s at %L",
   14685              :                  omp_udr->name, &omp_udr->where);
   14686           26 :       return;
   14687              :     }
   14688              : 
   14689          632 :   if (gfc_omp_udr_predef (omp_udr->rop, omp_udr->name,
   14690              :                           &omp_udr->ts, &predef_name))
   14691              :     {
   14692           19 :       if (predef_name)
   14693           19 :         gfc_error ("Redefinition of predefined %qs in "
   14694              :                    "!$OMP DECLARE REDUCTION at %L",
   14695              :                    predef_name, &omp_udr->where);
   14696              :       else
   14697            0 :         gfc_error ("Redefinition of predefined %qs in "
   14698              :                    "!$OMP DECLARE REDUCTION at %L", omp_udr->name,
   14699              :                    &omp_udr->where);
   14700              :       return;
   14701              :     }
   14702              : 
   14703          613 :   if (omp_udr->ts.type == BT_CHARACTER
   14704           62 :       && omp_udr->ts.u.cl->length
   14705           32 :       && omp_udr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
   14706              :     {
   14707            1 :       gfc_error ("CHARACTER length in !$OMP DECLARE REDUCTION %qs not "
   14708              :                  "constant at %L", omp_udr->name, &omp_udr->where);
   14709            1 :       return;
   14710              :     }
   14711              : 
   14712          612 :   struct omp_udr_callback_data cd;
   14713          612 :   cd.omp_udr = omp_udr;
   14714          612 :   cd.is_initializer = false;
   14715          612 :   gfc_code_walker (&omp_udr->combiner_ns->code, gfc_dummy_code_callback,
   14716              :                    omp_udr_callback, &cd);
   14717          612 :   if (omp_udr->combiner_ns->code->op == EXEC_CALL)
   14718              :     {
   14719          346 :       for (a = omp_udr->combiner_ns->code->ext.actual; a; a = a->next)
   14720          237 :         if (a->expr == NULL)
   14721              :           break;
   14722          110 :       if (a)
   14723            1 :         gfc_error ("Subroutine call with alternate returns in combiner "
   14724              :                    "of !$OMP DECLARE REDUCTION at %L",
   14725              :                    &omp_udr->combiner_ns->code->loc);
   14726              :     }
   14727          612 :   if (omp_udr->initializer_ns)
   14728              :     {
   14729          383 :       cd.is_initializer = true;
   14730          383 :       gfc_code_walker (&omp_udr->initializer_ns->code, gfc_dummy_code_callback,
   14731              :                        omp_udr_callback, &cd);
   14732          383 :       if (omp_udr->initializer_ns->code->op == EXEC_CALL)
   14733              :         {
   14734          377 :           for (a = omp_udr->initializer_ns->code->ext.actual; a; a = a->next)
   14735          243 :             if (a->expr == NULL)
   14736              :               break;
   14737          135 :           if (a)
   14738            1 :             gfc_error ("Subroutine call with alternate returns in "
   14739              :                        "INITIALIZER clause of !$OMP DECLARE REDUCTION "
   14740              :                        "at %L", &omp_udr->initializer_ns->code->loc);
   14741          136 :           for (a = omp_udr->initializer_ns->code->ext.actual; a; a = a->next)
   14742          135 :             if (a->expr
   14743          135 :                 && a->expr->expr_type == EXPR_VARIABLE
   14744          135 :                 && a->expr->symtree->n.sym == omp_udr->omp_priv
   14745          134 :                 && a->expr->ref == NULL)
   14746              :               break;
   14747          135 :           if (a == NULL)
   14748            1 :             gfc_error ("One of actual subroutine arguments in INITIALIZER "
   14749              :                        "clause of !$OMP DECLARE REDUCTION must be OMP_PRIV "
   14750              :                        "at %L", &omp_udr->initializer_ns->code->loc);
   14751              :         }
   14752              :     }
   14753          229 :   else if (omp_udr->ts.type == BT_DERIVED
   14754          229 :            && !gfc_has_default_initializer (omp_udr->ts.u.derived))
   14755              :     {
   14756            4 :       gfc_error ("Missing INITIALIZER clause for !$OMP DECLARE REDUCTION "
   14757              :                  "of derived type without default initializer at %L",
   14758              :                  &omp_udr->where);
   14759            4 :       return;
   14760              :     }
   14761              : }
   14762              : 
   14763              : void
   14764       363850 : gfc_resolve_omp_udrs (gfc_symtree *st)
   14765              : {
   14766       363850 :   gfc_omp_udr *omp_udr;
   14767              : 
   14768       363850 :   if (st == NULL)
   14769              :     return;
   14770          534 :   gfc_resolve_omp_udrs (st->left);
   14771          534 :   gfc_resolve_omp_udrs (st->right);
   14772         1167 :   for (omp_udr = st->n.omp_udr; omp_udr; omp_udr = omp_udr->next)
   14773          633 :     gfc_resolve_omp_udr (omp_udr);
   14774              : }
   14775              : 
   14776              : /* Resolve !$omp declare mapper constructs.  */
   14777              : 
   14778              : static void
   14779           30 : gfc_resolve_omp_udm (gfc_omp_udm *omp_udm)
   14780              : {
   14781           30 :   resolve_omp_clauses (NULL, omp_udm->clauses, omp_udm->mapper_ns);
   14782              : 
   14783           30 :   gfc_omp_namelist *n;
   14784           32 :   for (n = omp_udm->clauses->lists[OMP_LIST_MAP]; n; n = n->next)
   14785           30 :     if (n->sym == omp_udm->var_sym)
   14786              :       break;
   14787           30 :   if (!n)
   14788            2 :     gfc_error ("At least one %<map%> clause in !$OMP DECLARE MAPPER at %L must "
   14789              :                "map %qs or an element of it",
   14790            2 :                &omp_udm->where, omp_udm->var_sym->name);
   14791           30 : }
   14792              : 
   14793              : void
   14794       362840 : gfc_resolve_omp_udms (gfc_symtree *st)
   14795              : {
   14796       362840 :   gfc_omp_udm *omp_udm;
   14797              : 
   14798       362840 :   if (st == NULL)
   14799              :     return;
   14800           29 :   gfc_resolve_omp_udms (st->left);
   14801           29 :   gfc_resolve_omp_udms (st->right);
   14802           59 :   for (omp_udm = st->n.omp_udm; omp_udm; omp_udm = omp_udm->next)
   14803           30 :     gfc_resolve_omp_udm (omp_udm);
   14804              : }
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.